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
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            from pathlib import Path
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            """
         | 
| 2 4 | 
             
            Configuration alias management for Claude PM Framework.
         | 
| 3 5 |  | 
| @@ -14,67 +16,72 @@ Aliases are stored in ~/.claude-mpm/config_aliases.json | |
| 14 16 | 
             
            import json
         | 
| 15 17 | 
             
            import logging
         | 
| 16 18 | 
             
            import os
         | 
| 17 | 
            -
            from  | 
| 18 | 
            -
            from typing import Dict, Optional, List, Tuple
         | 
| 19 | 
            +
            from typing import Dict, List, Optional, Tuple
         | 
| 19 20 |  | 
| 20 21 | 
             
            from ..utils.config_manager import ConfigurationManager
         | 
| 21 | 
            -
            from . | 
| 22 | 
            +
            from .unified_paths import get_path_manager
         | 
| 22 23 |  | 
| 23 24 | 
             
            logger = logging.getLogger(__name__)
         | 
| 24 25 |  | 
| 25 26 |  | 
| 26 27 | 
             
            class ConfigAliasError(Exception):
         | 
| 27 28 | 
             
                """Base exception for configuration alias errors."""
         | 
| 29 | 
            +
             | 
| 28 30 | 
             
                pass
         | 
| 29 31 |  | 
| 30 32 |  | 
| 31 33 | 
             
            class AliasNotFoundError(ConfigAliasError):
         | 
| 32 34 | 
             
                """Raised when attempting to resolve a non-existent alias."""
         | 
| 35 | 
            +
             | 
| 33 36 | 
             
                pass
         | 
| 34 37 |  | 
| 35 38 |  | 
| 36 39 | 
             
            class DuplicateAliasError(ConfigAliasError):
         | 
| 37 40 | 
             
                """Raised when attempting to create an alias that already exists."""
         | 
| 41 | 
            +
             | 
| 38 42 | 
             
                pass
         | 
| 39 43 |  | 
| 40 44 |  | 
| 41 45 | 
             
            class InvalidDirectoryError(ConfigAliasError):
         | 
| 42 46 | 
             
                """Raised when a directory path is invalid or cannot be created."""
         | 
| 47 | 
            +
             | 
| 43 48 | 
             
                pass
         | 
| 44 49 |  | 
| 45 50 |  | 
| 46 51 | 
             
            class ConfigAliasManager:
         | 
| 47 52 | 
             
                """
         | 
| 48 53 | 
             
                Manages configuration directory aliases for the Claude PM Framework.
         | 
| 49 | 
            -
             | 
| 54 | 
            +
             | 
| 50 55 | 
             
                Provides methods to create, delete, list, and resolve aliases that map
         | 
| 51 56 | 
             
                friendly names to actual directory paths.
         | 
| 52 57 | 
             
                """
         | 
| 53 | 
            -
             | 
| 58 | 
            +
             | 
| 54 59 | 
             
                def __init__(self, aliases_file: Optional[Path] = None):
         | 
| 55 60 | 
             
                    """
         | 
| 56 61 | 
             
                    Initialize the configuration alias manager.
         | 
| 57 | 
            -
             | 
| 62 | 
            +
             | 
| 58 63 | 
             
                    Args:
         | 
| 59 64 | 
             
                        aliases_file: Path to the aliases JSON file. Defaults to
         | 
| 60 65 | 
             
                                     ~/.claude-pm/config_aliases.json
         | 
