claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__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/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/engineer.json +33 -11
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +50 -2
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +648 -1098
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +339 -967
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +233 -542
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +280 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +22 -29
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +500 -680
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -17
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
- claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +11 -7
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/cache_manager.py +311 -0
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
- claude_mpm-4.1.3.dist-info/RECORD +528 -0
- claude_mpm/cli/commands/run_config_checker.py +0 -160
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@ import os
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any, Dict, Optional
|
|
11
11
|
|
|
12
|
-
from ....core.typing_utils import EventData
|
|
12
|
+
from ....core.typing_utils import EventData
|
|
13
13
|
from ....core.unified_paths import get_project_root
|
|
14
14
|
from .base import BaseEventHandler
|
|
15
15
|
|
|
@@ -156,7 +156,7 @@ class FileEventHandler(BaseEventHandler):
|
|
|
156
156
|
|
|
157
157
|
# Read file content
|
|
158
158
|
try:
|
|
159
|
-
with open(real_path,
|
|
159
|
+
with open(real_path, encoding="utf-8") as f:
|
|
160
160
|
content = f.read()
|
|
161
161
|
|
|
162
162
|
# Get file extension for syntax highlighting hint
|
|
@@ -203,17 +203,16 @@ class FileEventHandler(BaseEventHandler):
|
|
|
203
203
|
"file_path": file_path,
|
|
204
204
|
"file_size": file_size,
|
|
205
205
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
}
|
|
206
|
+
# Text file with different encoding
|
|
207
|
+
ext = real_path.suffix
|
|
208
|
+
return {
|
|
209
|
+
"success": True,
|
|
210
|
+
"file_path": file_path,
|
|
211
|
+
"content": text_content,
|
|
212
|
+
"file_size": file_size,
|
|
213
|
+
"extension": ext.lower(),
|
|
214
|
+
"encoding": "latin-1",
|
|
215
|
+
}
|
|
217
216
|
except Exception:
|
|
218
217
|
return {
|
|
219
218
|
"success": False,
|
|
@@ -223,6 +222,6 @@ class FileEventHandler(BaseEventHandler):
|
|
|
223
222
|
except Exception as read_error:
|
|
224
223
|
return {
|
|
225
224
|
"success": False,
|
|
226
|
-
"error": f"Failed to read file: {
|
|
225
|
+
"error": f"Failed to read file: {read_error!s}",
|
|
227
226
|
"file_path": file_path,
|
|
228
227
|
}
|
|
@@ -10,9 +10,8 @@ import os
|
|
|
10
10
|
import subprocess
|
|
11
11
|
from datetime import datetime
|
|
12
12
|
from pathlib import Path
|
|
13
|
-
from typing import Any, Dict,
|
|
13
|
+
from typing import Any, Dict, Optional
|
|
14
14
|
|
|
15
|
-
from ....core.typing_utils import EventData, PathLike, SocketId
|
|
16
15
|
from .base import BaseEventHandler
|
|
17
16
|
|
|
18
17
|
|
|
@@ -53,6 +52,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
53
52
|
cwd=working_dir,
|
|
54
53
|
capture_output=True,
|
|
55
54
|
text=True,
|
|
55
|
+
check=False,
|
|
56
56
|
)
|
|
57
57
|
|
|
58
58
|
# Debug: Git command completed
|
|
@@ -125,6 +125,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
125
125
|
["git", "-C", working_dir, "ls-files", "--", file_path],
|
|
126
126
|
capture_output=True,
|
|
127
127
|
text=True,
|
|
128
|
+
check=False,
|
|
128
129
|
)
|
|
129
130
|
|
|
130
131
|
is_tracked = result.returncode == 0 and result.stdout.strip()
|
|
@@ -318,6 +319,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
318
319
|
["git", "-C", working_dir, "add", file_path],
|
|
319
320
|
capture_output=True,
|
|
320
321
|
text=True,
|
|
322
|
+
check=False,
|
|
321
323
|
)
|
|
322
324
|
|
|
323
325
|
# Debug: Git add completed
|
|
@@ -389,7 +391,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
389
391
|
):
|
|
390
392
|
working_dir = os.getcwd()
|
|
391
393
|
self.logger.info(
|
|
392
|
-
f"[{operation}] working_dir was invalid ({
|
|
394
|
+
f"[{operation}] working_dir was invalid ({original_working_dir!r}), using cwd: {working_dir}"
|
|
393
395
|
)
|
|
394
396
|
else:
|
|
395
397
|
self.logger.info(f"[{operation}] Using provided working_dir: {working_dir}")
|
|
@@ -424,7 +426,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
424
426
|
response_event,
|
|
425
427
|
{
|
|
426
428
|
"success": False,
|
|
427
|
-
"error":
|
|
429
|
+
"error": "Directory not found",
|
|
428
430
|
"working_dir": working_dir,
|
|
429
431
|
"detail": f"Path does not exist: {working_dir}",
|
|
430
432
|
},
|
|
@@ -440,7 +442,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
440
442
|
response_event,
|
|
441
443
|
{
|
|
442
444
|
"success": False,
|
|
443
|
-
"error":
|
|
445
|
+
"error": "Not a directory",
|
|
444
446
|
"working_dir": working_dir,
|
|
445
447
|
"detail": f"Path is not a directory: {working_dir}",
|
|
446
448
|
},
|
|
@@ -529,6 +531,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
529
531
|
["git", "-C", working_dir, "rev-parse", "--git-dir"],
|
|
530
532
|
capture_output=True,
|
|
531
533
|
text=True,
|
|
534
|
+
check=False,
|
|
532
535
|
)
|
|
533
536
|
return git_check.returncode == 0
|
|
534
537
|
|
|
@@ -543,6 +546,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
543
546
|
["git", "-C", working_dir, "rev-parse", "--show-toplevel"],
|
|
544
547
|
capture_output=True,
|
|
545
548
|
text=True,
|
|
549
|
+
check=False,
|
|
546
550
|
)
|
|
547
551
|
|
|
548
552
|
if git_root_result.returncode == 0:
|
|
@@ -570,6 +574,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
570
574
|
["git", "-C", working_dir, "status", "--porcelain", file_path],
|
|
571
575
|
capture_output=True,
|
|
572
576
|
text=True,
|
|
577
|
+
check=False,
|
|
573
578
|
)
|
|
574
579
|
|
|
575
580
|
# Check if file is tracked by git
|
|
@@ -577,6 +582,7 @@ class GitEventHandler(BaseEventHandler):
|
|
|
577
582
|
["git", "-C", working_dir, "ls-files", file_path],
|
|
578
583
|
capture_output=True,
|
|
579
584
|
text=True,
|
|
585
|
+
check=False,
|
|
580
586
|
)
|
|
581
587
|
|
|
582
588
|
is_tracked = ls_files_result.returncode == 0 and ls_files_result.stdout.strip()
|
|
@@ -633,7 +639,6 @@ class GitEventHandler(BaseEventHandler):
|
|
|
633
639
|
)
|
|
634
640
|
|
|
635
641
|
# Handle case where working_dir is None, empty string, or 'Unknown'
|
|
636
|
-
original_working_dir = working_dir
|
|
637
642
|
if not working_dir or working_dir == "Unknown" or working_dir.strip() == "":
|
|
638
643
|
working_dir = os.getcwd()
|
|
639
644
|
# Debug: working_dir was invalid, using cwd
|
|
@@ -952,6 +957,6 @@ class GitEventHandler(BaseEventHandler):
|
|
|
952
957
|
self.logger.error(f"Error in generate_git_diff: {e}")
|
|
953
958
|
return {
|
|
954
959
|
"success": False,
|
|
955
|
-
"error": f"Git diff generation failed: {
|
|
960
|
+
"error": f"Git diff generation failed: {e!s}",
|
|
956
961
|
"file_path": file_path,
|
|
957
962
|
}
|
|
@@ -5,48 +5,47 @@ agent delegations, and other hook-based activity for the system heartbeat.
|
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
from datetime import datetime
|
|
8
|
-
from typing import Any, Dict
|
|
8
|
+
from typing import Any, Dict
|
|
9
9
|
|
|
10
10
|
from .base import BaseEventHandler
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class HookEventHandler(BaseEventHandler):
|
|
14
14
|
"""Handles hook events from Claude for session tracking.
|
|
15
|
-
|
|
15
|
+
|
|
16
16
|
WHY: Hook events provide rich information about Claude's activity including
|
|
17
17
|
session starts/stops, agent delegations, and tool usage. This handler
|
|
18
18
|
extracts session information to populate the system heartbeat data.
|
|
19
19
|
"""
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
def register_events(self) -> None:
|
|
22
22
|
"""Register hook event handlers.
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
NOTE: This handler no longer registers a claude_event handler directly
|
|
25
25
|
to avoid conflicts with ConnectionEventHandler. Instead, it processes
|
|
26
26
|
hook events passed from ConnectionEventHandler.
|
|
27
27
|
"""
|
|
28
28
|
# No direct event registration - events are passed from ConnectionEventHandler
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
async def process_hook_event(self, data: Dict[str, Any]) -> None:
|
|
32
31
|
"""Process a hook event received from ConnectionEventHandler.
|
|
33
|
-
|
|
32
|
+
|
|
34
33
|
WHY: This method is called by ConnectionEventHandler when it receives
|
|
35
34
|
a claude_event with type starting with 'hook.'. This separation avoids handler conflicts.
|
|
36
|
-
|
|
35
|
+
|
|
37
36
|
Args:
|
|
38
37
|
data: The complete event data including type, timestamp, and data fields
|
|
39
38
|
"""
|
|
40
39
|
if not isinstance(data, dict):
|
|
41
40
|
return
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
# Extract hook event details
|
|
44
43
|
# Hook events can come in two formats:
|
|
45
44
|
# 1. Normalized: { type: "hook", subtype: "user_prompt", ... }
|
|
46
45
|
# 2. Legacy: { type: "hook.user_prompt", ... }
|
|
47
46
|
event_type = data.get("type", "")
|
|
48
47
|
event_subtype = data.get("subtype", "")
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
# Determine the actual hook event name
|
|
51
50
|
hook_event = ""
|
|
52
51
|
if event_type == "hook" and event_subtype:
|
|
@@ -58,26 +57,26 @@ class HookEventHandler(BaseEventHandler):
|
|
|
58
57
|
else:
|
|
59
58
|
# Fallback: check for 'event' field (another legacy format)
|
|
60
59
|
hook_event = data.get("event", "")
|
|
61
|
-
|
|
60
|
+
|
|
62
61
|
hook_data = data.get("data", {})
|
|
63
|
-
|
|
62
|
+
|
|
64
63
|
# Create properly formatted event for history
|
|
65
64
|
# Note: add_to_history expects the event data directly, not wrapped
|
|
66
65
|
history_event = {
|
|
67
66
|
"type": "hook",
|
|
68
67
|
"event": hook_event,
|
|
69
68
|
"data": hook_data,
|
|
70
|
-
"timestamp": data.get("timestamp") or datetime.now().isoformat()
|
|
69
|
+
"timestamp": data.get("timestamp") or datetime.now().isoformat(),
|
|
71
70
|
}
|
|
72
|
-
|
|
71
|
+
|
|
73
72
|
# Add the event to history for replay
|
|
74
73
|
# The base handler's add_to_history will wrap it properly
|
|
75
74
|
self.event_history.append(history_event)
|
|
76
|
-
|
|
75
|
+
|
|
77
76
|
# Broadcast the original event to all connected clients
|
|
78
77
|
# (preserves all original fields)
|
|
79
78
|
await self.broadcast_event("claude_event", data)
|
|
80
|
-
|
|
79
|
+
|
|
81
80
|
# Track sessions based on hook events
|
|
82
81
|
if hook_event == "subagent_start":
|
|
83
82
|
await self._handle_subagent_start(hook_data)
|
|
@@ -87,23 +86,23 @@ class HookEventHandler(BaseEventHandler):
|
|
|
87
86
|
await self._handle_user_prompt(hook_data)
|
|
88
87
|
elif hook_event == "pre_tool":
|
|
89
88
|
await self._handle_pre_tool(hook_data)
|
|
90
|
-
|
|
89
|
+
|
|
91
90
|
self.logger.debug(f"Processed hook event: {hook_event}")
|
|
92
|
-
|
|
91
|
+
|
|
93
92
|
async def _handle_subagent_start(self, data: Dict[str, Any]):
|
|
94
93
|
"""Handle subagent start events.
|
|
95
|
-
|
|
94
|
+
|
|
96
95
|
WHY: When a subagent starts, we track it as an active session
|
|
97
96
|
with the agent type and start time for the heartbeat.
|
|
98
97
|
"""
|
|
99
98
|
session_id = data.get("session_id")
|
|
100
99
|
agent_type = data.get("agent_type", "unknown")
|
|
101
|
-
|
|
100
|
+
|
|
102
101
|
if not session_id:
|
|
103
102
|
return
|
|
104
|
-
|
|
103
|
+
|
|
105
104
|
# Update or create session tracking
|
|
106
|
-
if hasattr(self.server,
|
|
105
|
+
if hasattr(self.server, "active_sessions"):
|
|
107
106
|
self.server.active_sessions[session_id] = {
|
|
108
107
|
"session_id": session_id,
|
|
109
108
|
"start_time": datetime.now().isoformat(),
|
|
@@ -112,46 +111,48 @@ class HookEventHandler(BaseEventHandler):
|
|
|
112
111
|
"prompt": data.get("prompt", "")[:100], # First 100 chars
|
|
113
112
|
"last_activity": datetime.now().isoformat(),
|
|
114
113
|
}
|
|
115
|
-
|
|
114
|
+
|
|
116
115
|
self.logger.debug(
|
|
117
116
|
f"Tracked subagent start: session={session_id[:8]}..., agent={agent_type}"
|
|
118
117
|
)
|
|
119
|
-
|
|
118
|
+
|
|
120
119
|
async def _handle_subagent_stop(self, data: Dict[str, Any]):
|
|
121
120
|
"""Handle subagent stop events.
|
|
122
|
-
|
|
121
|
+
|
|
123
122
|
WHY: When a subagent stops, we update its status or remove it
|
|
124
123
|
from active sessions depending on the stop reason.
|
|
125
124
|
"""
|
|
126
125
|
session_id = data.get("session_id")
|
|
127
|
-
|
|
126
|
+
|
|
128
127
|
if not session_id:
|
|
129
128
|
return
|
|
130
|
-
|
|
129
|
+
|
|
131
130
|
# Update session status
|
|
132
|
-
if hasattr(self.server,
|
|
131
|
+
if hasattr(self.server, "active_sessions"):
|
|
133
132
|
if session_id in self.server.active_sessions:
|
|
134
133
|
# Mark as completed rather than removing immediately
|
|
135
134
|
self.server.active_sessions[session_id]["status"] = "completed"
|
|
136
|
-
self.server.active_sessions[session_id][
|
|
137
|
-
|
|
135
|
+
self.server.active_sessions[session_id][
|
|
136
|
+
"last_activity"
|
|
137
|
+
] = datetime.now().isoformat()
|
|
138
|
+
|
|
138
139
|
self.logger.debug(
|
|
139
140
|
f"Marked session completed: session={session_id[:8]}..."
|
|
140
141
|
)
|
|
141
|
-
|
|
142
|
+
|
|
142
143
|
async def _handle_user_prompt(self, data: Dict[str, Any]):
|
|
143
144
|
"""Handle user prompt events.
|
|
144
|
-
|
|
145
|
+
|
|
145
146
|
WHY: User prompts indicate the start of a new interaction,
|
|
146
147
|
which we track as a PM session if no delegation occurs.
|
|
147
148
|
"""
|
|
148
149
|
session_id = data.get("session_id")
|
|
149
|
-
|
|
150
|
+
|
|
150
151
|
if not session_id:
|
|
151
152
|
return
|
|
152
|
-
|
|
153
|
+
|
|
153
154
|
# Create or update PM session
|
|
154
|
-
if hasattr(self.server,
|
|
155
|
+
if hasattr(self.server, "active_sessions"):
|
|
155
156
|
if session_id not in self.server.active_sessions:
|
|
156
157
|
self.server.active_sessions[session_id] = {
|
|
157
158
|
"session_id": session_id,
|
|
@@ -164,31 +165,35 @@ class HookEventHandler(BaseEventHandler):
|
|
|
164
165
|
}
|
|
165
166
|
else:
|
|
166
167
|
# Update last activity
|
|
167
|
-
self.server.active_sessions[session_id][
|
|
168
|
-
|
|
168
|
+
self.server.active_sessions[session_id][
|
|
169
|
+
"last_activity"
|
|
170
|
+
] = datetime.now().isoformat()
|
|
171
|
+
|
|
169
172
|
async def _handle_pre_tool(self, data: Dict[str, Any]):
|
|
170
173
|
"""Handle pre-tool events.
|
|
171
|
-
|
|
174
|
+
|
|
172
175
|
WHY: Pre-tool events with Task delegation indicate agent changes
|
|
173
176
|
that we need to track for accurate session information.
|
|
174
177
|
"""
|
|
175
178
|
if data.get("tool_name") != "Task":
|
|
176
179
|
return
|
|
177
|
-
|
|
180
|
+
|
|
178
181
|
session_id = data.get("session_id")
|
|
179
182
|
delegation_details = data.get("delegation_details", {})
|
|
180
183
|
agent_type = delegation_details.get("agent_type", "unknown")
|
|
181
|
-
|
|
184
|
+
|
|
182
185
|
if not session_id:
|
|
183
186
|
return
|
|
184
|
-
|
|
187
|
+
|
|
185
188
|
# Update session with new agent
|
|
186
|
-
if hasattr(self.server,
|
|
189
|
+
if hasattr(self.server, "active_sessions"):
|
|
187
190
|
if session_id in self.server.active_sessions:
|
|
188
191
|
self.server.active_sessions[session_id]["agent"] = agent_type
|
|
189
192
|
self.server.active_sessions[session_id]["status"] = "delegated"
|
|
190
|
-
self.server.active_sessions[session_id][
|
|
191
|
-
|
|
193
|
+
self.server.active_sessions[session_id][
|
|
194
|
+
"last_activity"
|
|
195
|
+
] = datetime.now().isoformat()
|
|
196
|
+
|
|
192
197
|
self.logger.debug(
|
|
193
198
|
f"Updated session delegation: session={session_id[:8]}..., agent={agent_type}"
|
|
194
199
|
)
|
|
@@ -5,13 +5,14 @@ providing a clean interface for the SocketIOServer to register all
|
|
|
5
5
|
events without knowing the details of each handler.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from logging import Logger
|
|
9
8
|
from typing import TYPE_CHECKING, List, Optional, Type
|
|
10
9
|
|
|
11
10
|
from ....core.logger import get_logger
|
|
12
11
|
from .base import BaseEventHandler
|
|
13
12
|
|
|
14
13
|
if TYPE_CHECKING:
|
|
14
|
+
from logging import Logger
|
|
15
|
+
|
|
15
16
|
from ..server import SocketIOServer
|
|
16
17
|
|
|
17
18
|
from .connection import ConnectionEventHandler
|
|
@@ -46,7 +47,7 @@ class EventHandlerRegistry:
|
|
|
46
47
|
Args:
|
|
47
48
|
server: The SocketIOServer instance
|
|
48
49
|
"""
|
|
49
|
-
self.server:
|
|
50
|
+
self.server: SocketIOServer = server
|
|
50
51
|
self.logger: Logger = get_logger("EventHandlerRegistry")
|
|
51
52
|
self.handlers: List[BaseEventHandler] = []
|
|
52
53
|
self._initialized: bool = False
|
|
@@ -73,8 +74,11 @@ class EventHandlerRegistry:
|
|
|
73
74
|
# Add debug logging for deployment context
|
|
74
75
|
try:
|
|
75
76
|
from ....core.unified_paths import PathContext
|
|
77
|
+
|
|
76
78
|
deployment_context = PathContext.detect_deployment_context()
|
|
77
|
-
self.logger.info(
|
|
79
|
+
self.logger.info(
|
|
80
|
+
f"Initializing event handlers in {deployment_context.value} mode"
|
|
81
|
+
)
|
|
78
82
|
except Exception as e:
|
|
79
83
|
self.logger.debug(f"Could not detect deployment context: {e}")
|
|
80
84
|
|
|
@@ -88,7 +92,9 @@ class EventHandlerRegistry:
|
|
|
88
92
|
self.handlers.append(handler)
|
|
89
93
|
self.logger.info(f"✅ Initialized handler: {handler_class.__name__}")
|
|
90
94
|
except Exception as e:
|
|
91
|
-
self.logger.error(
|
|
95
|
+
self.logger.error(
|
|
96
|
+
f"❌ Failed to initialize {handler_class.__name__}: {e}"
|
|
97
|
+
)
|
|
92
98
|
import traceback
|
|
93
99
|
|
|
94
100
|
self.logger.error(f"Stack trace: {traceback.format_exc()}")
|
|
@@ -107,31 +113,43 @@ class EventHandlerRegistry:
|
|
|
107
113
|
self.logger.error("Registry not initialized. Call initialize() first.")
|
|
108
114
|
raise RuntimeError("EventHandlerRegistry not initialized")
|
|
109
115
|
|
|
110
|
-
self.logger.info(
|
|
111
|
-
|
|
116
|
+
self.logger.info(
|
|
117
|
+
f"🔄 Starting event registration for {len(self.handlers)} handlers"
|
|
118
|
+
)
|
|
119
|
+
|
|
112
120
|
# Verify Socket.IO server is available
|
|
113
|
-
if
|
|
114
|
-
self.
|
|
121
|
+
if (
|
|
122
|
+
not hasattr(self.server, "core")
|
|
123
|
+
or not self.server.core
|
|
124
|
+
or not self.server.core.sio
|
|
125
|
+
):
|
|
126
|
+
self.logger.error(
|
|
127
|
+
"❌ Socket.IO server instance not available for event registration"
|
|
128
|
+
)
|
|
115
129
|
raise RuntimeError("Socket.IO server not available")
|
|
116
|
-
|
|
130
|
+
|
|
117
131
|
self.logger.debug(f"Socket.IO server available: {type(self.server.core.sio)}")
|
|
118
132
|
|
|
119
133
|
registered_count = 0
|
|
120
134
|
for handler in self.handlers:
|
|
121
135
|
try:
|
|
122
|
-
self.logger.debug(
|
|
123
|
-
|
|
136
|
+
self.logger.debug(
|
|
137
|
+
f"Registering events for {handler.__class__.__name__}"
|
|
138
|
+
)
|
|
139
|
+
|
|
124
140
|
# Get the number of registered events before and after
|
|
125
|
-
sio_events_before = len(getattr(self.server.core.sio,
|
|
126
|
-
|
|
141
|
+
sio_events_before = len(getattr(self.server.core.sio, "handlers", {}))
|
|
142
|
+
|
|
127
143
|
handler.register_events()
|
|
128
|
-
|
|
129
|
-
sio_events_after = len(getattr(self.server.core.sio,
|
|
144
|
+
|
|
145
|
+
sio_events_after = len(getattr(self.server.core.sio, "handlers", {}))
|
|
130
146
|
events_added = sio_events_after - sio_events_before
|
|
131
|
-
|
|
147
|
+
|
|
132
148
|
registered_count += 1
|
|
133
|
-
self.logger.info(
|
|
134
|
-
|
|
149
|
+
self.logger.info(
|
|
150
|
+
f"✅ Registered {events_added} events for {handler.__class__.__name__}"
|
|
151
|
+
)
|
|
152
|
+
|
|
135
153
|
except NotImplementedError:
|
|
136
154
|
# Handler has no events to register (like ProjectEventHandler)
|
|
137
155
|
self.logger.debug(
|
|
@@ -146,7 +164,7 @@ class EventHandlerRegistry:
|
|
|
146
164
|
self.logger.error(f"Stack trace: {traceback.format_exc()}")
|
|
147
165
|
|
|
148
166
|
# Final verification
|
|
149
|
-
total_sio_events = len(getattr(self.server.core.sio,
|
|
167
|
+
total_sio_events = len(getattr(self.server.core.sio, "handlers", {}))
|
|
150
168
|
self.logger.info(
|
|
151
169
|
f"🎉 Event registration complete: {registered_count} handlers processed, "
|
|
152
170
|
f"{total_sio_events} total Socket.IO events registered"
|