claude-mpm 3.9.11__py3-none-any.whl → 4.0.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/VERSION +1 -1
- claude_mpm/__init__.py +2 -2
- claude_mpm/__main__.py +3 -2
- claude_mpm/agents/__init__.py +85 -79
- claude_mpm/agents/agent_loader.py +464 -1003
- claude_mpm/agents/agent_loader_integration.py +45 -45
- claude_mpm/agents/agents_metadata.py +29 -30
- claude_mpm/agents/async_agent_loader.py +156 -138
- claude_mpm/agents/base_agent.json +1 -1
- claude_mpm/agents/base_agent_loader.py +179 -151
- claude_mpm/agents/frontmatter_validator.py +229 -130
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +213 -147
- claude_mpm/agents/templates/__init__.py +13 -13
- claude_mpm/agents/templates/code_analyzer.json +2 -2
- claude_mpm/agents/templates/data_engineer.json +1 -1
- claude_mpm/agents/templates/documentation.json +23 -11
- claude_mpm/agents/templates/engineer.json +22 -6
- claude_mpm/agents/templates/memory_manager.json +1 -1
- claude_mpm/agents/templates/ops.json +2 -2
- claude_mpm/agents/templates/project_organizer.json +1 -1
- claude_mpm/agents/templates/qa.json +1 -1
- claude_mpm/agents/templates/refactoring_engineer.json +222 -0
- claude_mpm/agents/templates/research.json +20 -14
- claude_mpm/agents/templates/security.json +1 -1
- claude_mpm/agents/templates/ticketing.json +1 -1
- claude_mpm/agents/templates/version_control.json +1 -1
- claude_mpm/agents/templates/web_qa.json +3 -1
- claude_mpm/agents/templates/web_ui.json +2 -2
- claude_mpm/cli/__init__.py +79 -51
- claude_mpm/cli/__main__.py +3 -2
- claude_mpm/cli/commands/__init__.py +20 -20
- claude_mpm/cli/commands/agents.py +279 -247
- claude_mpm/cli/commands/aggregate.py +138 -157
- claude_mpm/cli/commands/cleanup.py +147 -147
- claude_mpm/cli/commands/config.py +93 -76
- claude_mpm/cli/commands/info.py +17 -16
- claude_mpm/cli/commands/mcp.py +140 -905
- claude_mpm/cli/commands/mcp_command_router.py +139 -0
- claude_mpm/cli/commands/mcp_config_commands.py +20 -0
- claude_mpm/cli/commands/mcp_install_commands.py +20 -0
- claude_mpm/cli/commands/mcp_server_commands.py +175 -0
- claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
- claude_mpm/cli/commands/memory.py +239 -203
- claude_mpm/cli/commands/monitor.py +203 -81
- claude_mpm/cli/commands/run.py +380 -429
- claude_mpm/cli/commands/run_config_checker.py +160 -0
- claude_mpm/cli/commands/socketio_monitor.py +235 -0
- claude_mpm/cli/commands/tickets.py +305 -197
- claude_mpm/cli/parser.py +24 -1156
- claude_mpm/cli/parsers/__init__.py +29 -0
- claude_mpm/cli/parsers/agents_parser.py +136 -0
- claude_mpm/cli/parsers/base_parser.py +331 -0
- claude_mpm/cli/parsers/config_parser.py +85 -0
- claude_mpm/cli/parsers/mcp_parser.py +152 -0
- claude_mpm/cli/parsers/memory_parser.py +138 -0
- claude_mpm/cli/parsers/monitor_parser.py +104 -0
- claude_mpm/cli/parsers/run_parser.py +147 -0
- claude_mpm/cli/parsers/tickets_parser.py +203 -0
- claude_mpm/cli/ticket_cli.py +7 -3
- claude_mpm/cli/utils.py +55 -37
- claude_mpm/cli_module/__init__.py +6 -6
- claude_mpm/cli_module/args.py +188 -140
- claude_mpm/cli_module/commands.py +79 -70
- claude_mpm/cli_module/migration_example.py +38 -60
- claude_mpm/config/__init__.py +32 -25
- claude_mpm/config/agent_config.py +151 -119
- claude_mpm/config/experimental_features.py +71 -73
- claude_mpm/config/paths.py +94 -208
- claude_mpm/config/socketio_config.py +84 -73
- claude_mpm/constants.py +35 -18
- claude_mpm/core/__init__.py +9 -6
- claude_mpm/core/agent_name_normalizer.py +68 -71
- claude_mpm/core/agent_registry.py +372 -521
- claude_mpm/core/agent_session_manager.py +74 -63
- claude_mpm/core/base_service.py +116 -87
- claude_mpm/core/cache.py +119 -153
- claude_mpm/core/claude_runner.py +425 -1120
- claude_mpm/core/config.py +263 -168
- claude_mpm/core/config_aliases.py +69 -61
- claude_mpm/core/config_constants.py +292 -0
- claude_mpm/core/constants.py +57 -99
- claude_mpm/core/container.py +211 -178
- claude_mpm/core/exceptions.py +233 -89
- claude_mpm/core/factories.py +92 -54
- claude_mpm/core/framework_loader.py +378 -220
- claude_mpm/core/hook_manager.py +198 -83
- claude_mpm/core/hook_performance_config.py +136 -0
- claude_mpm/core/injectable_service.py +61 -55
- claude_mpm/core/interactive_session.py +165 -155
- claude_mpm/core/interfaces.py +221 -195
- claude_mpm/core/lazy.py +96 -96
- claude_mpm/core/logger.py +133 -107
- claude_mpm/core/logging_config.py +185 -157
- claude_mpm/core/minimal_framework_loader.py +20 -15
- claude_mpm/core/mixins.py +30 -29
- claude_mpm/core/oneshot_session.py +215 -181
- claude_mpm/core/optimized_agent_loader.py +134 -138
- claude_mpm/core/optimized_startup.py +159 -157
- claude_mpm/core/pm_hook_interceptor.py +85 -72
- claude_mpm/core/service_registry.py +103 -101
- claude_mpm/core/session_manager.py +97 -87
- claude_mpm/core/socketio_pool.py +212 -158
- claude_mpm/core/tool_access_control.py +58 -51
- claude_mpm/core/types.py +46 -24
- claude_mpm/core/typing_utils.py +166 -82
- claude_mpm/core/unified_agent_registry.py +721 -0
- claude_mpm/core/unified_config.py +550 -0
- claude_mpm/core/unified_paths.py +549 -0
- claude_mpm/dashboard/index.html +1 -1
- claude_mpm/dashboard/open_dashboard.py +51 -17
- claude_mpm/dashboard/static/css/dashboard.css +27 -8
- claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
- claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
- claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
- claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
- claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
- claude_mpm/dashboard/static/dist/dashboard.js +2 -0
- claude_mpm/dashboard/static/dist/socket-client.js +2 -0
- claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
- claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
- claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
- claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
- claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
- claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
- claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
- claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
- claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
- claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
- claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
- claude_mpm/dashboard/static/js/dashboard.js +178 -453
- claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
- claude_mpm/dashboard/static/js/socket-client.js +120 -54
- claude_mpm/dashboard/templates/index.html +40 -50
- claude_mpm/experimental/cli_enhancements.py +60 -58
- claude_mpm/generators/__init__.py +1 -1
- claude_mpm/generators/agent_profile_generator.py +75 -65
- claude_mpm/hooks/__init__.py +1 -1
- claude_mpm/hooks/base_hook.py +33 -28
- claude_mpm/hooks/claude_hooks/__init__.py +1 -1
- claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
- claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
- claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
- claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
- claude_mpm/hooks/memory_integration_hook.py +140 -100
- claude_mpm/hooks/tool_call_interceptor.py +89 -76
- claude_mpm/hooks/validation_hooks.py +57 -49
- claude_mpm/init.py +145 -121
- claude_mpm/models/__init__.py +9 -9
- claude_mpm/models/agent_definition.py +33 -23
- claude_mpm/models/agent_session.py +228 -200
- claude_mpm/scripts/__init__.py +1 -1
- claude_mpm/scripts/socketio_daemon.py +192 -75
- claude_mpm/scripts/socketio_server_manager.py +328 -0
- claude_mpm/scripts/start_activity_logging.py +25 -22
- claude_mpm/services/__init__.py +68 -43
- claude_mpm/services/agent_capabilities_service.py +271 -0
- claude_mpm/services/agents/__init__.py +23 -32
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
- claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
- claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
- claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
- claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
- claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
- claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
- claude_mpm/services/agents/deployment/agent_validator.py +352 -0
- claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
- claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
- claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
- claude_mpm/services/agents/deployment/config/__init__.py +13 -0
- claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
- claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
- claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
- claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
- claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
- claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
- claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
- claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
- claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
- claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
- claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
- claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
- claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
- claude_mpm/services/agents/deployment/results/__init__.py +13 -0
- claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
- claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
- claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
- claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
- claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
- claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
- claude_mpm/services/agents/loading/__init__.py +2 -2
- claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
- claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
- claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
- claude_mpm/services/agents/management/__init__.py +2 -2
- claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
- claude_mpm/services/agents/management/agent_management_service.py +209 -156
- claude_mpm/services/agents/memory/__init__.py +9 -6
- claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
- claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
- claude_mpm/services/agents/memory/analyzer.py +430 -0
- claude_mpm/services/agents/memory/content_manager.py +376 -0
- claude_mpm/services/agents/memory/template_generator.py +468 -0
- claude_mpm/services/agents/registry/__init__.py +7 -10
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
- claude_mpm/services/agents/registry/modification_tracker.py +351 -285
- claude_mpm/services/async_session_logger.py +187 -153
- claude_mpm/services/claude_session_logger.py +87 -72
- claude_mpm/services/command_handler_service.py +217 -0
- claude_mpm/services/communication/__init__.py +3 -2
- claude_mpm/services/core/__init__.py +50 -97
- claude_mpm/services/core/base.py +60 -53
- claude_mpm/services/core/interfaces/__init__.py +188 -0
- claude_mpm/services/core/interfaces/agent.py +351 -0
- claude_mpm/services/core/interfaces/communication.py +343 -0
- claude_mpm/services/core/interfaces/infrastructure.py +413 -0
- claude_mpm/services/core/interfaces/service.py +434 -0
- claude_mpm/services/core/interfaces.py +19 -944
- claude_mpm/services/event_aggregator.py +208 -170
- claude_mpm/services/exceptions.py +387 -308
- claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
- claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
- claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
- claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
- claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
- claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
- claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
- claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
- claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
- claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
- claude_mpm/services/hook_service.py +106 -114
- claude_mpm/services/infrastructure/__init__.py +7 -5
- claude_mpm/services/infrastructure/context_preservation.py +233 -199
- claude_mpm/services/infrastructure/daemon_manager.py +279 -0
- claude_mpm/services/infrastructure/logging.py +83 -76
- claude_mpm/services/infrastructure/monitoring.py +547 -404
- claude_mpm/services/mcp_gateway/__init__.py +30 -13
- claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
- claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
- claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
- claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
- claude_mpm/services/mcp_gateway/core/base.py +80 -67
- claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
- claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
- claude_mpm/services/mcp_gateway/main.py +287 -137
- claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
- claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
- claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
- claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
- claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
- claude_mpm/services/memory/__init__.py +2 -2
- claude_mpm/services/memory/builder.py +451 -362
- claude_mpm/services/memory/cache/__init__.py +2 -2
- claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
- claude_mpm/services/memory/cache/simple_cache.py +107 -93
- claude_mpm/services/memory/indexed_memory.py +195 -193
- claude_mpm/services/memory/optimizer.py +267 -234
- claude_mpm/services/memory/router.py +571 -263
- claude_mpm/services/memory_hook_service.py +237 -0
- claude_mpm/services/port_manager.py +223 -0
- claude_mpm/services/project/__init__.py +3 -3
- claude_mpm/services/project/analyzer.py +451 -305
- claude_mpm/services/project/registry.py +262 -240
- claude_mpm/services/recovery_manager.py +287 -231
- claude_mpm/services/response_tracker.py +87 -67
- claude_mpm/services/runner_configuration_service.py +587 -0
- claude_mpm/services/session_management_service.py +304 -0
- claude_mpm/services/socketio/__init__.py +4 -4
- claude_mpm/services/socketio/client_proxy.py +174 -0
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +44 -30
- claude_mpm/services/socketio/handlers/connection.py +145 -65
- claude_mpm/services/socketio/handlers/file.py +123 -108
- claude_mpm/services/socketio/handlers/git.py +607 -373
- claude_mpm/services/socketio/handlers/hook.py +170 -0
- claude_mpm/services/socketio/handlers/memory.py +4 -4
- claude_mpm/services/socketio/handlers/project.py +4 -4
- claude_mpm/services/socketio/handlers/registry.py +53 -38
- claude_mpm/services/socketio/server/__init__.py +18 -0
- claude_mpm/services/socketio/server/broadcaster.py +252 -0
- claude_mpm/services/socketio/server/core.py +399 -0
- claude_mpm/services/socketio/server/main.py +323 -0
- claude_mpm/services/socketio_client_manager.py +160 -133
- claude_mpm/services/socketio_server.py +36 -1885
- claude_mpm/services/subprocess_launcher_service.py +316 -0
- claude_mpm/services/system_instructions_service.py +258 -0
- claude_mpm/services/ticket_manager.py +19 -533
- claude_mpm/services/utility_service.py +285 -0
- claude_mpm/services/version_control/__init__.py +18 -21
- claude_mpm/services/version_control/branch_strategy.py +20 -10
- claude_mpm/services/version_control/conflict_resolution.py +37 -13
- claude_mpm/services/version_control/git_operations.py +52 -21
- claude_mpm/services/version_control/semantic_versioning.py +92 -53
- claude_mpm/services/version_control/version_parser.py +145 -125
- claude_mpm/services/version_service.py +270 -0
- claude_mpm/storage/__init__.py +2 -2
- claude_mpm/storage/state_storage.py +177 -181
- claude_mpm/ticket_wrapper.py +2 -2
- claude_mpm/utils/__init__.py +2 -2
- claude_mpm/utils/agent_dependency_loader.py +453 -243
- claude_mpm/utils/config_manager.py +157 -118
- claude_mpm/utils/console.py +1 -1
- claude_mpm/utils/dependency_cache.py +102 -107
- claude_mpm/utils/dependency_manager.py +52 -47
- claude_mpm/utils/dependency_strategies.py +131 -96
- claude_mpm/utils/environment_context.py +110 -102
- claude_mpm/utils/error_handler.py +75 -55
- claude_mpm/utils/file_utils.py +80 -67
- claude_mpm/utils/framework_detection.py +12 -11
- claude_mpm/utils/import_migration_example.py +12 -60
- claude_mpm/utils/imports.py +48 -45
- claude_mpm/utils/path_operations.py +100 -93
- claude_mpm/utils/robust_installer.py +172 -164
- claude_mpm/utils/session_logging.py +30 -23
- claude_mpm/utils/subprocess_utils.py +99 -61
- claude_mpm/validation/__init__.py +1 -1
- claude_mpm/validation/agent_validator.py +151 -111
- claude_mpm/validation/frontmatter_validator.py +92 -71
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
- claude_mpm-4.0.3.dist-info/RECORD +402 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
- claude_mpm/cli/commands/run_guarded.py +0 -511
- claude_mpm/config/memory_guardian_config.py +0 -325
- claude_mpm/config/memory_guardian_yaml.py +0 -335
- claude_mpm/core/config_paths.py +0 -150
- claude_mpm/core/memory_aware_runner.py +0 -353
- claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
- claude_mpm/deployment_paths.py +0 -261
- claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
- claude_mpm/models/state_models.py +0 -433
- claude_mpm/services/agent/__init__.py +0 -24
- claude_mpm/services/agent/deployment.py +0 -2548
- claude_mpm/services/agent/management.py +0 -598
- claude_mpm/services/agent/registry.py +0 -813
- claude_mpm/services/agents/registry/agent_registry.py +0 -813
- claude_mpm/services/communication/socketio.py +0 -1935
- claude_mpm/services/communication/websocket.py +0 -479
- claude_mpm/services/framework_claude_md_generator.py +0 -624
- claude_mpm/services/health_monitor.py +0 -893
- claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
- claude_mpm/services/infrastructure/health_monitor.py +0 -775
- claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
- claude_mpm/services/infrastructure/memory_guardian.py +0 -944
- claude_mpm/services/infrastructure/restart_protection.py +0 -642
- claude_mpm/services/infrastructure/state_manager.py +0 -774
- claude_mpm/services/mcp_gateway/manager.py +0 -334
- claude_mpm/services/optimized_hook_service.py +0 -542
- claude_mpm/services/project_analyzer.py +0 -864
- claude_mpm/services/project_registry.py +0 -608
- claude_mpm/services/standalone_socketio_server.py +0 -1300
- claude_mpm/services/ticket_manager_di.py +0 -318
- claude_mpm/services/ticketing_service_original.py +0 -510
- claude_mpm/utils/paths.py +0 -395
- claude_mpm/utils/platform_memory.py +0 -524
- claude_mpm-3.9.11.dist-info/RECORD +0 -306
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
- {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
| @@ -0,0 +1,328 @@ | |
| 1 | 
            +
            #!/usr/bin/env python3
         | 
| 2 | 
            +
            """
         | 
| 3 | 
            +
            Socket.IO Server Manager wrapper for claude-mpm.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            WHY: This module provides a wrapper around the ServerManager class from
         | 
| 6 | 
            +
            tools/admin/socketio_server_manager.py to make it accessible from the
         | 
| 7 | 
            +
            scripts directory as expected by the CLI monitor command.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            DESIGN DECISION: Rather than duplicating code, we import and re-export
         | 
| 10 | 
            +
            the ServerManager class from its actual location in tools/admin. This
         | 
| 11 | 
            +
            ensures consistency and maintainability.
         | 
| 12 | 
            +
            """
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            import sys
         | 
| 15 | 
            +
            from pathlib import Path
         | 
| 16 | 
            +
             | 
| 17 | 
            +
            # Add the tools/admin directory to Python path to import ServerManager
         | 
| 18 | 
            +
            script_dir = Path(__file__).parent
         | 
| 19 | 
            +
            project_root = script_dir.parent.parent.parent  # Up to project root
         | 
| 20 | 
            +
            tools_admin_dir = project_root / "tools" / "admin"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            if tools_admin_dir.exists() and str(tools_admin_dir) not in sys.path:
         | 
| 23 | 
            +
                sys.path.insert(0, str(tools_admin_dir))
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            try:
         | 
| 26 | 
            +
                # Import ServerManager from the actual implementation
         | 
| 27 | 
            +
                from socketio_server_manager import ServerManager as BaseServerManager
         | 
| 28 | 
            +
                import subprocess
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
                # Patch the ServerManager to use project-local PID file and daemon
         | 
| 31 | 
            +
                class ServerManager(BaseServerManager):
         | 
| 32 | 
            +
                    """Patched ServerManager that uses project-local PID file and daemon.
         | 
| 33 | 
            +
                    
         | 
| 34 | 
            +
                    WHY: The daemon stores its PID file in the project's .claude-mpm
         | 
| 35 | 
            +
                    directory, not in the home directory. This patch ensures the
         | 
| 36 | 
            +
                    ServerManager looks in the correct location and uses the daemon
         | 
| 37 | 
            +
                    for starting servers when the standalone module is not available.
         | 
| 38 | 
            +
                    """
         | 
| 39 | 
            +
                    
         | 
| 40 | 
            +
                    def __init__(self):
         | 
| 41 | 
            +
                        super().__init__()
         | 
| 42 | 
            +
                        # Override the daemon PID file path to use project root
         | 
| 43 | 
            +
                        from claude_mpm.core.unified_paths import get_project_root
         | 
| 44 | 
            +
                        self.daemon_pidfile_path = get_project_root() / ".claude-mpm" / "socketio-server.pid"
         | 
| 45 | 
            +
                        self.daemon_script = script_dir / "socketio_daemon.py"
         | 
| 46 | 
            +
                    
         | 
| 47 | 
            +
                    def start_server(self, port: int = None, host: str = "localhost", 
         | 
| 48 | 
            +
                                    server_id: str = None) -> bool:
         | 
| 49 | 
            +
                        """Start Socket.IO server, preferring daemon over standalone.
         | 
| 50 | 
            +
                        
         | 
| 51 | 
            +
                        WHY: When the standalone_socketio_server module is not available,
         | 
| 52 | 
            +
                        we fallback to using the daemon script which is always present.
         | 
| 53 | 
            +
                        """
         | 
| 54 | 
            +
                        # First check if the daemon is already running
         | 
| 55 | 
            +
                        if self.daemon_pidfile_path.exists():
         | 
| 56 | 
            +
                            try:
         | 
| 57 | 
            +
                                with open(self.daemon_pidfile_path) as f:
         | 
| 58 | 
            +
                                    pid = int(f.read().strip())
         | 
| 59 | 
            +
                                # Check if process is running
         | 
| 60 | 
            +
                                import psutil
         | 
| 61 | 
            +
                                process = psutil.Process(pid)
         | 
| 62 | 
            +
                                if process.is_running():
         | 
| 63 | 
            +
                                    print(f"Socket.IO daemon server is already running (PID: {pid})")
         | 
| 64 | 
            +
                                    return True
         | 
| 65 | 
            +
                            except:
         | 
| 66 | 
            +
                                pass
         | 
| 67 | 
            +
                        
         | 
| 68 | 
            +
                        # Try to use the daemon script for starting
         | 
| 69 | 
            +
                        if self.daemon_script.exists():
         | 
| 70 | 
            +
                            print(f"Starting server on {host}:{port or self.base_port} using daemon...")
         | 
| 71 | 
            +
                            try:
         | 
| 72 | 
            +
                                result = subprocess.run(
         | 
| 73 | 
            +
                                    [sys.executable, str(self.daemon_script), "start"],
         | 
| 74 | 
            +
                                    capture_output=True,
         | 
| 75 | 
            +
                                    text=True
         | 
| 76 | 
            +
                                )
         | 
| 77 | 
            +
                                
         | 
| 78 | 
            +
                                if result.returncode == 0:
         | 
| 79 | 
            +
                                    # Check if output contains success message
         | 
| 80 | 
            +
                                    if "started successfully" in result.stdout.lower():
         | 
| 81 | 
            +
                                        print(result.stdout)
         | 
| 82 | 
            +
                                        return True
         | 
| 83 | 
            +
                                    # Even if no explicit success message, check if process is running
         | 
| 84 | 
            +
                                    elif self.daemon_pidfile_path.exists():
         | 
| 85 | 
            +
                                        print("Socket.IO daemon server started")
         | 
| 86 | 
            +
                                        return True
         | 
| 87 | 
            +
                                else:
         | 
| 88 | 
            +
                                    # If daemon fails, try parent's start_server method
         | 
| 89 | 
            +
                                    if result.stderr:
         | 
| 90 | 
            +
                                        print(f"Daemon error: {result.stderr}")
         | 
| 91 | 
            +
                                    print("Trying standalone method...")
         | 
| 92 | 
            +
                            except Exception as e:
         | 
| 93 | 
            +
                                print(f"Error running daemon: {e}")
         | 
| 94 | 
            +
                                pass
         | 
| 95 | 
            +
                        
         | 
| 96 | 
            +
                        # Fall back to parent implementation
         | 
| 97 | 
            +
                        return super().start_server(port=port, host=host, server_id=server_id)
         | 
| 98 | 
            +
                    
         | 
| 99 | 
            +
                    def stop_server(self, port: int = None) -> bool:
         | 
| 100 | 
            +
                        """Stop Socket.IO server, handling daemon-style servers.
         | 
| 101 | 
            +
                        
         | 
| 102 | 
            +
                        WHY: The daemon server needs special handling for stopping.
         | 
| 103 | 
            +
                        """
         | 
| 104 | 
            +
                        # Check if daemon is running
         | 
| 105 | 
            +
                        if self.daemon_pidfile_path.exists():
         | 
| 106 | 
            +
                            print(f"🔄 Stopping daemon server", end="")
         | 
| 107 | 
            +
                            try:
         | 
| 108 | 
            +
                                with open(self.daemon_pidfile_path) as f:
         | 
| 109 | 
            +
                                    pid = int(f.read().strip())
         | 
| 110 | 
            +
                                print(f" (PID: {pid})...")
         | 
| 111 | 
            +
                                
         | 
| 112 | 
            +
                                result = subprocess.run(
         | 
| 113 | 
            +
                                    [sys.executable, str(self.daemon_script), "stop"],
         | 
| 114 | 
            +
                                    capture_output=True,
         | 
| 115 | 
            +
                                    text=True
         | 
| 116 | 
            +
                                )
         | 
| 117 | 
            +
                                
         | 
| 118 | 
            +
                                if result.returncode == 0:
         | 
| 119 | 
            +
                                    print("✅ Daemon server stopped successfully")
         | 
| 120 | 
            +
                                    return True
         | 
| 121 | 
            +
                                else:
         | 
| 122 | 
            +
                                    print(f"❌ Failed to stop daemon: {result.stderr}")
         | 
| 123 | 
            +
                            except Exception as e:
         | 
| 124 | 
            +
                                print(f"❌ Error stopping daemon: {e}")
         | 
| 125 | 
            +
                        
         | 
| 126 | 
            +
                        # Fall back to parent implementation for non-daemon servers
         | 
| 127 | 
            +
                        return super().stop_server(port=port)
         | 
| 128 | 
            +
                    
         | 
| 129 | 
            +
                    def restart_server(self, port: int = None) -> bool:
         | 
| 130 | 
            +
                        """Restart Socket.IO server, handling daemon-style servers.
         | 
| 131 | 
            +
                        
         | 
| 132 | 
            +
                        WHY: The daemon server needs special handling for restarting.
         | 
| 133 | 
            +
                        """
         | 
| 134 | 
            +
                        # Check if daemon is running
         | 
| 135 | 
            +
                        if self.daemon_pidfile_path.exists():
         | 
| 136 | 
            +
                            try:
         | 
| 137 | 
            +
                                with open(self.daemon_pidfile_path) as f:
         | 
| 138 | 
            +
                                    pid = int(f.read().strip())
         | 
| 139 | 
            +
                                
         | 
| 140 | 
            +
                                print(f"🔄 Stopping daemon server (PID: {pid})...")
         | 
| 141 | 
            +
                                
         | 
| 142 | 
            +
                                # Stop the daemon
         | 
| 143 | 
            +
                                result = subprocess.run(
         | 
| 144 | 
            +
                                    [sys.executable, str(self.daemon_script), "stop"],
         | 
| 145 | 
            +
                                    capture_output=True,
         | 
| 146 | 
            +
                                    text=True
         | 
| 147 | 
            +
                                )
         | 
| 148 | 
            +
                                
         | 
| 149 | 
            +
                                if result.returncode == 0:
         | 
| 150 | 
            +
                                    print("✅ Daemon server stopped successfully")
         | 
| 151 | 
            +
                                    # Wait a moment for clean shutdown
         | 
| 152 | 
            +
                                    import time
         | 
| 153 | 
            +
                                    time.sleep(1)
         | 
| 154 | 
            +
                                    
         | 
| 155 | 
            +
                                    # Start it again
         | 
| 156 | 
            +
                                    return self.start_server(port=port)
         | 
| 157 | 
            +
                                else:
         | 
| 158 | 
            +
                                    print(f"❌ Failed to stop daemon: {result.stderr}")
         | 
| 159 | 
            +
                                    return False
         | 
| 160 | 
            +
                                    
         | 
| 161 | 
            +
                            except Exception as e:
         | 
| 162 | 
            +
                                print(f"❌ Error restarting daemon: {e}")
         | 
| 163 | 
            +
                                return False
         | 
| 164 | 
            +
                        else:
         | 
| 165 | 
            +
                            print("❌ No daemon server found (no PID file at {})".format(self.daemon_pidfile_path))
         | 
| 166 | 
            +
                            
         | 
| 167 | 
            +
                        # Fall back to parent implementation for non-daemon servers
         | 
| 168 | 
            +
                        return super().restart_server(port=port)
         | 
| 169 | 
            +
                
         | 
| 170 | 
            +
                # Re-export for use by CLI
         | 
| 171 | 
            +
                __all__ = ["ServerManager"]
         | 
| 172 | 
            +
                
         | 
| 173 | 
            +
            except ImportError as e:
         | 
| 174 | 
            +
                # Fallback: If tools/admin version not available, provide basic implementation
         | 
| 175 | 
            +
                # that delegates to socketio_daemon.py
         | 
| 176 | 
            +
                
         | 
| 177 | 
            +
                import subprocess
         | 
| 178 | 
            +
                import json
         | 
| 179 | 
            +
                import time
         | 
| 180 | 
            +
                from typing import Dict, List, Optional, Any
         | 
| 181 | 
            +
                
         | 
| 182 | 
            +
                class ServerManager:
         | 
| 183 | 
            +
                    """Fallback ServerManager that uses socketio_daemon.py.
         | 
| 184 | 
            +
                    
         | 
| 185 | 
            +
                    WHY: This fallback ensures the monitor CLI command works even if
         | 
| 186 | 
            +
                    the full ServerManager from tools/admin is not available. It provides
         | 
| 187 | 
            +
                    basic functionality by delegating to the socketio_daemon.py script.
         | 
| 188 | 
            +
                    """
         | 
| 189 | 
            +
                    
         | 
| 190 | 
            +
                    def __init__(self):
         | 
| 191 | 
            +
                        self.daemon_script = script_dir / "socketio_daemon.py"
         | 
| 192 | 
            +
                        self.base_port = 8765
         | 
| 193 | 
            +
                        
         | 
| 194 | 
            +
                    def start_server(self, port: int = None, host: str = "localhost", 
         | 
| 195 | 
            +
                                    server_id: str = None) -> bool:
         | 
| 196 | 
            +
                        """Start the Socket.IO server using daemon script.
         | 
| 197 | 
            +
                        
         | 
| 198 | 
            +
                        WHY: The daemon script handles port selection and process management,
         | 
| 199 | 
            +
                        so we delegate to it for starting servers.
         | 
| 200 | 
            +
                        """
         | 
| 201 | 
            +
                        if port and port != self.base_port:
         | 
| 202 | 
            +
                            print(f"Note: Daemon only supports default port {self.base_port}")
         | 
| 203 | 
            +
                            print(f"Starting on port {self.base_port} instead...")
         | 
| 204 | 
            +
                        
         | 
| 205 | 
            +
                        try:
         | 
| 206 | 
            +
                            result = subprocess.run(
         | 
| 207 | 
            +
                                [sys.executable, str(self.daemon_script), "start"],
         | 
| 208 | 
            +
                                capture_output=True,
         | 
| 209 | 
            +
                                text=True
         | 
| 210 | 
            +
                            )
         | 
| 211 | 
            +
                            
         | 
| 212 | 
            +
                            if result.returncode == 0:
         | 
| 213 | 
            +
                                print("Socket.IO server started successfully")
         | 
| 214 | 
            +
                                return True
         | 
| 215 | 
            +
                            else:
         | 
| 216 | 
            +
                                print(f"Failed to start server: {result.stderr}")
         | 
| 217 | 
            +
                                return False
         | 
| 218 | 
            +
                                
         | 
| 219 | 
            +
                        except Exception as e:
         | 
| 220 | 
            +
                            print(f"Error starting server: {e}")
         | 
| 221 | 
            +
                            return False
         | 
| 222 | 
            +
                    
         | 
| 223 | 
            +
                    def stop_server(self, port: int = None) -> bool:
         | 
| 224 | 
            +
                        """Stop the Socket.IO server using daemon script."""
         | 
| 225 | 
            +
                        if port and port != self.base_port:
         | 
| 226 | 
            +
                            print(f"Note: Daemon only supports default port {self.base_port}")
         | 
| 227 | 
            +
                        
         | 
| 228 | 
            +
                        try:
         | 
| 229 | 
            +
                            result = subprocess.run(
         | 
| 230 | 
            +
                                [sys.executable, str(self.daemon_script), "stop"],
         | 
| 231 | 
            +
                                capture_output=True,
         | 
| 232 | 
            +
                                text=True
         | 
| 233 | 
            +
                            )
         | 
| 234 | 
            +
                            
         | 
| 235 | 
            +
                            if result.returncode == 0:
         | 
| 236 | 
            +
                                print("Socket.IO server stopped successfully")
         | 
| 237 | 
            +
                                return True
         | 
| 238 | 
            +
                            else:
         | 
| 239 | 
            +
                                print(f"Failed to stop server: {result.stderr}")
         | 
| 240 | 
            +
                                return False
         | 
| 241 | 
            +
                                
         | 
| 242 | 
            +
                        except Exception as e:
         | 
| 243 | 
            +
                            print(f"Error stopping server: {e}")
         | 
| 244 | 
            +
                            return False
         | 
| 245 | 
            +
                    
         | 
| 246 | 
            +
                    def restart_server(self, port: int = None) -> bool:
         | 
| 247 | 
            +
                        """Restart the Socket.IO server using daemon script."""
         | 
| 248 | 
            +
                        if port and port != self.base_port:
         | 
| 249 | 
            +
                            print(f"Note: Daemon only supports default port {self.base_port}")
         | 
| 250 | 
            +
                        
         | 
| 251 | 
            +
                        try:
         | 
| 252 | 
            +
                            result = subprocess.run(
         | 
| 253 | 
            +
                                [sys.executable, str(self.daemon_script), "restart"],
         | 
| 254 | 
            +
                                capture_output=True,
         | 
| 255 | 
            +
                                text=True
         | 
| 256 | 
            +
                            )
         | 
| 257 | 
            +
                            
         | 
| 258 | 
            +
                            if result.returncode == 0:
         | 
| 259 | 
            +
                                print("Socket.IO server restarted successfully")
         | 
| 260 | 
            +
                                return True
         | 
| 261 | 
            +
                            else:
         | 
| 262 | 
            +
                                print(f"Failed to restart server: {result.stderr}")
         | 
| 263 | 
            +
                                return False
         | 
| 264 | 
            +
                                
         | 
| 265 | 
            +
                        except Exception as e:
         | 
| 266 | 
            +
                            print(f"Error restarting server: {e}")
         | 
| 267 | 
            +
                            return False
         | 
| 268 | 
            +
                    
         | 
| 269 | 
            +
                    def list_running_servers(self) -> List[Dict[str, Any]]:
         | 
| 270 | 
            +
                        """List running servers using daemon script status."""
         | 
| 271 | 
            +
                        try:
         | 
| 272 | 
            +
                            result = subprocess.run(
         | 
| 273 | 
            +
                                [sys.executable, str(self.daemon_script), "status"],
         | 
| 274 | 
            +
                                capture_output=True,
         | 
| 275 | 
            +
                                text=True
         | 
| 276 | 
            +
                            )
         | 
| 277 | 
            +
                            
         | 
| 278 | 
            +
                            # Parse status output to determine if server is running
         | 
| 279 | 
            +
                            if "is running" in result.stdout:
         | 
| 280 | 
            +
                                # Extract port from output if possible
         | 
| 281 | 
            +
                                port = self.base_port
         | 
| 282 | 
            +
                                for line in result.stdout.split('\n'):
         | 
| 283 | 
            +
                                    if "port" in line.lower():
         | 
| 284 | 
            +
                                        try:
         | 
| 285 | 
            +
                                            # Try to extract port number
         | 
| 286 | 
            +
                                            import re
         | 
| 287 | 
            +
                                            match = re.search(r'port\s+(\d+)', line.lower())
         | 
| 288 | 
            +
                                            if match:
         | 
| 289 | 
            +
                                                port = int(match.group(1))
         | 
| 290 | 
            +
                                        except:
         | 
| 291 | 
            +
                                            pass
         | 
| 292 | 
            +
                                
         | 
| 293 | 
            +
                                return [{
         | 
| 294 | 
            +
                                    "port": port,
         | 
| 295 | 
            +
                                    "server_id": "daemon-socketio",
         | 
| 296 | 
            +
                                    "status": "running"
         | 
| 297 | 
            +
                                }]
         | 
| 298 | 
            +
                            else:
         | 
| 299 | 
            +
                                return []
         | 
| 300 | 
            +
                                
         | 
| 301 | 
            +
                        except Exception as e:
         | 
| 302 | 
            +
                            print(f"Error checking server status: {e}")
         | 
| 303 | 
            +
                            return []
         | 
| 304 | 
            +
                    
         | 
| 305 | 
            +
                    def get_server_info(self, port: int) -> Optional[Dict[str, Any]]:
         | 
| 306 | 
            +
                        """Get information about a server on a specific port."""
         | 
| 307 | 
            +
                        servers = self.list_running_servers()
         | 
| 308 | 
            +
                        for server in servers:
         | 
| 309 | 
            +
                            if server.get("port") == port:
         | 
| 310 | 
            +
                                return server
         | 
| 311 | 
            +
                        return None
         | 
| 312 | 
            +
             | 
| 313 | 
            +
             | 
| 314 | 
            +
            # If running as a script, delegate to the actual socketio_server_manager.py
         | 
| 315 | 
            +
            if __name__ == "__main__":
         | 
| 316 | 
            +
                try:
         | 
| 317 | 
            +
                    # Try to run the actual script from tools/admin
         | 
| 318 | 
            +
                    import subprocess
         | 
| 319 | 
            +
                    tools_script = tools_admin_dir / "socketio_server_manager.py"
         | 
| 320 | 
            +
                    if tools_script.exists():
         | 
| 321 | 
            +
                        subprocess.run([sys.executable, str(tools_script)] + sys.argv[1:])
         | 
| 322 | 
            +
                    else:
         | 
| 323 | 
            +
                        print("Socket.IO server manager not found in tools/admin")
         | 
| 324 | 
            +
                        print("Please ensure claude-mpm is properly installed")
         | 
| 325 | 
            +
                        sys.exit(1)
         | 
| 326 | 
            +
                except Exception as e:
         | 
| 327 | 
            +
                    print(f"Error running server manager: {e}")
         | 
| 328 | 
            +
                    sys.exit(1)
         | 
| @@ -6,18 +6,18 @@ This script starts the event aggregator that captures all agent activity | |
| 6 6 | 
             
            from the Socket.IO dashboard and saves it to .claude-mpm/activity/
         | 
| 7 7 | 
             
            """
         | 
| 8 8 |  | 
| 9 | 
            +
            import signal
         | 
| 9 10 | 
             
            import sys
         | 
| 10 11 | 
             
            import time
         | 
| 11 | 
            -
            import signal
         | 
| 12 | 
            -
            from pathlib import Path
         | 
| 13 12 |  | 
| 14 13 | 
             
            # Since we're now inside the claude_mpm package, use relative imports
         | 
| 15 14 | 
             
            from ..core.config import Config
         | 
| 16 | 
            -
            from ..services.event_aggregator import EventAggregator
         | 
| 17 15 | 
             
            from ..core.logger import get_logger
         | 
| 16 | 
            +
            from ..services.event_aggregator import EventAggregator
         | 
| 18 17 |  | 
| 19 18 | 
             
            logger = get_logger("activity_logging")
         | 
| 20 19 |  | 
| 20 | 
            +
             | 
| 21 21 | 
             
            def signal_handler(signum, frame):
         | 
| 22 22 | 
             
                """Handle shutdown signals gracefully."""
         | 
| 23 23 | 
             
                logger.info("Shutting down activity logging...")
         | 
| @@ -25,55 +25,58 @@ def signal_handler(signum, frame): | |
| 25 25 | 
             
                    aggregator.stop()
         | 
| 26 26 | 
             
                sys.exit(0)
         | 
| 27 27 |  | 
| 28 | 
            +
             | 
| 28 29 | 
             
            if __name__ == "__main__":
         | 
| 29 30 | 
             
                # Load configuration
         | 
| 30 31 | 
             
                config = Config()
         | 
| 31 | 
            -
             | 
| 32 | 
            +
             | 
| 32 33 | 
             
                # Check if event aggregator is enabled
         | 
| 33 | 
            -
                if not config.get( | 
| 34 | 
            +
                if not config.get("event_aggregator.enabled", True):
         | 
| 34 35 | 
             
                    logger.warning("Event aggregator is disabled in configuration")
         | 
| 35 36 | 
             
                    logger.warning("Enable it by setting event_aggregator.enabled: true")
         | 
| 36 37 | 
             
                    sys.exit(1)
         | 
| 37 | 
            -
             | 
| 38 | 
            +
             | 
| 38 39 | 
             
                # Get configuration values
         | 
| 39 | 
            -
                activity_dir = config.get( | 
| 40 | 
            -
             | 
| 41 | 
            -
                
         | 
| 40 | 
            +
                activity_dir = config.get(
         | 
| 41 | 
            +
                    "event_aggregator.activity_directory", ".claude-mpm/activity"
         | 
| 42 | 
            +
                )
         | 
| 43 | 
            +
                dashboard_port = config.get("event_aggregator.dashboard_port", 8765)
         | 
| 44 | 
            +
             | 
| 42 45 | 
             
                logger.info("=" * 60)
         | 
| 43 46 | 
             
                logger.info("Starting Activity Logging Service")
         | 
| 44 47 | 
             
                logger.info("=" * 60)
         | 
| 45 48 | 
             
                logger.info(f"Activity Directory: {activity_dir}")
         | 
| 46 49 | 
             
                logger.info(f"Dashboard Port: {dashboard_port}")
         | 
| 47 50 | 
             
                logger.info("Connecting to Socket.IO dashboard...")
         | 
| 48 | 
            -
             | 
| 51 | 
            +
             | 
| 49 52 | 
             
                # Initialize aggregator
         | 
| 50 53 | 
             
                aggregator = EventAggregator(
         | 
| 51 | 
            -
                    host="localhost",
         | 
| 52 | 
            -
                    port=dashboard_port,
         | 
| 53 | 
            -
                    save_dir=None  # Will use config value
         | 
| 54 | 
            +
                    host="localhost", port=dashboard_port, save_dir=None  # Will use config value
         | 
| 54 55 | 
             
                )
         | 
| 55 | 
            -
             | 
| 56 | 
            +
             | 
| 56 57 | 
             
                # Set up signal handlers
         | 
| 57 58 | 
             
                signal.signal(signal.SIGINT, signal_handler)
         | 
| 58 59 | 
             
                signal.signal(signal.SIGTERM, signal_handler)
         | 
| 59 | 
            -
             | 
| 60 | 
            +
             | 
| 60 61 | 
             
                # Start the aggregator
         | 
| 61 62 | 
             
                try:
         | 
| 62 63 | 
             
                    aggregator.start()
         | 
| 63 64 | 
             
                    logger.info("✅ Activity logging started successfully!")
         | 
| 64 65 | 
             
                    logger.info(f"📁 Saving activity to: {aggregator.save_dir}")
         | 
| 65 66 | 
             
                    logger.info("Press Ctrl+C to stop")
         | 
| 66 | 
            -
             | 
| 67 | 
            +
             | 
| 67 68 | 
             
                    # Keep running and show periodic status
         | 
| 68 69 | 
             
                    while aggregator.running:
         | 
| 69 70 | 
             
                        time.sleep(30)
         | 
| 70 | 
            -
             | 
| 71 | 
            +
             | 
| 71 72 | 
             
                        # Show status every 30 seconds
         | 
| 72 73 | 
             
                        status = aggregator.get_status()
         | 
| 73 | 
            -
                        if status[ | 
| 74 | 
            -
                            logger.info( | 
| 75 | 
            -
             | 
| 76 | 
            -
             | 
| 74 | 
            +
                        if status["active_sessions"] > 0:
         | 
| 75 | 
            +
                            logger.info(
         | 
| 76 | 
            +
                                f"📊 Status: {status['active_sessions']} active sessions, "
         | 
| 77 | 
            +
                                f"{status['total_events']} events captured"
         | 
| 78 | 
            +
                            )
         | 
| 79 | 
            +
             | 
| 77 80 | 
             
                except KeyboardInterrupt:
         | 
| 78 81 | 
             
                    logger.info("Received shutdown signal")
         | 
| 79 82 | 
             
                except Exception as e:
         | 
| @@ -83,4 +86,4 @@ if __name__ == "__main__": | |
| 83 86 | 
             
                        aggregator.stop()
         | 
| 84 87 | 
             
                        # Save any remaining sessions
         | 
| 85 88 | 
             
                        aggregator._save_all_sessions()
         | 
| 86 | 
            -
                        logger.info("Activity logging stopped")
         | 
| 89 | 
            +
                        logger.info("Activity logging stopped")
         | 
    
        claude_mpm/services/__init__.py
    CHANGED
    
    | @@ -11,156 +11,181 @@ New structure: | |
| 11 11 | 
             
            - infrastructure/: Logging and monitoring services
         | 
| 12 12 | 
             
            """
         | 
| 13 13 |  | 
| 14 | 
            +
             | 
| 14 15 | 
             
            # Use lazy imports to prevent circular dependency issues
         | 
| 15 16 | 
             
            def __getattr__(name):
         | 
| 16 17 | 
             
                """Lazy import to prevent circular dependencies."""
         | 
| 17 18 | 
             
                if name == "TicketManager":
         | 
| 18 19 | 
             
                    from .ticket_manager import TicketManager
         | 
| 20 | 
            +
             | 
| 19 21 | 
             
                    return TicketManager
         | 
| 20 22 | 
             
                elif name == "AgentDeploymentService":
         | 
| 21 | 
            -
                    #  | 
| 22 | 
            -
                     | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
                    except ImportError:
         | 
| 26 | 
            -
                        from .agents.deployment import AgentDeploymentService
         | 
| 27 | 
            -
                        return AgentDeploymentService
         | 
| 23 | 
            +
                    # Use correct path
         | 
| 24 | 
            +
                    from .agents.deployment import AgentDeploymentService
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    return AgentDeploymentService
         | 
| 28 27 | 
             
                elif name == "AgentMemoryManager":
         | 
| 29 28 | 
             
                    from .agents.memory import AgentMemoryManager
         | 
| 29 | 
            +
             | 
| 30 30 | 
             
                    return AgentMemoryManager
         | 
| 31 31 | 
             
                elif name == "get_memory_manager":
         | 
| 32 32 | 
             
                    from .agents.memory import get_memory_manager
         | 
| 33 | 
            +
             | 
| 33 34 | 
             
                    return get_memory_manager
         | 
| 34 35 | 
             
                # Add backward compatibility for other agent services
         | 
| 35 36 | 
             
                elif name == "AgentRegistry":
         | 
| 36 | 
            -
                    #  | 
| 37 | 
            -
                     | 
| 38 | 
            -
             | 
| 39 | 
            -
             | 
| 40 | 
            -
                    except ImportError:
         | 
| 41 | 
            -
                        from .agents.registry import AgentRegistry
         | 
| 42 | 
            -
                        return AgentRegistry
         | 
| 37 | 
            +
                    # Use correct path
         | 
| 38 | 
            +
                    from .agents.registry import AgentRegistry
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                    return AgentRegistry
         | 
| 43 41 | 
             
                elif name == "AgentLifecycleManager":
         | 
| 44 42 | 
             
                    from .agents.deployment import AgentLifecycleManager
         | 
| 43 | 
            +
             | 
| 45 44 | 
             
                    return AgentLifecycleManager
         | 
| 46 45 | 
             
                elif name == "AgentManager":
         | 
| 47 46 | 
             
                    from .agents.management import AgentManager
         | 
| 47 | 
            +
             | 
| 48 48 | 
             
                    return AgentManager
         | 
| 49 49 | 
             
                elif name == "AgentCapabilitiesGenerator":
         | 
| 50 50 | 
             
                    from .agents.management import AgentCapabilitiesGenerator
         | 
| 51 | 
            +
             | 
| 51 52 | 
             
                    return AgentCapabilitiesGenerator
         | 
| 52 53 | 
             
                elif name == "AgentModificationTracker":
         | 
| 53 54 | 
             
                    from .agents.registry import AgentModificationTracker
         | 
| 55 | 
            +
             | 
| 54 56 | 
             
                    return AgentModificationTracker
         | 
| 55 57 | 
             
                elif name == "AgentPersistenceService":
         | 
| 56 58 | 
             
                    from .agents.memory import AgentPersistenceService
         | 
| 59 | 
            +
             | 
| 57 60 | 
             
                    return AgentPersistenceService
         | 
| 58 61 | 
             
                elif name == "AgentProfileLoader":
         | 
| 59 62 | 
             
                    from .agents.loading import AgentProfileLoader
         | 
| 63 | 
            +
             | 
| 60 64 | 
             
                    return AgentProfileLoader
         | 
| 61 65 | 
             
                elif name == "AgentVersionManager":
         | 
| 62 66 | 
             
                    from .agents.deployment import AgentVersionManager
         | 
| 67 | 
            +
             | 
| 63 68 | 
             
                    return AgentVersionManager
         | 
| 64 69 | 
             
                elif name == "BaseAgentManager":
         | 
| 65 70 | 
             
                    from .agents.loading import BaseAgentManager
         | 
| 71 | 
            +
             | 
| 66 72 | 
             
                    return BaseAgentManager
         | 
| 67 73 | 
             
                elif name == "DeployedAgentDiscovery":
         | 
| 68 74 | 
             
                    from .agents.registry import DeployedAgentDiscovery
         | 
| 75 | 
            +
             | 
| 69 76 | 
             
                    return DeployedAgentDiscovery
         | 
| 70 77 | 
             
                elif name == "FrameworkAgentLoader":
         | 
| 71 78 | 
             
                    from .agents.loading import FrameworkAgentLoader
         | 
| 79 | 
            +
             | 
| 72 80 | 
             
                    return FrameworkAgentLoader
         | 
| 73 81 | 
             
                elif name == "HookService":
         | 
| 74 82 | 
             
                    from .hook_service import HookService
         | 
| 83 | 
            +
             | 
| 75 84 | 
             
                    return HookService
         | 
| 76 85 | 
             
                elif name == "ProjectAnalyzer":
         | 
| 77 | 
            -
                     | 
| 78 | 
            -
             | 
| 79 | 
            -
             | 
| 80 | 
            -
             | 
| 81 | 
            -
                     | 
| 82 | 
            -
             | 
| 83 | 
            -
             | 
| 84 | 
            -
                elif name == " | 
| 85 | 
            -
                     | 
| 86 | 
            -
             | 
| 87 | 
            -
             | 
| 88 | 
            -
             | 
| 89 | 
            -
             | 
| 90 | 
            -
                            from .health_monitor import AdvancedHealthMonitor
         | 
| 91 | 
            -
                            return AdvancedHealthMonitor
         | 
| 92 | 
            -
                        except ImportError:
         | 
| 93 | 
            -
                            raise AttributeError(f"Health monitoring not available: {name}")
         | 
| 86 | 
            +
                    from .project.analyzer import ProjectAnalyzer
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                    return ProjectAnalyzer
         | 
| 89 | 
            +
                elif name == "AdvancedHealthMonitor":
         | 
| 90 | 
            +
                    from .infrastructure.monitoring import AdvancedHealthMonitor
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                    return AdvancedHealthMonitor
         | 
| 93 | 
            +
                elif name == "HealthMonitor":
         | 
| 94 | 
            +
                    # For backward compatibility, return AdvancedHealthMonitor
         | 
| 95 | 
            +
                    # Note: There's also a different HealthMonitor in infrastructure.health_monitor
         | 
| 96 | 
            +
                    from .infrastructure.monitoring import AdvancedHealthMonitor
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                    return AdvancedHealthMonitor
         | 
| 94 99 | 
             
                elif name == "RecoveryManager":
         | 
| 95 100 | 
             
                    try:
         | 
| 96 101 | 
             
                        from .recovery_manager import RecoveryManager
         | 
| 102 | 
            +
             | 
| 97 103 | 
             
                        return RecoveryManager
         | 
| 98 104 | 
             
                    except ImportError:
         | 
| 99 105 | 
             
                        raise AttributeError(f"Recovery management not available: {name}")
         | 
| 100 106 | 
             
                elif name == "StandaloneSocketIOServer" or name == "SocketIOServer":
         | 
| 101 | 
            -
                     | 
| 102 | 
            -
             | 
| 103 | 
            -
             | 
| 104 | 
            -
                    except ImportError:
         | 
| 105 | 
            -
                        from .standalone_socketio_server import StandaloneSocketIOServer
         | 
| 106 | 
            -
                        return StandaloneSocketIOServer
         | 
| 107 | 
            +
                    from .socketio_server import SocketIOServer
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                    return SocketIOServer
         | 
| 107 110 | 
             
                # Backward compatibility for memory services
         | 
| 108 111 | 
             
                elif name == "MemoryBuilder":
         | 
| 109 112 | 
             
                    from .memory.builder import MemoryBuilder
         | 
| 113 | 
            +
             | 
| 110 114 | 
             
                    return MemoryBuilder
         | 
| 111 115 | 
             
                elif name == "MemoryRouter":
         | 
| 112 116 | 
             
                    from .memory.router import MemoryRouter
         | 
| 117 | 
            +
             | 
| 113 118 | 
             
                    return MemoryRouter
         | 
| 114 119 | 
             
                elif name == "MemoryOptimizer":
         | 
| 115 120 | 
             
                    from .memory.optimizer import MemoryOptimizer
         | 
| 121 | 
            +
             | 
| 116 122 | 
             
                    return MemoryOptimizer
         | 
| 117 123 | 
             
                elif name == "SimpleCacheService":
         | 
| 118 124 | 
             
                    from .memory.cache.simple_cache import SimpleCacheService
         | 
| 125 | 
            +
             | 
| 119 126 | 
             
                    return SimpleCacheService
         | 
| 120 127 | 
             
                elif name == "SharedPromptCache":
         | 
| 121 128 | 
             
                    from .memory.cache.shared_prompt_cache import SharedPromptCache
         | 
| 129 | 
            +
             | 
| 122 130 | 
             
                    return SharedPromptCache
         | 
| 123 131 | 
             
                # New service organization imports
         | 
| 124 132 | 
             
                elif name == "AgentManagementService":
         | 
| 125 | 
            -
                    from . | 
| 126 | 
            -
             | 
| 133 | 
            +
                    from .agents.management import AgentManager
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    return AgentManager
         | 
| 127 136 | 
             
                elif name == "ProjectRegistry":
         | 
| 128 137 | 
             
                    from .project.registry import ProjectRegistry
         | 
| 138 | 
            +
             | 
| 129 139 | 
             
                    return ProjectRegistry
         | 
| 130 140 | 
             
                elif name == "LoggingService":
         | 
| 131 141 | 
             
                    from .infrastructure.logging import LoggingService
         | 
| 142 | 
            +
             | 
| 132 143 | 
             
                    return LoggingService
         | 
| 133 144 | 
             
                elif name == "SocketIOClientManager":
         | 
| 134 | 
            -
                    from . | 
| 145 | 
            +
                    from .socketio_client_manager import SocketIOClientManager
         | 
| 146 | 
            +
             | 
| 135 147 | 
             
                    return SocketIOClientManager
         | 
| 136 148 | 
             
                # MCP Gateway services
         | 
| 137 149 | 
             
                elif name == "MCPConfiguration":
         | 
| 138 150 | 
             
                    from .mcp_gateway.config.configuration import MCPConfiguration
         | 
| 151 | 
            +
             | 
| 139 152 | 
             
                    return MCPConfiguration
         | 
| 140 153 | 
             
                elif name == "MCPConfigLoader":
         | 
| 141 154 | 
             
                    from .mcp_gateway.config.config_loader import MCPConfigLoader
         | 
| 155 | 
            +
             | 
| 142 156 | 
             
                    return MCPConfigLoader
         | 
| 143 157 | 
             
                elif name == "MCPServer":
         | 
| 144 158 | 
             
                    from .mcp_gateway.server.mcp_server import MCPServer
         | 
| 159 | 
            +
             | 
| 145 160 | 
             
                    return MCPServer
         | 
| 146 161 | 
             
                elif name == "MCPToolRegistry":
         | 
| 147 162 | 
             
                    from .mcp_gateway.tools.tool_registry import MCPToolRegistry
         | 
| 163 | 
            +
             | 
| 148 164 | 
             
                    return MCPToolRegistry
         | 
| 149 165 | 
             
                elif name == "BaseMCPService":
         | 
| 150 166 | 
             
                    from .mcp_gateway.core.base import BaseMCPService
         | 
| 167 | 
            +
             | 
| 151 168 | 
             
                    return BaseMCPService
         | 
| 152 169 | 
             
                elif name.startswith("IMCP"):
         | 
| 153 170 | 
             
                    from .mcp_gateway.core import interfaces
         | 
| 171 | 
            +
             | 
| 154 172 | 
             
                    return getattr(interfaces, name)
         | 
| 155 173 | 
             
                elif name.startswith("MCP") and "Error" in name:
         | 
| 156 174 | 
             
                    from .mcp_gateway.core import exceptions
         | 
| 175 | 
            +
             | 
| 157 176 | 
             
                    return getattr(exceptions, name)
         | 
| 158 177 | 
             
                # Core interfaces and base classes
         | 
| 159 | 
            -
                elif name.startswith( | 
| 178 | 
            +
                elif name.startswith("I") or name in [
         | 
| 179 | 
            +
                    "BaseService",
         | 
| 180 | 
            +
                    "SyncBaseService",
         | 
| 181 | 
            +
                    "SingletonService",
         | 
| 182 | 
            +
                ]:
         | 
| 160 183 | 
             
                    from . import core
         | 
| 184 | 
            +
             | 
| 161 185 | 
             
                    return getattr(core, name)
         | 
| 162 186 | 
             
                raise AttributeError(f"module '{__name__}' has no attribute '{name}'")
         | 
| 163 187 |  | 
| 188 | 
            +
             | 
| 164 189 | 
             
            __all__ = [
         | 
| 165 190 | 
             
                "TicketManager",
         | 
| 166 191 | 
             
                "AgentDeploymentService",
         | 
| @@ -170,7 +195,7 @@ __all__ = [ | |
| 170 195 | 
             
                "ProjectAnalyzer",
         | 
| 171 196 | 
             
                "AdvancedHealthMonitor",
         | 
| 172 197 | 
             
                "HealthMonitor",  # New alias
         | 
| 173 | 
            -
                "RecoveryManager", | 
| 198 | 
            +
                "RecoveryManager",
         | 
| 174 199 | 
             
                "StandaloneSocketIOServer",
         | 
| 175 200 | 
             
                "SocketIOServer",  # New alias
         | 
| 176 201 | 
             
                # Additional agent services for backward compatibility
         | 
| @@ -208,4 +233,4 @@ __all__ = [ | |
| 208 233 | 
             
                "BaseService",
         | 
| 209 234 | 
             
                "SyncBaseService",
         | 
| 210 235 | 
             
                "SingletonService",
         | 
| 211 | 
            -
            ]
         | 
| 236 | 
            +
            ]
         |