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,315 @@
|
|
|
1
|
+
"""Single agent deployer for deploying individual agents."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
import time
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Dict, Optional, Tuple
|
|
7
|
+
|
|
8
|
+
from claude_mpm.core.exceptions import AgentDeploymentError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class SingleAgentDeployer:
|
|
12
|
+
"""Service for deploying individual agents.
|
|
13
|
+
|
|
14
|
+
This service handles the deployment of single agent templates,
|
|
15
|
+
including version checking, building, and writing agent files.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
template_builder,
|
|
21
|
+
version_manager,
|
|
22
|
+
results_manager,
|
|
23
|
+
logger: Optional[logging.Logger] = None,
|
|
24
|
+
):
|
|
25
|
+
"""Initialize the single agent deployer.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
template_builder: Template builder service
|
|
29
|
+
version_manager: Version manager service
|
|
30
|
+
results_manager: Results manager service
|
|
31
|
+
logger: Optional logger instance
|
|
32
|
+
"""
|
|
33
|
+
self.template_builder = template_builder
|
|
34
|
+
self.version_manager = version_manager
|
|
35
|
+
self.results_manager = results_manager
|
|
36
|
+
self.logger = logger or logging.getLogger(__name__)
|
|
37
|
+
|
|
38
|
+
def deploy_single_agent(
|
|
39
|
+
self,
|
|
40
|
+
template_file: Path,
|
|
41
|
+
agents_dir: Path,
|
|
42
|
+
base_agent_data: dict,
|
|
43
|
+
base_agent_version: tuple,
|
|
44
|
+
force_rebuild: bool,
|
|
45
|
+
deployment_mode: str,
|
|
46
|
+
results: Dict[str, Any],
|
|
47
|
+
source_info: str = "unknown",
|
|
48
|
+
) -> None:
|
|
49
|
+
"""Deploy a single agent template.
|
|
50
|
+
|
|
51
|
+
WHY: Extracting single agent deployment logic reduces complexity
|
|
52
|
+
and makes the main deployment loop more readable.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
template_file: Agent template file
|
|
56
|
+
agents_dir: Target agents directory
|
|
57
|
+
base_agent_data: Base agent data
|
|
58
|
+
base_agent_version: Base agent version
|
|
59
|
+
force_rebuild: Whether to force rebuild
|
|
60
|
+
deployment_mode: Deployment mode (update/project)
|
|
61
|
+
results: Results dictionary to update
|
|
62
|
+
source_info: Source of the agent (system/project/user)
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
# METRICS: Track individual agent deployment time
|
|
66
|
+
agent_start_time = time.time()
|
|
67
|
+
|
|
68
|
+
agent_name = template_file.stem
|
|
69
|
+
target_file = agents_dir / f"{agent_name}.md"
|
|
70
|
+
|
|
71
|
+
# Check if agent needs update
|
|
72
|
+
needs_update, is_migration, reason = self._check_update_status(
|
|
73
|
+
target_file,
|
|
74
|
+
template_file,
|
|
75
|
+
base_agent_version,
|
|
76
|
+
force_rebuild,
|
|
77
|
+
deployment_mode,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Skip if exists and doesn't need update (only in update mode)
|
|
81
|
+
if (
|
|
82
|
+
target_file.exists()
|
|
83
|
+
and not needs_update
|
|
84
|
+
and deployment_mode != "project"
|
|
85
|
+
):
|
|
86
|
+
results["skipped"].append(agent_name)
|
|
87
|
+
self.logger.debug(f"Skipped up-to-date agent: {agent_name}")
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
# Build the agent file as markdown with YAML frontmatter
|
|
91
|
+
agent_content = self.template_builder.build_agent_markdown(
|
|
92
|
+
agent_name, template_file, base_agent_data, source_info
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Write the agent file
|
|
96
|
+
is_update = target_file.exists()
|
|
97
|
+
target_file.write_text(agent_content)
|
|
98
|
+
|
|
99
|
+
# Record metrics and update results
|
|
100
|
+
self.results_manager.record_agent_deployment(
|
|
101
|
+
agent_name,
|
|
102
|
+
template_file,
|
|
103
|
+
target_file,
|
|
104
|
+
is_update,
|
|
105
|
+
is_migration,
|
|
106
|
+
reason,
|
|
107
|
+
agent_start_time,
|
|
108
|
+
results,
|
|
109
|
+
self.logger,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
except AgentDeploymentError as e:
|
|
113
|
+
# Re-raise our custom exceptions
|
|
114
|
+
self.logger.error(str(e))
|
|
115
|
+
results["errors"].append(str(e))
|
|
116
|
+
except Exception as e:
|
|
117
|
+
# Wrap generic exceptions with context
|
|
118
|
+
error_msg = f"Failed to build {template_file.name}: {e}"
|
|
119
|
+
self.logger.error(error_msg)
|
|
120
|
+
results["errors"].append(error_msg)
|
|
121
|
+
|
|
122
|
+
def _check_update_status(
|
|
123
|
+
self,
|
|
124
|
+
target_file: Path,
|
|
125
|
+
template_file: Path,
|
|
126
|
+
base_agent_version: tuple,
|
|
127
|
+
force_rebuild: bool,
|
|
128
|
+
deployment_mode: str,
|
|
129
|
+
) -> Tuple[bool, bool, str]:
|
|
130
|
+
"""Check if agent needs update and determine status.
|
|
131
|
+
|
|
132
|
+
WHY: Centralized update checking logic ensures consistent
|
|
133
|
+
version comparison and migration detection.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
target_file: Target agent file
|
|
137
|
+
template_file: Template file
|
|
138
|
+
base_agent_version: Base agent version
|
|
139
|
+
force_rebuild: Whether to force rebuild
|
|
140
|
+
deployment_mode: Deployment mode
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
Tuple of (needs_update, is_migration, reason)
|
|
144
|
+
"""
|
|
145
|
+
needs_update = force_rebuild
|
|
146
|
+
is_migration = False
|
|
147
|
+
reason = ""
|
|
148
|
+
|
|
149
|
+
# In project deployment mode, always deploy regardless of version
|
|
150
|
+
if deployment_mode == "project":
|
|
151
|
+
if target_file.exists():
|
|
152
|
+
needs_update = True
|
|
153
|
+
self.logger.debug(
|
|
154
|
+
f"Project deployment mode: will deploy {template_file.stem}"
|
|
155
|
+
)
|
|
156
|
+
else:
|
|
157
|
+
needs_update = True
|
|
158
|
+
elif not needs_update and target_file.exists():
|
|
159
|
+
# In update mode, check version compatibility
|
|
160
|
+
needs_update, reason = self.version_manager.check_agent_needs_update(
|
|
161
|
+
target_file, template_file, base_agent_version
|
|
162
|
+
)
|
|
163
|
+
if needs_update:
|
|
164
|
+
# Check if this is a migration from old format
|
|
165
|
+
if "migration needed" in reason:
|
|
166
|
+
is_migration = True
|
|
167
|
+
self.logger.info(f"Migrating agent {template_file.stem}: {reason}")
|
|
168
|
+
else:
|
|
169
|
+
self.logger.info(
|
|
170
|
+
f"Agent {template_file.stem} needs update: {reason}"
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
return needs_update, is_migration, reason
|
|
174
|
+
|
|
175
|
+
def deploy_agent(
|
|
176
|
+
self,
|
|
177
|
+
agent_name: str,
|
|
178
|
+
templates_dir: Path,
|
|
179
|
+
target_dir: Path,
|
|
180
|
+
base_agent_path: Path,
|
|
181
|
+
force_rebuild: bool = False,
|
|
182
|
+
working_directory: Optional[Path] = None,
|
|
183
|
+
) -> bool:
|
|
184
|
+
"""Deploy a single agent to the specified directory.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
agent_name: Name of the agent to deploy
|
|
188
|
+
templates_dir: Directory containing templates
|
|
189
|
+
target_dir: Target directory for deployment (Path object)
|
|
190
|
+
base_agent_path: Path to base agent configuration
|
|
191
|
+
force_rebuild: Whether to force rebuild even if version is current
|
|
192
|
+
working_directory: Working directory for determining agent source
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
True if deployment was successful, False otherwise
|
|
196
|
+
|
|
197
|
+
WHY: Single agent deployment because:
|
|
198
|
+
- Users may want to deploy specific agents only
|
|
199
|
+
- Reduces deployment time for targeted updates
|
|
200
|
+
- Enables selective agent management in projects
|
|
201
|
+
"""
|
|
202
|
+
try:
|
|
203
|
+
# Find the template file
|
|
204
|
+
template_file = templates_dir / f"{agent_name}.json"
|
|
205
|
+
if not template_file.exists():
|
|
206
|
+
self.logger.error(f"Agent template not found: {agent_name}")
|
|
207
|
+
return False
|
|
208
|
+
|
|
209
|
+
# Ensure target directory exists
|
|
210
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
211
|
+
|
|
212
|
+
# Build and deploy the agent
|
|
213
|
+
target_file = target_dir / f"{agent_name}.md"
|
|
214
|
+
|
|
215
|
+
# Check if update is needed
|
|
216
|
+
if not force_rebuild and target_file.exists():
|
|
217
|
+
# Load base agent data for version checking
|
|
218
|
+
base_agent_data = {}
|
|
219
|
+
base_agent_version = (0, 0, 0)
|
|
220
|
+
if base_agent_path.exists():
|
|
221
|
+
try:
|
|
222
|
+
import json
|
|
223
|
+
|
|
224
|
+
base_agent_data = json.loads(base_agent_path.read_text())
|
|
225
|
+
base_agent_version = self.version_manager.parse_version(
|
|
226
|
+
base_agent_data.get("base_version")
|
|
227
|
+
or base_agent_data.get("version", 0)
|
|
228
|
+
)
|
|
229
|
+
except Exception as e:
|
|
230
|
+
self.logger.warning(
|
|
231
|
+
f"Could not load base agent for version check: {e}"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
needs_update, reason = self.version_manager.check_agent_needs_update(
|
|
235
|
+
target_file, template_file, base_agent_version
|
|
236
|
+
)
|
|
237
|
+
if not needs_update:
|
|
238
|
+
self.logger.info(f"Agent {agent_name} is up to date")
|
|
239
|
+
return True
|
|
240
|
+
self.logger.info(f"Updating agent {agent_name}: {reason}")
|
|
241
|
+
|
|
242
|
+
# Load base agent data for building
|
|
243
|
+
base_agent_data = {}
|
|
244
|
+
if base_agent_path.exists():
|
|
245
|
+
try:
|
|
246
|
+
import json
|
|
247
|
+
|
|
248
|
+
base_agent_data = json.loads(base_agent_path.read_text())
|
|
249
|
+
except Exception as e:
|
|
250
|
+
self.logger.warning(f"Could not load base agent: {e}")
|
|
251
|
+
|
|
252
|
+
# Build the agent markdown
|
|
253
|
+
# For single agent deployment, determine source from template location
|
|
254
|
+
source_info = self._determine_agent_source(
|
|
255
|
+
template_file, working_directory or Path.cwd()
|
|
256
|
+
)
|
|
257
|
+
agent_content = self.template_builder.build_agent_markdown(
|
|
258
|
+
agent_name, template_file, base_agent_data, source_info
|
|
259
|
+
)
|
|
260
|
+
if not agent_content:
|
|
261
|
+
self.logger.error(f"Failed to build agent content for {agent_name}")
|
|
262
|
+
return False
|
|
263
|
+
|
|
264
|
+
# Write to target file
|
|
265
|
+
target_file.write_text(agent_content)
|
|
266
|
+
self.logger.info(
|
|
267
|
+
f"Successfully deployed agent: {agent_name} to {target_file}"
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
return True
|
|
271
|
+
|
|
272
|
+
except AgentDeploymentError:
|
|
273
|
+
# Re-raise our custom exceptions
|
|
274
|
+
raise
|
|
275
|
+
except Exception as e:
|
|
276
|
+
# Wrap generic exceptions with context
|
|
277
|
+
raise AgentDeploymentError(
|
|
278
|
+
f"Failed to deploy agent {agent_name}",
|
|
279
|
+
context={"agent_name": agent_name, "error": str(e)},
|
|
280
|
+
) from e
|
|
281
|
+
|
|
282
|
+
def _determine_agent_source(
|
|
283
|
+
self, template_path: Path, working_directory: Path
|
|
284
|
+
) -> str:
|
|
285
|
+
"""Determine the source of an agent from its template path.
|
|
286
|
+
|
|
287
|
+
WHY: When deploying single agents, we need to track their source
|
|
288
|
+
for proper version management and debugging.
|
|
289
|
+
|
|
290
|
+
Args:
|
|
291
|
+
template_path: Path to the agent template
|
|
292
|
+
working_directory: Current working directory
|
|
293
|
+
|
|
294
|
+
Returns:
|
|
295
|
+
Source string (system/project/user/unknown)
|
|
296
|
+
"""
|
|
297
|
+
template_str = str(template_path.resolve())
|
|
298
|
+
|
|
299
|
+
# Check if it's a system template
|
|
300
|
+
if (
|
|
301
|
+
"/claude_mpm/agents/templates/" in template_str
|
|
302
|
+
or "/src/claude_mpm/agents/templates/" in template_str
|
|
303
|
+
):
|
|
304
|
+
return "system"
|
|
305
|
+
|
|
306
|
+
# Check if it's a project agent
|
|
307
|
+
if "/.claude-mpm/agents/" in template_str:
|
|
308
|
+
# Check if it's in the current working directory
|
|
309
|
+
if str(working_directory) in template_str:
|
|
310
|
+
return "project"
|
|
311
|
+
# Check if it's in user home
|
|
312
|
+
if str(Path.home()) in template_str:
|
|
313
|
+
return "user"
|
|
314
|
+
|
|
315
|
+
return "unknown"
|
|
@@ -18,8 +18,8 @@ from .user_strategy import UserAgentDeploymentStrategy
|
|
|
18
18
|
__all__ = [
|
|
19
19
|
"BaseDeploymentStrategy",
|
|
20
20
|
"DeploymentContext",
|
|
21
|
-
"
|
|
21
|
+
"DeploymentStrategySelector",
|
|
22
22
|
"ProjectAgentDeploymentStrategy",
|
|
23
|
+
"SystemAgentDeploymentStrategy",
|
|
23
24
|
"UserAgentDeploymentStrategy",
|
|
24
|
-
"DeploymentStrategySelector",
|
|
25
25
|
]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from pathlib import Path
|
|
6
|
-
from typing import
|
|
6
|
+
from typing import List, Optional
|
|
7
7
|
|
|
8
8
|
from claude_mpm.core.config import Config
|
|
9
9
|
|
|
@@ -48,7 +48,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
48
48
|
Returns:
|
|
49
49
|
True if this strategy should handle the deployment
|
|
50
50
|
"""
|
|
51
|
-
pass
|
|
52
51
|
|
|
53
52
|
@abstractmethod
|
|
54
53
|
def determine_target_directory(self, context: DeploymentContext) -> Path:
|
|
@@ -60,7 +59,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
60
59
|
Returns:
|
|
61
60
|
Path where agents should be deployed
|
|
62
61
|
"""
|
|
63
|
-
pass
|
|
64
62
|
|
|
65
63
|
@abstractmethod
|
|
66
64
|
def get_templates_directory(self, context: DeploymentContext) -> Path:
|
|
@@ -72,7 +70,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
72
70
|
Returns:
|
|
73
71
|
Path to the templates directory
|
|
74
72
|
"""
|
|
75
|
-
pass
|
|
76
73
|
|
|
77
74
|
@abstractmethod
|
|
78
75
|
def get_excluded_agents(self, context: DeploymentContext) -> List[str]:
|
|
@@ -84,7 +81,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
84
81
|
Returns:
|
|
85
82
|
List of agent names to exclude from deployment
|
|
86
83
|
"""
|
|
87
|
-
pass
|
|
88
84
|
|
|
89
85
|
@abstractmethod
|
|
90
86
|
def should_deploy_system_instructions(self, context: DeploymentContext) -> bool:
|
|
@@ -96,7 +92,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
96
92
|
Returns:
|
|
97
93
|
True if system instructions should be deployed
|
|
98
94
|
"""
|
|
99
|
-
pass
|
|
100
95
|
|
|
101
96
|
@abstractmethod
|
|
102
97
|
def get_deployment_priority(self) -> int:
|
|
@@ -108,7 +103,6 @@ class BaseDeploymentStrategy(ABC):
|
|
|
108
103
|
Returns:
|
|
109
104
|
Priority number (lower = higher priority)
|
|
110
105
|
"""
|
|
111
|
-
pass
|
|
112
106
|
|
|
113
107
|
def __str__(self) -> str:
|
|
114
108
|
"""String representation of the strategy."""
|
|
@@ -58,10 +58,7 @@ class ProjectAgentDeploymentStrategy(BaseDeploymentStrategy):
|
|
|
58
58
|
pass
|
|
59
59
|
|
|
60
60
|
# Check if deployment_mode is "project" - this should be sufficient
|
|
61
|
-
|
|
62
|
-
return True
|
|
63
|
-
|
|
64
|
-
return False
|
|
61
|
+
return context.deployment_mode == "project"
|
|
65
62
|
|
|
66
63
|
def determine_target_directory(self, context: DeploymentContext) -> Path:
|
|
67
64
|
"""Determine target directory for project agents.
|
|
@@ -76,9 +76,8 @@ class SystemAgentDeploymentStrategy(BaseDeploymentStrategy):
|
|
|
76
76
|
# Always deploy to project directory
|
|
77
77
|
if context.working_directory:
|
|
78
78
|
return context.working_directory / ".claude" / "agents"
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return Path.cwd() / ".claude" / "agents"
|
|
79
|
+
# Fallback to current working directory if not specified
|
|
80
|
+
return Path.cwd() / ".claude" / "agents"
|
|
82
81
|
|
|
83
82
|
def get_templates_directory(self, context: DeploymentContext) -> Path:
|
|
84
83
|
"""Get templates directory for system agents.
|
|
@@ -49,10 +49,7 @@ class UserAgentDeploymentStrategy(BaseDeploymentStrategy):
|
|
|
49
49
|
# Check for user-specific environment variable
|
|
50
50
|
import os
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
return True
|
|
54
|
-
|
|
55
|
-
return False
|
|
52
|
+
return "CLAUDE_MPM_USER_PWD" in os.environ
|
|
56
53
|
|
|
57
54
|
def determine_target_directory(self, context: DeploymentContext) -> Path:
|
|
58
55
|
"""Determine target directory for user agents.
|
|
@@ -70,9 +67,8 @@ class UserAgentDeploymentStrategy(BaseDeploymentStrategy):
|
|
|
70
67
|
# Always deploy to project directory
|
|
71
68
|
if context.working_directory:
|
|
72
69
|
return context.working_directory / ".claude" / "agents"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return Path.cwd() / ".claude" / "agents"
|
|
70
|
+
# Fallback to current working directory if not specified
|
|
71
|
+
return Path.cwd() / ".claude" / "agents"
|
|
76
72
|
|
|
77
73
|
def get_templates_directory(self, context: DeploymentContext) -> Path:
|
|
78
74
|
"""Get templates directory for user agents.
|
|
@@ -11,8 +11,8 @@ from .template_validator import TemplateValidator
|
|
|
11
11
|
from .validation_result import ValidationResult, ValidationSeverity
|
|
12
12
|
|
|
13
13
|
__all__ = [
|
|
14
|
-
"DeploymentValidator",
|
|
15
14
|
"AgentValidator",
|
|
15
|
+
"DeploymentValidator",
|
|
16
16
|
"TemplateValidator",
|
|
17
17
|
"ValidationResult",
|
|
18
18
|
"ValidationSeverity",
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import Any, Dict
|
|
5
|
+
from typing import Any, Dict
|
|
6
6
|
|
|
7
7
|
from claude_mpm.core.logger import get_logger
|
|
8
8
|
|
|
9
|
-
from .validation_result import ValidationResult
|
|
9
|
+
from .validation_result import ValidationResult
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class TemplateValidator:
|
|
@@ -175,12 +175,11 @@ class ValidationResult:
|
|
|
175
175
|
Returns:
|
|
176
176
|
New ValidationResult with merged issues
|
|
177
177
|
"""
|
|
178
|
-
|
|
178
|
+
return ValidationResult(
|
|
179
179
|
is_valid=self.is_valid and other.is_valid,
|
|
180
180
|
issues=self.issues + other.issues,
|
|
181
181
|
metadata={**self.metadata, **other.metadata},
|
|
182
182
|
)
|
|
183
|
-
return merged
|
|
184
183
|
|
|
185
184
|
def to_dict(self) -> Dict[str, Any]:
|
|
186
185
|
"""Convert validation result to dictionary.
|
|
@@ -208,10 +207,7 @@ class ValidationResult:
|
|
|
208
207
|
|
|
209
208
|
def __str__(self) -> str:
|
|
210
209
|
"""String representation of the validation result."""
|
|
211
|
-
if self.is_valid
|
|
212
|
-
status = "VALID"
|
|
213
|
-
else:
|
|
214
|
-
status = "INVALID"
|
|
210
|
+
status = "VALID" if self.is_valid else "INVALID"
|
|
215
211
|
|
|
216
212
|
summary = f"Validation {status}"
|
|
217
213
|
|
|
@@ -20,7 +20,6 @@ multi-file implementation for better maintainability.
|
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
22
|
import asyncio
|
|
23
|
-
import hashlib
|
|
24
23
|
import json
|
|
25
24
|
import logging
|
|
26
25
|
import os
|
|
@@ -28,7 +27,7 @@ from dataclasses import dataclass, field
|
|
|
28
27
|
from datetime import datetime
|
|
29
28
|
from enum import Enum
|
|
30
29
|
from pathlib import Path
|
|
31
|
-
from typing import Any, Dict, List, Optional,
|
|
30
|
+
from typing import Any, Dict, List, Optional, Tuple
|
|
32
31
|
|
|
33
32
|
import yaml
|
|
34
33
|
|
|
@@ -37,7 +36,6 @@ from claude_mpm.core.config import Config
|
|
|
37
36
|
from claude_mpm.core.unified_paths import get_path_manager
|
|
38
37
|
from claude_mpm.services.agents.registry import AgentRegistry
|
|
39
38
|
from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
|
|
40
|
-
from claude_mpm.utils.path_operations import path_ops
|
|
41
39
|
|
|
42
40
|
logger = logging.getLogger(__name__)
|
|
43
41
|
|
|
@@ -146,7 +144,7 @@ class AgentProfileLoader(BaseService):
|
|
|
146
144
|
# Performance tracking
|
|
147
145
|
self.load_metrics: Dict[str, float] = {}
|
|
148
146
|
|
|
149
|
-
logger.info(
|
|
147
|
+
logger.info("AgentProfileLoader initialized successfully")
|
|
150
148
|
logger.info(f" Working directory: {self.working_directory}")
|
|
151
149
|
logger.info(f" Framework path: {self.framework_path}")
|
|
152
150
|
logger.info(f" Tier paths: {list(self.tier_paths.keys())}")
|
|
@@ -329,7 +327,7 @@ class AgentProfileLoader(BaseService):
|
|
|
329
327
|
instructions = data.get("instructions", "")
|
|
330
328
|
|
|
331
329
|
# Create profile
|
|
332
|
-
|
|
330
|
+
return AgentProfile(
|
|
333
331
|
name=data.get("name", file_path.stem),
|
|
334
332
|
role=data.get("role", "agent"),
|
|
335
333
|
description=data.get("description", ""),
|
|
@@ -342,8 +340,6 @@ class AgentProfileLoader(BaseService):
|
|
|
342
340
|
status=ProfileStatus.LOADED,
|
|
343
341
|
)
|
|
344
342
|
|
|
345
|
-
return profile
|
|
346
|
-
|
|
347
343
|
except Exception as e:
|
|
348
344
|
logger.error(f"Error parsing profile {file_path}: {e}")
|
|
349
345
|
return AgentProfile(
|
|
@@ -421,9 +417,7 @@ class AgentProfileLoader(BaseService):
|
|
|
421
417
|
for file_path in tier_path.glob(pattern):
|
|
422
418
|
agent_name = file_path.stem
|
|
423
419
|
# Remove common suffixes
|
|
424
|
-
if agent_name.endswith("_agent"):
|
|
425
|
-
agent_name = agent_name[:-6]
|
|
426
|
-
elif agent_name.endswith("-agent"):
|
|
420
|
+
if agent_name.endswith(("_agent", "-agent")):
|
|
427
421
|
agent_name = agent_name[:-6]
|
|
428
422
|
|
|
429
423
|
if agent_name not in agents:
|
|
@@ -448,7 +442,7 @@ class AgentProfileLoader(BaseService):
|
|
|
448
442
|
for agents in discovered.values():
|
|
449
443
|
all_agents.update(agents)
|
|
450
444
|
|
|
451
|
-
return sorted(
|
|
445
|
+
return sorted(all_agents)
|
|
452
446
|
|
|
453
447
|
# ========================================================================
|
|
454
448
|
# Improved Prompts Management
|
|
@@ -461,7 +455,7 @@ class AgentProfileLoader(BaseService):
|
|
|
461
455
|
|
|
462
456
|
if prompt_file.exists():
|
|
463
457
|
try:
|
|
464
|
-
with open(prompt_file
|
|
458
|
+
with open(prompt_file) as f:
|
|
465
459
|
data = json.load(f)
|
|
466
460
|
for prompt_data in data:
|
|
467
461
|
prompt = ImprovedPrompt(
|
|
@@ -67,7 +67,9 @@ class BaseAgentStructure:
|
|
|
67
67
|
class BaseAgentManager(ConfigServiceBase):
|
|
68
68
|
"""Manages base_agent.md with structured updates and validation."""
|
|
69
69
|
|
|
70
|
-
def __init__(
|
|
70
|
+
def __init__(
|
|
71
|
+
self, agents_dir: Optional[Path] = None, config: Optional[Dict[str, Any]] = None
|
|
72
|
+
):
|
|
71
73
|
"""Initialize BaseAgentManager."""
|
|
72
74
|
super().__init__("base_agent_manager", config=config)
|
|
73
75
|
|
|
@@ -75,7 +77,7 @@ class BaseAgentManager(ConfigServiceBase):
|
|
|
75
77
|
self.agents_dir = self.get_config_value(
|
|
76
78
|
"agents_dir",
|
|
77
79
|
default=agents_dir or Path(__file__).parent.parent / "agents",
|
|
78
|
-
config_type=Path
|
|
80
|
+
config_type=Path,
|
|
79
81
|
)
|
|
80
82
|
self.base_agent_path = self.agents_dir / "BASE_AGENT_TEMPLATE.md"
|
|
81
83
|
self.cache = SharedPromptCache.get_instance()
|
|
@@ -347,9 +349,7 @@ class BaseAgentManager(ConfigServiceBase):
|
|
|
347
349
|
items = []
|
|
348
350
|
for line in content.split("\n"):
|
|
349
351
|
line = line.strip()
|
|
350
|
-
if line.startswith("- "):
|
|
351
|
-
items.append(line[2:].strip())
|
|
352
|
-
elif line.startswith("* "):
|
|
352
|
+
if line.startswith(("- ", "* ")):
|
|
353
353
|
items.append(line[2:].strip())
|
|
354
354
|
elif line.startswith("**") and line.endswith("**"):
|
|
355
355
|
# Skip bold headers
|
|
@@ -12,14 +12,12 @@ This service integrates with the main agent_loader.py to provide
|
|
|
12
12
|
markdown-based agent profiles alongside JSON-based templates.
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
-
import json
|
|
16
15
|
import logging
|
|
17
16
|
from pathlib import Path
|
|
18
17
|
from typing import Any, Dict, Optional
|
|
19
18
|
|
|
20
19
|
from claude_mpm.agents.agent_loader import (
|
|
21
20
|
AgentTier,
|
|
22
|
-
get_agent_tier,
|
|
23
21
|
list_agents_by_tier,
|
|
24
22
|
)
|
|
25
23
|
from claude_mpm.core.unified_paths import get_path_manager
|
|
@@ -97,7 +95,7 @@ class FrameworkAgentLoader:
|
|
|
97
95
|
current = Path.cwd()
|
|
98
96
|
|
|
99
97
|
# Check current directory and parents
|
|
100
|
-
for path in [current
|
|
98
|
+
for path in [current, *list(current.parents)]:
|
|
101
99
|
framework_instructions = path / "agents" / "INSTRUCTIONS.md"
|
|
102
100
|
framework_claude = path / "agents" / "CLAUDE.md" # Legacy
|
|
103
101
|
if framework_instructions.exists() or framework_claude.exists():
|
|
@@ -110,7 +108,7 @@ class FrameworkAgentLoader:
|
|
|
110
108
|
current = Path.cwd()
|
|
111
109
|
|
|
112
110
|
# Check current directory and parents for .claude-mpm
|
|
113
|
-
for path in [current
|
|
111
|
+
for path in [current, *list(current.parents)]:
|
|
114
112
|
claude_pm_dir = path / get_path_manager().CONFIG_DIR
|
|
115
113
|
if claude_pm_dir.exists():
|
|
116
114
|
return path
|
|
@@ -44,15 +44,13 @@ class AgentCapabilitiesGenerator:
|
|
|
44
44
|
)
|
|
45
45
|
|
|
46
46
|
# Render template
|
|
47
|
-
|
|
47
|
+
return self.template.render(
|
|
48
48
|
core_agents=core_agent_list,
|
|
49
49
|
detailed_capabilities=detailed_capabilities,
|
|
50
50
|
agents_by_tier=agents_by_tier,
|
|
51
51
|
total_agents=len(deployed_agents),
|
|
52
52
|
)
|
|
53
53
|
|
|
54
|
-
return content
|
|
55
|
-
|
|
56
54
|
except Exception as e:
|
|
57
55
|
logger.error(f"Failed to generate capabilities section: {e}")
|
|
58
56
|
# Return fallback content on error
|