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
|
@@ -29,7 +29,6 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
|
29
29
|
import aiofiles
|
|
30
30
|
|
|
31
31
|
from claude_mpm.config.paths import paths
|
|
32
|
-
from claude_mpm.constants import EnvironmentVars, Paths
|
|
33
32
|
from claude_mpm.core.config import Config
|
|
34
33
|
from claude_mpm.core.logger import get_logger
|
|
35
34
|
|
|
@@ -95,12 +94,12 @@ class AsyncAgentDeploymentService:
|
|
|
95
94
|
"parallel_files_processed": 0,
|
|
96
95
|
"time_saved_ms": 0.0,
|
|
97
96
|
}
|
|
98
|
-
|
|
97
|
+
|
|
99
98
|
self.logger.info(f"Base agent path: {self.base_agent_path}")
|
|
100
|
-
|
|
99
|
+
|
|
101
100
|
def _find_base_agent_file(self) -> Path:
|
|
102
101
|
"""Find base agent file with priority-based search.
|
|
103
|
-
|
|
102
|
+
|
|
104
103
|
Priority order:
|
|
105
104
|
1. Environment variable override (CLAUDE_MPM_BASE_AGENT_PATH)
|
|
106
105
|
2. Current working directory (for local development)
|
|
@@ -113,49 +112,68 @@ class AsyncAgentDeploymentService:
|
|
|
113
112
|
if env_path:
|
|
114
113
|
env_base_agent = Path(env_path)
|
|
115
114
|
if env_base_agent.exists():
|
|
116
|
-
self.logger.info(
|
|
115
|
+
self.logger.info(
|
|
116
|
+
f"Using environment variable base_agent: {env_base_agent}"
|
|
117
|
+
)
|
|
117
118
|
return env_base_agent
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
self.logger.warning(
|
|
120
|
+
f"CLAUDE_MPM_BASE_AGENT_PATH set but file doesn't exist: {env_base_agent}"
|
|
121
|
+
)
|
|
122
|
+
|
|
121
123
|
# Priority 1: Check current working directory for local development
|
|
122
124
|
cwd = Path.cwd()
|
|
123
125
|
cwd_base_agent = cwd / "src" / "claude_mpm" / "agents" / "base_agent.json"
|
|
124
126
|
if cwd_base_agent.exists():
|
|
125
|
-
self.logger.info(
|
|
127
|
+
self.logger.info(
|
|
128
|
+
f"Using local development base_agent from cwd: {cwd_base_agent}"
|
|
129
|
+
)
|
|
126
130
|
return cwd_base_agent
|
|
127
|
-
|
|
131
|
+
|
|
128
132
|
# Priority 2: Check known development locations
|
|
129
133
|
known_dev_paths = [
|
|
130
|
-
Path(
|
|
131
|
-
|
|
132
|
-
|
|
134
|
+
Path(
|
|
135
|
+
"/Users/masa/Projects/claude-mpm/src/claude_mpm/agents/base_agent.json"
|
|
136
|
+
),
|
|
137
|
+
Path.home()
|
|
138
|
+
/ "Projects"
|
|
139
|
+
/ "claude-mpm"
|
|
140
|
+
/ "src"
|
|
141
|
+
/ "claude_mpm"
|
|
142
|
+
/ "agents"
|
|
143
|
+
/ "base_agent.json",
|
|
144
|
+
Path.home()
|
|
145
|
+
/ "projects"
|
|
146
|
+
/ "claude-mpm"
|
|
147
|
+
/ "src"
|
|
148
|
+
/ "claude_mpm"
|
|
149
|
+
/ "agents"
|
|
150
|
+
/ "base_agent.json",
|
|
133
151
|
]
|
|
134
|
-
|
|
152
|
+
|
|
135
153
|
for dev_path in known_dev_paths:
|
|
136
154
|
if dev_path.exists():
|
|
137
155
|
self.logger.info(f"Using development base_agent: {dev_path}")
|
|
138
156
|
return dev_path
|
|
139
|
-
|
|
157
|
+
|
|
140
158
|
# Priority 3: Check user override location
|
|
141
159
|
user_base_agent = Path.home() / ".claude" / "agents" / "base_agent.json"
|
|
142
160
|
if user_base_agent.exists():
|
|
143
161
|
self.logger.info(f"Using user override base_agent: {user_base_agent}")
|
|
144
162
|
return user_base_agent
|
|
145
|
-
|
|
163
|
+
|
|
146
164
|
# Priority 4: Use framework agents directory (fallback)
|
|
147
165
|
framework_base_agent = paths.agents_dir / "base_agent.json"
|
|
148
166
|
if framework_base_agent.exists():
|
|
149
167
|
self.logger.info(f"Using framework base_agent: {framework_base_agent}")
|
|
150
168
|
return framework_base_agent
|
|
151
|
-
|
|
169
|
+
|
|
152
170
|
# If still not found, log all searched locations
|
|
153
171
|
self.logger.warning("Base agent file not found in any location:")
|
|
154
172
|
self.logger.warning(f" 1. CWD: {cwd_base_agent}")
|
|
155
173
|
self.logger.warning(f" 2. Dev paths: {known_dev_paths}")
|
|
156
174
|
self.logger.warning(f" 3. User: {user_base_agent}")
|
|
157
175
|
self.logger.warning(f" 4. Framework: {framework_base_agent}")
|
|
158
|
-
|
|
176
|
+
|
|
159
177
|
# Final fallback to framework path even if it doesn't exist
|
|
160
178
|
return framework_base_agent
|
|
161
179
|
|
|
@@ -233,7 +251,7 @@ class AsyncAgentDeploymentService:
|
|
|
233
251
|
"""Load and parse a single agent file asynchronously."""
|
|
234
252
|
try:
|
|
235
253
|
# Non-blocking file read
|
|
236
|
-
async with aiofiles.open(file_path
|
|
254
|
+
async with aiofiles.open(file_path) as f:
|
|
237
255
|
content = await f.read()
|
|
238
256
|
|
|
239
257
|
# Parse JSON in thread pool (CPU-bound)
|
|
@@ -291,13 +309,12 @@ class AsyncAgentDeploymentService:
|
|
|
291
309
|
required_fields = ["agent_id", "instructions"]
|
|
292
310
|
if all(field in agent for field in required_fields):
|
|
293
311
|
return agent
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
return None
|
|
312
|
+
missing = [f for f in required_fields if f not in agent]
|
|
313
|
+
self.logger.warning(
|
|
314
|
+
f"Agent {agent.get('_agent_name', 'unknown')} "
|
|
315
|
+
f"missing required fields: {missing}"
|
|
316
|
+
)
|
|
317
|
+
return None
|
|
301
318
|
except Exception as e:
|
|
302
319
|
self.logger.error(f"Validation error: {e}")
|
|
303
320
|
return None
|
|
@@ -415,10 +432,9 @@ class AsyncAgentDeploymentService:
|
|
|
415
432
|
|
|
416
433
|
if target_dir.name == "agents":
|
|
417
434
|
return target_dir
|
|
418
|
-
|
|
435
|
+
if target_dir.name in [".claude-mpm", ".claude"]:
|
|
419
436
|
return target_dir / "agents"
|
|
420
|
-
|
|
421
|
-
return target_dir / ".claude" / "agents"
|
|
437
|
+
return target_dir / ".claude" / "agents"
|
|
422
438
|
|
|
423
439
|
def _filter_excluded_agents(
|
|
424
440
|
self,
|
|
@@ -494,7 +510,6 @@ class AsyncAgentDeploymentService:
|
|
|
494
510
|
|
|
495
511
|
def _build_agent_markdown_sync(self, agent_data: Dict[str, Any]) -> str:
|
|
496
512
|
"""Build agent markdown content matching the synchronous deployment format."""
|
|
497
|
-
from datetime import datetime
|
|
498
513
|
|
|
499
514
|
# Extract agent info from the loaded JSON data
|
|
500
515
|
agent_name = agent_data.get("_agent_name", "unknown")
|
|
@@ -521,7 +536,7 @@ class AsyncAgentDeploymentService:
|
|
|
521
536
|
)
|
|
522
537
|
|
|
523
538
|
# Get tags from new format (metadata.tags) or old format
|
|
524
|
-
|
|
539
|
+
(
|
|
525
540
|
agent_data.get("metadata", {}).get("tags")
|
|
526
541
|
or agent_data.get("configuration_fields", {}).get("tags")
|
|
527
542
|
or agent_data.get("tags")
|
|
@@ -583,7 +598,7 @@ class AsyncAgentDeploymentService:
|
|
|
583
598
|
f"description: {description}",
|
|
584
599
|
f"version: {version_string}",
|
|
585
600
|
f"base_version: {self._format_version_display(base_version)}",
|
|
586
|
-
|
|
601
|
+
"author: claude-mpm", # Identify as system agent for deployment
|
|
587
602
|
f"tools: {tools_str}",
|
|
588
603
|
f"model: {model}",
|
|
589
604
|
]
|
|
@@ -667,9 +682,8 @@ class AsyncAgentDeploymentService:
|
|
|
667
682
|
if isinstance(version_tuple, tuple) and len(version_tuple) == 3:
|
|
668
683
|
major, minor, patch = version_tuple
|
|
669
684
|
return f"{major}.{minor}.{patch}"
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
return str(version_tuple)
|
|
685
|
+
# Fallback for legacy format
|
|
686
|
+
return str(version_tuple)
|
|
673
687
|
|
|
674
688
|
async def cleanup(self):
|
|
675
689
|
"""Clean up resources."""
|
|
@@ -706,10 +720,9 @@ def deploy_agents_async_wrapper(
|
|
|
706
720
|
)
|
|
707
721
|
|
|
708
722
|
try:
|
|
709
|
-
|
|
723
|
+
return await service.deploy_agents_async(
|
|
710
724
|
target_dir=target_dir, force_rebuild=force_rebuild, config=config
|
|
711
725
|
)
|
|
712
|
-
return results
|
|
713
726
|
finally:
|
|
714
727
|
await service.cleanup()
|
|
715
728
|
|
|
@@ -717,7 +730,7 @@ def deploy_agents_async_wrapper(
|
|
|
717
730
|
try:
|
|
718
731
|
# Check if we're already in an async context
|
|
719
732
|
try:
|
|
720
|
-
|
|
733
|
+
asyncio.get_running_loop()
|
|
721
734
|
# We're in an async context, run in thread pool to avoid blocking
|
|
722
735
|
import concurrent.futures
|
|
723
736
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"""Base agent locator service for finding base agent configuration files."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import os
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BaseAgentLocator:
|
|
10
|
+
"""Service for locating base agent configuration files.
|
|
11
|
+
|
|
12
|
+
This service handles the priority-based search for base_agent.json
|
|
13
|
+
files across multiple possible locations including environment
|
|
14
|
+
variables, development paths, and user overrides.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, logger: Optional[logging.Logger] = None):
|
|
18
|
+
"""Initialize the base agent locator.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
logger: Optional logger instance
|
|
22
|
+
"""
|
|
23
|
+
self.logger = logger or logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
def find_base_agent_file(self, paths_agents_dir: Path) -> Path:
|
|
26
|
+
"""Find base agent file with priority-based search.
|
|
27
|
+
|
|
28
|
+
Priority order:
|
|
29
|
+
1. Environment variable override (CLAUDE_MPM_BASE_AGENT_PATH)
|
|
30
|
+
2. Current working directory (for local development)
|
|
31
|
+
3. Known development locations
|
|
32
|
+
4. User override location (~/.claude/agents/)
|
|
33
|
+
5. Framework agents directory (from paths)
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
paths_agents_dir: Framework agents directory from paths
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
Path to base agent file
|
|
40
|
+
"""
|
|
41
|
+
# Priority 0: Check environment variable override
|
|
42
|
+
env_path = os.environ.get("CLAUDE_MPM_BASE_AGENT_PATH")
|
|
43
|
+
if env_path:
|
|
44
|
+
env_base_agent = Path(env_path)
|
|
45
|
+
if env_base_agent.exists():
|
|
46
|
+
self.logger.info(
|
|
47
|
+
f"Using environment variable base_agent: {env_base_agent}"
|
|
48
|
+
)
|
|
49
|
+
return env_base_agent
|
|
50
|
+
self.logger.warning(
|
|
51
|
+
f"CLAUDE_MPM_BASE_AGENT_PATH set but file doesn't exist: {env_base_agent}"
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
# Priority 1: Check current working directory for local development
|
|
55
|
+
cwd = Path.cwd()
|
|
56
|
+
cwd_base_agent = cwd / "src" / "claude_mpm" / "agents" / "base_agent.json"
|
|
57
|
+
if cwd_base_agent.exists():
|
|
58
|
+
self.logger.info(
|
|
59
|
+
f"Using local development base_agent from cwd: {cwd_base_agent}"
|
|
60
|
+
)
|
|
61
|
+
return cwd_base_agent
|
|
62
|
+
|
|
63
|
+
# Priority 2: Check known development locations
|
|
64
|
+
known_dev_paths = [
|
|
65
|
+
Path(
|
|
66
|
+
"/Users/masa/Projects/claude-mpm/src/claude_mpm/agents/base_agent.json"
|
|
67
|
+
),
|
|
68
|
+
Path.home()
|
|
69
|
+
/ "Projects"
|
|
70
|
+
/ "claude-mpm"
|
|
71
|
+
/ "src"
|
|
72
|
+
/ "claude_mpm"
|
|
73
|
+
/ "agents"
|
|
74
|
+
/ "base_agent.json",
|
|
75
|
+
Path.home()
|
|
76
|
+
/ "projects"
|
|
77
|
+
/ "claude-mpm"
|
|
78
|
+
/ "src"
|
|
79
|
+
/ "claude_mpm"
|
|
80
|
+
/ "agents"
|
|
81
|
+
/ "base_agent.json",
|
|
82
|
+
]
|
|
83
|
+
|
|
84
|
+
for dev_path in known_dev_paths:
|
|
85
|
+
if dev_path.exists():
|
|
86
|
+
self.logger.info(f"Using development base_agent: {dev_path}")
|
|
87
|
+
return dev_path
|
|
88
|
+
|
|
89
|
+
# Priority 3: Check user override location
|
|
90
|
+
user_base_agent = Path.home() / ".claude" / "agents" / "base_agent.json"
|
|
91
|
+
if user_base_agent.exists():
|
|
92
|
+
self.logger.info(f"Using user override base_agent: {user_base_agent}")
|
|
93
|
+
return user_base_agent
|
|
94
|
+
|
|
95
|
+
# Priority 4: Use framework agents directory (fallback)
|
|
96
|
+
framework_base_agent = paths_agents_dir / "base_agent.json"
|
|
97
|
+
if framework_base_agent.exists():
|
|
98
|
+
self.logger.info(f"Using framework base_agent: {framework_base_agent}")
|
|
99
|
+
return framework_base_agent
|
|
100
|
+
|
|
101
|
+
# If still not found, log all searched locations and raise error
|
|
102
|
+
self.logger.error("Base agent file not found in any location:")
|
|
103
|
+
self.logger.error(f" 1. CWD: {cwd_base_agent}")
|
|
104
|
+
self.logger.error(f" 2. Dev paths: {known_dev_paths}")
|
|
105
|
+
self.logger.error(f" 3. User: {user_base_agent}")
|
|
106
|
+
self.logger.error(f" 4. Framework: {framework_base_agent}")
|
|
107
|
+
|
|
108
|
+
# Final fallback to framework path even if it doesn't exist
|
|
109
|
+
# (will fail later with better error message)
|
|
110
|
+
return framework_base_agent
|
|
111
|
+
|
|
112
|
+
def determine_source_tier(self, templates_dir: Path) -> str:
|
|
113
|
+
"""Determine the source tier for logging.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
templates_dir: Templates directory path
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Source tier string (framework/user/project)
|
|
120
|
+
"""
|
|
121
|
+
templates_str = str(templates_dir.resolve())
|
|
122
|
+
|
|
123
|
+
# Check if this is a user-level installation
|
|
124
|
+
if str(Path.home()) in templates_str and ".claude-mpm" in templates_str:
|
|
125
|
+
return "user"
|
|
126
|
+
|
|
127
|
+
# Check if this is a project-level installation
|
|
128
|
+
if ".claude-mpm" in templates_str:
|
|
129
|
+
return "project"
|
|
130
|
+
|
|
131
|
+
# Default to framework
|
|
132
|
+
return "framework"
|
|
@@ -87,8 +87,7 @@ class DeploymentConfig:
|
|
|
87
87
|
"""
|
|
88
88
|
if self.case_sensitive_exclusion:
|
|
89
89
|
return agent_name in self.excluded_agents
|
|
90
|
-
|
|
91
|
-
return agent_name.lower() in [name.lower() for name in self.excluded_agents]
|
|
90
|
+
return agent_name.lower() in [name.lower() for name in self.excluded_agents]
|
|
92
91
|
|
|
93
92
|
def get_effective_excluded_agents(self) -> List[str]:
|
|
94
93
|
"""Get the effective list of excluded agents.
|
|
@@ -159,12 +158,12 @@ class DeploymentConfig:
|
|
|
159
158
|
"use_async": self.use_async,
|
|
160
159
|
"target_dir": str(self.target_dir) if self.target_dir else None,
|
|
161
160
|
"templates_dir": str(self.templates_dir) if self.templates_dir else None,
|
|
162
|
-
"base_agent_path":
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
"working_directory":
|
|
166
|
-
|
|
167
|
-
|
|
161
|
+
"base_agent_path": (
|
|
162
|
+
str(self.base_agent_path) if self.base_agent_path else None
|
|
163
|
+
),
|
|
164
|
+
"working_directory": (
|
|
165
|
+
str(self.working_directory) if self.working_directory else None
|
|
166
|
+
),
|
|
168
167
|
"deploy_system_instructions": self.deploy_system_instructions,
|
|
169
168
|
"deploy_user_instructions": self.deploy_user_instructions,
|
|
170
169
|
"repair_existing_agents": self.repair_existing_agents,
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
"""Deployment results manager for tracking deployment outcomes."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DeploymentResultsManager:
|
|
10
|
+
"""Service for managing deployment results and metrics.
|
|
11
|
+
|
|
12
|
+
This service handles initialization and updates of deployment
|
|
13
|
+
results dictionaries, ensuring consistent structure across
|
|
14
|
+
all deployment operations.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
def __init__(self, logger: Optional[logging.Logger] = None):
|
|
18
|
+
"""Initialize the deployment results manager.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
logger: Optional logger instance
|
|
22
|
+
"""
|
|
23
|
+
self.logger = logger or logging.getLogger(__name__)
|
|
24
|
+
|
|
25
|
+
# Initialize deployment metrics tracking
|
|
26
|
+
self._deployment_metrics = {
|
|
27
|
+
"total_deployments": 0,
|
|
28
|
+
"successful_deployments": 0,
|
|
29
|
+
"failed_deployments": 0,
|
|
30
|
+
"migrations_performed": 0,
|
|
31
|
+
"version_migration_count": 0,
|
|
32
|
+
"agent_type_counts": {},
|
|
33
|
+
"deployment_errors": {},
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
def initialize_deployment_results(
|
|
37
|
+
self, agents_dir: Path, deployment_start_time: float
|
|
38
|
+
) -> Dict[str, Any]:
|
|
39
|
+
"""Initialize the deployment results dictionary.
|
|
40
|
+
|
|
41
|
+
WHY: Consistent result structure ensures all deployment
|
|
42
|
+
operations return the same format for easier processing.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
agents_dir: Target agents directory
|
|
46
|
+
deployment_start_time: Start time for metrics
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Initialized results dictionary
|
|
50
|
+
"""
|
|
51
|
+
return {
|
|
52
|
+
"target_dir": str(agents_dir),
|
|
53
|
+
"deployed": [],
|
|
54
|
+
"errors": [],
|
|
55
|
+
"skipped": [],
|
|
56
|
+
"updated": [],
|
|
57
|
+
"migrated": [], # Track agents migrated from old format
|
|
58
|
+
"converted": [], # Track YAML to MD conversions
|
|
59
|
+
"repaired": [], # Track agents with repaired frontmatter
|
|
60
|
+
"total": 0,
|
|
61
|
+
# METRICS: Add detailed timing and performance data to results
|
|
62
|
+
"metrics": {
|
|
63
|
+
"start_time": deployment_start_time,
|
|
64
|
+
"end_time": None,
|
|
65
|
+
"duration_ms": None,
|
|
66
|
+
"agent_timings": {}, # Track individual agent deployment times
|
|
67
|
+
"validation_times": {}, # Track template validation times
|
|
68
|
+
"resource_usage": {}, # Could track memory/CPU if needed
|
|
69
|
+
},
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
def record_agent_deployment(
|
|
73
|
+
self,
|
|
74
|
+
agent_name: str,
|
|
75
|
+
template_file: Path,
|
|
76
|
+
target_file: Path,
|
|
77
|
+
is_update: bool,
|
|
78
|
+
is_migration: bool,
|
|
79
|
+
reason: str,
|
|
80
|
+
agent_start_time: float,
|
|
81
|
+
results: Dict[str, Any],
|
|
82
|
+
logger: Optional[logging.Logger] = None,
|
|
83
|
+
) -> None:
|
|
84
|
+
"""Record deployment metrics and update results.
|
|
85
|
+
|
|
86
|
+
WHY: Centralized metrics recording ensures consistent tracking
|
|
87
|
+
of deployment performance and statistics.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
agent_name: Name of the agent
|
|
91
|
+
template_file: Template file
|
|
92
|
+
target_file: Target file
|
|
93
|
+
is_update: Whether this is an update
|
|
94
|
+
is_migration: Whether this is a migration
|
|
95
|
+
reason: Update/migration reason
|
|
96
|
+
agent_start_time: Start time for this agent
|
|
97
|
+
results: Results dictionary to update
|
|
98
|
+
logger: Optional logger for output
|
|
99
|
+
"""
|
|
100
|
+
logger = logger or self.logger
|
|
101
|
+
|
|
102
|
+
# METRICS: Record deployment time for this agent
|
|
103
|
+
agent_deployment_time = (time.time() - agent_start_time) * 1000 # Convert to ms
|
|
104
|
+
results["metrics"]["agent_timings"][agent_name] = agent_deployment_time
|
|
105
|
+
|
|
106
|
+
# METRICS: Update agent type deployment counts
|
|
107
|
+
self._deployment_metrics["agent_type_counts"][agent_name] = (
|
|
108
|
+
self._deployment_metrics["agent_type_counts"].get(agent_name, 0) + 1
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
deployment_info = {
|
|
112
|
+
"name": agent_name,
|
|
113
|
+
"template": str(template_file),
|
|
114
|
+
"target": str(target_file),
|
|
115
|
+
"deployment_time_ms": agent_deployment_time,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if is_migration:
|
|
119
|
+
deployment_info["reason"] = reason
|
|
120
|
+
results["migrated"].append(deployment_info)
|
|
121
|
+
logger.info(
|
|
122
|
+
f"Successfully migrated agent: {agent_name} to semantic versioning"
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# METRICS: Track migration statistics
|
|
126
|
+
self._deployment_metrics["migrations_performed"] += 1
|
|
127
|
+
self._deployment_metrics["version_migration_count"] += 1
|
|
128
|
+
|
|
129
|
+
elif is_update:
|
|
130
|
+
results["updated"].append(deployment_info)
|
|
131
|
+
logger.debug(f"Updated agent: {agent_name}")
|
|
132
|
+
else:
|
|
133
|
+
results["deployed"].append(deployment_info)
|
|
134
|
+
logger.debug(f"Built and deployed agent: {agent_name}")
|
|
135
|
+
|
|
136
|
+
def finalize_results(
|
|
137
|
+
self, results: Dict[str, Any], deployment_start_time: float
|
|
138
|
+
) -> None:
|
|
139
|
+
"""Finalize deployment results with end metrics.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
results: Results dictionary to finalize
|
|
143
|
+
deployment_start_time: Original start time
|
|
144
|
+
"""
|
|
145
|
+
deployment_end_time = time.time()
|
|
146
|
+
deployment_duration = (deployment_end_time - deployment_start_time) * 1000 # ms
|
|
147
|
+
|
|
148
|
+
results["metrics"]["end_time"] = deployment_end_time
|
|
149
|
+
results["metrics"]["duration_ms"] = deployment_duration
|
|
150
|
+
|
|
151
|
+
def update_deployment_metrics(
|
|
152
|
+
self, success: bool, error_type: Optional[str] = None
|
|
153
|
+
) -> None:
|
|
154
|
+
"""Update internal deployment metrics.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
success: Whether deployment succeeded
|
|
158
|
+
error_type: Type of error if failed
|
|
159
|
+
"""
|
|
160
|
+
self._deployment_metrics["total_deployments"] += 1
|
|
161
|
+
|
|
162
|
+
if success:
|
|
163
|
+
self._deployment_metrics["successful_deployments"] += 1
|
|
164
|
+
else:
|
|
165
|
+
self._deployment_metrics["failed_deployments"] += 1
|
|
166
|
+
if error_type:
|
|
167
|
+
self._deployment_metrics["deployment_errors"][error_type] = (
|
|
168
|
+
self._deployment_metrics["deployment_errors"].get(error_type, 0) + 1
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
def get_deployment_metrics(self) -> Dict[str, Any]:
|
|
172
|
+
"""Get current deployment metrics."""
|
|
173
|
+
return self._deployment_metrics.copy()
|
|
174
|
+
|
|
175
|
+
def reset_metrics(self) -> None:
|
|
176
|
+
"""Reset deployment metrics."""
|
|
177
|
+
self._deployment_metrics = {
|
|
178
|
+
"total_deployments": 0,
|
|
179
|
+
"successful_deployments": 0,
|
|
180
|
+
"failed_deployments": 0,
|
|
181
|
+
"migrations_performed": 0,
|
|
182
|
+
"version_migration_count": 0,
|
|
183
|
+
"agent_type_counts": {},
|
|
184
|
+
"deployment_errors": {},
|
|
185
|
+
}
|
|
@@ -1,52 +1,52 @@
|
|
|
1
1
|
"""Temporary wrapper to provide backward compatibility for CLI commands."""
|
|
2
2
|
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import Any, Dict
|
|
5
5
|
|
|
6
6
|
from claude_mpm.services.agents.deployment import AgentDeploymentService
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class DeploymentServiceWrapper:
|
|
10
10
|
"""Wrapper to provide backward-compatible methods for the CLI."""
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
def __init__(self, deployment_service: AgentDeploymentService):
|
|
13
13
|
"""Initialize wrapper with actual deployment service."""
|
|
14
14
|
self.service = deployment_service
|
|
15
15
|
# Pass through all attributes
|
|
16
16
|
for attr in dir(deployment_service):
|
|
17
|
-
if not attr.startswith(
|
|
17
|
+
if not attr.startswith("_") and not hasattr(self, attr):
|
|
18
18
|
setattr(self, attr, getattr(deployment_service, attr))
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
def deploy_system_agents(self, force: bool = False) -> Dict[str, Any]:
|
|
21
21
|
"""Deploy system agents only.
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
Args:
|
|
24
24
|
force: Force rebuild even if agents are up to date
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
Returns:
|
|
27
27
|
Deployment results
|
|
28
28
|
"""
|
|
29
29
|
# Deploy agents with default target (system agents location)
|
|
30
30
|
result = self.service.deploy_agents(
|
|
31
|
-
force_rebuild=force,
|
|
32
|
-
deployment_mode="update"
|
|
31
|
+
force_rebuild=force, deployment_mode="update"
|
|
33
32
|
)
|
|
34
|
-
|
|
33
|
+
|
|
35
34
|
# Transform result to expected format
|
|
36
35
|
return {
|
|
37
|
-
"deployed_count": len(result.get("deployed", []))
|
|
36
|
+
"deployed_count": len(result.get("deployed", []))
|
|
37
|
+
+ len(result.get("updated", [])),
|
|
38
38
|
"deployed": result.get("deployed", []),
|
|
39
39
|
"updated": result.get("updated", []),
|
|
40
40
|
"errors": result.get("errors", []),
|
|
41
|
-
"target_dir": result.get("target_dir", "")
|
|
41
|
+
"target_dir": result.get("target_dir", ""),
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
def deploy_project_agents(self, force: bool = False) -> Dict[str, Any]:
|
|
45
45
|
"""Deploy project agents only.
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
Args:
|
|
48
48
|
force: Force rebuild even if agents are up to date
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
Returns:
|
|
51
51
|
Deployment results
|
|
52
52
|
"""
|
|
@@ -58,14 +58,14 @@ class DeploymentServiceWrapper:
|
|
|
58
58
|
"deployed": [],
|
|
59
59
|
"updated": [],
|
|
60
60
|
"errors": [],
|
|
61
|
-
"target_dir": ""
|
|
61
|
+
"target_dir": "",
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
# For now, return empty result as project agents are handled differently
|
|
65
65
|
return {
|
|
66
66
|
"deployed_count": 0,
|
|
67
67
|
"deployed": [],
|
|
68
68
|
"updated": [],
|
|
69
69
|
"errors": [],
|
|
70
|
-
"target_dir": str(project_dir)
|
|
71
|
-
}
|
|
70
|
+
"target_dir": str(project_dir),
|
|
71
|
+
}
|
|
@@ -11,8 +11,8 @@ from .deployment_facade import DeploymentFacade
|
|
|
11
11
|
from .sync_deployment_executor import SyncDeploymentExecutor
|
|
12
12
|
|
|
13
13
|
__all__ = [
|
|
14
|
+
"AsyncDeploymentExecutor",
|
|
14
15
|
"DeploymentExecutor",
|
|
15
16
|
"DeploymentFacade",
|
|
16
|
-
"AsyncDeploymentExecutor",
|
|
17
17
|
"SyncDeploymentExecutor",
|
|
18
18
|
]
|