claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/engineer.json +33 -11
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +50 -2
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +648 -1098
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +339 -967
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +233 -542
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +280 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +22 -29
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +500 -680
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -17
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
- claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +11 -7
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/cache_manager.py +311 -0
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
- claude_mpm-4.1.3.dist-info/RECORD +528 -0
- claude_mpm/cli/commands/run_config_checker.py +0 -160
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
"""Startup checking service for CLI commands.
|
|
2
|
+
|
|
3
|
+
WHY: This service extracts startup validation logic from run.py to improve
|
|
4
|
+
separation of concerns, testability, and reusability across CLI commands.
|
|
5
|
+
|
|
6
|
+
DESIGN DECISIONS:
|
|
7
|
+
- Interface-based design for dependency injection
|
|
8
|
+
- Single responsibility: startup validation only
|
|
9
|
+
- Returns structured warnings for better handling
|
|
10
|
+
- Non-blocking: warns but doesn't prevent execution
|
|
11
|
+
- Reusable across multiple CLI commands
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
from abc import ABC, abstractmethod
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import List, Optional
|
|
19
|
+
|
|
20
|
+
from claude_mpm.core.logger import get_logger
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# Interface Definition
|
|
24
|
+
class IStartupChecker(ABC):
|
|
25
|
+
"""Interface for startup checking service."""
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def check_configuration(self) -> List["StartupWarning"]:
|
|
29
|
+
"""Validate configuration and return warnings."""
|
|
30
|
+
|
|
31
|
+
@abstractmethod
|
|
32
|
+
def check_memory(self, resume_enabled: bool = False) -> Optional["StartupWarning"]:
|
|
33
|
+
"""Check Claude.json memory usage."""
|
|
34
|
+
|
|
35
|
+
@abstractmethod
|
|
36
|
+
def check_environment(self) -> List["StartupWarning"]:
|
|
37
|
+
"""Validate environment and paths."""
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def get_startup_warnings(
|
|
41
|
+
self, resume_enabled: bool = False
|
|
42
|
+
) -> List["StartupWarning"]:
|
|
43
|
+
"""Collect all startup warnings."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class StartupWarning:
|
|
48
|
+
"""Structured warning information."""
|
|
49
|
+
|
|
50
|
+
category: str # 'config', 'memory', 'environment'
|
|
51
|
+
message: str
|
|
52
|
+
suggestion: Optional[str] = None
|
|
53
|
+
severity: str = "warning" # 'info', 'warning', 'error'
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class StartupCheckerService(IStartupChecker):
|
|
57
|
+
"""Service for startup validation and health checks."""
|
|
58
|
+
|
|
59
|
+
def __init__(self, config_service):
|
|
60
|
+
"""Initialize the startup checker.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
config_service: Configuration service instance (IConfigurationService)
|
|
64
|
+
"""
|
|
65
|
+
self.config_service = config_service
|
|
66
|
+
self.logger = get_logger("StartupChecker")
|
|
67
|
+
|
|
68
|
+
def check_configuration(self) -> List[StartupWarning]:
|
|
69
|
+
"""Validate configuration and return warnings.
|
|
70
|
+
|
|
71
|
+
Checks:
|
|
72
|
+
- Response logging directory exists and is writable
|
|
73
|
+
- Agent deployment configuration
|
|
74
|
+
- Memory management configuration
|
|
75
|
+
- Common configuration issues
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
List of configuration warnings
|
|
79
|
+
"""
|
|
80
|
+
warnings = []
|
|
81
|
+
|
|
82
|
+
try:
|
|
83
|
+
# Check response logging configuration
|
|
84
|
+
response_logging = self.config_service.get("response_logging", {})
|
|
85
|
+
if response_logging.get("enabled", False):
|
|
86
|
+
log_dir = response_logging.get("directory")
|
|
87
|
+
if log_dir:
|
|
88
|
+
warnings.extend(self._check_log_directory(log_dir))
|
|
89
|
+
|
|
90
|
+
# Check memory management configuration
|
|
91
|
+
memory_config = self.config_service.get("memory_management", {})
|
|
92
|
+
if memory_config.get("auto_cleanup", False):
|
|
93
|
+
cleanup_threshold = memory_config.get("cleanup_threshold_mb", 100)
|
|
94
|
+
if cleanup_threshold < 50:
|
|
95
|
+
warnings.append(
|
|
96
|
+
StartupWarning(
|
|
97
|
+
category="config",
|
|
98
|
+
message=f"Memory cleanup threshold very low: {cleanup_threshold}MB",
|
|
99
|
+
suggestion="Consider increasing to at least 50MB",
|
|
100
|
+
severity="warning",
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
# Check for deprecated configuration keys
|
|
105
|
+
warnings.extend(self._check_deprecated_keys())
|
|
106
|
+
|
|
107
|
+
# Check configuration file access
|
|
108
|
+
warnings.extend(self._check_config_file_access())
|
|
109
|
+
|
|
110
|
+
except Exception as e:
|
|
111
|
+
self.logger.warning(f"Configuration check failed: {e}")
|
|
112
|
+
warnings.append(
|
|
113
|
+
StartupWarning(
|
|
114
|
+
category="config",
|
|
115
|
+
message=f"Configuration check failed: {e}",
|
|
116
|
+
severity="info",
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
return warnings
|
|
121
|
+
|
|
122
|
+
def check_memory(self, resume_enabled: bool = False) -> Optional[StartupWarning]:
|
|
123
|
+
"""Check .claude.json memory usage.
|
|
124
|
+
|
|
125
|
+
WHY: Large .claude.json files (>500KB) cause significant memory issues
|
|
126
|
+
when using --resume. Claude Code loads the entire conversation history
|
|
127
|
+
into memory, leading to 2GB+ memory consumption.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
resume_enabled: Whether --mpm-resume is being used
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
Warning if memory issue detected, None otherwise
|
|
134
|
+
"""
|
|
135
|
+
if not resume_enabled:
|
|
136
|
+
return None
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
claude_json_path = Path.cwd() / ".claude.json"
|
|
140
|
+
if not claude_json_path.exists():
|
|
141
|
+
self.logger.debug("No .claude.json file found")
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
file_size = claude_json_path.stat().st_size
|
|
145
|
+
|
|
146
|
+
# Only warn if file is larger than 500KB
|
|
147
|
+
if file_size > 500 * 1024:
|
|
148
|
+
formatted_size = self._format_file_size(file_size)
|
|
149
|
+
return StartupWarning(
|
|
150
|
+
category="memory",
|
|
151
|
+
message=f"Large .claude.json file detected ({formatted_size})",
|
|
152
|
+
suggestion="Consider running 'claude-mpm cleanup-memory' to archive old conversations",
|
|
153
|
+
severity="warning",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
self.logger.info(f".claude.json size: {self._format_file_size(file_size)}")
|
|
157
|
+
|
|
158
|
+
except Exception as e:
|
|
159
|
+
self.logger.warning(f"Failed to check .claude.json size: {e}")
|
|
160
|
+
|
|
161
|
+
return None
|
|
162
|
+
|
|
163
|
+
def check_environment(self) -> List[StartupWarning]:
|
|
164
|
+
"""Validate environment and paths.
|
|
165
|
+
|
|
166
|
+
Checks:
|
|
167
|
+
- Python version compatibility
|
|
168
|
+
- Virtual environment activation
|
|
169
|
+
- Required directories exist
|
|
170
|
+
- File permissions
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
List of environment warnings
|
|
174
|
+
"""
|
|
175
|
+
warnings = []
|
|
176
|
+
|
|
177
|
+
try:
|
|
178
|
+
# Check Python version
|
|
179
|
+
import sys
|
|
180
|
+
|
|
181
|
+
if sys.version_info < (3, 8):
|
|
182
|
+
warnings.append(
|
|
183
|
+
StartupWarning(
|
|
184
|
+
category="environment",
|
|
185
|
+
message=f"Python {sys.version_info.major}.{sys.version_info.minor} detected",
|
|
186
|
+
suggestion="Python 3.8+ is recommended for optimal performance",
|
|
187
|
+
severity="info",
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
# Check for common missing directories
|
|
192
|
+
warnings.extend(self._check_required_directories())
|
|
193
|
+
|
|
194
|
+
except Exception as e:
|
|
195
|
+
self.logger.warning(f"Environment check failed: {e}")
|
|
196
|
+
warnings.append(
|
|
197
|
+
StartupWarning(
|
|
198
|
+
category="environment",
|
|
199
|
+
message=f"Environment check failed: {e}",
|
|
200
|
+
severity="info",
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
return warnings
|
|
205
|
+
|
|
206
|
+
def get_startup_warnings(
|
|
207
|
+
self, resume_enabled: bool = False
|
|
208
|
+
) -> List[StartupWarning]:
|
|
209
|
+
"""Collect all startup warnings.
|
|
210
|
+
|
|
211
|
+
Args:
|
|
212
|
+
resume_enabled: Whether --mpm-resume is being used
|
|
213
|
+
|
|
214
|
+
Returns:
|
|
215
|
+
Complete list of startup warnings
|
|
216
|
+
"""
|
|
217
|
+
all_warnings = []
|
|
218
|
+
|
|
219
|
+
# Collect configuration warnings
|
|
220
|
+
all_warnings.extend(self.check_configuration())
|
|
221
|
+
|
|
222
|
+
# Check memory if resume is enabled
|
|
223
|
+
memory_warning = self.check_memory(resume_enabled)
|
|
224
|
+
if memory_warning:
|
|
225
|
+
all_warnings.append(memory_warning)
|
|
226
|
+
|
|
227
|
+
# Collect environment warnings
|
|
228
|
+
all_warnings.extend(self.check_environment())
|
|
229
|
+
|
|
230
|
+
return all_warnings
|
|
231
|
+
|
|
232
|
+
def display_warnings(self, warnings: List[StartupWarning]) -> None:
|
|
233
|
+
"""Display warnings to the user.
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
warnings: List of warnings to display
|
|
237
|
+
"""
|
|
238
|
+
if not warnings:
|
|
239
|
+
return
|
|
240
|
+
|
|
241
|
+
# Group warnings by severity
|
|
242
|
+
errors = [w for w in warnings if w.severity == "error"]
|
|
243
|
+
warnings_list = [w for w in warnings if w.severity == "warning"]
|
|
244
|
+
info = [w for w in warnings if w.severity == "info"]
|
|
245
|
+
|
|
246
|
+
# Display errors first
|
|
247
|
+
for warning in errors:
|
|
248
|
+
print(f"❌ {warning.message}")
|
|
249
|
+
if warning.suggestion:
|
|
250
|
+
print(f" {warning.suggestion}")
|
|
251
|
+
|
|
252
|
+
# Display warnings
|
|
253
|
+
for warning in warnings_list:
|
|
254
|
+
print(f"⚠️ {warning.message}")
|
|
255
|
+
if warning.suggestion:
|
|
256
|
+
print(f" 💡 {warning.suggestion}")
|
|
257
|
+
|
|
258
|
+
# Display info last
|
|
259
|
+
for warning in info:
|
|
260
|
+
print(f"ℹ️ {warning.message}")
|
|
261
|
+
if warning.suggestion:
|
|
262
|
+
print(f" {warning.suggestion}")
|
|
263
|
+
|
|
264
|
+
if errors or warnings_list:
|
|
265
|
+
print() # Add spacing after warnings
|
|
266
|
+
|
|
267
|
+
# Private helper methods
|
|
268
|
+
|
|
269
|
+
def _check_log_directory(self, log_dir: str) -> List[StartupWarning]:
|
|
270
|
+
"""Check if log directory exists and is writable."""
|
|
271
|
+
warnings = []
|
|
272
|
+
log_path = Path(log_dir)
|
|
273
|
+
|
|
274
|
+
if not log_path.exists():
|
|
275
|
+
warnings.append(
|
|
276
|
+
StartupWarning(
|
|
277
|
+
category="config",
|
|
278
|
+
message=f"Response logging directory does not exist: {log_path}",
|
|
279
|
+
suggestion=f"Run: mkdir -p {log_path}",
|
|
280
|
+
severity="warning",
|
|
281
|
+
)
|
|
282
|
+
)
|
|
283
|
+
elif not log_path.is_dir():
|
|
284
|
+
warnings.append(
|
|
285
|
+
StartupWarning(
|
|
286
|
+
category="config",
|
|
287
|
+
message=f"Response logging path is not a directory: {log_path}",
|
|
288
|
+
severity="warning",
|
|
289
|
+
)
|
|
290
|
+
)
|
|
291
|
+
elif not os.access(log_path, os.W_OK):
|
|
292
|
+
warnings.append(
|
|
293
|
+
StartupWarning(
|
|
294
|
+
category="config",
|
|
295
|
+
message=f"Response logging directory is not writable: {log_path}",
|
|
296
|
+
suggestion=f"Run: chmod 755 {log_path}",
|
|
297
|
+
severity="warning",
|
|
298
|
+
)
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
return warnings
|
|
302
|
+
|
|
303
|
+
def _check_deprecated_keys(self) -> List[StartupWarning]:
|
|
304
|
+
"""Check for deprecated configuration keys."""
|
|
305
|
+
warnings = []
|
|
306
|
+
deprecated_keys = ["legacy_mode", "old_agent_format", "deprecated_logging"]
|
|
307
|
+
|
|
308
|
+
for key in deprecated_keys:
|
|
309
|
+
if self.config_service.get(key) is not None:
|
|
310
|
+
warnings.append(
|
|
311
|
+
StartupWarning(
|
|
312
|
+
category="config",
|
|
313
|
+
message=f"Deprecated configuration key found: {key}",
|
|
314
|
+
suggestion="Consider removing this key from your configuration",
|
|
315
|
+
severity="info",
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
|
|
319
|
+
return warnings
|
|
320
|
+
|
|
321
|
+
def _check_config_file_access(self) -> List[StartupWarning]:
|
|
322
|
+
"""Check configuration file accessibility."""
|
|
323
|
+
warnings = []
|
|
324
|
+
|
|
325
|
+
try:
|
|
326
|
+
# Try to get config file path from config service
|
|
327
|
+
config_file = getattr(self.config_service, "config_file", None)
|
|
328
|
+
if config_file and Path(config_file).exists():
|
|
329
|
+
if not os.access(config_file, os.R_OK):
|
|
330
|
+
warnings.append(
|
|
331
|
+
StartupWarning(
|
|
332
|
+
category="config",
|
|
333
|
+
message=f"Configuration file is not readable: {config_file}",
|
|
334
|
+
suggestion=f"Run: chmod 644 {config_file}",
|
|
335
|
+
severity="warning",
|
|
336
|
+
)
|
|
337
|
+
)
|
|
338
|
+
except Exception as e:
|
|
339
|
+
self.logger.debug(f"Config file access check failed: {e}")
|
|
340
|
+
|
|
341
|
+
return warnings
|
|
342
|
+
|
|
343
|
+
def _check_required_directories(self) -> List[StartupWarning]:
|
|
344
|
+
"""Check for required directories."""
|
|
345
|
+
warnings = []
|
|
346
|
+
|
|
347
|
+
# Check .claude directory
|
|
348
|
+
claude_dir = Path.cwd() / ".claude"
|
|
349
|
+
if not claude_dir.exists():
|
|
350
|
+
self.logger.debug(
|
|
351
|
+
".claude directory does not exist (will be created on first use)"
|
|
352
|
+
)
|
|
353
|
+
elif not claude_dir.is_dir():
|
|
354
|
+
warnings.append(
|
|
355
|
+
StartupWarning(
|
|
356
|
+
category="environment",
|
|
357
|
+
message=".claude path exists but is not a directory",
|
|
358
|
+
severity="warning",
|
|
359
|
+
)
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
return warnings
|
|
363
|
+
|
|
364
|
+
def _format_file_size(self, size_bytes: int) -> str:
|
|
365
|
+
"""Format file size in human readable format."""
|
|
366
|
+
if size_bytes < 1024:
|
|
367
|
+
return f"{size_bytes} B"
|
|
368
|
+
if size_bytes < 1024 * 1024:
|
|
369
|
+
return f"{size_bytes / 1024:.1f} KB"
|
|
370
|
+
return f"{size_bytes / (1024 * 1024):.1f} MB"
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
"""Service for deploying MPM slash commands to user's Claude configuration.
|
|
2
|
+
|
|
3
|
+
This service handles:
|
|
4
|
+
1. Copying command markdown files from source to user's ~/.claude/commands directory
|
|
5
|
+
2. Creating the commands directory if it doesn't exist
|
|
6
|
+
3. Overwriting existing commands to ensure they're up-to-date
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import shutil
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from typing import Any, Dict, List
|
|
12
|
+
|
|
13
|
+
from claude_mpm.core.base_service import BaseService
|
|
14
|
+
from claude_mpm.core.logger import get_logger
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class CommandDeploymentService(BaseService):
|
|
18
|
+
"""Service for deploying MPM slash commands."""
|
|
19
|
+
|
|
20
|
+
def __init__(self):
|
|
21
|
+
"""Initialize the command deployment service."""
|
|
22
|
+
super().__init__(name="command_deployment")
|
|
23
|
+
|
|
24
|
+
# Source commands directory in the package
|
|
25
|
+
self.source_dir = Path(__file__).parent.parent / "commands"
|
|
26
|
+
|
|
27
|
+
# Target directory in user's home
|
|
28
|
+
self.target_dir = Path.home() / ".claude" / "commands"
|
|
29
|
+
|
|
30
|
+
async def _initialize(self) -> None:
|
|
31
|
+
"""Initialize the service."""
|
|
32
|
+
|
|
33
|
+
async def _cleanup(self) -> None:
|
|
34
|
+
"""Cleanup service resources."""
|
|
35
|
+
|
|
36
|
+
def deploy_commands(self, force: bool = False) -> Dict[str, Any]:
|
|
37
|
+
"""Deploy MPM slash commands to user's Claude configuration.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
force: Force deployment even if files exist
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Dictionary with deployment results
|
|
44
|
+
"""
|
|
45
|
+
result = {
|
|
46
|
+
"success": False,
|
|
47
|
+
"deployed": [],
|
|
48
|
+
"errors": [],
|
|
49
|
+
"target_dir": str(self.target_dir),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
# Check if source directory exists
|
|
54
|
+
if not self.source_dir.exists():
|
|
55
|
+
self.logger.warning(
|
|
56
|
+
f"Source commands directory not found: {self.source_dir}"
|
|
57
|
+
)
|
|
58
|
+
result["errors"].append(
|
|
59
|
+
f"Source directory not found: {self.source_dir}"
|
|
60
|
+
)
|
|
61
|
+
return result
|
|
62
|
+
|
|
63
|
+
# Create target directory if it doesn't exist
|
|
64
|
+
self.target_dir.mkdir(parents=True, exist_ok=True)
|
|
65
|
+
self.logger.debug(f"Ensured target directory exists: {self.target_dir}")
|
|
66
|
+
|
|
67
|
+
# Get all .md files from source directory
|
|
68
|
+
command_files = list(self.source_dir.glob("*.md"))
|
|
69
|
+
|
|
70
|
+
if not command_files:
|
|
71
|
+
self.logger.info("No command files found to deploy")
|
|
72
|
+
result["success"] = True
|
|
73
|
+
return result
|
|
74
|
+
|
|
75
|
+
# Deploy each command file
|
|
76
|
+
for source_file in command_files:
|
|
77
|
+
target_file = self.target_dir / source_file.name
|
|
78
|
+
|
|
79
|
+
try:
|
|
80
|
+
# Check if file exists and if we should overwrite
|
|
81
|
+
if target_file.exists() and not force:
|
|
82
|
+
# Check if source is newer
|
|
83
|
+
if source_file.stat().st_mtime <= target_file.stat().st_mtime:
|
|
84
|
+
self.logger.debug(
|
|
85
|
+
f"Skipping {source_file.name} - target is up to date"
|
|
86
|
+
)
|
|
87
|
+
continue
|
|
88
|
+
|
|
89
|
+
# Copy the file
|
|
90
|
+
shutil.copy2(source_file, target_file)
|
|
91
|
+
self.logger.info(f"Deployed command: {source_file.name}")
|
|
92
|
+
result["deployed"].append(source_file.name)
|
|
93
|
+
|
|
94
|
+
except Exception as e:
|
|
95
|
+
error_msg = f"Failed to deploy {source_file.name}: {e}"
|
|
96
|
+
self.logger.error(error_msg)
|
|
97
|
+
result["errors"].append(error_msg)
|
|
98
|
+
|
|
99
|
+
result["success"] = len(result["errors"]) == 0
|
|
100
|
+
|
|
101
|
+
if result["deployed"]:
|
|
102
|
+
self.logger.info(
|
|
103
|
+
f"Successfully deployed {len(result['deployed'])} commands to {self.target_dir}"
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return result
|
|
107
|
+
|
|
108
|
+
except Exception as e:
|
|
109
|
+
error_msg = f"Command deployment failed: {e}"
|
|
110
|
+
self.logger.error(error_msg)
|
|
111
|
+
result["errors"].append(error_msg)
|
|
112
|
+
return result
|
|
113
|
+
|
|
114
|
+
def list_available_commands(self) -> List[str]:
|
|
115
|
+
"""List available commands in the source directory.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
List of command file names
|
|
119
|
+
"""
|
|
120
|
+
if not self.source_dir.exists():
|
|
121
|
+
return []
|
|
122
|
+
|
|
123
|
+
return [f.name for f in self.source_dir.glob("*.md")]
|
|
124
|
+
|
|
125
|
+
def list_deployed_commands(self) -> List[str]:
|
|
126
|
+
"""List deployed commands in the target directory.
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
List of deployed command file names
|
|
130
|
+
"""
|
|
131
|
+
if not self.target_dir.exists():
|
|
132
|
+
return []
|
|
133
|
+
|
|
134
|
+
return [f.name for f in self.target_dir.glob("mpm*.md")]
|
|
135
|
+
|
|
136
|
+
def remove_deployed_commands(self) -> int:
|
|
137
|
+
"""Remove all deployed MPM commands from target directory.
|
|
138
|
+
|
|
139
|
+
Returns:
|
|
140
|
+
Number of files removed
|
|
141
|
+
"""
|
|
142
|
+
if not self.target_dir.exists():
|
|
143
|
+
return 0
|
|
144
|
+
|
|
145
|
+
removed = 0
|
|
146
|
+
for file in self.target_dir.glob("mpm*.md"):
|
|
147
|
+
try:
|
|
148
|
+
file.unlink()
|
|
149
|
+
self.logger.info(f"Removed command: {file.name}")
|
|
150
|
+
removed += 1
|
|
151
|
+
except Exception as e:
|
|
152
|
+
self.logger.error(f"Failed to remove {file.name}: {e}")
|
|
153
|
+
|
|
154
|
+
return removed
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def deploy_commands_on_startup(force: bool = False) -> None:
|
|
158
|
+
"""Convenience function to deploy commands during startup.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
force: Force deployment even if files exist
|
|
162
|
+
"""
|
|
163
|
+
service = CommandDeploymentService()
|
|
164
|
+
result = service.deploy_commands(force=force)
|
|
165
|
+
|
|
166
|
+
if result["deployed"]:
|
|
167
|
+
logger = get_logger("startup")
|
|
168
|
+
logger.info(f"MPM commands deployed: {', '.join(result['deployed'])}")
|
|
169
|
+
|
|
170
|
+
if result["errors"]:
|
|
171
|
+
logger = get_logger("startup")
|
|
172
|
+
for error in result["errors"]:
|
|
173
|
+
logger.warning(f"Command deployment issue: {error}")
|
|
@@ -29,11 +29,9 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
29
29
|
|
|
30
30
|
async def _initialize(self) -> None:
|
|
31
31
|
"""Initialize the service. No special initialization needed."""
|
|
32
|
-
pass
|
|
33
32
|
|
|
34
33
|
async def _cleanup(self) -> None:
|
|
35
34
|
"""Cleanup service resources. No cleanup needed."""
|
|
36
|
-
pass
|
|
37
35
|
|
|
38
36
|
def handle_mpm_command(self, prompt: str) -> bool:
|
|
39
37
|
"""Handle /mpm: commands directly without going to Claude.
|
|
@@ -59,12 +57,11 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
59
57
|
# Route to appropriate handler
|
|
60
58
|
if command == "test":
|
|
61
59
|
return self._handle_test_command(args)
|
|
62
|
-
|
|
60
|
+
if command == "agents":
|
|
63
61
|
return self._handle_agents_command(args)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
return True
|
|
62
|
+
print(f"Unknown command: {command}")
|
|
63
|
+
print("Available commands: test, agents")
|
|
64
|
+
return True
|
|
68
65
|
|
|
69
66
|
except KeyboardInterrupt:
|
|
70
67
|
print("\nCommand interrupted")
|
|
@@ -175,28 +172,29 @@ class CommandHandlerService(BaseService, CommandHandlerInterface):
|
|
|
175
172
|
"success": success,
|
|
176
173
|
"command": command,
|
|
177
174
|
"args": args,
|
|
178
|
-
"message":
|
|
179
|
-
|
|
180
|
-
|
|
175
|
+
"message": (
|
|
176
|
+
"Test command executed" if success else "Test command failed"
|
|
177
|
+
),
|
|
181
178
|
}
|
|
182
|
-
|
|
179
|
+
if command == "agents":
|
|
183
180
|
success = self._handle_agents_command(args)
|
|
184
181
|
return {
|
|
185
182
|
"success": success,
|
|
186
183
|
"command": command,
|
|
187
184
|
"args": args,
|
|
188
|
-
"message":
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
"success": False,
|
|
195
|
-
"command": command,
|
|
196
|
-
"args": args,
|
|
197
|
-
"error": f"Unknown command: {command}",
|
|
198
|
-
"available_commands": self.get_available_commands(),
|
|
185
|
+
"message": (
|
|
186
|
+
"Agents command executed"
|
|
187
|
+
if success
|
|
188
|
+
else "Agents command failed"
|
|
189
|
+
),
|
|
199
190
|
}
|
|
191
|
+
return {
|
|
192
|
+
"success": False,
|
|
193
|
+
"command": command,
|
|
194
|
+
"args": args,
|
|
195
|
+
"error": f"Unknown command: {command}",
|
|
196
|
+
"available_commands": self.get_available_commands(),
|
|
197
|
+
}
|
|
200
198
|
except Exception as e:
|
|
201
199
|
return {"success": False, "command": command, "args": args, "error": str(e)}
|
|
202
200
|
|
|
@@ -40,37 +40,37 @@ from .interfaces import ( # Core dependency injection; Configuration management
|
|
|
40
40
|
)
|
|
41
41
|
|
|
42
42
|
__all__ = [
|
|
43
|
-
#
|
|
44
|
-
"
|
|
45
|
-
"ServiceType",
|
|
46
|
-
"IConfigurationService",
|
|
47
|
-
"IConfigurationManager",
|
|
48
|
-
"IAgentRegistry",
|
|
43
|
+
# Service interfaces
|
|
44
|
+
"AgentDeploymentInterface",
|
|
49
45
|
"AgentMetadata",
|
|
50
|
-
|
|
46
|
+
# Base classes
|
|
47
|
+
"BaseService",
|
|
48
|
+
"CacheEntry",
|
|
51
49
|
"HealthStatus",
|
|
50
|
+
"HookServiceInterface",
|
|
51
|
+
"IAgentRegistry",
|
|
52
|
+
"ICacheService",
|
|
53
|
+
"IConfigurationManager",
|
|
54
|
+
"IConfigurationService",
|
|
55
|
+
"IErrorHandler",
|
|
56
|
+
"IEventBus",
|
|
57
|
+
"IHealthMonitor",
|
|
58
|
+
"IPerformanceMonitor",
|
|
52
59
|
"IPromptCache",
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"TemplateRenderContext",
|
|
60
|
+
# Core interfaces
|
|
61
|
+
"IServiceContainer",
|
|
56
62
|
"IServiceFactory",
|
|
57
|
-
"IEventBus",
|
|
58
|
-
"IStructuredLogger",
|
|
59
63
|
"IServiceLifecycle",
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
"ICacheService",
|
|
63
|
-
# Service interfaces
|
|
64
|
-
"AgentDeploymentInterface",
|
|
65
|
-
"MemoryServiceInterface",
|
|
66
|
-
"HookServiceInterface",
|
|
67
|
-
"SocketIOServiceInterface",
|
|
68
|
-
"ProjectAnalyzerInterface",
|
|
69
|
-
"TicketManagerInterface",
|
|
64
|
+
"IStructuredLogger",
|
|
65
|
+
"ITemplateManager",
|
|
70
66
|
# Registry
|
|
71
67
|
"InterfaceRegistry",
|
|
72
|
-
|
|
73
|
-
"
|
|
74
|
-
"
|
|
68
|
+
"MemoryServiceInterface",
|
|
69
|
+
"ProjectAnalyzerInterface",
|
|
70
|
+
"ServiceType",
|
|
75
71
|
"SingletonService",
|
|
72
|
+
"SocketIOServiceInterface",
|
|
73
|
+
"SyncBaseService",
|
|
74
|
+
"TemplateRenderContext",
|
|
75
|
+
"TicketManagerInterface",
|
|
76
76
|
]
|