claude-mpm 4.1.26__py3-none-any.whl → 5.0.9__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/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__init__.py +20 -5
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_DOCUMENTATION.md +53 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- claude_mpm/agents/BASE_OPS.md +219 -0
- claude_mpm/agents/BASE_PM.md +432 -158
- claude_mpm/agents/BASE_PROMPT_ENGINEER.md +787 -0
- claude_mpm/agents/BASE_QA.md +167 -0
- claude_mpm/agents/BASE_RESEARCH.md +53 -0
- claude_mpm/agents/OUTPUT_STYLE.md +254 -29
- claude_mpm/agents/PM_INSTRUCTIONS.md +969 -0
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
- claude_mpm/agents/WORKFLOW.md +355 -191
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +41 -14
- claude_mpm/agents/agent_loader_integration.py +3 -2
- claude_mpm/agents/async_agent_loader.py +3 -3
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/base_agent_loader.py +21 -44
- claude_mpm/agents/frontmatter_validator.py +292 -252
- claude_mpm/agents/system_agent_config.py +3 -2
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/circuit-breakers.md +1005 -0
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/git-file-tracking.md +584 -0
- claude_mpm/agents/templates/pm-examples.md +474 -0
- claude_mpm/agents/templates/pm-red-flags.md +310 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/response-format.md +583 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/agents/templates/validation-templates.md +312 -0
- claude_mpm/cli/__init__.py +72 -376
- claude_mpm/cli/commands/__init__.py +4 -0
- claude_mpm/cli/commands/agent_manager.py +675 -20
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +344 -0
- claude_mpm/cli/commands/agents.py +1673 -178
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +11 -7
- claude_mpm/cli/commands/analyze.py +18 -13
- claude_mpm/cli/commands/analyze_code.py +8 -4
- claude_mpm/cli/commands/auto_configure.py +566 -0
- claude_mpm/cli/commands/cleanup.py +12 -12
- claude_mpm/cli/commands/config.py +54 -17
- claude_mpm/cli/commands/configure.py +1184 -1055
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +184 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/dashboard.py +50 -52
- claude_mpm/cli/commands/debug.py +19 -19
- claude_mpm/cli/commands/doctor.py +51 -7
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/info.py +3 -4
- claude_mpm/cli/commands/local_deploy.py +534 -0
- claude_mpm/cli/commands/mcp.py +17 -10
- claude_mpm/cli/commands/mcp_command_router.py +11 -0
- claude_mpm/cli/commands/mcp_config.py +154 -0
- claude_mpm/cli/commands/mcp_external_commands.py +249 -0
- claude_mpm/cli/commands/mcp_install_commands.py +101 -32
- claude_mpm/cli/commands/mcp_pipx_config.py +2 -2
- claude_mpm/cli/commands/mcp_setup_external.py +868 -0
- claude_mpm/cli/commands/memory.py +55 -21
- claude_mpm/cli/commands/monitor.py +160 -70
- claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
- claude_mpm/cli/commands/mpm_init/core.py +573 -0
- claude_mpm/cli/commands/mpm_init/display.py +341 -0
- claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
- claude_mpm/cli/commands/mpm_init/modes.py +397 -0
- claude_mpm/cli/commands/mpm_init/prompts.py +442 -0
- claude_mpm/cli/commands/mpm_init_cli.py +396 -0
- claude_mpm/cli/commands/mpm_init_handler.py +114 -4
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +252 -167
- claude_mpm/cli/commands/search.py +458 -0
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +1225 -0
- claude_mpm/cli/commands/uninstall.py +176 -0
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/commands/verify.py +119 -0
- claude_mpm/cli/executor.py +279 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +21 -0
- claude_mpm/cli/interactive/agent_wizard.py +1872 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parser.py +79 -2
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +161 -1
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +369 -1
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +196 -3
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/configure_parser.py +11 -15
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mcp_parser.py +15 -0
- claude_mpm/cli/parsers/monitor_parser.py +12 -2
- claude_mpm/cli/parsers/mpm_init_parser.py +179 -9
- claude_mpm/cli/parsers/run_parser.py +5 -0
- claude_mpm/cli/parsers/search_parser.py +245 -0
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +282 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/shared/argument_patterns.py +20 -13
- claude_mpm/cli/shared/base_command.py +2 -2
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +994 -0
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/startup_logging.py +179 -13
- claude_mpm/cli/utils.py +54 -3
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/mpm-agents-auto-configure.md +278 -0
- claude_mpm/commands/mpm-agents-detect.md +177 -0
- claude_mpm/commands/mpm-agents-list.md +131 -0
- claude_mpm/commands/mpm-agents-recommend.md +223 -0
- claude_mpm/commands/mpm-config-view.md +150 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +297 -5
- claude_mpm/commands/mpm-init.md +401 -17
- claude_mpm/commands/mpm-monitor.md +418 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/mpm-session-resume.md +381 -0
- claude_mpm/commands/mpm-status.md +79 -8
- claude_mpm/commands/mpm-ticket-organize.md +304 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +122 -0
- claude_mpm/commands/mpm.md +12 -0
- claude_mpm/config/agent_config.py +4 -4
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/experimental_features.py +7 -7
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/config/paths.py +3 -2
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/config/socketio_config.py +3 -3
- claude_mpm/constants.py +28 -1
- claude_mpm/core/__init__.py +53 -17
- claude_mpm/core/agent_name_normalizer.py +3 -2
- claude_mpm/core/agent_registry.py +2 -2
- claude_mpm/core/agent_session_manager.py +10 -10
- claude_mpm/core/api_validator.py +330 -0
- claude_mpm/core/base_service.py +33 -23
- claude_mpm/core/cache.py +9 -9
- claude_mpm/core/claude_runner.py +24 -42
- claude_mpm/core/config.py +101 -8
- claude_mpm/core/config_aliases.py +7 -6
- claude_mpm/core/constants.py +66 -1
- claude_mpm/core/container.py +11 -5
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/error_handler.py +623 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/file_utils.py +764 -0
- claude_mpm/core/framework/__init__.py +25 -0
- claude_mpm/core/framework/formatters/__init__.py +11 -0
- claude_mpm/core/framework/formatters/capability_generator.py +367 -0
- claude_mpm/core/framework/formatters/content_formatter.py +288 -0
- claude_mpm/core/framework/formatters/context_generator.py +185 -0
- claude_mpm/core/framework/loaders/__init__.py +13 -0
- claude_mpm/core/framework/loaders/agent_loader.py +210 -0
- claude_mpm/core/framework/loaders/file_loader.py +176 -0
- claude_mpm/core/framework/loaders/instruction_loader.py +181 -0
- claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
- claude_mpm/core/framework/processors/__init__.py +11 -0
- claude_mpm/core/framework/processors/memory_processor.py +230 -0
- claude_mpm/core/framework/processors/metadata_processor.py +146 -0
- claude_mpm/core/framework/processors/template_processor.py +244 -0
- claude_mpm/core/framework_loader.py +321 -1631
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +49 -8
- claude_mpm/core/injectable_service.py +11 -8
- claude_mpm/core/instruction_reinforcement_hook.py +4 -3
- claude_mpm/core/interactive_session.py +146 -18
- claude_mpm/core/interfaces.py +56 -1
- claude_mpm/core/lazy.py +3 -3
- claude_mpm/core/log_manager.py +92 -23
- claude_mpm/core/logger.py +22 -15
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/logging_utils.py +520 -0
- claude_mpm/core/oneshot_session.py +122 -15
- claude_mpm/core/optimized_agent_loader.py +9 -9
- claude_mpm/core/optimized_startup.py +1 -1
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/pm_hook_interceptor.py +18 -12
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/service_registry.py +7 -3
- claude_mpm/core/session_manager.py +14 -12
- claude_mpm/core/shared/config_loader.py +1 -1
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/socketio_pool.py +15 -15
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/core/tool_access_control.py +3 -2
- claude_mpm/core/types.py +4 -11
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/core/unified_agent_registry.py +115 -11
- claude_mpm/core/unified_config.py +6 -6
- claude_mpm/core/unified_paths.py +23 -20
- claude_mpm/dashboard/analysis_runner.py +4 -4
- claude_mpm/dashboard/api/simple_directory.py +261 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +600 -18
- claude_mpm/dashboard/static/js/components/activity-tree.js +181 -195
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +105 -102
- claude_mpm/dashboard/static/js/components/agent-inference.js +34 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +67 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +857 -0
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +891 -0
- claude_mpm/dashboard/static/js/components/event-processor.js +3 -0
- claude_mpm/dashboard/static/js/components/event-viewer.js +50 -13
- claude_mpm/dashboard/static/js/components/export-manager.js +3 -0
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +443 -0
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +690 -0
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +36 -16
- claude_mpm/dashboard/static/js/components/file-viewer.js +580 -0
- claude_mpm/dashboard/static/js/components/module-viewer.js +49 -23
- claude_mpm/dashboard/static/js/components/session-manager.js +19 -19
- claude_mpm/dashboard/static/js/components/socket-manager.js +5 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +356 -41
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +520 -88
- claude_mpm/dashboard/static/js/components/working-directory.js +46 -11
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +309 -178
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/socket-client.js +183 -139
- claude_mpm/dashboard/static/js/tab-isolation-fix.js +185 -0
- claude_mpm/dashboard/static/socket.io.min.js +7 -0
- claude_mpm/dashboard/static/socket.io.v4.8.1.backup.js +7 -0
- claude_mpm/dashboard/templates/code_simple.html +153 -0
- claude_mpm/dashboard/templates/index.html +125 -122
- claude_mpm/experimental/cli_enhancements.py +5 -7
- claude_mpm/generators/agent_profile_generator.py +5 -3
- claude_mpm/hooks/__init__.py +37 -1
- claude_mpm/hooks/base_hook.py +5 -4
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/connection_pool.py +4 -4
- claude_mpm/hooks/claude_hooks/event_handlers.py +24 -19
- claude_mpm/hooks/claude_hooks/hook_handler.py +29 -22
- claude_mpm/hooks/claude_hooks/installer.py +67 -22
- claude_mpm/hooks/claude_hooks/memory_integration.py +3 -3
- claude_mpm/hooks/claude_hooks/response_tracking.py +57 -17
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +62 -64
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +140 -76
- claude_mpm/hooks/claude_hooks/services/state_manager.py +11 -9
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +3 -3
- claude_mpm/hooks/failure_learning/__init__.py +54 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
- claude_mpm/hooks/instruction_reinforcement.py +301 -0
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +386 -0
- claude_mpm/hooks/kuzu_response_hook.py +179 -0
- claude_mpm/hooks/memory_integration_hook.py +1 -1
- claude_mpm/hooks/session_resume_hook.py +121 -0
- claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
- claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
- claude_mpm/hooks/tool_call_interceptor.py +8 -5
- claude_mpm/hooks/validation_hooks.py +3 -3
- claude_mpm/init.py +23 -4
- claude_mpm/models/agent_session.py +8 -6
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/scripts/claude-hook-handler.sh +35 -9
- claude_mpm/scripts/launch_monitor.py +85 -0
- claude_mpm/scripts/mcp_server.py +3 -5
- claude_mpm/scripts/mpm_doctor.py +3 -2
- claude_mpm/scripts/socketio_daemon.py +159 -512
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/__init__.py +144 -160
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/agent_builder.py +56 -18
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_deployment.py +164 -17
- claude_mpm/services/agents/deployment/agent_discovery_service.py +191 -41
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_format_converter.py +56 -12
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -7
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_operation_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_record_service.py +4 -4
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_state_service.py +2 -2
- claude_mpm/services/agents/deployment/agent_template_builder.py +939 -50
- claude_mpm/services/agents/deployment/agent_validator.py +31 -7
- claude_mpm/services/agents/deployment/agent_version_manager.py +8 -5
- claude_mpm/services/agents/deployment/agent_versioning.py +1 -1
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +3 -2
- claude_mpm/services/agents/deployment/deployment_config_loader.py +131 -7
- claude_mpm/services/agents/deployment/deployment_type_detector.py +10 -14
- claude_mpm/services/agents/deployment/deployment_wrapper.py +58 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +360 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +249 -53
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +8 -7
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +7 -5
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +10 -10
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -43
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/template_validator.py +64 -44
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/agent_profile_loader.py +10 -9
- claude_mpm/services/agents/loading/base_agent_manager.py +16 -6
- claude_mpm/services/agents/loading/framework_agent_loader.py +11 -14
- claude_mpm/services/agents/local_template_manager.py +784 -0
- claude_mpm/services/agents/management/agent_capabilities_generator.py +3 -2
- claude_mpm/services/agents/management/agent_management_service.py +5 -5
- claude_mpm/services/agents/memory/agent_memory_manager.py +32 -29
- claude_mpm/services/agents/memory/content_manager.py +17 -9
- claude_mpm/services/agents/memory/memory_categorization_service.py +4 -2
- claude_mpm/services/agents/memory/memory_file_service.py +32 -6
- claude_mpm/services/agents/memory/memory_format_service.py +6 -4
- claude_mpm/services/agents/memory/memory_limits_service.py +4 -2
- claude_mpm/services/agents/memory/template_generator.py +3 -3
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +615 -0
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +3 -3
- claude_mpm/services/agents/registry/modification_tracker.py +30 -19
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/async_session_logger.py +141 -98
- claude_mpm/services/claude_session_logger.py +82 -74
- claude_mpm/services/cli/agent_cleanup_service.py +5 -0
- claude_mpm/services/cli/agent_listing_service.py +5 -5
- claude_mpm/services/cli/agent_validation_service.py +3 -1
- claude_mpm/services/cli/memory_crud_service.py +12 -7
- claude_mpm/services/cli/memory_output_formatter.py +2 -2
- claude_mpm/services/cli/resume_service.py +617 -0
- claude_mpm/services/cli/session_manager.py +104 -13
- claude_mpm/services/cli/session_pause_manager.py +504 -0
- claude_mpm/services/cli/session_resume_helper.py +372 -0
- claude_mpm/services/cli/startup_checker.py +13 -10
- claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
- claude_mpm/services/command_deployment_service.py +209 -13
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/base.py +31 -11
- claude_mpm/services/core/interfaces/__init__.py +88 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +169 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/interfaces.py +56 -1
- claude_mpm/services/core/memory_manager.py +92 -47
- claude_mpm/services/core/models/__init__.py +70 -0
- claude_mpm/services/core/models/agent_config.py +384 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +239 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +36 -14
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/__init__.py +8 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +30 -34
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +28 -27
- claude_mpm/services/diagnostics/checks/configuration_check.py +26 -25
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +165 -60
- claude_mpm/services/diagnostics/checks/instructions_check.py +21 -21
- claude_mpm/services/diagnostics/checks/mcp_check.py +57 -44
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +24 -24
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +14 -11
- claude_mpm/services/diagnostics/diagnostic_runner.py +31 -13
- claude_mpm/services/diagnostics/doctor_reporter.py +305 -47
- claude_mpm/services/diagnostics/models.py +37 -21
- claude_mpm/services/event_aggregator.py +5 -3
- claude_mpm/services/event_bus/direct_relay.py +11 -7
- claude_mpm/services/event_bus/event_bus.py +51 -9
- claude_mpm/services/event_bus/relay.py +33 -14
- claude_mpm/services/events/consumers/dead_letter.py +7 -5
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/events/core.py +5 -6
- claude_mpm/services/events/producers/hook.py +6 -6
- claude_mpm/services/events/producers/system.py +8 -8
- claude_mpm/services/exceptions.py +5 -5
- claude_mpm/services/framework_claude_md_generator/__init__.py +1 -1
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +5 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +2 -2
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +3 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +2 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +1 -1
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/hook_installer_service.py +506 -0
- claude_mpm/services/hook_service.py +5 -6
- claude_mpm/services/infrastructure/context_preservation.py +13 -11
- claude_mpm/services/infrastructure/daemon_manager.py +9 -9
- claude_mpm/services/infrastructure/logging.py +2 -2
- claude_mpm/services/infrastructure/monitoring/__init__.py +2 -6
- claude_mpm/services/infrastructure/monitoring/aggregator.py +13 -18
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +8 -7
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +155 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +427 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +1542 -0
- claude_mpm/services/mcp_gateway/__init__.py +97 -93
- claude_mpm/services/mcp_gateway/auto_configure.py +43 -38
- claude_mpm/services/mcp_gateway/config/config_loader.py +3 -3
- claude_mpm/services/mcp_gateway/config/configuration.py +24 -5
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +20 -33
- claude_mpm/services/mcp_gateway/core/process_pool.py +591 -31
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +2 -2
- claude_mpm/services/mcp_gateway/core/startup_verification.py +3 -3
- claude_mpm/services/mcp_gateway/main.py +90 -15
- claude_mpm/services/mcp_gateway/registry/service_registry.py +4 -2
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +12 -9
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +5 -10
- claude_mpm/services/mcp_gateway/server/stdio_server.py +9 -17
- claude_mpm/services/mcp_gateway/tools/__init__.py +14 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +15 -15
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +10 -9
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +654 -0
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +36 -34
- claude_mpm/services/mcp_gateway/tools/hello_world.py +8 -8
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +555 -0
- claude_mpm/services/mcp_gateway/utils/__init__.py +14 -0
- claude_mpm/services/mcp_gateway/utils/package_version_checker.py +160 -0
- claude_mpm/services/mcp_gateway/utils/update_preferences.py +170 -0
- claude_mpm/services/mcp_service_verifier.py +732 -0
- claude_mpm/services/memory/builder.py +9 -8
- claude_mpm/services/memory/cache/shared_prompt_cache.py +2 -1
- claude_mpm/services/memory/cache/simple_cache.py +2 -2
- claude_mpm/services/memory/failure_tracker.py +578 -0
- claude_mpm/services/memory/indexed_memory.py +8 -8
- claude_mpm/services/memory/optimizer.py +8 -9
- claude_mpm/services/memory/router.py +3 -3
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +452 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/__init__.py +20 -0
- claude_mpm/services/monitor/daemon.py +691 -0
- claude_mpm/services/monitor/daemon_manager.py +1040 -0
- claude_mpm/services/monitor/event_emitter.py +350 -0
- claude_mpm/services/monitor/handlers/__init__.py +21 -0
- claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
- claude_mpm/services/monitor/handlers/dashboard.py +299 -0
- claude_mpm/services/monitor/handlers/file.py +264 -0
- claude_mpm/services/monitor/handlers/hooks.py +512 -0
- claude_mpm/services/monitor/management/__init__.py +18 -0
- claude_mpm/services/monitor/management/health.py +124 -0
- claude_mpm/services/monitor/management/lifecycle.py +724 -0
- claude_mpm/services/monitor/server.py +817 -0
- claude_mpm/services/monitor_build_service.py +2 -2
- claude_mpm/services/native_agent_converter.py +356 -0
- claude_mpm/services/orphan_detection.py +786 -0
- claude_mpm/services/port_manager.py +3 -3
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/analyzer.py +3 -3
- claude_mpm/services/project/architecture_analyzer.py +5 -5
- claude_mpm/services/project/archive_manager.py +1045 -0
- claude_mpm/services/project/dependency_analyzer.py +4 -4
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/documentation_manager.py +554 -0
- claude_mpm/services/project/enhanced_analyzer.py +572 -0
- claude_mpm/services/project/metrics_collector.py +4 -4
- claude_mpm/services/project/project_organizer.py +1005 -0
- claude_mpm/services/project/registry.py +13 -7
- claude_mpm/services/project/toolchain_analyzer.py +583 -0
- claude_mpm/services/project_port_allocator.py +596 -0
- claude_mpm/services/response_tracker.py +21 -10
- claude_mpm/services/runner_configuration_service.py +17 -3
- claude_mpm/services/self_upgrade_service.py +500 -0
- claude_mpm/services/session_management_service.py +23 -9
- claude_mpm/services/session_manager.py +380 -0
- claude_mpm/services/shared/__init__.py +2 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/config_service_base.py +17 -14
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/shared/service_factory.py +8 -5
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/client_proxy.py +60 -5
- claude_mpm/services/socketio/dashboard_server.py +361 -0
- claude_mpm/services/socketio/event_normalizer.py +10 -6
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/base.py +2 -2
- claude_mpm/services/socketio/handlers/code_analysis.py +90 -27
- claude_mpm/services/socketio/handlers/connection.py +22 -41
- claude_mpm/services/socketio/handlers/connection_handler.py +13 -10
- claude_mpm/services/socketio/handlers/file.py +46 -10
- claude_mpm/services/socketio/handlers/git.py +9 -9
- claude_mpm/services/socketio/handlers/hook.py +29 -17
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/monitor_client.py +364 -0
- claude_mpm/services/socketio/server/broadcaster.py +9 -7
- claude_mpm/services/socketio/server/connection_manager.py +2 -2
- claude_mpm/services/socketio/server/core.py +142 -8
- claude_mpm/services/socketio/server/eventbus_integration.py +20 -14
- claude_mpm/services/socketio/server/main.py +24 -24
- claude_mpm/services/socketio_client_manager.py +4 -4
- claude_mpm/services/subprocess_launcher_service.py +19 -15
- claude_mpm/services/system_instructions_service.py +3 -5
- claude_mpm/services/ticket_services/formatter_service.py +1 -1
- claude_mpm/services/ticket_services/validation_service.py +5 -5
- claude_mpm/services/unified/__init__.py +65 -0
- claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
- claude_mpm/services/unified/config_strategies/__init__.py +175 -0
- claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
- claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
- claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
- claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
- claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
- claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
- claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
- claude_mpm/services/unified/deployment_strategies/base.py +553 -0
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
- claude_mpm/services/unified/deployment_strategies/local.py +607 -0
- claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
- claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
- claude_mpm/services/unified/interfaces.py +475 -0
- claude_mpm/services/unified/migration.py +509 -0
- claude_mpm/services/unified/strategies.py +534 -0
- claude_mpm/services/unified/unified_analyzer.py +542 -0
- claude_mpm/services/unified/unified_config.py +691 -0
- claude_mpm/services/unified/unified_deployment.py +466 -0
- claude_mpm/services/utility_service.py +6 -3
- claude_mpm/services/version_control/branch_strategy.py +2 -2
- claude_mpm/services/version_control/conflict_resolution.py +14 -8
- claude_mpm/services/version_control/git_operations.py +26 -24
- claude_mpm/services/version_control/semantic_versioning.py +14 -14
- claude_mpm/services/version_control/version_parser.py +14 -11
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/__init__.py +42 -0
- claude_mpm/skills/agent_skills_injector.py +324 -0
- claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
- claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
- claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +573 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
- claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/skills/skills_registry.py +347 -0
- claude_mpm/skills/skills_service.py +739 -0
- claude_mpm/storage/state_storage.py +31 -31
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +9 -9
- claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
- claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
- claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
- claude_mpm/tools/code_tree_analyzer/core.py +380 -0
- claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
- claude_mpm/tools/code_tree_analyzer/events.py +168 -0
- claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
- claude_mpm/tools/code_tree_analyzer/models.py +39 -0
- claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
- claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
- claude_mpm/tools/code_tree_builder.py +6 -6
- claude_mpm/tools/code_tree_events.py +14 -10
- claude_mpm/tools/socketio_debug.py +11 -11
- claude_mpm/utils/agent_dependency_loader.py +184 -36
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/common.py +544 -0
- claude_mpm/utils/config_manager.py +12 -6
- claude_mpm/utils/database_connector.py +298 -0
- claude_mpm/utils/dependency_cache.py +5 -3
- claude_mpm/utils/dependency_strategies.py +15 -10
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/environment_context.py +4 -3
- claude_mpm/utils/error_handler.py +5 -3
- claude_mpm/utils/file_utils.py +13 -14
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/gitignore.py +241 -0
- claude_mpm/utils/log_cleanup.py +627 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/path_operations.py +7 -4
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +131 -24
- claude_mpm/utils/session_logging.py +2 -2
- claude_mpm/utils/structured_questions.py +619 -0
- claude_mpm/utils/subprocess_utils.py +9 -8
- claude_mpm/validation/agent_validator.py +6 -6
- claude_mpm/validation/frontmatter_validator.py +6 -6
- claude_mpm-5.0.9.dist-info/METADATA +1028 -0
- claude_mpm-5.0.9.dist-info/RECORD +864 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-5.0.9.dist-info}/entry_points.txt +1 -0
- claude_mpm/agents/INSTRUCTIONS.md +0 -261
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -270
- claude_mpm/agents/templates/agent-manager.md +0 -619
- claude_mpm/agents/templates/agentic_coder_optimizer.json +0 -222
- claude_mpm/agents/templates/api_qa.json +0 -171
- claude_mpm/agents/templates/code_analyzer.json +0 -95
- claude_mpm/agents/templates/data_engineer.json +0 -152
- claude_mpm/agents/templates/documentation.json +0 -175
- claude_mpm/agents/templates/engineer.json +0 -176
- claude_mpm/agents/templates/imagemagick.json +0 -261
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/memory_manager.json +0 -155
- claude_mpm/agents/templates/ops.json +0 -175
- claude_mpm/agents/templates/project_organizer.json +0 -130
- claude_mpm/agents/templates/qa.json +0 -223
- claude_mpm/agents/templates/refactoring_engineer.json +0 -266
- claude_mpm/agents/templates/research.json +0 -163
- claude_mpm/agents/templates/security.json +0 -153
- claude_mpm/agents/templates/ticketing.json +0 -169
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -281
- claude_mpm/agents/templates/version_control.json +0 -147
- claude_mpm/agents/templates/web_qa.json +0 -254
- claude_mpm/agents/templates/web_ui.json +0 -176
- claude_mpm/cli/commands/configure_tui.py +0 -1927
- claude_mpm/cli/commands/mpm_init.py +0 -594
- claude_mpm/cli/commands/socketio_monitor.py +0 -233
- claude_mpm/commands/mpm-agents.md +0 -12
- claude_mpm/commands/mpm-config.md +0 -18
- claude_mpm/commands/mpm-tickets.md +0 -102
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/css/code-tree.css +0 -1408
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -3220
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -480
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1040
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/scripts/socketio_daemon_hardened.py +0 -937
- claude_mpm/scripts/socketio_daemon_wrapper.py +0 -78
- claude_mpm/scripts/socketio_server_manager.py +0 -349
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/cli/dashboard_launcher.py +0 -423
- claude_mpm/services/cli/socketio_manager.py +0 -537
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +0 -286
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +0 -645
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +0 -602
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- claude_mpm/tools/code_tree_analyzer.py +0 -1693
- claude_mpm-4.1.26.dist-info/METADATA +0 -332
- claude_mpm-4.1.26.dist-info/RECORD +0 -606
- {claude_mpm-4.1.26.dist-info → claude_mpm-5.0.9.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-5.0.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.26.dist-info → claude_mpm-5.0.9.dist-info}/top_level.txt +0 -0
|
@@ -1,233 +0,0 @@
|
|
|
1
|
-
"""Socket.IO monitoring functionality for run commands.
|
|
2
|
-
|
|
3
|
-
This module provides Socket.IO server management and monitoring dashboard functionality.
|
|
4
|
-
Extracted from run.py to reduce complexity and improve maintainability.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import os
|
|
8
|
-
import subprocess
|
|
9
|
-
import sys
|
|
10
|
-
import webbrowser
|
|
11
|
-
|
|
12
|
-
from ...core.unified_paths import get_package_root
|
|
13
|
-
from ...services.port_manager import PortManager
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class SocketIOMonitor:
|
|
17
|
-
"""Handles Socket.IO monitoring and server management."""
|
|
18
|
-
|
|
19
|
-
def __init__(self, logger):
|
|
20
|
-
"""Initialize the Socket.IO monitor."""
|
|
21
|
-
self.logger = logger
|
|
22
|
-
|
|
23
|
-
def launch_monitor(self, port):
|
|
24
|
-
"""
|
|
25
|
-
Launch the Socket.IO monitoring dashboard using static HTML file.
|
|
26
|
-
|
|
27
|
-
Returns:
|
|
28
|
-
tuple: (success: bool, browser_opened: bool)
|
|
29
|
-
"""
|
|
30
|
-
try:
|
|
31
|
-
# Verify Socket.IO dependencies are available
|
|
32
|
-
try:
|
|
33
|
-
import aiohttp
|
|
34
|
-
import engineio
|
|
35
|
-
import socketio
|
|
36
|
-
|
|
37
|
-
self.logger.debug("Socket.IO dependencies verified")
|
|
38
|
-
except ImportError as e:
|
|
39
|
-
self.logger.error(f"Socket.IO dependencies not available: {e}")
|
|
40
|
-
print(f"❌ Socket.IO dependencies missing: {e}")
|
|
41
|
-
print(" This is unexpected - dependency installation may have failed.")
|
|
42
|
-
return False, False
|
|
43
|
-
|
|
44
|
-
print("🚀 Setting up Socket.IO monitor...")
|
|
45
|
-
self.logger.info(f"Launching Socket.IO monitor (requested port: {port})")
|
|
46
|
-
|
|
47
|
-
# First, check if there's already a running SocketIO server
|
|
48
|
-
port_manager = PortManager()
|
|
49
|
-
port_manager.cleanup_dead_instances()
|
|
50
|
-
active_instances = port_manager.list_active_instances()
|
|
51
|
-
|
|
52
|
-
if active_instances:
|
|
53
|
-
# Use the first active instance (prefer port 8765 if available)
|
|
54
|
-
socketio_port = None
|
|
55
|
-
for instance in active_instances:
|
|
56
|
-
if instance.get("port") == 8765:
|
|
57
|
-
socketio_port = 8765
|
|
58
|
-
break
|
|
59
|
-
if not socketio_port:
|
|
60
|
-
socketio_port = active_instances[0].get("port")
|
|
61
|
-
|
|
62
|
-
print(f"🔍 Found existing SocketIO server on port {socketio_port}")
|
|
63
|
-
server_running = True
|
|
64
|
-
else:
|
|
65
|
-
# No existing server, use requested port
|
|
66
|
-
socketio_port = port
|
|
67
|
-
server_running = self.check_server_running(socketio_port)
|
|
68
|
-
|
|
69
|
-
# Use HTTP URL to access dashboard from Socket.IO server
|
|
70
|
-
dashboard_url = f"http://localhost:{socketio_port}"
|
|
71
|
-
|
|
72
|
-
if server_running:
|
|
73
|
-
print(f"✅ Socket.IO server already running on port {socketio_port}")
|
|
74
|
-
print(f"📊 Dashboard: {dashboard_url}")
|
|
75
|
-
|
|
76
|
-
# Open browser with static HTML file
|
|
77
|
-
try:
|
|
78
|
-
# Check if we should suppress browser opening (for tests)
|
|
79
|
-
if os.environ.get("CLAUDE_MPM_NO_BROWSER") != "1":
|
|
80
|
-
print("🌐 Opening dashboard in browser...")
|
|
81
|
-
self.open_in_browser_tab(dashboard_url)
|
|
82
|
-
self.logger.info(f"Socket.IO dashboard opened: {dashboard_url}")
|
|
83
|
-
else:
|
|
84
|
-
print("🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)")
|
|
85
|
-
self.logger.info(
|
|
86
|
-
"Browser opening suppressed by environment variable"
|
|
87
|
-
)
|
|
88
|
-
return True, True
|
|
89
|
-
except Exception as e:
|
|
90
|
-
self.logger.warning(f"Failed to open browser: {e}")
|
|
91
|
-
print("⚠️ Could not open browser automatically")
|
|
92
|
-
print(f"📊 Please open manually: {dashboard_url}")
|
|
93
|
-
return True, False
|
|
94
|
-
else:
|
|
95
|
-
# Start standalone Socket.IO server
|
|
96
|
-
print("🔧 Starting Socket.IO server...")
|
|
97
|
-
server_started = self.start_standalone_server(socketio_port)
|
|
98
|
-
|
|
99
|
-
if server_started:
|
|
100
|
-
print("✅ Socket.IO server started successfully")
|
|
101
|
-
print(f"📊 Dashboard: {dashboard_url}")
|
|
102
|
-
|
|
103
|
-
# Open browser
|
|
104
|
-
try:
|
|
105
|
-
if os.environ.get("CLAUDE_MPM_NO_BROWSER") != "1":
|
|
106
|
-
print("🌐 Opening dashboard in browser...")
|
|
107
|
-
self.open_in_browser_tab(dashboard_url)
|
|
108
|
-
self.logger.info(
|
|
109
|
-
f"Socket.IO dashboard opened: {dashboard_url}"
|
|
110
|
-
)
|
|
111
|
-
else:
|
|
112
|
-
print(
|
|
113
|
-
"🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)"
|
|
114
|
-
)
|
|
115
|
-
return True, True
|
|
116
|
-
except Exception as e:
|
|
117
|
-
self.logger.warning(f"Failed to open browser: {e}")
|
|
118
|
-
print("⚠️ Could not open browser automatically")
|
|
119
|
-
print(f"📊 Please open manually: {dashboard_url}")
|
|
120
|
-
return True, False
|
|
121
|
-
else:
|
|
122
|
-
print("❌ Failed to start Socket.IO server")
|
|
123
|
-
print("💡 Troubleshooting tips:")
|
|
124
|
-
print(f" - Check if port {socketio_port} is already in use")
|
|
125
|
-
print(
|
|
126
|
-
" - Verify Socket.IO dependencies: pip install python-socketio aiohttp"
|
|
127
|
-
)
|
|
128
|
-
print(" - Try a different port with --websocket-port")
|
|
129
|
-
return False, False
|
|
130
|
-
|
|
131
|
-
except Exception as e:
|
|
132
|
-
self.logger.error(f"Failed to launch Socket.IO monitor: {e}")
|
|
133
|
-
print(f"❌ Failed to launch Socket.IO monitor: {e}")
|
|
134
|
-
return False, False
|
|
135
|
-
|
|
136
|
-
def check_server_running(self, port):
|
|
137
|
-
"""Check if a Socket.IO server is running on the specified port."""
|
|
138
|
-
try:
|
|
139
|
-
import socket
|
|
140
|
-
import urllib.error
|
|
141
|
-
import urllib.request
|
|
142
|
-
|
|
143
|
-
# First, do a basic TCP connection check
|
|
144
|
-
try:
|
|
145
|
-
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
|
146
|
-
s.settimeout(2.0)
|
|
147
|
-
result = s.connect_ex(("127.0.0.1", port))
|
|
148
|
-
if result != 0:
|
|
149
|
-
self.logger.debug(f"TCP connection to port {port} failed")
|
|
150
|
-
return False
|
|
151
|
-
except Exception as e:
|
|
152
|
-
self.logger.debug(f"TCP socket check failed for port {port}: {e}")
|
|
153
|
-
return False
|
|
154
|
-
|
|
155
|
-
# If TCP connection succeeds, try HTTP health check
|
|
156
|
-
try:
|
|
157
|
-
response = urllib.request.urlopen(
|
|
158
|
-
f"http://localhost:{port}/status", timeout=5
|
|
159
|
-
)
|
|
160
|
-
if response.getcode() == 200:
|
|
161
|
-
self.logger.debug(
|
|
162
|
-
f"✅ Socket.IO server health check passed on port {port}"
|
|
163
|
-
)
|
|
164
|
-
return True
|
|
165
|
-
except Exception as e:
|
|
166
|
-
self.logger.debug(f"HTTP health check failed for port {port}: {e}")
|
|
167
|
-
|
|
168
|
-
except Exception as e:
|
|
169
|
-
self.logger.debug(
|
|
170
|
-
f"❌ Unexpected error checking Socket.IO server on port {port}: {e}"
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
return False
|
|
174
|
-
|
|
175
|
-
def start_standalone_server(self, port):
|
|
176
|
-
"""Start a standalone Socket.IO server using the Python daemon."""
|
|
177
|
-
try:
|
|
178
|
-
daemon_script = get_package_root() / "scripts" / "socketio_daemon.py"
|
|
179
|
-
if not daemon_script.exists():
|
|
180
|
-
self.logger.error(f"Daemon script not found: {daemon_script}")
|
|
181
|
-
return False
|
|
182
|
-
|
|
183
|
-
# Start the daemon
|
|
184
|
-
result = subprocess.run(
|
|
185
|
-
[sys.executable, str(daemon_script), "start", "--port", str(port)],
|
|
186
|
-
capture_output=True,
|
|
187
|
-
text=True,
|
|
188
|
-
timeout=30,
|
|
189
|
-
check=False,
|
|
190
|
-
)
|
|
191
|
-
|
|
192
|
-
if result.returncode == 0:
|
|
193
|
-
self.logger.info(
|
|
194
|
-
f"Socket.IO daemon started successfully on port {port}"
|
|
195
|
-
)
|
|
196
|
-
return True
|
|
197
|
-
self.logger.error(f"Failed to start Socket.IO daemon: {result.stderr}")
|
|
198
|
-
return False
|
|
199
|
-
|
|
200
|
-
except Exception as e:
|
|
201
|
-
self.logger.error(f"Failed to start standalone Socket.IO server: {e}")
|
|
202
|
-
return False
|
|
203
|
-
|
|
204
|
-
def open_in_browser_tab(self, url):
|
|
205
|
-
"""Open URL in browser, attempting to reuse existing tabs when possible."""
|
|
206
|
-
try:
|
|
207
|
-
# Try different methods based on platform
|
|
208
|
-
import platform
|
|
209
|
-
|
|
210
|
-
system = platform.system().lower()
|
|
211
|
-
|
|
212
|
-
if system == "darwin": # macOS
|
|
213
|
-
try:
|
|
214
|
-
# Try to open in existing tab
|
|
215
|
-
subprocess.run(["open", "-g", url], check=True, timeout=5)
|
|
216
|
-
return
|
|
217
|
-
except Exception:
|
|
218
|
-
pass
|
|
219
|
-
elif system == "linux":
|
|
220
|
-
try:
|
|
221
|
-
# Try xdg-open
|
|
222
|
-
subprocess.run(["xdg-open", url], check=True, timeout=5)
|
|
223
|
-
return
|
|
224
|
-
except Exception:
|
|
225
|
-
pass
|
|
226
|
-
|
|
227
|
-
# Fallback to standard webbrowser
|
|
228
|
-
webbrowser.open(url)
|
|
229
|
-
|
|
230
|
-
except Exception as e:
|
|
231
|
-
self.logger.warning(f"Browser opening failed: {e}")
|
|
232
|
-
# Final fallback
|
|
233
|
-
webbrowser.open(url)
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Show available agents and their versions
|
|
2
|
-
|
|
3
|
-
Show all available Claude MPM agents with their versions and deployment status.
|
|
4
|
-
|
|
5
|
-
This command displays:
|
|
6
|
-
- Agent names and descriptions
|
|
7
|
-
- Version information
|
|
8
|
-
- Tool availability
|
|
9
|
-
- Model preferences
|
|
10
|
-
- Deployment status
|
|
11
|
-
|
|
12
|
-
Usage: /mpm-agents
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# View or modify claude-mpm configuration
|
|
2
|
-
|
|
3
|
-
Manage Claude MPM configuration settings.
|
|
4
|
-
|
|
5
|
-
Usage: /mpm-config [key] [value]
|
|
6
|
-
|
|
7
|
-
Examples:
|
|
8
|
-
- /mpm-config - Show all configuration
|
|
9
|
-
- /mpm-config list - List all configuration keys
|
|
10
|
-
- /mpm-config set logging debug - Set logging level to debug
|
|
11
|
-
- /mpm-config get websocket-port - Get WebSocket port setting
|
|
12
|
-
|
|
13
|
-
Configuration categories:
|
|
14
|
-
- logging: Logging levels and output
|
|
15
|
-
- websocket: WebSocket server settings
|
|
16
|
-
- hooks: Hook service configuration
|
|
17
|
-
- memory: Memory system settings
|
|
18
|
-
- agents: Agent deployment options
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
# mpm-tickets
|
|
2
|
-
|
|
3
|
-
Create and manage tickets using aitrackdown
|
|
4
|
-
|
|
5
|
-
## Usage
|
|
6
|
-
|
|
7
|
-
Use this command to create and manage tickets (epics, issues, tasks) through aitrackdown CLI integration.
|
|
8
|
-
|
|
9
|
-
## Commands
|
|
10
|
-
|
|
11
|
-
### Create tickets
|
|
12
|
-
```bash
|
|
13
|
-
# Create an epic
|
|
14
|
-
aitrackdown create epic "Title" --description "Description"
|
|
15
|
-
|
|
16
|
-
# Create an issue
|
|
17
|
-
aitrackdown create issue "Title" --description "Description"
|
|
18
|
-
|
|
19
|
-
# Create a task
|
|
20
|
-
aitrackdown create task "Title" --description "Description"
|
|
21
|
-
|
|
22
|
-
# Create task under an issue
|
|
23
|
-
aitrackdown create task "Title" --issue ISS-0001
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
### View tickets
|
|
27
|
-
```bash
|
|
28
|
-
# Show all tasks
|
|
29
|
-
aitrackdown status tasks
|
|
30
|
-
|
|
31
|
-
# Show specific ticket
|
|
32
|
-
aitrackdown show ISS-0001
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Update tickets
|
|
36
|
-
```bash
|
|
37
|
-
# Change status
|
|
38
|
-
aitrackdown transition ISS-0001 in-progress
|
|
39
|
-
aitrackdown transition ISS-0001 done
|
|
40
|
-
|
|
41
|
-
# Add comment
|
|
42
|
-
aitrackdown comment ISS-0001 "Your comment"
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
### Search tickets
|
|
46
|
-
```bash
|
|
47
|
-
aitrackdown search tasks "keyword"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
## Ticket Types
|
|
51
|
-
|
|
52
|
-
- **EP-XXXX**: Epics (major initiatives)
|
|
53
|
-
- **ISS-XXXX**: Issues (bugs, features, user requests)
|
|
54
|
-
- **TSK-XXXX**: Tasks (individual work items)
|
|
55
|
-
|
|
56
|
-
## Workflow States
|
|
57
|
-
|
|
58
|
-
Valid transitions:
|
|
59
|
-
- `open` → `in-progress` → `ready` → `tested` → `done`
|
|
60
|
-
- Any state → `waiting` (when blocked)
|
|
61
|
-
- Any state → `closed` (to close)
|
|
62
|
-
|
|
63
|
-
## Examples
|
|
64
|
-
|
|
65
|
-
### Bug Report Flow
|
|
66
|
-
```bash
|
|
67
|
-
# Create issue for bug
|
|
68
|
-
aitrackdown create issue "Login bug" --description "Users can't login" --severity high
|
|
69
|
-
|
|
70
|
-
# Create investigation task
|
|
71
|
-
aitrackdown create task "Investigate login bug" --issue ISS-0001
|
|
72
|
-
|
|
73
|
-
# Update status
|
|
74
|
-
aitrackdown transition TSK-0001 in-progress
|
|
75
|
-
aitrackdown comment TSK-0001 "Found the issue"
|
|
76
|
-
|
|
77
|
-
# Complete
|
|
78
|
-
aitrackdown transition TSK-0001 done
|
|
79
|
-
aitrackdown transition ISS-0001 done
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Feature Implementation
|
|
83
|
-
```bash
|
|
84
|
-
# Create epic
|
|
85
|
-
aitrackdown create epic "OAuth2 Support"
|
|
86
|
-
|
|
87
|
-
# Create issues
|
|
88
|
-
aitrackdown create issue "Google OAuth2" --description "Add Google auth"
|
|
89
|
-
aitrackdown create issue "GitHub OAuth2" --description "Add GitHub auth"
|
|
90
|
-
|
|
91
|
-
# Create tasks
|
|
92
|
-
aitrackdown create task "Design OAuth flow" --issue ISS-0001
|
|
93
|
-
aitrackdown create task "Implement Google client" --issue ISS-0001
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
## Tips
|
|
97
|
-
|
|
98
|
-
- Always use aitrackdown directly (not claude-mpm tickets)
|
|
99
|
-
- Check ticket exists with `show` before updating
|
|
100
|
-
- Add comments to document progress
|
|
101
|
-
- Use `--severity` for bugs, `--priority` for features
|
|
102
|
-
- Associate tasks with issues using `--issue`
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{U as e}from"./unified-data-viewer.js";class t{constructor(){this.container=null,this.events=[],this.processedEventIds=new Set,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,this.renderTreeDebounced=this.debounce(()=>this.renderTree(),100)}debounce(e,t){let s;return function(...n){clearTimeout(s),s=setTimeout(()=>{clearTimeout(s),e(...n)},t)}}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 o=document.getElementById("activity-search");o&&o.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`);for(const[n,o]of t.entries())if(this.sessions.has(n)){const e=this.sessions.get(n);e.timestamp=new Date(o.lastActivity||o.startTime||e.timestamp),e.eventCount=o.eventCount,e.status=o.status||e.status,e.working_directory=o.working_directory||e.working_directory,e.git_branch=o.git_branch||e.git_branch}else{const e={id:n,timestamp:new Date(o.lastActivity||o.startTime||new Date),expanded:this.expandedSessions.has(n)||!0,agents:new Map,todos:[],userInstructions:[],tools:[],toolsMap:new Map,status:"active",currentTodoTool:null,working_directory:o.working_directory,git_branch:o.git_branch,eventCount:o.eventCount};this.sessions.set(n,e)}const s=e.filter(e=>{const t=e.id||`${e.type}-${e.timestamp}-${Math.random()}`;return!this.processedEventIds.has(t)});s.length>0&&(console.log(`ActivityTree: Processing ${s.length} new events`,s),s.forEach(e=>{const t=e.id||`${e.type}-${e.timestamp}-${Math.random()}`;this.processedEventIds.add(t),this.processEvent(e)})),this.events=[...e],this.renderTreeDebounced(),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`);for(const[s,n]of e.sessions.entries())if(!this.sessions.has(s)){const e={id:s,timestamp:new Date(n.lastActivity||n.startTime||new Date),expanded:this.expandedSessions.has(s)||!0,agents:new Map,todos:[],userInstructions:[],tools:[],toolsMap:new Map,status:"active",currentTodoTool:null,working_directory:n.working_directory,git_branch:n.git_branch,eventCount:n.eventCount};this.sessions.set(s,e)}const t=e.events.filter(e=>{const t=e.id||`${e.type}-${e.timestamp}-${Math.random()}`;return!this.processedEventIds.has(t)});t.length>0&&(console.log(`ActivityTree: Processing ${t.length} unprocessed events from initial load`),t.forEach(e=>{const t=e.id||`${e.type}-${e.timestamp}-${Math.random()}`;this.processedEventIds.add(t),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 o=this.sessions.get(n);switch(s){case"Start":this.currentSession=o;break;case"user_prompt":this.processUserInstruction(e,o);break;case"TodoWrite":break;case"SubagentStart":this.processSubagentStart(e,o);break;case"SubagentStop":this.processSubagentStop(e,o);break;case"PreToolUse":this.processToolUse(e,o);break;case"PostToolUse":this.updateToolStatus(e,o,"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"};if(t.agents.size>0){console.log("ActivityTree: New user prompt detected, collapsing previous agents");for(let e of t.agents.values())"active"===e.status&&(e.status="completed"),this.expandedAgents.delete(e.id)}t.currentActiveAgent=null,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.currentTodos=s.map(t=>({content:t.content,activeForm:t.activeForm,status:t.status,timestamp:e.timestamp}));let n=t.currentActiveAgent;if(!n){const e=this.getAllAgents(t).filter(e=>"active"===e.status||"in_progress"===e.status).sort((e,t)=>new Date(t.timestamp)-new Date(e.timestamp));if(e.length>0)n=e[0];else{const e=this.getAllAgents(t),s=e.find(e=>e.isPM);s?n=s:e.length>0&&(n=e[0])}}if(n){n.todoWritesMap||(n.todoWritesMap=new Map),n.todoWrites||(n.todoWrites=[]);const t=n.todoWritesMap.get("TodoWrite");if(t)t.todos=s,t.timestamp=e.timestamp,t.updateCount=(t.updateCount||1)+1;else{const t={id:`todowrite-${n.id}-${Date.now()}`,name:"TodoWrite",type:"todowrite",icon:"📝",timestamp:e.timestamp,status:"completed",todos:s,params:{todos:s},updateCount:1};n.todoWritesMap.set("TodoWrite",t),n.todoWrites=[t]}n.currentTodos=s}else{t.todoWrites||(t.todoWrites=[]),t.todoWritesMap||(t.todoWritesMap=new Map);const n=t.todoWritesMap.get("TodoWrite");if(n)n.todos=s,n.timestamp=e.timestamp,n.updateCount=(n.updateCount||1)+1;else{const n={id:`todowrite-session-${Date.now()}`,name:"TodoWrite",type:"todowrite",icon:"📝",timestamp:e.timestamp,status:"completed",todos:s,updateCount:1};t.todoWritesMap.set("TodoWrite",n),t.todoWrites=[n]}}}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,o=e.parent_agent||e.data?.parent_agent,i=`${s}-${n||"no-session"}`;let a=null;let r;if(a=this.getAllAgents(t).find(e=>e.name===s&&e.sessionId===n&&"active"===e.status),a)r=a,r.timestamp=e.timestamp,r.instanceCount=(r.instanceCount||1)+1,this.expandedAgents.add(r.id);else{if(r={id:`agent-${i}-${Date.now()}`,name:s,type:"agent",icon:this.getAgentIcon(s),timestamp:e.timestamp,status:"active",tools:[],subagents:new Map,sessionId:n,parentAgent:o,isPM:"pm"===s.toLowerCase()||s.toLowerCase().includes("project manager"),instanceCount:1,toolsMap:new Map},o){let e=null;for(let[s,n]of t.agents.entries())if(n.sessionId===o||n.name===o){e=n;break}e?(e.subagents||(e.subagents=new Map),e.subagents.set(r.id,r)):t.agents.set(r.id,r)}else t.agents.set(r.id,r);this.expandedAgents.add(r.id)}t.currentActiveAgent=r}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||{},o=e.session_id||e.data?.session_id;let i=t.currentActiveAgent;if(!i){const e=this.getAllAgents(t);i=e.find(e=>e.sessionId===o)||e.find(e=>"active"===e.status)||e[0]}if(i){i.toolsMap||(i.toolsMap=new Map),i.tools||(i.tools=[]);const t=this.getToolKey(s,n);let o=i.toolsMap.get(t);if(o)o.params=n,o.timestamp=e.timestamp,o.status="in_progress",o.eventId=e.id,o.callCount=(o.callCount||1)+1,i.currentTool=o;else{const o={id:`tool-${i.id}-${s}-${Date.now()}`,name:s,type:"tool",icon:this.getToolIcon(s),timestamp:e.timestamp,status:"in_progress",params:n,eventId:e.id,callCount:1,createdAt:e.timestamp};"Task"===s&&n.subagent_type&&(o.isSubagentTask=!0,o.subagentType=n.subagent_type),i.toolsMap.set(t,o),"TodoWrite"===s?i.tools.unshift(o):i.tools.push(o),i.currentTool=o}}else{t.tools||(t.tools=[]),t.toolsMap||(t.toolsMap=new Map);const o=this.getToolKey(s,n);let i=t.toolsMap.get(o);if(i)i.params=n,i.timestamp=e.timestamp,i.status="in_progress",i.eventId=e.id,i.callCount=(i.callCount||1)+1,t.currentTool=i;else{const i={id:`tool-session-${s}-${Date.now()}`,name:s,type:"tool",icon:this.getToolIcon(s),timestamp:e.timestamp,status:"in_progress",params:n,eventId:e.id,callCount:1,createdAt:e.timestamp};t.toolsMap.set(o,i),"TodoWrite"===s?t.tools.unshift(i):t.tools.push(i),t.currentTool=i}}}getToolKey(e,t){if("TodoWrite"===e)return"TodoWrite";let s=e;return"Edit"!==e&&"Write"!==e&&"Read"!==e||t.file_path&&(s+=`-${t.file_path}`),"Grep"!==e&&"Glob"!==e||!t.pattern||(s+=`-${t.pattern.substring(0,20)}`),s}updateToolStatus(e,t,s){const n=e.tool_name||e.data?.tool_name||e.tool||"unknown",o=e.tool_parameters||e.data?.tool_parameters||e.parameters||e.data?.parameters||{},i=e.session_id||e.data?.session_id,a=this.getToolKey(n,o);let r=t.currentActiveAgent;if(!r){const e=this.getAllAgents(t);r=e.find(e=>e.sessionId===i)||e.find(e=>"active"===e.status)}if(r&&r.toolsMap){const t=r.toolsMap.get(a);if(t)return t.status=s,t.completedAt=e.timestamp,(e.data?.result||e.result)&&(t.result=e.data?.result||e.result),void(e.data?.duration_ms&&(t.duration=e.data.duration_ms))}if(t.toolsMap){const n=t.toolsMap.get(a);if(n)return n.status=s,n.completedAt=e.timestamp,(e.data?.result||e.result)&&(n.result=e.data?.result||e.result),void(e.data?.duration_ms&&(n.duration=e.data.duration_ms))}console.log(`ActivityTree: Could not find tool to update status for ${n} with key ${a} (event ${e.id})`)}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 o=t?"▼":"▶",i=this.getAllAgents(e).length,a=e.currentTodos?e.currentTodos.length:0,r=e.userInstructions?e.userInstructions.length:0;return console.log(`ActivityTree: Rendering session ${e.id}: ${i} agents, ${r} instructions, ${a} todos at ${s}`),n.innerHTML=`\n <div class="tree-node-content" onclick="window.activityTreeInstance.toggleSession('${e.id}')">\n <span class="tree-expand-icon">${o}</span>\n <span class="tree-icon">🎯</span>\n <span class="tree-label">PM Session</span>\n <span class="tree-meta">${s} • ${i} agent(s) • ${r} instruction(s) • ${a} 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.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),o=n?"▼":"▶";let i=0,a=0;e.forEach(e=>{"completed"===e.status?i++:"in_progress"===e.status&&a++});let r="";r=a>0?`${a} in progress, ${i} completed`:i===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();">${o}</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}`,o="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(o)}</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),o=e.tools&&e.tools.length>0,i=e.subagents&&e.subagents.size>0,a=o||i,r=a?n?"▼":"▶":"",l=this.selectedItem&&"agent"===this.selectedItem.type&&this.selectedItem.data.id===e.id?"selected":"",c=e.instanceCount>1?` (${e.instanceCount}x)`:"";let d="";if(!n&&a){const t=[];if(e.currentTodos&&e.currentTodos.length>0){const s=e.currentTodos.find(e=>"in_progress"===e.status);s&&t.push(`📝 ${s.activeForm||s.content}`)}e.currentTool&&t.push(`${e.currentTool.icon} ${e.currentTool.name}`),t.length>0&&(d=` • ${t.join(" • ")}`)}let p=`\n <div class="tree-node agent ${s} ${l}" data-level="${t}">\n <div class="tree-node-content">\n ${r?`<span class="tree-expand-icon" onclick="window.activityTreeInstance.toggleAgent('${e.id}'); event.stopPropagation();">${r}</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}${c}${d}</span>\n <span class="tree-status ${s}">${e.status}</span>\n </div>\n `;if(a&&n){if(p+='<div class="tree-children">',o)for(let s of e.tools)p+=this.renderToolElement(s,t+1);if(i){const s=Array.from(e.subagents.values());for(let e of s)p+=this.renderAgentElement(e,t+1)}p+="</div>"}return p+="</div>",p}renderToolElement(e,t){const s=`status-${e.status}`,n=this.getToolParams(e),o=this.selectedItem&&"tool"===this.selectedItem.type&&this.selectedItem.data.id===e.id?"selected":"",i=this.getToolStatusIcon(e.status),a=this.getToolStatusLabel(e.status),r=e.callCount>1?` (${e.callCount} calls)`:"";return`\n <div class="tree-node tool ${s} ${o}" 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-status-icon">${i}</span>\n <span class="tree-label clickable" onclick="window.activityTreeInstance.selectItem(${this.escapeJson(e)}, 'tool', event)">${e.name}${r}</span>\n <span class="tree-params">${n}</span>\n <span class="tree-status ${s}">${a}</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:"🏗️","project manager":"📊"}[e.toLowerCase()]||"🤖"}getAllAgents(e){const t=[],s=e=>{if(e)for(let n of e.values())t.push(n),n.subagents&&n.subagents.size>0&&s(n.subagents)};return s(e.agents),t}renderTodoWriteElement(e,t){const s=e.id,n=this.expandedTools.has(s),o=n?"▼":"▶",i=e.todos||[];let a=0,r=0;i.forEach(e=>{"completed"===e.status?a++:"in_progress"===e.status&&r++});const l=i.find(e=>"in_progress"===e.status),c=l?` • 🔄 ${l.activeForm||l.content}`:"";let d="";d=r>0?`${r} in progress, ${a}/${i.length} done`:a===i.length&&i.length>0?`All ${i.length} completed ✅`:`${a}/${i.length} done`;let p=`\n <div class="tree-node todowrite ${l?"has-active":""}" data-level="${t}">\n <div class="tree-node-content">\n <span class="tree-expand-icon" onclick="window.activityTreeInstance.toggleTodoWrite('${s}'); event.stopPropagation();">${o}</span>\n <span class="tree-icon">📝</span>\n <span class="tree-label">TodoWrite${e.updateCount>1?` (${e.updateCount} updates)`:""}${n?"":c}</span>\n <span class="tree-params">${d}</span>\n <span class="tree-status status-active">todos</span>\n </div>\n `;if(n&&i.length>0){p+='<div class="tree-children">';for(let e of i){const s=this.getCheckboxIcon(e.status),n=`status-${e.status}`,o="in_progress"===e.status?e.activeForm:e.content;p+=`\n <div class="tree-node todo-item ${n} ${e===l?"current-active":""}" data-level="${t+1}">\n <div class="tree-node-content">\n <span class="tree-expand-icon"></span>\n <span class="tree-icon">${s}</span>\n <span class="tree-label">${this.escapeHtml(o)}</span>\n <span class="tree-status ${n}">${e.status.replace("_"," ")}</span>\n </div>\n </div>\n `}p+="</div>"}return p+="</div>",p}toggleTodoWrite(e){this.expandedTools.has(e)?this.expandedTools.delete(e):this.expandedTools.add(e),this.renderTree()}getToolIcon(e){return{read:"👁️",write:"✍️",edit:"✏️",bash:"💻",webfetch:"🌐",grep:"🔍",glob:"📂",todowrite:"📝"}[e.toLowerCase()]||"🔧"}getToolStatusIcon(e){return{in_progress:"⏳",completed:"✅",failed:"❌",error:"❌",pending:"⏸️",active:"🔄"}[e]||"❓"}getToolStatusLabel(e){return{in_progress:"in progress",completed:"completed",failed:"failed",error:"error",pending:"pending",active:"active"}[e]||e}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"),o=document.getElementById("active-count"),i=document.getElementById("tree-depth");n&&(n.textContent=e),o&&(o.textContent=t),i&&(i.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()}renderPinnedTodosElement(e,t){const s=`pinned-todos-${Date.now()}`,n=!1!==this.expandedTools.has(s),o=n?"▼":"▶",i=e.todos||[];let a=0,r=0;i.forEach(e=>{"completed"===e.status?a++:"in_progress"===e.status&&r++});let l="";l=r>0?`${r} in progress, ${a} completed`:a===i.length&&i.length>0?`All ${i.length} completed`:`${i.length} todo(s)`;let c=`\n <div class="tree-node pinned-todos" data-level="${t}">\n <div class="tree-node-content">\n <span class="tree-expand-icon" onclick="window.activityTreeInstance.toggleTodoChecklist('${s}'); event.stopPropagation();">${o}</span>\n <span class="tree-icon">📌</span>\n <span class="tree-label">Pinned TODOs</span>\n <span class="tree-params">${l}</span>\n <span class="tree-status status-active">pinned</span>\n </div>\n `;if(n){c+='<div class="tree-children">';for(let e of i){const s=this.getCheckboxIcon(e.status),n=`status-${e.status}`,o="in_progress"===e.status?e.activeForm:e.content;c+=`\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">${s}</span>\n <span class="tree-label">${this.escapeHtml(o)}</span>\n <span class="tree-status ${n}">${e.status.replace("_"," ")}</span>\n </div>\n </div>\n `}c+="</div>"}return c+="</div>",c}selectItem(e,t,s){s&&s.stopPropagation(),this.selectedItem={data:e,type:t},this.displayItemData(e,t),this.renderTree()}displayItemData(t,s){this.unifiedViewer||(this.unifiedViewer=new e("module-data-content")),this.unifiedViewer.display(t,s);const n=document.querySelector(".module-data-header h5");if(n){const e={agent:"🤖",tool:"🔧",instruction:"💬",session:"🎯",todo:"📝"}[s]||"📊",o=t.name||t.agentName||t.tool_name||"Item";n.textContent=`${e} ${s}: ${o}`}}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,"'").replace(/"/g,""")}}window.ActivityTree=t;const s=()=>{let e=null;const s=()=>{e||(console.log("Creating new Activity Tree instance..."),e=new t,window.activityTreeInstance=e,window.activityTree=()=>e),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..."),s(),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..."),s(),e&&setTimeout(()=>{e.renderWhenVisible(),e.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 o=document.getElementById("activity-tab");o&&o.classList.contains("active")&&(console.log("Activity panel is active on load, initializing tree..."),e||s())};"loading"===document.readyState?document.addEventListener("DOMContentLoaded",s):s();
|
|
2
|
-
//# sourceMappingURL=activity-tree.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
class e{constructor(e){this.eventViewer=e,this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map,orphanSubagents:new Map,subagentStartEvents:new Map},console.log("Agent inference system initialized")}initialize(){this.state={currentDelegation:null,sessionAgents:new Map,eventAgentMap:new Map,pmDelegations:new Map,agentToDelegation:new Map,orphanSubagents:new Map,subagentStartEvents:new Map}}inferAgentFromEvent(e){const t=e.data||{},n=e.session_id||t.session_id||"unknown",a=e.hook_event_name||t.hook_event_name||e.type||"",s=e.subtype||t.subtype||"",i=e.tool_name||t.tool_name||"";if(Math.random()<.1&&console.log("Agent inference debug:",{eventType:a,toolName:i,hasData:!!e.data,dataKeys:Object.keys(t),eventKeys:Object.keys(e),agentType:e.agent_type||t.agent_type,subagentType:e.subagent_type||t.subagent_type}),"SubagentStop"===a||"subagent_stop"===s){const i=this.extractAgentNameFromEvent(e);return console.log("SubagentStop event detected:",{agentName:i,sessionId:n,eventType:a,subtype:s,rawAgentType:e.agent_type||t.agent_type}),{type:"subagent",confidence:"definitive",agentName:i,reason:"SubagentStop event"}}if("Stop"===a||"stop"===s)return{type:"main_agent",confidence:"definitive",agentName:"PM",reason:"Stop event"};if("Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return console.log("Task delegation detected:",{agentName:t,sessionId:n,eventType:a}),{type:"subagent",confidence:"high",agentName:t,reason:"Task tool with subagent_type"}}if("PreToolUse"===a&&"Task"===i){const t=this.extractSubagentTypeFromTask(e);if(t)return{type:"subagent",confidence:"high",agentName:t,reason:"PreToolUse Task delegation"}}{const e=n.toLowerCase();if(["subagent","task","agent-"].some(t=>e.includes(t)))return{type:"subagent",confidence:"medium",agentName:"Subagent",reason:"Session ID pattern"}}const o=e.agent_type||t.agent_type||e.agent_id||t.agent_id,g=e.subagent_type||t.subagent_type;if(g&&"unknown"!==g)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(g),reason:"subagent_type field"};if(o&&"unknown"!==o&&"main"!==o)return{type:"subagent",confidence:"medium",agentName:this.normalizeAgentName(o),reason:"agent_type field"};if(t.delegation_details?.agent_type)return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(t.delegation_details.agent_type),reason:"delegation_details"};if(e.type&&e.type.startsWith("hook.")){const a=e.type.replace("hook.","");if("subagent_start"===a||"SubagentStart"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return console.log("SubagentStart event from Socket.IO:",{agentName:e,sessionId:n,hookType:a}),{type:"subagent",confidence:"definitive",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStart"}}if("subagent_stop"===a||"SubagentStop"===t.hook_event_name){const e=t.agent_type||t.agent_id||"Subagent";return{type:"subagent",confidence:"high",agentName:this.normalizeAgentName(e),reason:"Socket.IO hook SubagentStop"}}}return{type:"main_agent",confidence:"default",agentName:"PM",reason:"default classification"}}normalizeAgentName(e){if(!e)return"Unknown";const t={engineer:"Engineer Agent",research:"Research Agent",qa:"QA Agent",documentation:"Documentation Agent",security:"Security Agent",ops:"Ops Agent",version_control:"Version Control Agent",data_engineer:"Data Engineer Agent",test_integration:"Test Integration Agent",pm:"PM Agent"}[e.toLowerCase()];if(t)return t;let n=e.replace(/_/g," ").split(" ").map(e=>e.charAt(0).toUpperCase()+e.slice(1).toLowerCase()).join(" ");return n.toLowerCase().includes("agent")||(n+=" Agent"),n}extractSubagentTypeFromTask(e){let t=null;return e.tool_parameters?.subagent_type?t=e.tool_parameters.subagent_type:e.data?.tool_parameters?.subagent_type?t=e.data.tool_parameters.subagent_type:e.data?.delegation_details?.agent_type?t=e.data.delegation_details.agent_type:e.tool_input?.subagent_type&&(t=e.tool_input.subagent_type),t?this.normalizeAgentName(t):null}extractAgentNameFromEvent(e){const t=e.data||{};if("Task"===e.tool_name||"Task"===t.tool_name){const t=this.extractSubagentTypeFromTask(e);if(t)return t}return e.subagent_type&&"unknown"!==e.subagent_type?this.normalizeAgentName(e.subagent_type):t.subagent_type&&"unknown"!==t.subagent_type?this.normalizeAgentName(t.subagent_type):t.delegation_details?.agent_type&&"unknown"!==t.delegation_details.agent_type?this.normalizeAgentName(t.delegation_details.agent_type):e.agent_type&&!["main","unknown"].includes(e.agent_type)?this.normalizeAgentName(e.agent_type):t.agent_type&&!["main","unknown"].includes(t.agent_type)?this.normalizeAgentName(t.agent_type):e.agent_id&&!["main","unknown"].includes(e.agent_id)?this.normalizeAgentName(e.agent_id):t.agent_id&&!["main","unknown"].includes(t.agent_id)?this.normalizeAgentName(t.agent_id):e.agent&&"unknown"!==e.agent?this.normalizeAgentName(e.agent):e.name&&"unknown"!==e.name?this.normalizeAgentName(e.name):"Unknown"}processAgentInference(){const e=this.eventViewer.events;this.state.currentDelegation=null,this.state.sessionAgents.clear(),this.state.eventAgentMap.clear(),this.state.pmDelegations.clear(),this.state.agentToDelegation.clear(),this.state.orphanSubagents.clear(),this.state.subagentStartEvents.clear(),console.log("Processing agent inference for",e.length,"events"),e&&0!==e.length?(e.forEach((e,t)=>{let n;try{const a=this.inferAgentFromEvent(e),s=e.session_id||e.data?.session_id||"default";n=a,this.state.currentDelegation&&"default"===a.confidence&&s===this.state.currentDelegation.sessionId&&(n={type:"subagent",confidence:"inherited",agentName:this.state.currentDelegation.agentName,reason:"inherited from delegation context"});const i=e.hook_event_name||e.data?.hook_event_name||"";if(("SubagentStart"===i||"hook.subagent_start"===e.type||"subagent_start"===e.subtype)&&"subagent"===a.type&&(this.state.subagentStartEvents.has(a.agentName)||this.state.subagentStartEvents.set(a.agentName,[]),this.state.subagentStartEvents.get(a.agentName).push({eventIndex:t,event:e,timestamp:e.timestamp,sessionId:s})),"Task"===e.tool_name&&"subagent"===a.type){const n=`pm_${s}_${t}_${a.agentName}`,i={id:n,agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,pmCall:e,timestamp:e.timestamp,agentEvents:[]};this.state.pmDelegations.set(n,i),this.state.agentToDelegation.set(a.agentName,n),this.state.currentDelegation={agentName:a.agentName,sessionId:s,startIndex:t,endIndex:null,delegationId:n},console.log("Delegation started:",this.state.currentDelegation)}else if("definitive"===a.confidence&&"SubagentStop event"===a.reason&&this.state.currentDelegation){this.state.currentDelegation.endIndex=t;const e=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);e&&(e.endIndex=t),console.log("Delegation ended:",this.state.currentDelegation),this.state.currentDelegation=null}if(this.state.currentDelegation&&"subagent"===n.type){const a=this.state.pmDelegations.get(this.state.currentDelegation.delegationId);a&&a.agentEvents.push({eventIndex:t,event:e,inference:n})}this.state.eventAgentMap.set(t,n),this.state.sessionAgents.set(s,n),t<5&&console.log(`Event ${t} agent inference:`,{event_type:e.type||e.hook_event_name,subtype:e.subtype,tool_name:e.tool_name,inference:n,hasData:!!e.data,agentType:e.agent_type||e.data?.agent_type})}catch(a){console.error(`Error processing event ${t} for agent inference:`,a),n||(n={type:"main_agent",confidence:"error",agentName:"PM",reason:"error during processing"}),this.state.eventAgentMap.set(t,n)}}),this.identifyOrphanSubagents(e),console.log("Agent inference processing complete. Results:",{total_events:e.length,inferred_agents:this.state.eventAgentMap.size,unique_sessions:this.state.sessionAgents.size,pm_delegations:this.state.pmDelegations.size,agent_to_delegation_mappings:this.state.agentToDelegation.size,orphan_subagents:this.state.orphanSubagents.size})):console.log("No events to process for agent inference")}getInferredAgent(e){return this.state.eventAgentMap.get(e)||null}getInferredAgentForEvent(e){const t=this.eventViewer.events;let n=t.indexOf(e);if(-1===n&&e.timestamp&&(n=t.findIndex(t=>t.timestamp===e.timestamp&&t.session_id===e.session_id)),-1===n)return console.log("Agent inference: Could not find event in events array, performing inline inference"),this.inferAgentFromEvent(e);let a=this.getInferredAgent(n);return a||(a=this.inferAgentFromEvent(e),this.state.eventAgentMap.set(n,a)),a}getCurrentDelegation(){return this.state.currentDelegation}getSessionAgents(){return this.state.sessionAgents}getEventAgentMap(){return this.state.eventAgentMap}getPMDelegations(){return this.state.pmDelegations}getAgentToDelegationMap(){return this.state.agentToDelegation}buildDelegationHierarchy(){const e=this.getPMDelegations(),t=this.eventViewer.events,n={mainPM:{type:"pm",name:"PM",delegations:[],ownEvents:[],totalEvents:0},impliedPM:{type:"pm_implied",name:"Implied PM",delegations:[],ownEvents:[],totalEvents:0}};for(const[s,i]of e)n.mainPM.delegations.push({id:s,agentName:i.agentName,taskContext:this.extractTaskContext(i.pmCall),events:i.agentEvents,startTime:i.timestamp,endTime:i.endIndex?t[i.endIndex]?.timestamp:null,status:i.endIndex?"completed":"active"}),n.mainPM.totalEvents+=i.agentEvents.length;t.forEach((e,t)=>{const a=this.getInferredAgent(t);a&&"main_agent"===a.type&&(n.mainPM.ownEvents.push({eventIndex:t,event:e}),n.mainPM.totalEvents++)});const a=new Map;t.forEach((t,n)=>{const s=this.getInferredAgent(n);if(s&&"subagent"===s.type){let i=!0;for(const[t,a]of e)if(a.agentEvents.some(e=>e.eventIndex===n)){i=!1;break}if(i){const e=s.agentName;a.has(e)||a.set(e,[]),a.get(e).push({eventIndex:n,event:t,inference:s})}}});for(const[s,i]of a)n.impliedPM.delegations.push({id:`implied_${s}`,agentName:s,taskContext:"No explicit PM delegation",events:i,startTime:i[0].event.timestamp,endTime:i[i.length-1].event.timestamp,status:"completed"}),n.impliedPM.totalEvents+=i.length;return n}extractTaskContext(e){if(!e)return"Unknown task";const t=e.tool_parameters||e.data?.tool_parameters||{};return t.task||t.request||t.description||"Task delegation"}identifyOrphanSubagents(e){for(const[t,n]of this.state.subagentStartEvents)for(const a of n){const n=a.eventIndex,s=new Date(a.timestamp).getTime();let i=!1;for(let a=Math.max(0,n-20);a<n;a++){const n=e[a];if(!n)continue;const o=s-new Date(n.timestamp).getTime();if("Task"===n.tool_name&&o>=0&&o<1e4){const e=this.state.eventAgentMap.get(a);if(e&&e.agentName===t){i=!0;break}}}i||this.state.orphanSubagents.set(n,{agentName:t,timestamp:a.timestamp,sessionId:a.sessionId,event:a.event,groupingKey:null})}this.groupOrphanSubagents(5e3)}groupOrphanSubagents(e){const t=Array.from(this.state.orphanSubagents.values()).sort((e,t)=>new Date(e.timestamp)-new Date(t.timestamp));let n=null,a=null;for(const s of t){const t=new Date(s.timestamp).getTime();(!n||a&&t-a>e)&&(n=`implied_pm_${s.sessionId}_${t}`),s.groupingKey=n,a=t}}isOrphanSubagent(e){return this.state.orphanSubagents.has(e)}getOrphanContext(e){return this.state.orphanSubagents.get(e)||null}getOrphanGroups(){const e=new Map;for(const t of this.state.orphanSubagents.values()){const n=t.groupingKey;e.has(n)||e.set(n,[]),e.get(n).push(t)}return e}getUniqueAgentInstances(){const e=new Map;for(const[a,s]of this.state.pmDelegations){const t=s.agentName;e.has(t)||e.set(t,{id:`consolidated_${t}`,type:"consolidated_agent",agentName:t,delegations:[],pmCalls:[],allEvents:[],firstTimestamp:s.timestamp,lastTimestamp:s.timestamp,totalEventCount:s.agentEvents.length,delegationCount:1});const n=e.get(t);n.delegations.push({id:a,pmCall:s.pmCall,timestamp:s.timestamp,eventCount:s.agentEvents.length,startIndex:s.startIndex,endIndex:s.endIndex,events:s.agentEvents}),s.pmCall&&n.pmCalls.push(s.pmCall),n.allEvents=n.allEvents.concat(s.agentEvents),new Date(s.timestamp)<new Date(n.firstTimestamp)&&(n.firstTimestamp=s.timestamp),new Date(s.timestamp)>new Date(n.lastTimestamp)&&(n.lastTimestamp=s.timestamp),n.totalEventCount+=s.agentEvents.length,n.delegationCount++}const t=this.eventViewer.events;for(let a=0;a<t.length;a++){const n=this.getInferredAgent(a);n&&"subagent"===n.type&&!e.has(n.agentName)&&e.set(n.agentName,{id:`consolidated_${n.agentName}`,type:"consolidated_agent",agentName:n.agentName,delegations:[{id:`implied_pm_${n.agentName}_${a}`,pmCall:null,timestamp:t[a].timestamp,eventCount:1,startIndex:a,endIndex:null,events:[{eventIndex:a,event:t[a],inference:n}]}],pmCalls:[],allEvents:[{eventIndex:a,event:t[a],inference:n}],firstTimestamp:t[a].timestamp,lastTimestamp:t[a].timestamp,totalEventCount:1,delegationCount:1,isImplied:!0})}const n=Array.from(e.values()).sort((e,t)=>new Date(e.firstTimestamp)-new Date(t.firstTimestamp));return console.log("Consolidated unique agents:",{total_unique_agents:n.length,agents:n.map(e=>({name:e.agentName,delegations:e.delegationCount,totalEvents:e.totalEventCount}))}),n}}export{e as A};
|
|
2
|
-
//# sourceMappingURL=agent-inference.js.map
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
class t{constructor(){this.container=null,this.svg=null,this.treeData=null,this.root=null,this.treeLayout=null,this.treeGroup=null,this.nodes=new Map,this.stats={files:0,classes:0,functions:0,methods:0,lines:0},this.isRadialLayout=!0,this.margin={top:20,right:20,bottom:20,left:20},this.width=960-this.margin.left-this.margin.right,this.height=600-this.margin.top-this.margin.bottom,this.radius=Math.min(this.width,this.height)/2,this.nodeId=0,this.duration=750,this.languageFilter="all",this.searchTerm="",this.tooltip=null,this.initialized=!1,this.analyzing=!1,this.selectedNode=null,this.socket=null,this.autoDiscovered=!1,this.zoom=null,this.activeNode=null,this.loadingNodes=new Set,this.bulkLoadMode=!1,this.expandedPaths=new Set}initialize(){if(this.initialized)return;if(this.container=document.getElementById("code-tree-container"),!this.container)return void console.error("Code tree container not found");const t=document.getElementById("code-tab");if(!t)return void console.error("Code tab panel not found");const e=this.getWorkingDirectory();if(!e||"Loading..."===e||"Not selected"===e)return this.showNoWorkingDirectoryMessage(),void(this.initialized=!0);this.setupControls(),this.initializeTreeData(),this.subscribeToEvents();document.getElementById("breadcrumb-content")&&!this.analyzing&&this.updateActivityTicker("Loading project structure...","info"),t.classList.contains("active")&&(this.createVisualization(),this.root&&this.svg&&this.update(this.root),this.autoDiscoverRootLevel()),this.initialized=!0}renderWhenVisible(){const t=this.getWorkingDirectory();t&&"Loading..."!==t&&"Not selected"!==t?(this.removeNoWorkingDirectoryMessage(),this.initialized?(this.svg?this.root&&this.svg&&this.update(this.root):(this.createVisualization(),this.svg&&this.treeGroup&&this.update(this.root)),this.autoDiscovered||this.autoDiscoverRootLevel()):this.initialize()):this.showNoWorkingDirectoryMessage()}setupControls(){const t=document.getElementById("language-filter");t&&t.addEventListener("change",t=>{this.languageFilter=t.target.value,this.filterTree()});const e=document.getElementById("code-search");e&&e.addEventListener("input",t=>{this.searchTerm=t.target.value.toLowerCase(),this.filterTree()});const i=document.getElementById("code-expand-all");i&&i.addEventListener("click",()=>this.expandAll());const o=document.getElementById("code-collapse-all");o&&o.addEventListener("click",()=>this.collapseAll());const s=document.getElementById("code-reset-zoom");s&&s.addEventListener("click",()=>this.resetZoom());const a=document.getElementById("code-toggle-legend");a&&a.addEventListener("click",()=>this.toggleLegend()),document.addEventListener("workingDirectoryChanged",t=>{this.onWorkingDirectoryChanged(t.detail.directory)})}onWorkingDirectoryChanged(t){if(!t||"Loading..."===t||"Not selected"===t)return this.showNoWorkingDirectoryMessage(),this.autoDiscovered=!1,this.analyzing=!1,this.nodes.clear(),this.stats={files:0,classes:0,functions:0,methods:0,lines:0},void this.updateStats();this.removeNoWorkingDirectoryMessage(),this.autoDiscovered=!1,this.analyzing=!1,this.nodes.clear(),this.stats={files:0,classes:0,functions:0,methods:0,lines:0},this.initializeTreeData(),this.svg&&this.update(this.root);const e=document.getElementById("code-tab");e&&e.classList.contains("active")&&this.autoDiscoverRootLevel(),this.updateStats()}showLoading(){let t=document.getElementById("code-tree-loading");if(!t){const e=document.getElementById("code-tree-container");e&&(t=document.createElement("div"),t.id="code-tree-loading",t.innerHTML='\n <div class="code-tree-spinner"></div>\n <div class="code-tree-loading-text">Analyzing code structure...</div>\n ',e.appendChild(t))}t&&t.classList.remove("hidden")}hideLoading(){const t=document.getElementById("code-tree-loading");t&&t.classList.add("hidden")}createVisualization(){if("undefined"==typeof d3)return void console.error("D3.js is not loaded");const t=d3.select("#code-tree-container");if(t.selectAll("*").remove(),this.addTreeControls(),this.addBreadcrumb(),!t||!t.node())return void console.error("Code tree container not found");const e=t.node(),i=e.clientWidth||960,o=e.clientHeight||600;this.width=i-this.margin.left-this.margin.right,this.height=o-this.margin.top-this.margin.bottom,this.radius=Math.min(this.width,this.height)/2,this.svg=t.append("svg").attr("width",i).attr("height",o);const s=i/2,a=o/2;this.isRadialLayout?this.treeGroup=this.svg.append("g").attr("transform",`translate(${s},${a})`):this.treeGroup=this.svg.append("g").attr("transform",`translate(${this.margin.left+100},${a})`),this.isRadialLayout?this.treeLayout=d3.cluster().size([2*Math.PI,this.radius-100]).separation((t,e)=>{if(t.parent==e.parent){const e=Math.max(1,4-t.depth),i=t.parent&&t.parent.children?.length||1,o=i>5?2:i>3?1.5:1,s=1+.2*t.depth;return e*o/(t.depth||1)*s}return 4/(t.depth||1)}):this.treeLayout=d3.tree().nodeSize([30,200]).separation((t,e)=>t.parent==e.parent?1:1.5),this.zoom=null,console.log("[CodeTree] All zoom and pan behavior disabled - tree is now completely stationary"),this.addVisualizationControls(),this.tooltip=d3.select("body").append("div").attr("class","code-tree-tooltip").style("opacity",0).style("position","absolute").style("background","rgba(0, 0, 0, 0.8)").style("color","white").style("padding","8px").style("border-radius","4px").style("font-size","12px").style("pointer-events","none")}clearD3Visualization(){this.treeGroup&&(this.treeGroup.selectAll("g.node").remove(),this.treeGroup.selectAll("path.link").remove()),this.nodeId=0}initializeTreeData(){const t=this.getWorkingDirectory(),e=t&&t.split("/").pop()||"Project Root";this.treeData={name:e,path:".",type:"root",children:[],loaded:!1,expanded:!0},"undefined"!=typeof d3&&(this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0)}subscribeToEvents(){this.socket||(window.socket?(this.socket=window.socket,this.setupEventHandlers()):window.dashboard?.socketClient?.socket?(this.socket=window.dashboard.socketClient.socket,this.setupEventHandlers()):window.socketClient?.socket&&(this.socket=window.socketClient.socket,this.setupEventHandlers()))}autoDiscoverRootLevel(){if(this.autoDiscovered||this.analyzing)return;this.updateActivityTicker("🔍 Discovering project structure...","info");const t=this.getWorkingDirectory();if(!t||"Loading..."===t||"Not selected"===t)return console.warn("Cannot auto-discover: no working directory set"),void this.showNoWorkingDirectoryMessage();if(!t.startsWith("/")&&!t.match(/^[A-Z]:\\/))return console.error("Working directory is not absolute:",t),void this.showNotification("Invalid working directory path","error");this.autoDiscovered=!0,this.analyzing=!0,this.nodes.clear(),this.stats={files:0,classes:0,functions:0,methods:0,lines:0},this.socket&&!this.socket.hasListeners("code:node:found")&&this.setupEventHandlers();const e=t.split("/").pop()||"Project Root";this.treeData={name:e,path:".",type:"root",children:[],loaded:!1,expanded:!0},"undefined"!=typeof d3&&(this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0),this.showLoading(),this.updateBreadcrumb(`Discovering structure in ${e}...`,"info");const i=[];document.querySelectorAll(".language-checkbox:checked").forEach(t=>{i.push(t.value)});const o=document.getElementById("ignore-patterns")?.value||"",s={path:t,depth:"top_level",languages:i,ignore_patterns:o,request_id:`discover_${Date.now()}`};this.socket&&this.socket.emit("code:discover:top_level",s),this.updateStats()}analyzeCode(){this.analyzing||this.autoDiscoverRootLevel()}cancelAnalysis(){this.analyzing=!1,this.hideLoading(),this.socket&&this.socket.emit("code:analysis:cancel")}addTreeControls(){const t=d3.select("#code-tree-container");t.select(".tree-controls-toolbar").remove();const e=t.append("div").attr("class","tree-controls-toolbar");e.append("button").attr("class","tree-control-btn").attr("title","Expand all loaded directories").text("⊞").on("click",()=>this.expandAll()),e.append("button").attr("class","tree-control-btn").attr("title","Collapse all directories").text("⊟").on("click",()=>this.collapseAll()),e.append("button").attr("class","tree-control-btn").attr("id","bulk-load-toggle").attr("title","Toggle bulk loading (load 2 levels at once)").text("↕").on("click",()=>this.toggleBulkLoad()),e.append("button").attr("class","tree-control-btn").attr("title","Toggle between radial and linear layouts").text("◎").on("click",()=>this.toggleLayout()),e.append("input").attr("class","tree-control-btn").attr("type","text").attr("placeholder","Search...").attr("title","Search for files and directories").style("width","120px").style("text-align","left").on("input",t=>this.searchTree(t.target.value)).on("keydown",t=>{"Escape"===t.key&&(t.target.value="",this.searchTree(""))})}addBreadcrumb(){const t=d3.select("#code-tree-container");t.select(".tree-breadcrumb").remove();t.append("div").attr("class","tree-breadcrumb").append("div").attr("class","breadcrumb-path").attr("id","tree-breadcrumb-path"),this.updateBreadcrumbPath("/")}updateBreadcrumbPath(t){const e=d3.select("#tree-breadcrumb-path");e.selectAll("*").remove();const i=this.getWorkingDirectory();if(!i||"Loading..."===i||"Not selected"===i)return void e.text("No project selected");const o="/"===t?[i.split("/").pop()||"Root"]:t.split("/").filter(t=>t.length>0);o.forEach((t,i)=>{i>0&&e.append("span").attr("class","breadcrumb-separator").text("/"),e.append("span").attr("class",i===o.length-1?"breadcrumb-segment current":"breadcrumb-segment").text(t).on("click",()=>{if(i<o.length-1){const t=o.slice(0,i+1).join("/");this.navigateToPath(t)}})})}expandAll(){if(!this.root)return;const t=e=>{"directory"===e.data.type&&!0===e.data.loaded&&e._children&&(e.children=e._children,e._children=null,e.data.expanded=!0),e.children&&e.children.forEach(t)};t(this.root),this.update(this.root),this.showNotification("Expanded all loaded directories","success")}collapseAll(){if(!this.root)return;const t=e=>{"directory"===e.data.type&&e.children&&(e._children=e.children,e.children=null,e.data.expanded=!1),e._children&&e._children.forEach(t)};t(this.root),this.update(this.root),this.showNotification("Collapsed all directories","info")}toggleBulkLoad(){this.bulkLoadMode=!this.bulkLoadMode;const t=d3.select("#bulk-load-toggle");this.bulkLoadMode?(t.classed("active",!0),this.showNotification("Bulk load enabled - will load 2 levels deep","info")):(t.classed("active",!1),this.showNotification("Bulk load disabled - load 1 level at a time","info"))}navigateToPath(t){this.updateBreadcrumbPath(t),this.showNotification(`Navigating to: ${t}`,"info")}searchTree(t){if(!this.root||!this.treeGroup)return;const e=t.toLowerCase().trim();if(this.treeGroup.selectAll(".code-node").classed("search-match",!1),!e)return;const i=[],o=t=>{const s=(t.data.name||"").toLowerCase(),a=(t.data.path||"").toLowerCase();(s.includes(e)||a.includes(e))&&i.push(t),t.children&&t.children.forEach(o),t._children&&t._children.forEach(o)};o(this.root),i.length>0?(this.treeGroup.selectAll(".code-node").data(),i.forEach(t=>{this.treeGroup.selectAll(".code-node").filter(e=>e.data.path===t.data.path).classed("search-match",!0),this.expandPathToNode(t)}),this.showNotification(`Found ${i.length} matches`,"success")):this.showNotification("No matches found","info")}expandPathToNode(t){const e=[];let i=t.parent;for(;i&&i!==this.root;)e.unshift(i),i=i.parent;e.forEach(t=>{"directory"===t.data.type&&t._children&&(t.children=t._children,t._children=null,t.data.expanded=!0)}),e.length>0&&this.update(this.root)}createEventsDisplay(){let t=document.getElementById("analysis-events");if(!t){const e=document.getElementById("code-tree-container");e&&(t=document.createElement("div"),t.id="analysis-events",t.className="analysis-events",t.style.display="none",e.appendChild(t))}}clearEventsDisplay(){const t=document.getElementById("analysis-events");t&&(t.innerHTML="",t.style.display="block")}addEventToDisplay(t,e="info"){const i=document.getElementById("analysis-events");if(i){const o=document.createElement("div");o.className="analysis-event",o.style.borderLeftColor="warning"===e?"#f59e0b":"error"===e?"#ef4444":"#3b82f6";const s=(new Date).toLocaleTimeString();o.innerHTML=`<span style="color: #718096;">[${s}]</span> ${t}`,i.appendChild(o),i.scrollTop=i.scrollHeight}}setupEventHandlers(){this.socket&&(this.socket.on("code:analysis:accepted",t=>this.onAnalysisAccepted(t)),this.socket.on("code:analysis:queued",t=>this.onAnalysisQueued(t)),this.socket.on("code:analysis:start",t=>this.onAnalysisStart(t)),this.socket.on("code:analysis:complete",t=>this.onAnalysisComplete(t)),this.socket.on("code:analysis:cancelled",t=>this.onAnalysisCancelled(t)),this.socket.on("code:analysis:error",t=>this.onAnalysisError(t)),this.socket.on("code:top_level:discovered",t=>this.onTopLevelDiscovered(t)),this.socket.on("code:directory:discovered",t=>this.onDirectoryDiscovered(t)),this.socket.on("code:file:discovered",t=>this.onFileDiscovered(t)),this.socket.on("code:file:analyzed",t=>this.onFileAnalyzed(t)),this.socket.on("code:node:found",t=>this.onNodeFound(t)),this.socket.on("code:analysis:progress",t=>this.onProgressUpdate(t)),this.socket.on("code:directory:contents",t=>{if(t.path){let e=t.path;const i=this.getWorkingDirectory();i&&e.startsWith(i)&&(e=e.substring(i.length).replace(/^\//,""),e||(e="."));const o=this.findNodeByPath(e);if(o&&t.children){const i=this.findD3NodeByPath(e);if(i&&this.loadingNodes.has(e)&&(this.removeLoadingPulse(i),this.loadingNodes.delete(e),console.log("🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set:",e)),o.children=t.children.map(t=>{let i;if("."===e||""===e)i=t.name||t.path;else{const o=t.name||t.path;i=`${e}/${o}`}return{...t,path:i,loaded:"directory"!==t.type&&void 0,analyzed:"file"!==t.type&&void 0,expanded:!1,children:[]}}),o.loaded=!0,o.expanded=!0,this.root&&this.svg){const t=this.root;this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,this.preserveExpansionState(t,this.root);const i=this.findD3NodeByPath(e);i&&(i.children=i._children||i.children,i._children=null,i.data.expanded=!0),this.update(this.root)}t.stats&&(this.stats.files+=t.stats.files||0,this.stats.directories+=t.stats.directories||0,this.updateStats()),this.updateBreadcrumb(`Loaded ${t.path}`,"success"),this.hideLoading()}}}),this.socket.on("code:top_level:discovered",t=>{t.items&&Array.isArray(t.items)&&(this.treeData.children=t.items.map(t=>({name:t.name,path:t.path,type:t.type,language:"file"===t.type?this.detectLanguage(t.path):void 0,size:t.size,lines:t.lines,loaded:"directory"!==t.type&&void 0,analyzed:"file"!==t.type&&void 0,expanded:!1,children:[]})),this.treeData.loaded=!0,t.stats&&(this.stats={...this.stats,...t.stats},this.updateStats()),"undefined"!=typeof d3&&(this.clearD3Visualization(),this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,this.svg&&this.update(this.root)),this.analyzing=!1,this.hideLoading(),this.updateBreadcrumb(`Discovered ${t.items.length} root items`,"success"),this.showNotification(`Found ${t.items.length} items in project root`,"success"))}))}onAnalysisStart(t){this.analyzing=!0;const e=t.message||"Starting code analysis...";this.updateActivityTicker("🚀 Starting analysis...","info"),this.updateBreadcrumb(e,"info"),this.addEventToDisplay(`🚀 ${e}`,"info"),this.treeData&&0!==this.treeData.children.length||this.initializeTreeData(),this.stats={files:0,classes:0,functions:0,methods:0,lines:0},this.updateStats()}onTopLevelDiscovered(t){this.updateActivityTicker(`📁 Discovered ${(t.items||[]).length} top-level items`,"success"),this.addEventToDisplay(`📁 Found ${(t.items||[]).length} top-level items in project root`,"info");const e=this.findNodeByPath(".");console.log('🔎 Looking for root node with path ".", found:',e?{name:e.name,path:e.path,currentChildren:e.children?e.children.length:0}:"NOT FOUND"),e&&t.items?(console.log("🌳 Populating root node with children"),e.children=t.items.map(t=>{const e=t.name;return console.log(` Adding child: ${t.name} with path: ${e}`),{name:t.name,path:e,type:t.type,loaded:"directory"!==t.type&&void 0,analyzed:"file"!==t.type&&void 0,expanded:!1,children:"directory"===t.type?[]:void 0,size:t.size,has_code:t.has_code}}),e.loaded=!0,e.expanded=!0,this.root&&this.svg&&(this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,this.update(this.root)),this.hideLoading(),this.updateBreadcrumb(`Discovered ${t.items.length} items`,"success"),this.showNotification(`Found ${t.items.length} top-level items`,"success")):(console.error("❌ Could not find root node to populate"),this.showNotification("Failed to populate root directory","error")),this.analyzing=!1}onDirectoryDiscovered(t){this.updateActivityTicker(`📁 Discovered: ${t.name||"directory"}`),this.addEventToDisplay(`📁 Found ${(t.children||[]).length} items in: ${t.name||t.path}`,"info"),console.log("✅ [SUBDIRECTORY LOADING] Received directory discovery response:",{path:t.path,name:t.name,childrenCount:(t.children||[]).length,children:(t.children||[]).map(t=>({name:t.name,type:t.type})),workingDir:this.getWorkingDirectory(),fullEventData:t});let e=t.path;const i=this.getWorkingDirectory();i&&e.startsWith(i)&&(e=e.substring(i.length).replace(/^\//,""),e||(e=".")),console.log("🔎 Searching for node with path:",e);const o=this.findNodeByPath(e);if(o&&t.children){o.children=t.children.map(t=>{let i;if("."===e||""===e)i=t.name||t.path;else{const o=t.name||t.path;i=`${e}/${o}`}return{name:t.name,path:i,type:t.type,loaded:"directory"!==t.type&&void 0,analyzed:"file"!==t.type&&void 0,expanded:!1,children:"directory"===t.type?[]:void 0,size:t.size,has_code:t.has_code}}),o.loaded=!0,o.expanded=!0;const i=this.findD3NodeByPath(e);if(i&&this.loadingNodes.has(e)&&(this.removeLoadingPulse(i),this.loadingNodes.delete(e),console.log("🎯 [SUBDIRECTORY LOADING] Successfully completed and removed from loading set (hierarchy update):",e)),this.root&&this.svg){const t=this.root;this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,this.preserveExpansionState(t,this.root);const i=this.findD3NodeByPath(e);i&&i.data.children&&i.data.children.length>0&&(i.children=i._children||i.children,i._children=null,i.data.expanded=!0),this.update(this.root)}0===o.children.length?(this.updateBreadcrumb(`Empty directory: ${o.name}`,"info"),this.showNotification(`Directory "${o.name}" is empty`,"info")):(this.updateBreadcrumb(`Loaded ${o.children.length} items from ${o.name}`,"success"),this.showNotification(`Loaded ${o.children.length} items from "${o.name}"`,"success")),this.updateStats()}else if(o){if(o&&!t.children){console.warn("⚠️ [SUBDIRECTORY LOADING] Directory response has no children:",{path:t.path,searchPath:e,nodeExists:!!o,dataKeys:Object.keys(t),fullData:t});const i=t.path?t.path.split("/").filter(t=>t):[];if(1===i.length||t.forceAdd){const e={name:t.name||i[i.length-1]||"Unknown",path:t.path,type:"directory",children:[],loaded:!1,expanded:!1,stats:t.stats||{}};this.addNodeToTree(e,t.parent||""),this.updateBreadcrumb(`Discovered: ${t.path}`,"info")}}}else console.error("❌ [SUBDIRECTORY LOADING] Node not found for path:",{searchPath:e,originalPath:t.path,workingDir:this.getWorkingDirectory(),allTreePaths:this.getAllTreePaths(this.treeData)}),this.showNotification(`Could not find directory "${e}" in tree`,"error"),this.logAllPaths(this.treeData)}onFileDiscovered(t){const e=t.name||(t.path?t.path.split("/").pop():"file");this.updateActivityTicker(`📄 Found: ${e}`),this.addEventToDisplay(`📄 Discovered: ${t.path||"Unknown file"}`,"info");const i=t.path?t.path.split("/").filter(t=>t):[],o=i.slice(0,-1).join("/"),s={name:t.name||i[i.length-1]||"Unknown",path:t.path,type:"file",language:t.language||this.detectLanguage(t.path),size:t.size||0,lines:t.lines||0,children:[],analyzed:!1};this.addNodeToTree(s,o),this.stats.files++,this.updateStats(),this.updateBreadcrumb(`Found: ${t.path}`,"info")}onFileAnalyzed(t){const e=this.findD3NodeByPath(t.path);if(e&&this.loadingNodes.has(t.path)&&(this.removeLoadingPulse(e),this.loadingNodes.delete(t.path)),t.path){const e=t.path.split("/").pop();this.updateActivityTicker(`🔍 Analyzed: ${e}`)}const i=this.findNodeByPath(t.path);i&&(i.analyzed=!0,i.complexity=t.complexity||0,i.lines=t.lines||0,t.elements&&Array.isArray(t.elements)&&(i.children=t.elements.map(e=>({name:e.name,type:e.type.toLowerCase(),path:`${t.path}#${e.name}`,line:e.line,complexity:e.complexity||1,docstring:e.docstring||"",children:e.methods?e.methods.map(i=>({name:i.name,type:"method",path:`${t.path}#${e.name}.${i.name}`,line:i.line,complexity:i.complexity||1,docstring:i.docstring||""})):[]}))),t.stats&&(this.stats.classes+=t.stats.classes||0,this.stats.functions+=t.stats.functions||0,this.stats.methods+=t.stats.methods||0,this.stats.lines+=t.stats.lines||0),this.updateStats(),this.root&&this.update(this.root),this.updateBreadcrumb(`Analyzed: ${t.path}`,"success"))}onNodeFound(t){const e="class"===t.type?"🏛️":"function"===t.type?"⚡":"method"===t.type?"🔧":"📦";this.addEventToDisplay(`${e} Found ${t.type||"node"}: ${t.name||"Unknown"}`);const i={name:t.name||"Unknown",type:(t.type||"unknown").toLowerCase(),path:t.path||"",line:t.line||0,complexity:t.complexity||1,docstring:t.docstring||""};i.type={class:"class",function:"function",method:"method",module:"module",file:"file",directory:"directory"}[i.type]||i.type;let o="";if(t.parent_path)o=t.parent_path;else if(t.file_path)o=t.file_path;else if(i.path.includes("/")){const t=i.path.split("/");t.pop(),o=t.join("/")}switch(i.type){case"class":this.stats.classes++;break;case"function":this.stats.functions++;break;case"method":this.stats.methods++;break;case"file":this.stats.files++}this.addNodeToTree(i,o),this.updateStats();const s=i.type.charAt(0).toUpperCase()+i.type.slice(1);this.updateBreadcrumb(`Found ${s}: ${i.name}`,"info")}onProgressUpdate(t){const e=t.progress||0,i=t.message||`Processing... ${e}%`;this.updateBreadcrumb(i,"info");const o=document.querySelector(".code-tree-progress");o&&(o.style.width=`${e}%`)}onAnalysisComplete(t){this.analyzing=!1,this.hideLoading(),this.updateActivityTicker("✅ Ready","success"),this.addEventToDisplay("✅ Analysis complete!","success"),this.root&&this.svg&&this.update(this.root),t.stats&&(this.stats={...this.stats,...t.stats},this.updateStats());const e=t.message||`Analysis complete: ${this.stats.files} files, ${this.stats.classes} classes, ${this.stats.functions} functions`;this.updateBreadcrumb(e,"success"),this.showNotification(e,"success")}onAnalysisError(t){this.analyzing=!1,this.hideLoading();const e=t.message||t.error||"Analysis failed";this.updateBreadcrumb(e,"error"),this.showNotification(e,"error")}onAnalysisAccepted(t){const e=t.message||"Analysis request accepted";this.updateBreadcrumb(e,"info")}onAnalysisQueued(t){const e=`Analysis queued (position ${t.position||0})`;this.updateBreadcrumb(e,"warning"),this.showNotification(e,"info")}onInfoEvent(t){t.type&&t.type.startsWith("discovery.")?"discovery.start"===t.type?this.updateBreadcrumb(t.message,"info"):"discovery.complete"===t.type?(this.updateBreadcrumb(t.message,"success"),t.stats):"discovery.directory"!==t.type&&"discovery.file"!==t.type||this.updateBreadcrumb(t.message,"info"):t.type&&t.type.startsWith("analysis.")?"analysis.start"===t.type?this.updateBreadcrumb(t.message,"info"):"analysis.complete"===t.type?(this.updateBreadcrumb(t.message,"success"),t.stats&&(t.stats.classes,t.stats.functions,t.stats.methods)):("analysis.class"===t.type||"analysis.function"===t.type||"analysis.method"===t.type||"analysis.parse"===t.type)&&this.updateBreadcrumb(t.message,"info"):t.type&&t.type.startsWith("filter.")?(window.debugMode||this.showFilterEvents)&&(console.debug("[FILTER]",t.type,t.path,t.reason),this.showFilterEvents&&this.updateBreadcrumb(t.message,"warning")):t.type&&t.type.startsWith("cache.")&&("cache.hit"===t.type?(console.debug("[CACHE HIT]",t.file),this.showCacheEvents&&this.updateBreadcrumb(t.message,"info")):"cache.miss"===t.type&&console.debug("[CACHE MISS]",t.file)),this.eventLogEnabled&&t.message&&this.addEventToDisplay(t)}addEventToDisplay(t){this.recentEvents||(this.recentEvents=[]),this.recentEvents.unshift({timestamp:t.timestamp||(new Date).toISOString(),type:t.type,message:t.message,data:t}),this.recentEvents.length>100&&this.recentEvents.pop()}onAnalysisCancelled(t){this.analyzing=!1,this.hideLoading();const e=t.message||"Analysis cancelled";this.updateBreadcrumb(e,"warning")}showNotification(t,e="info"){const i=document.createElement("div");i.className=`code-tree-notification ${e}`,i.textContent=t;const o=document.getElementById("code-tree-container");o&&(i.style.position="absolute",i.style.top="10px",i.style.right="10px",i.style.zIndex="1000",o.style.position&&"static"!==o.style.position||(o.style.position="relative"),o.appendChild(i),setTimeout(()=>{i.style.animation="slideOutRight 0.3s ease",setTimeout(()=>i.remove(),300)},3e3))}addNodeToTree(t,e=""){if(t.path&&t.path.startsWith("/"))return void console.error("Absolute path detected in node, skipping:",t.path);if(e&&e.startsWith("/"))return void console.error("Absolute path detected in parent, skipping:",e);let i=this.treeData;if(e&&(i=this.findNodeByPath(e),!i))return console.warn("Parent node not found, skipping node creation:",e),void console.warn("Attempted to add node:",t);const o=i.children?.find(e=>e.path===t.path||e.name===t.name&&e.type===t.type);o?Object.assign(o,t):(i.children||(i.children=[]),t.children||(t.children=[]),i.children.push(t),this.nodes.set(t.path,t),this.root&&this.svg&&(this.root=d3.hierarchy(this.treeData),this.root.x0=this.height/2,this.root.y0=0,(this.nodes.size<1e3||this.nodes.size%100==0)&&this.update(this.root)))}findNodeByPath(t,e=null){if(e||(e=this.treeData,console.log("🔍 [SUBDIRECTORY LOADING] Starting search for path:",t)),e.path===t)return console.log("✅ [SUBDIRECTORY LOADING] Found node for path:",t),e;if(e.children)for(const i of e.children){const e=this.findNodeByPath(t,i);if(e)return e}return e.parent||e!==this.treeData||console.warn("❌ [SUBDIRECTORY LOADING] Path not found in tree:",t),null}logAllPaths(t,e=""){if(console.log(`${e}${t.path} (${t.name})`),t.children)for(const i of t.children)this.logAllPaths(i,e+" ")}getAllTreePaths(t){const e=[t.path];if(t.children)for(const i of t.children)e.push(...this.getAllTreePaths(i));return e}findD3NodeByPath(t){return this.root?this.root.descendants().find(e=>e.data.path===t):null}preserveExpansionState(t,e){if(!t||!e)return;const i=new Map;t.descendants().forEach(t=>{(t.data.expanded||t.children&&!t._children)&&i.set(t.data.path,!0)}),e.descendants().forEach(t=>{i.has(t.data.path)&&(t.children=t._children||t.children,t._children=null,t.data.expanded=!0)})}updateStats(){const t={"file-count":this.stats.files,"class-count":this.stats.classes,"function-count":this.stats.functions,"line-count":this.stats.lines};for(const[i,o]of Object.entries(t)){const t=document.getElementById(i);t&&(t.textContent=o.toLocaleString())}const e=document.getElementById("code-progress-text");if(e){const t=this.analyzing?`Analyzing... ${this.stats.files} files processed`:`Ready - ${this.stats.files} files in tree`;e.textContent=t}}updateBreadcrumb(t,e="info"){const i=document.getElementById("breadcrumb-content");i&&(i.textContent=t,i.className=`breadcrumb-${e}`)}detectLanguage(t){return{py:"python",js:"javascript",ts:"typescript",jsx:"javascript",tsx:"typescript",java:"java",cpp:"cpp",c:"c",cs:"csharp",rb:"ruby",go:"go",rs:"rust",php:"php",swift:"swift",kt:"kotlin",scala:"scala",r:"r",sh:"bash",ps1:"powershell"}[t.split(".").pop().toLowerCase()]||"unknown"}addVisualizationControls(){const t=this.svg.append("g").attr("class","viz-controls").attr("transform","translate(10, 10)").append("g").attr("class","layout-toggle").style("cursor","pointer").on("click",()=>this.toggleLayout());t.append("rect").attr("width",120).attr("height",30).attr("rx",5).attr("fill","#3b82f6").attr("opacity",.8),t.append("text").attr("x",60).attr("y",20).attr("text-anchor","middle").attr("fill","white").style("font-size","12px").text(this.isRadialLayout?"Switch to Linear":"Switch to Radial")}toggleLayout(){this.isRadialLayout=!this.isRadialLayout,this.createVisualization(),this.root&&this.update(this.root),this.showNotification(this.isRadialLayout?"Switched to radial layout":"Switched to linear layout","info")}radialPoint(t,e){return[(e=+e)*Math.cos(t-=Math.PI/2),e*Math.sin(t)]}update(t){if(!this.treeLayout||!this.treeGroup||!t)return;const e=this.treeLayout(this.root),i=e.descendants(),o=e.descendants().slice(1);this.isRadialLayout&&i.forEach(t=>{void 0===t.x0&&(t.x0=t.x,t.y0=t.y)});const s=this.treeGroup.selectAll("g.node").data(i,t=>t.id||(t.id=++this.nodeId)),a=s.enter().append("g").attr("class",t=>{let e=["node","code-node"];return"directory"===t.data.type?(e.push("directory"),!0===t.data.loaded&&t.children&&e.push("expanded"),"loading"===t.data.loaded&&e.push("loading"),t.data.children&&0===t.data.children.length&&e.push("empty")):"file"===t.data.type&&e.push("file"),e.join(" ")}).attr("transform",e=>{if(this.isRadialLayout){const[e,i]=this.radialPoint(t.x0||0,t.y0||0);return`translate(${e},${i})`}return`translate(${t.y0},${t.x0})`}).on("click",(t,e)=>this.onNodeClick(t,e));a.append("circle").attr("class","node-circle").attr("r",1e-6).style("fill",t=>this.getNodeColor(t)).style("stroke",t=>this.getNodeStrokeColor(t)).style("stroke-width",t=>"directory"===t.data.type?2:1.5).style("cursor","pointer").on("click",(t,e)=>this.onNodeClick(t,e)).on("mouseover",(t,e)=>this.showTooltip(t,e)).on("mouseout",()=>this.hideTooltip()),a.filter(t=>"directory"===t.data.type).append("text").attr("class","expand-icon").attr("x",0).attr("y",0).attr("text-anchor","middle").attr("dominant-baseline","central").text(t=>"loading"===t.data.loaded?"⟳":!0===t.data.loaded&&t.children?"▼":"▶").style("font-size","10px").style("pointer-events","none"),a.append("text").attr("class","node-label").attr("dy",".35em").attr("x",t=>this.isRadialLayout?0:t.children||t._children?-13:13).attr("text-anchor",t=>this.isRadialLayout?"start":t.children||t._children?"end":"start").text(t=>{const e=t.data.name||"";return e.length>20?e.substring(0,17)+"...":e}).style("fill-opacity",1e-6).style("font-size","12px").style("font-family",'-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif').style("text-shadow","1px 1px 2px rgba(255,255,255,0.8), -1px -1px 2px rgba(255,255,255,0.8)").on("click",(t,e)=>this.onNodeClick(t,e)).style("cursor","pointer"),a.filter(t=>"directory"!==t.data.type).append("text").attr("class","node-icon").attr("dy",".35em").attr("x",0).attr("text-anchor","middle").text(t=>this.getNodeIcon(t)).style("font-size","10px").style("fill","white").on("click",(t,e)=>this.onNodeClick(t,e)).style("cursor","pointer"),a.filter(t=>"directory"===t.data.type&&t.data.children).append("text").attr("class","item-count-badge").attr("x",12).attr("y",-8).attr("text-anchor","middle").text(t=>{const e=t.data.children?t.data.children.length:0;return e>0?e:""}).style("font-size","9px").style("opacity",.7).on("click",(t,e)=>this.onNodeClick(t,e)).style("cursor","pointer");const n=a.merge(s);n.on("click",(t,e)=>this.onNodeClick(t,e)),n.transition().duration(this.duration).attr("transform",t=>{if(this.isRadialLayout){const[e,i]=this.radialPoint(t.x,t.y);return`translate(${e},${i})`}return`translate(${t.y},${t.x})`}),n.attr("class",t=>{let e=["node","code-node"];return"directory"===t.data.type?(e.push("directory"),!0===t.data.loaded&&t.children&&e.push("expanded"),"loading"===t.data.loaded&&e.push("loading"),t.data.children&&0===t.data.children.length&&e.push("empty")):"file"===t.data.type&&e.push("file"),e.join(" ")}),n.select("circle.node-circle").attr("r",t=>"directory"===t.data.type?10:8).style("fill",t=>this.getNodeColor(t)),n.select(".expand-icon").text(t=>"loading"===t.data.loaded?"⟳":!0===t.data.loaded&&t.children?"▼":"▶"),n.select(".item-count-badge").text(t=>{if("directory"!==t.data.type)return"";const e=t.data.children?t.data.children.length:0;return e>0?e:""}).style("stroke",t=>this.getNodeStrokeColor(t)).attr("cursor","pointer");const r=this.isRadialLayout;n.select("text.node-label").style("fill-opacity",1).style("fill","#333").each(function(t){const e=d3.select(this);if(r){const i=180*t.x/Math.PI-90;i>90||i<-90?e.attr("transform",`rotate(${i+180})`).attr("x",-15).attr("text-anchor","end").attr("dy",".35em"):e.attr("transform",`rotate(${i})`).attr("x",15).attr("text-anchor","start").attr("dy",".35em")}else e.attr("transform",null).attr("x",t.children||t._children?-13:13).attr("text-anchor",t.children||t._children?"end":"start").attr("dy",".35em")});const d=s.exit().transition().duration(this.duration).attr("transform",e=>{if(this.isRadialLayout){const[e,i]=this.radialPoint(t.x,t.y);return`translate(${e},${i})`}return`translate(${t.y},${t.x})`}).remove();d.select("circle").attr("r",1e-6),d.select("text.node-label").style("fill-opacity",1e-6),d.select("text.node-icon").style("fill-opacity",1e-6);const l=this.treeGroup.selectAll("path.link").data(o,t=>t.id);l.enter().insert("path","g").attr("class","link").attr("d",e=>{const i={x:t.x0,y:t.y0};return this.isRadialLayout?this.radialDiagonal(i,i):this.diagonal(i,i)}).style("fill","none").style("stroke","#ccc").style("stroke-width",2).merge(l).transition().duration(this.duration).attr("d",t=>this.isRadialLayout?this.radialDiagonal(t,t.parent):this.diagonal(t,t.parent)),l.exit().transition().duration(this.duration).attr("d",e=>{const i={x:t.x,y:t.y};return this.isRadialLayout?this.radialDiagonal(i,i):this.diagonal(i,i)}).remove(),i.forEach(t=>{t.x0=t.x,t.y0=t.y})}centerOnNode(t){console.log("[CodeTree] centerOnNode called but disabled - no centering will occur")}centerOnNodeRadial(t){console.log("[CodeTree] centerOnNodeRadial called but disabled - no centering will occur")}highlightActiveNode(t){const e=this.treeGroup.selectAll("circle.node-circle");e.classed("active",!1).classed("parent-context",!1),e.transition().duration(300).attr("r",8).style("stroke",null).style("stroke-width",null).style("opacity",null),this.treeGroup.selectAll("text.node-label").style("font-weight","normal").style("font-size","12px");const i=this.treeGroup.selectAll("g.node").filter(e=>e===t).select("circle.node-circle");i.classed("active",!0),i.transition().duration(300).attr("r",20).style("stroke","#3b82f6").style("stroke-width",5).style("filter","drop-shadow(0 0 15px rgba(59, 130, 246, 0.6))"),this.treeGroup.selectAll("g.node").filter(e=>e===t).select("text.node-label").style("font-weight","bold").style("font-size","14px"),this.activeNode=t}addLoadingPulse(t){const e=this.treeGroup.selectAll("g.node").filter(e=>e===t).select("circle.node-circle");this.loadingNodes.add(t.data.path),e.classed("loading-pulse",!0),e.style("fill","#fb923c");const i=()=>{this.loadingNodes.has(t.data.path)&&e.transition().duration(600).attr("r",14).style("opacity",.6).transition().duration(600).attr("r",10).style("opacity",1).on("end",()=>{this.loadingNodes.has(t.data.path)&&i()})};i()}removeLoadingPulse(t){this.loadingNodes.delete(t.data.path);const e=this.treeGroup.selectAll("g.node").filter(e=>e===t).select("circle.node-circle");e.classed("loading-pulse",!1),e.interrupt().transition().duration(300).attr("r",this.activeNode===t?20:8).style("opacity",1).style("fill",t=>this.getNodeColor(t))}showWithParent(t){if(!t.parent)return;const e=this.treeGroup.selectAll("g.node").filter(e=>e===t.parent).select("circle.node-circle");e.classed("parent-context",!0),e.style("stroke","#10b981").style("stroke-width",3).style("opacity",.8)}onNodeClick(t,e){if(t)try{"function"==typeof t.stopPropagation&&t.stopPropagation()}catch(a){console.error("[CodeTree] ERROR calling stopPropagation:",a)}if(!e)return void console.error("[CodeTree] ERROR: d is null/undefined, cannot continue");if(!e.data)return void console.error("[CodeTree] ERROR: d.data is null/undefined, cannot continue");try{"function"==typeof this.highlightActiveNode?this.highlightActiveNode(e):console.error("[CodeTree] highlightActiveNode is not a function!")}catch(a){console.error("[CodeTree] ERROR during highlightActiveNode:",a,a.stack)}try{"function"==typeof this.showWithParent?this.showWithParent(e):console.error("[CodeTree] showWithParent is not a function!")}catch(a){console.error("[CodeTree] ERROR during showWithParent:",a,a.stack)}if("directory"===e.data.type&&!e.data.loaded)try{"function"==typeof this.addLoadingPulse?this.addLoadingPulse(e):console.error("[CodeTree] addLoadingPulse is not a function!")}catch(a){console.error("[CodeTree] ERROR during addLoadingPulse:",a,a.stack)}const i=[];document.querySelectorAll(".language-checkbox:checked").forEach(t=>{i.push(t.value)});const o=document.getElementById("ignore-patterns"),s=o?.value||"";if("directory"!==e.data.type||e.data.loaded)if("file"!==e.data.type||e.data.analyzed)if("directory"===e.data.type&&!0===e.data.loaded){if(e.children)e._children=e.children,e.children=null,e.data.expanded=!1;else if(e._children)e.children=e._children,e._children=null,e.data.expanded=!0;else if(e.data.children&&e.data.children.length>0){this.root=d3.hierarchy(this.treeData);const t=this.findD3NodeByPath(e.data.path);t&&(t.children=t._children||t.children,t._children=null,t.data.expanded=!0)}this.update(this.root)}else(e.children||e._children)&&(e.children?(e._children=e.children,e.children=null,e.data.expanded=!1):(e.children=e._children,e._children=null,e.data.expanded=!0),this.update(e));else{const t=this.detectLanguage(e.data.path);if(!i.includes(t)&&"unknown"!==t)return void this.showNotification(`Skipping ${e.data.name} - ${t} not selected`,"warning");this.addLoadingPulse(e),e.data.analyzed="loading";const o=this.ensureFullPath(e.data.path);setTimeout(()=>{this.socket&&(this.socket.emit("code:analyze:file",{path:o}),this.updateBreadcrumb(`Analyzing ${e.data.name}...`,"info"),this.showNotification(`Analyzing: ${e.data.name}`,"info"))},100)}else{if(this.loadingNodes.has(e.data.path))return void this.showNotification(`Already loading: ${e.data.name}`,"warning");e.data.loaded="loading",this.loadingNodes.add(e.data.path);const t=this.ensureFullPath(e.data.path);console.log("🚀 [SUBDIRECTORY LOADING] Attempting to load:",{originalPath:e.data.path,fullPath:t,nodeType:e.data.type,loaded:e.data.loaded,hasSocket:!!this.socket,workingDir:this.getWorkingDirectory()}),setTimeout(()=>{this.socket?(console.log("📡 [SUBDIRECTORY LOADING] Emitting WebSocket request:",{event:"code:discover:directory",data:{path:t,depth:this.bulkLoadMode?2:1,languages:i,ignore_patterns:s}}),this.socket.emit("code:discover:directory",{path:t,depth:this.bulkLoadMode?2:1,languages:i,ignore_patterns:s}),this.updateBreadcrumb(`Loading ${e.data.name}...`,"info"),this.showNotification(`Loading directory: ${e.data.name}`,"info")):(console.error("❌ [SUBDIRECTORY LOADING] No WebSocket connection available!"),this.showNotification("Cannot load directory: No connection","error"))},100)}this.selectedNode=e;try{this.highlightNode(e)}catch(a){console.error("[CodeTree] ERROR during highlightNode:",a)}}ensureFullPath(t){if(console.log("🔗 ensureFullPath called with:",t),!t)return t;if(t.startsWith("/"))return console.log(" → Already absolute, returning:",t),t;const e=this.getWorkingDirectory();if(console.log(" → Working directory:",e),!e)return console.log(" → No working directory, returning original:",t),t;if("."===t)return console.log(" → Root path detected, returning working dir:",e),e;if(t===e)return console.log(" → Path equals working directory, returning:",e),e;const i=`${e}/${t}`.replace(/\/+/g,"/");return console.log(" → Combining with working dir, result:",i),i}highlightNode(t){this.treeGroup.selectAll("circle.node-circle").style("stroke-width",2).classed("selected",!1),this.treeGroup.selectAll("circle.node-circle").filter(e=>e===t).style("stroke-width",4).classed("selected",!0)}diagonal(t,e){return`M ${t.y} ${t.x}\n C ${(t.y+e.y)/2} ${t.x},\n ${(t.y+e.y)/2} ${e.x},\n ${e.y} ${e.x}`}radialDiagonal(t,e){return d3.linkRadial().angle(t=>t.x).radius(t=>t.y)({source:t,target:e})}getNodeColor(t){const e=t.data.type,i=t.data.complexity||1,o={root:"#6B7280",directory:"#3B82F6",file:"#10B981",module:"#8B5CF6",class:"#F59E0B",function:"#EF4444",method:"#EC4899"}[e]||"#6B7280";return i>10?d3.color(o).darker(.5):i>5?d3.color(o).darker(.25):o}getNodeStrokeColor(t){return"loading"===t.data.loaded||"loading"===t.data.analyzed?"#FCD34D":"directory"!==t.data.type||t.data.loaded?"file"!==t.data.type||t.data.analyzed?this.getNodeColor(t):"#CBD5E1":"#94A3B8"}getNodeIcon(t){return{root:"📦",directory:"📁",file:"📄",module:"📦",class:"C",function:"ƒ",method:"m"}[t.data.type]||"•"}showTooltip(t,e){if(!this.tooltip)return;const i=[];i.push(`<strong>${e.data.name}</strong>`),i.push(`Type: ${e.data.type}`),e.data.language&&i.push(`Language: ${e.data.language}`),e.data.complexity&&i.push(`Complexity: ${e.data.complexity}`),e.data.lines&&i.push(`Lines: ${e.data.lines}`),e.data.path&&i.push(`Path: ${e.data.path}`),"directory"!==e.data.type||e.data.loaded?"file"!==e.data.type||e.data.analyzed||i.push("<em>Click to analyze file</em>"):i.push("<em>Click to explore contents</em>"),this.tooltip.transition().duration(200).style("opacity",.9),this.tooltip.html(i.join("<br>")).style("left",t.pageX+10+"px").style("top",t.pageY-28+"px")}hideTooltip(){this.tooltip&&this.tooltip.transition().duration(500).style("opacity",0)}filterTree(){this.root&&(this.root.descendants().forEach(t=>{t.data._hidden=!1,"all"!==this.languageFilter&&"file"===t.data.type&&t.data.language!==this.languageFilter&&(t.data._hidden=!0),this.searchTerm&&(t.data.name.toLowerCase().includes(this.searchTerm)||(t.data._hidden=!0))}),this.update(this.root))}expandAll(){if(!this.root)return;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),this.showNotification("All nodes expanded","info")}collapseAll(){if(!this.root)return;const t=e=>{e.children&&(e._children=e.children,e.children=null),e._children&&e._children.forEach(t)};this.root.children?.forEach(t),this.update(this.root),this.showNotification("All nodes collapsed","info")}resetZoom(){console.log("[CodeTree] resetZoom called but disabled - no zoom reset will occur"),this.showNotification("Zoom reset disabled - tree remains stationary","info")}focusOnNode(t){console.log("[CodeTree] focusOnNode called but disabled - no focusing will occur")}getNodePath(t){const e=[];let i=t;for(;i;)i.data&&i.data.name&&e.unshift(i.data.name),i=i.parent;return e.join(" / ")}toggleLegend(){const t=document.getElementById("tree-legend");t&&("none"===t.style.display?t.style.display="block":t.style.display="none")}getWorkingDirectory(){if(window.dashboard&&window.dashboard.workingDirectoryManager)return window.dashboard.workingDirectoryManager.getCurrentWorkingDir();const t=document.getElementById("working-dir-path");if(t){const e=t.textContent.trim();if(e&&"Loading..."!==e&&"Not selected"!==e)return e}return null}showNoWorkingDirectoryMessage(){const t=document.getElementById("code-tree-container");if(!t)return;this.removeNoWorkingDirectoryMessage(),this.hideLoading();const e=document.createElement("div");e.id="no-working-dir-message",e.className="no-working-dir-message",e.innerHTML='\n <div class="message-icon">📁</div>\n <h3>No Working Directory Selected</h3>\n <p>Please select a working directory from the top menu to analyze code.</p>\n <button id="select-working-dir-btn" class="btn btn-primary">\n Select Working Directory\n </button>\n ',e.style.cssText="\n text-align: center;\n padding: 40px;\n color: #666;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n ";const i=e.querySelector(".message-icon");i&&(i.style.cssText="font-size: 48px; margin-bottom: 16px; opacity: 0.5;");const o=e.querySelector("h3");o&&(o.style.cssText="margin: 16px 0; color: #333; font-size: 20px;");const s=e.querySelector("p");s&&(s.style.cssText="margin: 16px 0; color: #666; font-size: 14px;");const a=e.querySelector("button");a&&(a.style.cssText="\n margin-top: 20px;\n padding: 10px 20px;\n background: #3b82f6;\n color: white;\n border: none;\n border-radius: 6px;\n cursor: pointer;\n font-size: 14px;\n transition: background 0.2s;\n ",a.addEventListener("mouseenter",()=>{a.style.background="#2563eb"}),a.addEventListener("mouseleave",()=>{a.style.background="#3b82f6"}),a.addEventListener("click",()=>{const t=document.getElementById("change-dir-btn");t?t.click():window.dashboard&&window.dashboard.workingDirectoryManager&&window.dashboard.workingDirectoryManager.showChangeDirDialog()})),t.appendChild(e),this.updateBreadcrumb("Please select a working directory","warning")}removeNoWorkingDirectoryMessage(){const t=document.getElementById("no-working-dir-message");t&&t.remove()}exportTree(){const t={timestamp:(new Date).toISOString(),workingDirectory:this.getWorkingDirectory(),stats:this.stats,tree:this.treeData},e=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),i=URL.createObjectURL(e),o=document.createElement("a");o.href=i,o.download=`code-tree-${Date.now()}.json`,o.click(),URL.revokeObjectURL(i),this.showNotification("Tree exported successfully","success")}updateActivityTicker(t,e="info"){const i=document.getElementById("breadcrumb-content");if(i){const o="info"===e&&t.includes("...")?"⟳ ":"";i.innerHTML=`${o}${t}`,i.className=`breadcrumb-${e}`}}updateTicker(t,e="info"){const i=document.getElementById("code-tree-ticker");i&&(i.textContent=t,i.className=`ticker ticker-${e}`,"error"!==e&&setTimeout(()=>{i.style.opacity="0",setTimeout(()=>{i.style.opacity="1",i.textContent=""},300)},5e3))}}window.CodeTree=t,document.addEventListener("DOMContentLoaded",()=>{document.getElementById("code-tree-container")&&(window.codeTree=new t,document.addEventListener("click",t=>{t.target.matches('[data-tab="code"]')&&setTimeout(()=>{window.codeTree&&!window.codeTree.initialized?window.codeTree.initialize():window.codeTree&&window.codeTree.renderWhenVisible()},100)}))});
|
|
2
|
-
//# sourceMappingURL=code-tree.js.map
|