| 61 66 | 
             
                    """
         | 
| 62 67 | 
             
                    if aliases_file is None:
         | 
| 63 | 
            -
                        self.aliases_file =  | 
| 68 | 
            +
                        self.aliases_file = (
         | 
| 69 | 
            +
                            get_path_manager().get_user_config_dir() / "config_aliases.json"
         | 
| 70 | 
            +
                        )
         | 
| 64 71 | 
             
                    else:
         | 
| 65 72 | 
             
                        self.aliases_file = Path(aliases_file)
         | 
| 66 | 
            -
             | 
| 73 | 
            +
             | 
| 67 74 | 
             
                    self.config_mgr = ConfigurationManager(cache_enabled=True)
         | 
| 68 75 | 
             
                    self._ensure_aliases_file()
         | 
| 69 76 | 
             
                    self._aliases: Dict[str, str] = self._load_aliases()
         | 
| 70 | 
            -
             | 
| 77 | 
            +
             | 
| 71 78 | 
             
                def _ensure_aliases_file(self) -> None:
         | 
| 72 79 | 
             
                    """Ensure the aliases file and its parent directory exist."""
         | 
| 73 80 | 
             
                    self.aliases_file.parent.mkdir(parents=True, exist_ok=True)
         | 
| 74 81 | 
             
                    if not self.aliases_file.exists():
         | 
| 75 82 | 
             
                        self._save_aliases({})
         | 
| 76 83 | 
             
                        logger.info(f"Created new aliases file at {self.aliases_file}")
         | 
| 77 | 
            -
             | 
| 84 | 
            +
             | 
| 78 85 | 
             
                def _load_aliases(self) -> Dict[str, str]:
         | 
| 79 86 | 
             
                    """Load aliases from the JSON file."""
         | 
| 80 87 | 
             
                    try:
         | 
| @@ -82,7 +89,7 @@ class ConfigAliasManager: | |
| 82 89 | 
             
                    except (json.JSONDecodeError, Exception) as e:
         | 
| 83 90 | 
             
                        logger.error(f"Failed to load aliases: {e}")
         | 
| 84 91 | 
             
                        return {}
         | 
| 85 | 
            -
             | 
| 92 | 
            +
             | 
| 86 93 | 
             
                def _save_aliases(self, aliases: Dict[str, str]) -> None:
         | 
| 87 94 | 
             
                    """Save aliases to the JSON file."""
         | 
| 88 95 | 
             
                    try:
         | 
| @@ -90,15 +97,15 @@ class ConfigAliasManager: | |
| 90 97 | 
             
                    except Exception as e:
         | 
| 91 98 | 
             
                        logger.error(f"Failed to save aliases: {e}")
         | 
| 92 99 | 
             
                        raise ConfigAliasError(f"Failed to save aliases: {e}")
         | 
| 93 | 
            -
             | 
| 100 | 
            +
             | 
| 94 101 | 
             
                def create_alias(self, alias_name: str, directory_path: str) -> None:
         | 
| 95 102 | 
             
                    """
         | 
| 96 103 | 
             
                    Create a new configuration alias.
         | 
| 97 | 
            -
             | 
| 104 | 
            +
             | 
| 98 105 | 
             
                    Args:
         | 
| 99 106 | 
             
                        alias_name: The friendly name for the alias
         | 
| 100 107 | 
             
                        directory_path: The directory path this alias should resolve to
         | 
| 101 | 
            -
             | 
| 108 | 
            +
             | 
| 102 109 | 
             
                    Raises:
         | 
| 103 110 | 
             
                        DuplicateAliasError: If the alias already exists
         | 
| 104 111 | 
             
                        InvalidDirectoryError: If the directory path is invalid
         | 
| @@ -106,103 +113,104 @@ class ConfigAliasManager: | |
| 106 113 | 
             
                    # Validate alias name
         | 
| 107 114 | 
             
                    if not alias_name or not alias_name.strip():
         | 
| 108 115 | 
             
                        raise ValueError("Alias name cannot be empty")
         | 
| 109 | 
            -
             | 
| 116 | 
            +
             | 
| 110 117 | 
             
                    alias_name = alias_name.strip()
         | 
| 111 | 
            -
             | 
| 118 | 
            +
             | 
| 112 119 | 
             
                    # Check for duplicate
         | 
| 113 120 | 
             
                    if alias_name in self._aliases:
         | 
| 114 121 | 
             
                        raise DuplicateAliasError(
         | 
| 115 122 | 
             
                            f"Alias '{alias_name}' already exists, pointing to: {self._aliases[alias_name]}"
         | 
| 116 123 | 
             
                        )
         | 
| 117 | 
            -
             | 
| 124 | 
            +
             | 
| 118 125 | 
             
                    # Validate and normalize the directory path
         | 
| 119 126 | 
             
                    validated_path = self.validate_directory(directory_path)
         | 
| 120 | 
            -
             | 
| 127 | 
            +
             | 
| 121 128 | 
             
                    # Add the alias
         | 
| 122 129 | 
             
                    self._aliases[alias_name] = str(validated_path)
         | 
| 123 130 | 
             
                    self._save_aliases(self._aliases)
         | 
| 124 | 
            -
             | 
| 131 | 
            +
             | 
| 125 132 | 
             
                    logger.info(f"Created alias '{alias_name}' -> {validated_path}")
         | 
| 126 | 
            -
             | 
| 133 | 
            +
             | 
| 127 134 | 
             
                def resolve_alias(self, alias_name: str) -> Path:
         | 
| 128 135 | 
             
                    """
         | 
| 129 136 | 
             
                    Resolve an alias to its directory path.
         | 
| 130 | 
            -
             | 
| 137 | 
            +
             | 
| 131 138 | 
             
                    Args:
         | 
| 132 139 | 
             
                        alias_name: The alias to resolve
         | 
| 133 | 
            -
             | 
| 140 | 
            +
             | 
| 134 141 | 
             
                    Returns:
         | 
| 135 142 | 
             
                        The Path object for the resolved directory
         | 
| 136 | 
            -
             | 
| 143 | 
            +
             | 
| 137 144 | 
             
                    Raises:
         | 
| 138 145 | 
             
                        AliasNotFoundError: If the alias does not exist
         | 
| 139 146 | 
             
                    """
         | 
