claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__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/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 +271 -268
- 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 +192 -141
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +120 -84
- claude_mpm/cli/commands/run_config_checker.py +4 -5
- 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 +204 -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 +20 -23
- 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 +581 -280
- 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 -15
- 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 +93 -38
- claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- 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/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 +136 -106
- 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/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- 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/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 +280 -160
- 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/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +10 -6
- 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/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/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/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
- 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.2.dist-info}/METADATA +1 -1
- claude_mpm-4.1.2.dist-info/RECORD +498 -0
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -10,25 +10,27 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
10
10
|
|
|
11
11
|
from ...core.config import Config
|
|
12
12
|
from ...core.mixins import LoggerMixin
|
|
13
|
-
from ...core.shared.config_loader import ConfigLoader
|
|
13
|
+
from ...core.shared.config_loader import ConfigLoader
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
class ConfigServiceBase(LoggerMixin, ABC):
|
|
17
17
|
"""
|
|
18
18
|
Base class for services that heavily use configuration.
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
Provides common patterns:
|
|
21
21
|
- Configuration loading and validation
|
|
22
22
|
- Environment variable handling
|
|
23
23
|
- Configuration file discovery
|
|
24
24
|
- Default value management
|
|
25
25
|
"""
|
|
26
|
-
|
|
27
|
-
def __init__(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
service_name: str,
|
|
30
|
+
config: Optional[Union[Dict[str, Any], Config]] = None,
|
|
31
|
+
config_section: Optional[str] = None,
|
|
32
|
+
config_dir: Optional[Union[str, Path]] = None,
|
|
33
|
+
):
|
|
32
34
|
"""
|
|
33
35
|
Initialize config service.
|
|
34
36
|
|
|
@@ -51,30 +53,31 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
51
53
|
else:
|
|
52
54
|
# Use ConfigLoader to load service configuration
|
|
53
55
|
self._config = self._config_loader.load_service_config(
|
|
54
|
-
service_name=service_name,
|
|
55
|
-
config_dir=config_dir
|
|
56
|
+
service_name=service_name, config_dir=config_dir
|
|
56
57
|
)
|
|
57
58
|
|
|
58
59
|
# Cache for processed config values
|
|
59
60
|
self._config_cache: Dict[str, Any] = {}
|
|
60
|
-
|
|
61
|
-
def get_config_value(
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
|
|
62
|
+
def get_config_value(
|
|
63
|
+
self,
|
|
64
|
+
key: str,
|
|
65
|
+
default: Any = None,
|
|
66
|
+
required: bool = False,
|
|
67
|
+
config_type: Optional[type] = None,
|
|
68
|
+
) -> Any:
|
|
66
69
|
"""
|
|
67
70
|
Get configuration value with validation and caching.
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
Args:
|
|
70
73
|
key: Configuration key (supports dot notation)
|
|
71
74
|
default: Default value if not found
|
|
72
75
|
required: Whether the value is required
|
|
73
76
|
config_type: Expected type for validation
|
|
74
|
-
|
|
77
|
+
|
|
75
78
|
Returns:
|
|
76
79
|
Configuration value
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
Raises:
|
|
79
82
|
ValueError: If required value is missing or type validation fails
|
|
80
83
|
"""
|
|
@@ -83,103 +86,107 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
83
86
|
full_key = f"{self.config_section}.{key}"
|
|
84
87
|
else:
|
|
85
88
|
full_key = key
|
|
86
|
-
|
|
89
|
+
|
|
87
90
|
# Check cache first
|
|
88
91
|
if full_key in self._config_cache:
|
|
89
92
|
return self._config_cache[full_key]
|
|
90
|
-
|
|
93
|
+
|
|
91
94
|
# Get value from config
|
|
92
95
|
value = self._config.get(full_key, default)
|
|
93
|
-
|
|
96
|
+
|
|
94
97
|
# Handle required values
|
|
95
98
|
if required and value is None:
|
|
96
99
|
raise ValueError(f"Required configuration value missing: {full_key}")
|
|
97
|
-
|
|
100
|
+
|
|
98
101
|
# Type validation
|
|
99
102
|
if config_type is not None and value is not None:
|
|
100
103
|
if not isinstance(value, config_type):
|
|
101
104
|
try:
|
|
102
105
|
# Try to convert
|
|
103
106
|
if config_type == bool and isinstance(value, str):
|
|
104
|
-
value = value.lower() in (
|
|
107
|
+
value = value.lower() in ("true", "1", "yes", "on")
|
|
105
108
|
elif config_type == Path:
|
|
106
109
|
value = Path(value).expanduser()
|
|
107
110
|
else:
|
|
108
111
|
value = config_type(value)
|
|
109
112
|
except (ValueError, TypeError) as e:
|
|
110
|
-
raise ValueError(
|
|
111
|
-
|
|
113
|
+
raise ValueError(
|
|
114
|
+
f"Invalid type for {full_key}: expected {config_type.__name__}, got {type(value).__name__}"
|
|
115
|
+
) from e
|
|
116
|
+
|
|
112
117
|
# Cache the processed value
|
|
113
118
|
self._config_cache[full_key] = value
|
|
114
119
|
return value
|
|
115
|
-
|
|
116
|
-
def get_config_section(self, section: str = None) -> Dict[str, Any]:
|
|
120
|
+
|
|
121
|
+
def get_config_section(self, section: Optional[str] = None) -> Dict[str, Any]:
|
|
117
122
|
"""
|
|
118
123
|
Get entire configuration section.
|
|
119
|
-
|
|
124
|
+
|
|
120
125
|
Args:
|
|
121
126
|
section: Section name (defaults to service section)
|
|
122
|
-
|
|
127
|
+
|
|
123
128
|
Returns:
|
|
124
129
|
Configuration section as dictionary
|
|
125
130
|
"""
|
|
126
131
|
section_name = section or self.config_section
|
|
127
132
|
return self._config.get(section_name, {})
|
|
128
|
-
|
|
133
|
+
|
|
129
134
|
def validate_config(self, schema: Dict[str, Any]) -> List[str]:
|
|
130
135
|
"""
|
|
131
136
|
Validate configuration against a schema.
|
|
132
|
-
|
|
137
|
+
|
|
133
138
|
Args:
|
|
134
139
|
schema: Validation schema
|
|
135
|
-
|
|
140
|
+
|
|
136
141
|
Returns:
|
|
137
142
|
List of validation errors
|
|
138
143
|
"""
|
|
139
144
|
errors = []
|
|
140
|
-
|
|
145
|
+
|
|
141
146
|
# Check required fields
|
|
142
|
-
required_fields = schema.get(
|
|
147
|
+
required_fields = schema.get("required", [])
|
|
143
148
|
for field in required_fields:
|
|
144
149
|
try:
|
|
145
150
|
self.get_config_value(field, required=True)
|
|
146
151
|
except ValueError as e:
|
|
147
152
|
errors.append(str(e))
|
|
148
|
-
|
|
153
|
+
|
|
149
154
|
# Check field types
|
|
150
|
-
field_types = schema.get(
|
|
155
|
+
field_types = schema.get("types", {})
|
|
151
156
|
for field, expected_type in field_types.items():
|
|
152
157
|
try:
|
|
153
158
|
value = self.get_config_value(field)
|
|
154
159
|
if value is not None and not isinstance(value, expected_type):
|
|
155
|
-
errors.append(
|
|
160
|
+
errors.append(
|
|
161
|
+
f"Invalid type for {field}: expected {expected_type.__name__}"
|
|
162
|
+
)
|
|
156
163
|
except Exception as e:
|
|
157
164
|
errors.append(f"Error validating {field}: {e}")
|
|
158
|
-
|
|
165
|
+
|
|
159
166
|
# Check field constraints
|
|
160
|
-
constraints = schema.get(
|
|
167
|
+
constraints = schema.get("constraints", {})
|
|
161
168
|
for field, constraint in constraints.items():
|
|
162
169
|
try:
|
|
163
170
|
value = self.get_config_value(field)
|
|
164
171
|
if value is not None:
|
|
165
|
-
if
|
|
172
|
+
if "min" in constraint and value < constraint["min"]:
|
|
166
173
|
errors.append(f"{field} must be >= {constraint['min']}")
|
|
167
|
-
if
|
|
174
|
+
if "max" in constraint and value > constraint["max"]:
|
|
168
175
|
errors.append(f"{field} must be <= {constraint['max']}")
|
|
169
|
-
if
|
|
176
|
+
if "choices" in constraint and value not in constraint["choices"]:
|
|
170
177
|
errors.append(f"{field} must be one of {constraint['choices']}")
|
|
171
178
|
except Exception as e:
|
|
172
179
|
errors.append(f"Error validating constraint for {field}: {e}")
|
|
173
|
-
|
|
180
|
+
|
|
174
181
|
return errors
|
|
175
|
-
|
|
182
|
+
|
|
176
183
|
def load_config_file(self, config_path: Union[str, Path]) -> bool:
|
|
177
184
|
"""
|
|
178
185
|
Load additional configuration from file.
|
|
179
|
-
|
|
186
|
+
|
|
180
187
|
Args:
|
|
181
188
|
config_path: Path to configuration file
|
|
182
|
-
|
|
189
|
+
|
|
183
190
|
Returns:
|
|
184
191
|
True if loaded successfully
|
|
185
192
|
"""
|
|
@@ -192,17 +199,17 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
192
199
|
except Exception as e:
|
|
193
200
|
self.logger.error(f"Failed to load config from {config_path}: {e}")
|
|
194
201
|
return False
|
|
195
|
-
|
|
196
|
-
def find_config_file(
|
|
197
|
-
|
|
198
|
-
|
|
202
|
+
|
|
203
|
+
def find_config_file(
|
|
204
|
+
self, filename: str, search_paths: Optional[List[Union[str, Path]]] = None
|
|
205
|
+
) -> Optional[Path]:
|
|
199
206
|
"""
|
|
200
207
|
Find configuration file in standard locations.
|
|
201
|
-
|
|
208
|
+
|
|
202
209
|
Args:
|
|
203
210
|
filename: Configuration filename
|
|
204
211
|
search_paths: Additional paths to search
|
|
205
|
-
|
|
212
|
+
|
|
206
213
|
Returns:
|
|
207
214
|
Path to found configuration file or None
|
|
208
215
|
"""
|
|
@@ -211,21 +218,21 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
211
218
|
Path.home() / ".claude-mpm",
|
|
212
219
|
Path.cwd(),
|
|
213
220
|
]
|
|
214
|
-
|
|
221
|
+
|
|
215
222
|
if search_paths:
|
|
216
223
|
search_paths = [Path(p) for p in search_paths] + default_paths
|
|
217
224
|
else:
|
|
218
225
|
search_paths = default_paths
|
|
219
|
-
|
|
226
|
+
|
|
220
227
|
for search_path in search_paths:
|
|
221
228
|
config_file = search_path / filename
|
|
222
229
|
if config_file.exists() and config_file.is_file():
|
|
223
230
|
self.logger.debug(f"Found config file: {config_file}")
|
|
224
231
|
return config_file
|
|
225
|
-
|
|
232
|
+
|
|
226
233
|
return None
|
|
227
|
-
|
|
228
|
-
def get_env_config(self, prefix: str = None) -> Dict[str, Any]:
|
|
234
|
+
|
|
235
|
+
def get_env_config(self, prefix: Optional[str] = None) -> Dict[str, Any]:
|
|
229
236
|
"""
|
|
230
237
|
Get configuration from environment variables.
|
|
231
238
|
|
|
@@ -239,11 +246,11 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
239
246
|
|
|
240
247
|
# Use shared ConfigLoader for consistent environment variable handling
|
|
241
248
|
return self._config_loader._load_env_config(env_prefix)
|
|
242
|
-
|
|
243
|
-
def merge_env_config(self, prefix: str = None) -> None:
|
|
249
|
+
|
|
250
|
+
def merge_env_config(self, prefix: Optional[str] = None) -> None:
|
|
244
251
|
"""
|
|
245
252
|
Merge environment configuration into main config.
|
|
246
|
-
|
|
253
|
+
|
|
247
254
|
Args:
|
|
248
255
|
prefix: Environment variable prefix
|
|
249
256
|
"""
|
|
@@ -252,7 +259,7 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
252
259
|
for key, value in env_config.items():
|
|
253
260
|
full_key = f"{self.config_section}.{key}"
|
|
254
261
|
self._config.set(full_key, value)
|
|
255
|
-
|
|
262
|
+
|
|
256
263
|
# Clear cache since config changed
|
|
257
264
|
self._config_cache.clear()
|
|
258
265
|
self.logger.debug(f"Merged {len(env_config)} environment variables")
|
|
@@ -265,8 +272,7 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
265
272
|
config_dir: Optional directory to search for config files
|
|
266
273
|
"""
|
|
267
274
|
self._config = self._config_loader.load_service_config(
|
|
268
|
-
service_name=self.service_name,
|
|
269
|
-
config_dir=config_dir
|
|
275
|
+
service_name=self.service_name, config_dir=config_dir
|
|
270
276
|
)
|
|
271
277
|
|
|
272
278
|
# Clear cache
|
|
@@ -277,16 +283,16 @@ class ConfigServiceBase(LoggerMixin, ABC):
|
|
|
277
283
|
def get_config_summary(self) -> Dict[str, Any]:
|
|
278
284
|
"""
|
|
279
285
|
Get summary of current configuration.
|
|
280
|
-
|
|
286
|
+
|
|
281
287
|
Returns:
|
|
282
288
|
Configuration summary
|
|
283
289
|
"""
|
|
284
290
|
section_config = self.get_config_section()
|
|
285
|
-
|
|
291
|
+
|
|
286
292
|
return {
|
|
287
293
|
"service": self.service_name,
|
|
288
294
|
"section": self.config_section,
|
|
289
295
|
"keys": list(section_config.keys()),
|
|
290
296
|
"key_count": len(section_config),
|
|
291
|
-
"cached_values": len(self._config_cache)
|
|
297
|
+
"cached_values": len(self._config_cache),
|
|
292
298
|
}
|