| 140 147 | 
             
                    if alias_name not in self._aliases:
         | 
| 141 148 | 
             
                        raise AliasNotFoundError(f"Alias '{alias_name}' not found")
         | 
| 142 | 
            -
             | 
| 149 | 
            +
             | 
| 143 150 | 
             
                    path = Path(self._aliases[alias_name])
         | 
| 144 | 
            -
             | 
| 151 | 
            +
             | 
| 145 152 | 
             
                    # Ensure the directory still exists or can be created
         | 
| 146 153 | 
             
                    try:
         | 
| 147 154 | 
             
                        path = self.validate_directory(str(path))
         | 
| 148 155 | 
             
                    except InvalidDirectoryError:
         | 
| 149 | 
            -
                        logger.warning( | 
| 156 | 
            +
                        logger.warning(
         | 
| 157 | 
            +
                            f"Directory for alias '{alias_name}' no longer valid: {path}"
         | 
| 158 | 
            +
                        )
         | 
| 150 159 | 
             
                        # Still return the path, let the caller handle the missing directory
         | 
| 151 | 
            -
             | 
| 160 | 
            +
             | 
| 152 161 | 
             
                    return path
         | 
| 153 | 
            -
             | 
| 162 | 
            +
             | 
| 154 163 | 
             
                def list_aliases(self) -> List[Tuple[str, str]]:
         | 
| 155 164 | 
             
                    """
         | 
| 156 165 | 
             
                    List all configured aliases.
         | 
| 157 | 
            -
             | 
| 166 | 
            +
             | 
| 158 167 | 
             
                    Returns:
         | 
| 159 168 | 
             
                        A list of tuples containing (alias_name, directory_path)
         | 
| 160 169 | 
             
                    """
         | 
| 161 170 | 
             
                    return sorted(self._aliases.items())
         | 
| 162 | 
            -
             | 
| 171 | 
            +
             | 
| 163 172 | 
             
                def delete_alias(self, alias_name: str) -> None:
         | 
| 164 173 | 
             
                    """
         | 
| 165 174 | 
             
                    Delete a configuration alias.
         | 
| 166 | 
            -
             | 
| 175 | 
            +
             | 
| 167 176 | 
             
                    Args:
         | 
| 168 177 | 
             
                        alias_name: The alias to delete
         | 
| 169 | 
            -
             | 
| 178 | 
            +
             | 
| 170 179 | 
             
                    Raises:
         | 
| 171 180 | 
             
                        AliasNotFoundError: If the alias does not exist
         | 
| 172 181 | 
             
                    """
         | 
| 173 182 | 
             
                    if alias_name not in self._aliases:
         | 
| 174 183 | 
             
                        raise AliasNotFoundError(f"Alias '{alias_name}' not found")
         | 
| 175 | 
            -
             | 
| 184 | 
            +
             | 
| 176 185 | 
             
                    directory_path = self._aliases[alias_name]
         | 
| 177 186 | 
             
                    del self._aliases[alias_name]
         | 
| 178 187 | 
             
                    self._save_aliases(self._aliases)
         | 
| 179 | 
            -
             | 
| 188 | 
            +
             | 
| 180 189 | 
             
                    logger.info(f"Deleted alias '{alias_name}' (was pointing to: {directory_path})")
         | 
| 181 | 
            -
             | 
| 190 | 
            +
             | 
| 182 191 | 
             
                def validate_directory(self, path: str) -> Path:
         | 
| 183 192 | 
             
                    """
         | 
| 184 193 | 
             
                    Validate that a directory exists or can be created.
         | 
| 185 | 
            -
             | 
| 194 | 
            +
             | 
| 186 195 | 
             
                    Args:
         | 
| 187 196 | 
             
                        path: The directory path to validate
         | 
| 188 | 
            -
             | 
| 197 | 
            +
             | 
| 189 198 | 
             
                    Returns:
         | 
| 190 199 | 
             
                        The normalized Path object
         | 
| 191 | 
            -
             | 
| 200 | 
            +
             | 
| 192 201 | 
             
                    Raises:
         | 
| 193 202 | 
             
                        InvalidDirectoryError: If the path is invalid or cannot be created
         | 
| 194 203 | 
             
                    """
         | 
| 195 204 | 
             
                    try:
         | 
| 196 205 | 
             
                        # Expand user home directory and environment variables
         | 
| 197 | 
            -
                         | 
| 198 | 
            -
             | 
| 199 | 
            -
                        
         | 
| 206 | 
            +
                        directory_path = Path(path).expanduser().resolve()
         | 
| 207 | 
            +
             | 
| 200 208 | 
             
                        # Check if it's a file
         | 
| 201 209 | 
             
                        if directory_path.exists() and directory_path.is_file():
         | 
| 202 210 | 
             
                            raise InvalidDirectoryError(
         | 
| 203 211 | 
             
                                f"Path exists but is a file, not a directory: {directory_path}"
         | 
| 204 212 | 
             
                            )
         | 
| 205 | 
            -
             | 
| 213 | 
            +
             | 
| 206 214 | 
             
                        # Try to create the directory if it doesn't exist
         | 
| 207 215 | 
             
                        if not directory_path.exists():
         | 
| 208 216 | 
             
                            try:
         | 
| @@ -212,7 +220,7 @@ class ConfigAliasManager: | |
| 212 220 | 
             
                                raise InvalidDirectoryError(
         | 
| 213 221 | 
             
                                    f"Cannot create directory '{directory_path}': {e}"
         | 
| 214 222 | 
             
                                )
         | 
| 215 | 
            -
             | 
| 223 | 
            +
             | 
| 216 224 | 
             
                        # Verify we can write to the directory
         | 
| 217 225 | 
             
                        test_file = directory_path / ".claude_pm_test"
         | 
| 218 226 | 
             
                        try:
         | 
| @@ -222,72 +230,72 @@ class ConfigAliasManager: | |
| 222 230 | 
             
                            raise InvalidDirectoryError(
         | 
| 223 231 | 
             
                                f"Directory '{directory_path}' is not writable: {e}"
         | 
| 224 232 | 
             
                            )
         | 
| 225 | 
            -
             | 
| 233 | 
            +
             | 
| 226 234 | 
             
                        return directory_path
         | 
| 227 | 
            -
             | 
| 235 | 
            +
             | 
| 228 236 | 
             
                    except InvalidDirectoryError:
         | 
| 229 237 | 
             
                        raise
         | 
| 230 238 | 
             
                    except Exception as e:
         | 
| 231 239 | 
             
                        raise InvalidDirectoryError(f"Invalid directory path '{path}': {e}")
         | 
| 232 | 
            -
             | 
| 240 | 
            +
             | 
| 233 241 | 
             
                def get_alias(self, alias_name: str) -> Optional[str]:
         | 
| 234 242 | 
             
                    """
         | 
| 235 243 | 
             
                    Get the directory path for an alias without validation.
         | 
| 236 | 
            -
             | 
| 244 | 
            +
             | 
| 237 245 | 
             
                    Args:
         | 
| 238 246 | 
             
                        alias_name: The alias to look up
         | 
| 239 | 
            -
             | 
| 247 | 
            +
             | 
| 240 248 | 
             
                    Returns:
         | 
| 241 249 | 
             
                        The directory path string if the alias exists, None otherwise
         | 
| 242 250 | 
             
                    """
         | 
| 243 251 | 
             
                    return self._aliases.get(alias_name)
         | 
| 244 | 
            -
             | 
| 252 | 
            +
             | 
| 245 253 | 
             
                def update_alias(self, alias_name: str, new_directory_path: str) -> None:
         | 
| 246 254 | 
             
                    """
         | 
| 247 255 | 
             
                    Update an existing alias to point to a new directory.
         | 
| 248 | 
            -
             | 
| 256 | 
            +
             | 
| 249 257 | 
             
                    Args:
         | 
| 250 258 | 
             
                        alias_name: The alias to update
         | 
| 251 259 | 
             
                        new_directory_path: The new directory path
         | 
| 252 | 
            -
             | 
| 260 | 
            +
             | 
| 253 261 | 
             
                    Raises:
         | 
| 254 262 | 
             
                        AliasNotFoundError: If the alias does not exist
         | 
| 255 263 | 
             
                        InvalidDirectoryError: If the new directory path is invalid
         | 
| 256 264 | 
             
                    """
         | 
| 257 265 | 
             
                    if alias_name not in self._aliases:
         | 
| 258 266 | 
             
                        raise AliasNotFoundError(f"Alias '{alias_name}' not found")
         | 
| 259 | 
            -
             | 
| 267 | 
            +
             | 
| 260 268 | 
             
                    # Validate the new directory path
         | 
| 261 269 | 
             
                    validated_path = self.validate_directory(new_directory_path)
         | 
| 262 | 
            -
             | 
| 270 | 
            +
             | 
| 263 271 | 
             
                    old_path = self._aliases[alias_name]
         | 
| 264 272 | 
             
                    self._aliases[alias_name] = str(validated_path)
         | 
| 265 273 | 
             
                    self._save_aliases(self._aliases)
         | 
| 266 | 
            -
             | 
| 274 | 
            +
             | 
| 267 275 | 
             
                    logger.info(f"Updated alias '{alias_name}': {old_path} -> {validated_path}")
         | 
| 268 | 
            -
             | 
| 276 | 
            +
             | 
| 269 277 | 
             
                def alias_exists(self, alias_name: str) -> bool:
         | 
| 270 278 | 
             
                    """
         | 
| 271 279 | 
             
                    Check if an alias exists.
         | 
| 272 | 
            -
             | 
| 280 | 
            +
             | 
| 273 281 | 
             
                    Args:
         | 
| 274 282 | 
             
                        alias_name: The alias to check
         | 
| 275 | 
            -
             | 
| 283 | 
            +
             | 
| 276 284 | 
             
                    Returns:
         | 
| 277 285 | 
             
                        True if the alias exists, False otherwise
         | 
| 278 286 | 
             
                    """
         | 
| 279 287 | 
             
                    return alias_name in self._aliases
         | 
| 280 | 
            -
             | 
| 288 | 
            +
             | 
| 281 289 | 
             
                def get_all_aliases(self) -> Dict[str, str]:
         | 
| 282 290 | 
             
                    """
         | 
| 283 291 | 
             
                    Get a copy of all aliases.
         | 
| 284 | 
            -
             | 
| 292 | 
            +
             | 
| 285 293 | 
             
                    Returns:
         | 
| 286 294 | 
             
                        A dictionary mapping alias names to directory paths
         | 
| 287 295 | 
             
                    """
         | 
| 288 296 | 
             
                    return self._aliases.copy()
         | 
| 289 | 
            -
             | 
| 297 | 
            +
             | 
| 290 298 | 
             
                def reload_aliases(self) -> None:
         | 
| 291 299 | 
             
                    """Reload aliases from the file, discarding any in-memory changes."""
         | 
| 292 300 | 
             
                    self._aliases = self._load_aliases()
         | 
| 293 | 
            -
                    logger.debug("Reloaded aliases from file")
         | 
| 301 | 
            +
                    logger.debug("Reloaded aliases from file")
         | 
| @@ -0,0 +1,292 @@ | |
| 1 | 
            +
            """
         | 
| 2 | 
            +
            Configuration constants for Claude MPM.
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            This module provides centralized access to configuration values that were
         | 
| 5 | 
            +
            previously hardcoded throughout the codebase. It serves as a bridge between
         | 
| 6 | 
            +
            the old hardcoded values and the new unified configuration system.
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            Usage:
         | 
| 9 | 
            +
                from claude_mpm.core.config_constants import ConfigConstants
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                # Get timeout value
         | 
| 12 | 
            +
                timeout = ConfigConstants.get_timeout('hook_execution')
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                # Get port value
         | 
| 15 | 
            +
                port = ConfigConstants.get_port('socketio')
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                # Get cache setting
         | 
| 18 | 
            +
                cache_size = ConfigConstants.get_cache_setting('max_size_mb')
         | 
| 19 | 
            +
            """
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            from typing import Any, Dict, Optional
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            from .unified_config import ConfigurationService
         | 
| 24 | 
            +
             | 
| 25 | 
            +
             | 
| 26 | 
            +
            class ConfigConstants:
         | 
| 27 | 
            +
                """
         | 
| 28 | 
            +
                Centralized access to configuration constants.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                This class provides a convenient way to access configuration values
         | 
| 31 | 
            +
                that were previously hardcoded, while maintaining backward compatibility.
         | 
| 32 | 
            +
                """
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                _config_service: Optional[ConfigurationService] = None
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                # Default values for backward compatibility
         | 
| 37 | 
            +
                DEFAULT_VALUES = {
         | 
| 38 | 
            +
                    # Timeouts (in seconds)
         | 
| 39 | 
            +
                    "timeouts": {
         | 
| 40 | 
            +
                        "hook_execution": 5,
         | 
| 41 | 
            +
                        "session_default": 30,
         | 
| 42 | 
            +
                        "session_extended": 60,
         | 
| 43 | 
            +
                        "agent_loading": 10,
         | 
| 44 | 
            +
                        "startup": 60,
         | 
| 45 | 
            +
                        "graceful_shutdown": 30,
         | 
| 46 | 
            +
                    },
         | 
| 47 | 
            +
                    # Ports
         | 
| 48 | 
            +
                    "ports": {
         | 
| 49 | 
            +
                        "socketio_default": 8765,
         | 
| 50 | 
            +
                        "socketio_range_start": 8765,
         | 
| 51 | 
            +
                        "socketio_range_end": 8775,
         | 
| 52 | 
            +
                    },
         | 
| 53 | 
            +
                    # Cache settings
         | 
| 54 | 
            +
                    "cache": {
         | 
| 55 | 
            +
                        "max_size_mb": 100,
         | 
| 56 | 
            +
                        "max_entries": 10000,
         | 
| 57 | 
            +
                        "default_ttl_seconds": 300,
         | 
| 58 | 
            +
                    },
         | 
| 59 | 
            +
                    # Session settings
         | 
| 60 | 
            +
                    "sessions": {
         | 
| 61 | 
            +
                        "max_age_minutes": 30,
         | 
| 62 | 
            +
                        "cleanup_max_age_hours": 24,
         | 
| 63 | 
            +
                        "timeout_minutes": 60,
         | 
| 64 | 
            +
                    },
         | 
| 65 | 
            +
                    # Retry and recovery
         | 
| 66 | 
            +
                    "recovery": {
         | 
| 67 | 
            +
                        "max_restarts": 3,
         | 
| 68 | 
            +
                        "max_recovery_attempts": 3,
         | 
| 69 | 
            +
                    },
         | 
| 70 | 
            +
                    # Sleep and polling intervals (in seconds)
         | 
| 71 | 
            +
                    "intervals": {
         | 
| 72 | 
            +
                        "health_check": 0.1,
         | 
| 73 | 
            +
                        "batch_window_ms": 100,
         | 
| 74 | 
            +
                        "polling": 1.0,
         | 
| 75 | 
            +
                        "brief_pause": 0.1,
         | 
| 76 | 
            +
                    },
         | 
| 77 | 
            +
                    # File and memory limits
         | 
| 78 | 
            +
                    "limits": {
         | 
| 79 | 
            +
                        "max_file_size_mb": 10,
         | 
| 80 | 
            +
                        "max_memory_usage_mb": 1024,
         | 
| 81 | 
            +
                    },
         | 
| 82 | 
            +
                }
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                @classmethod
         | 
| 85 | 
            +
                def _get_config_service(cls) -> ConfigurationService:
         | 
| 86 | 
            +
                    """Get or create the configuration service."""
         | 
| 87 | 
            +
                    if cls._config_service is None:
         | 
| 88 | 
            +
                        cls._config_service = ConfigurationService()
         | 
| 89 | 
            +
                    return cls._config_service
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                @classmethod
         | 
| 92 | 
            +
                def set_config_service(cls, config_service: ConfigurationService) -> None:
         | 
| 93 | 
            +
                    """Set the configuration service (for dependency injection)."""
         | 
| 94 | 
            +
                    cls._config_service = config_service
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                @classmethod
         | 
| 97 | 
            +
                def get_timeout(cls, timeout_type: str) -> int:
         | 
| 98 | 
            +
                    """
         | 
| 99 | 
            +
                    Get timeout value by type.
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    Args:
         | 
| 102 | 
            +
                        timeout_type: Type of timeout (e.g., 'hook_execution', 'session_default')
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                    Returns:
         | 
| 105 | 
            +
                        Timeout value in seconds
         | 
| 106 | 
            +
                    """
         | 
| 107 | 
            +
                    try:
         | 
| 108 | 
            +
                        config = cls._get_config_service().config
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                        if timeout_type == "hook_execution":
         | 
| 111 | 
            +
                            return config.performance.hook_timeout_seconds
         | 
| 112 | 
            +
                        elif timeout_type == "session_default":
         | 
| 113 | 
            +
                            return config.performance.session_timeout_seconds
         | 
| 114 | 
            +
                        elif timeout_type == "session_extended":
         | 
| 115 | 
            +
                            return config.sessions.session_timeout_minutes * 60
         | 
| 116 | 
            +
                        elif timeout_type == "agent_loading":
         | 
| 117 | 
            +
                            return config.performance.agent_load_timeout_seconds
         | 
| 118 | 
            +
                        elif timeout_type == "startup":
         | 
| 119 | 
            +
                            return config.performance.startup_timeout
         | 
| 120 | 
            +
                        elif timeout_type == "graceful_shutdown":
         | 
| 121 | 
            +
                            return config.performance.graceful_shutdown_timeout
         | 
| 122 | 
            +
                        else:
         | 
| 123 | 
            +
                            return cls.DEFAULT_VALUES["timeouts"].get(timeout_type, 30)
         | 
| 124 | 
            +
                    except Exception:
         | 
| 125 | 
            +
                        return cls.DEFAULT_VALUES["timeouts"].get(timeout_type, 30)
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                @classmethod
         | 
| 128 | 
            +
                def get_port(cls, port_type: str) -> int:
         | 
| 129 | 
            +
                    """
         | 
| 130 | 
            +
                    Get port value by type.
         | 
| 131 | 
            +
             | 
| 132 | 
            +
                    Args:
         | 
| 133 | 
            +
                        port_type: Type of port (e.g., 'socketio_default')
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                    Returns:
         | 
| 136 | 
            +
                        Port number
         | 
| 137 | 
            +
                    """
         | 
| 138 | 
            +
                    try:
         | 
| 139 | 
            +
                        config = cls._get_config_service().config
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                        if port_type == "socketio_default":
         | 
| 142 | 
            +
                            return config.network.socketio_port
         | 
| 143 | 
            +
                        elif port_type == "socketio_range_start":
         | 
| 144 | 
            +
                            return config.network.socketio_port_range[0]
         | 
| 145 | 
            +
                        elif port_type == "socketio_range_end":
         | 
| 146 | 
            +
                            return config.network.socketio_port_range[1]
         | 
| 147 | 
            +
                        else:
         | 
| 148 | 
            +
                            return cls.DEFAULT_VALUES["ports"].get(port_type, 8765)
         | 
| 149 | 
            +
                    except Exception:
         | 
| 150 | 
            +
                        return cls.DEFAULT_VALUES["ports"].get(port_type, 8765)
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                @classmethod
         | 
| 153 | 
            +
                def get_cache_setting(cls, setting_name: str) -> Any:
         | 
| 154 | 
            +
                    """
         | 
| 155 | 
            +
                    Get cache setting by name.
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                    Args:
         | 
| 158 | 
            +
                        setting_name: Name of cache setting
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                    Returns:
         | 
| 161 | 
            +
                        Cache setting value
         | 
| 162 | 
            +
                    """
         | 
| 163 | 
            +
                    try:
         | 
| 164 | 
            +
                        config = cls._get_config_service().config
         | 
| 165 | 
            +
             | 
| 166 | 
            +
                        if setting_name == "max_size_mb":
         | 
| 167 | 
            +
                            return config.performance.cache_max_size_mb
         | 
| 168 | 
            +
                        elif setting_name == "max_entries":
         | 
| 169 | 
            +
                            return config.performance.cache_max_entries
         | 
| 170 | 
            +
                        elif setting_name == "default_ttl_seconds":
         | 
| 171 | 
            +
                            return config.performance.cache_default_ttl_seconds
         | 
| 172 | 
            +
                        else:
         | 
| 173 | 
            +
                            return cls.DEFAULT_VALUES["cache"].get(setting_name)
         | 
| 174 | 
            +
                    except Exception:
         | 
| 175 | 
            +
                        return cls.DEFAULT_VALUES["cache"].get(setting_name)
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                @classmethod
         | 
| 178 | 
            +
                def get_session_setting(cls, setting_name: str) -> Any:
         | 
| 179 | 
            +
                    """
         | 
| 180 | 
            +
                    Get session setting by name.
         | 
| 181 | 
            +
             | 
| 182 | 
            +
                    Args:
         | 
| 183 | 
            +
                        setting_name: Name of session setting
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                    Returns:
         | 
| 186 | 
            +
                        Session setting value
         | 
| 187 | 
            +
                    """
         | 
| 188 | 
            +
                    try:
         | 
| 189 | 
            +
                        config = cls._get_config_service().config
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                        if setting_name == "max_age_minutes":
         | 
| 192 | 
            +
                            return config.sessions.max_age_minutes
         | 
| 193 | 
            +
                        elif setting_name == "cleanup_max_age_hours":
         | 
| 194 | 
            +
                            return config.sessions.cleanup_max_age_hours
         | 
| 195 | 
            +
                        elif setting_name == "timeout_minutes":
         | 
| 196 | 
            +
                            return config.sessions.session_timeout_minutes
         | 
| 197 | 
            +
                        else:
         | 
| 198 | 
            +
                            return cls.DEFAULT_VALUES["sessions"].get(setting_name)
         | 
| 199 | 
            +
                    except Exception:
         | 
| 200 | 
            +
                        return cls.DEFAULT_VALUES["sessions"].get(setting_name)
         | 
| 201 | 
            +
             | 
| 202 | 
            +
                @classmethod
         | 
| 203 | 
            +
                def get_recovery_setting(cls, setting_name: str) -> int:
         | 
| 204 | 
            +
                    """
         | 
| 205 | 
            +
                    Get recovery setting by name.
         | 
| 206 | 
            +
             | 
| 207 | 
            +
                    Args:
         | 
| 208 | 
            +
                        setting_name: Name of recovery setting
         | 
| 209 | 
            +
             | 
| 210 | 
            +
                    Returns:
         | 
| 211 | 
            +
                        Recovery setting value
         | 
| 212 | 
            +
                    """
         | 
| 213 | 
            +
                    try:
         | 
| 214 | 
            +
                        config = cls._get_config_service().config
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                        if setting_name == "max_restarts":
         | 
| 217 | 
            +
                            return config.performance.max_restarts
         | 
| 218 | 
            +
                        elif setting_name == "max_recovery_attempts":
         | 
| 219 | 
            +
                            return config.performance.max_recovery_attempts
         | 
| 220 | 
            +
                        else:
         | 
| 221 | 
            +
                            return cls.DEFAULT_VALUES["recovery"].get(setting_name, 3)
         | 
| 222 | 
            +
                    except Exception:
         | 
| 223 | 
            +
                        return cls.DEFAULT_VALUES["recovery"].get(setting_name, 3)
         | 
| 224 | 
            +
             | 
| 225 | 
            +
                @classmethod
         | 
| 226 | 
            +
                def get_interval(cls, interval_type: str) -> float:
         | 
| 227 | 
            +
                    """
         | 
| 228 | 
            +
                    Get interval value by type.
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                    Args:
         | 
| 231 | 
            +
                        interval_type: Type of interval
         | 
| 232 | 
            +
             | 
| 233 | 
            +
                    Returns:
         | 
| 234 | 
            +
                        Interval value in seconds
         | 
| 235 | 
            +
                    """
         | 
| 236 | 
            +
                    try:
         | 
| 237 | 
            +
                        config = cls._get_config_service().config
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                        if interval_type == "health_check":
         | 
| 240 | 
            +
                            return config.performance.health_check_interval_seconds
         | 
| 241 | 
            +
                        elif interval_type == "polling":
         | 
| 242 | 
            +
                            return config.performance.polling_interval_seconds
         | 
| 243 | 
            +
                        elif interval_type == "batch_window_ms":
         | 
| 244 | 
            +
                            return config.performance.batch_window_ms / 1000.0
         | 
| 245 | 
            +
                        else:
         | 
| 246 | 
            +
                            return cls.DEFAULT_VALUES["intervals"].get(interval_type, 1.0)
         | 
| 247 | 
            +
                    except Exception:
         | 
| 248 | 
            +
                        return cls.DEFAULT_VALUES["intervals"].get(interval_type, 1.0)
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                @classmethod
         | 
| 251 | 
            +
                def get_limit(cls, limit_type: str) -> int:
         | 
| 252 | 
            +
                    """
         | 
| 253 | 
            +
                    Get limit value by type.
         | 
| 254 | 
            +
             | 
| 255 | 
            +
                    Args:
         | 
| 256 | 
            +
                        limit_type: Type of limit
         | 
| 257 | 
            +
             | 
| 258 | 
            +
                    Returns:
         | 
| 259 | 
            +
                        Limit value
         | 
| 260 | 
            +
                    """
         | 
| 261 | 
            +
                    try:
         | 
| 262 | 
            +
                        config = cls._get_config_service().config
         | 
| 263 | 
            +
             | 
| 264 | 
            +
                        if limit_type == "max_file_size_mb":
         | 
| 265 | 
            +
                            return config.security.max_file_size_mb
         | 
| 266 | 
            +
                        elif limit_type == "max_memory_usage_mb":
         | 
| 267 | 
            +
                            return config.performance.max_memory_usage_mb
         | 
| 268 | 
            +
                        else:
         | 
| 269 | 
            +
                            return cls.DEFAULT_VALUES["limits"].get(limit_type, 100)
         | 
| 270 | 
            +
                    except Exception:
         | 
| 271 | 
            +
                        return cls.DEFAULT_VALUES["limits"].get(limit_type, 100)
         | 
| 272 | 
            +
             | 
| 273 | 
            +
             | 
| 274 | 
            +
            # Convenience functions for common values
         | 
| 275 | 
            +
            def get_default_timeout() -> int:
         | 
| 276 | 
            +
                """Get default timeout value."""
         | 
| 277 | 
            +
                return ConfigConstants.get_timeout("session_default")
         | 
| 278 | 
            +
             | 
| 279 | 
            +
             | 
| 280 | 
            +
            def get_socketio_port() -> int:
         | 
| 281 | 
            +
                """Get default SocketIO port."""
         | 
| 282 | 
            +
                return ConfigConstants.get_port("socketio_default")
         | 
| 283 | 
            +
             | 
| 284 | 
            +
             | 
| 285 | 
            +
            def get_cache_size() -> float:
         | 
| 286 | 
            +
                """Get default cache size in MB."""
         | 
| 287 | 
            +
                return ConfigConstants.get_cache_setting("max_size_mb")
         | 
| 288 | 
            +
             | 
| 289 | 
            +
             | 
| 290 | 
            +
            def get_max_restarts() -> int:
         | 
| 291 | 
            +
                """Get maximum restart attempts."""
         | 
| 292 | 
            +
                return ConfigConstants.get_recovery_setting("max_restarts")
         |