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
|
@@ -12,6 +12,7 @@ from ...core.mixins import LoggerMixin
|
|
|
12
12
|
|
|
13
13
|
class ServiceState(Enum):
|
|
14
14
|
"""Standard service states."""
|
|
15
|
+
|
|
15
16
|
UNINITIALIZED = "uninitialized"
|
|
16
17
|
INITIALIZING = "initializing"
|
|
17
18
|
INITIALIZED = "initialized"
|
|
@@ -25,18 +26,18 @@ class ServiceState(Enum):
|
|
|
25
26
|
class LifecycleServiceBase(LoggerMixin, ABC):
|
|
26
27
|
"""
|
|
27
28
|
Base class for services with complex lifecycle management.
|
|
28
|
-
|
|
29
|
+
|
|
29
30
|
Provides common patterns:
|
|
30
31
|
- State machine management
|
|
31
32
|
- Lifecycle hooks
|
|
32
33
|
- Health monitoring
|
|
33
34
|
- Dependency management
|
|
34
35
|
"""
|
|
35
|
-
|
|
36
|
+
|
|
36
37
|
def __init__(self, service_name: str, config: Optional[Dict[str, Any]] = None):
|
|
37
38
|
"""
|
|
38
39
|
Initialize lifecycle service.
|
|
39
|
-
|
|
40
|
+
|
|
40
41
|
Args:
|
|
41
42
|
service_name: Name of the service
|
|
42
43
|
config: Optional configuration
|
|
@@ -44,122 +45,125 @@ class LifecycleServiceBase(LoggerMixin, ABC):
|
|
|
44
45
|
self.service_name = service_name
|
|
45
46
|
self._logger_name = f"service.{service_name}"
|
|
46
47
|
self.config = config or {}
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
# State management
|
|
49
50
|
self._state = ServiceState.UNINITIALIZED
|
|
50
51
|
self._previous_state = None
|
|
51
52
|
self._state_history: List[tuple] = []
|
|
52
|
-
|
|
53
|
+
|
|
53
54
|
# Lifecycle tracking
|
|
54
55
|
self._start_time: Optional[float] = None
|
|
55
56
|
self._last_health_check: Optional[float] = None
|
|
56
57
|
self._health_status: Dict[str, Any] = {}
|
|
57
|
-
|
|
58
|
+
|
|
58
59
|
# Dependencies
|
|
59
60
|
self._dependencies: List[str] = []
|
|
60
61
|
self._dependents: List[str] = []
|
|
61
|
-
|
|
62
|
+
|
|
62
63
|
# Error tracking
|
|
63
64
|
self._errors: List[Dict[str, Any]] = []
|
|
64
65
|
self._max_errors = 10
|
|
65
|
-
|
|
66
|
+
|
|
66
67
|
@property
|
|
67
68
|
def state(self) -> ServiceState:
|
|
68
69
|
"""Get current service state."""
|
|
69
70
|
return self._state
|
|
70
|
-
|
|
71
|
+
|
|
71
72
|
@property
|
|
72
73
|
def is_running(self) -> bool:
|
|
73
74
|
"""Check if service is running."""
|
|
74
75
|
return self._state == ServiceState.RUNNING
|
|
75
|
-
|
|
76
|
+
|
|
76
77
|
@property
|
|
77
78
|
def is_healthy(self) -> bool:
|
|
78
79
|
"""Check if service is healthy."""
|
|
79
80
|
return (
|
|
80
|
-
self._state == ServiceState.RUNNING
|
|
81
|
-
len(self._errors) == 0
|
|
82
|
-
self._health_status.get(
|
|
81
|
+
self._state == ServiceState.RUNNING
|
|
82
|
+
and len(self._errors) == 0
|
|
83
|
+
and self._health_status.get("healthy", True)
|
|
83
84
|
)
|
|
84
|
-
|
|
85
|
+
|
|
85
86
|
@property
|
|
86
87
|
def uptime(self) -> Optional[float]:
|
|
87
88
|
"""Get service uptime in seconds."""
|
|
88
89
|
if self._start_time and self.is_running:
|
|
89
90
|
return time.time() - self._start_time
|
|
90
91
|
return None
|
|
91
|
-
|
|
92
|
+
|
|
92
93
|
def add_dependency(self, service_name: str) -> None:
|
|
93
94
|
"""Add a service dependency."""
|
|
94
95
|
if service_name not in self._dependencies:
|
|
95
96
|
self._dependencies.append(service_name)
|
|
96
97
|
self.logger.debug(f"Added dependency: {service_name}")
|
|
97
|
-
|
|
98
|
+
|
|
98
99
|
def add_dependent(self, service_name: str) -> None:
|
|
99
100
|
"""Add a dependent service."""
|
|
100
101
|
if service_name not in self._dependents:
|
|
101
102
|
self._dependents.append(service_name)
|
|
102
103
|
self.logger.debug(f"Added dependent: {service_name}")
|
|
103
|
-
|
|
104
|
+
|
|
104
105
|
def initialize(self) -> bool:
|
|
105
106
|
"""
|
|
106
107
|
Initialize the service.
|
|
107
|
-
|
|
108
|
+
|
|
108
109
|
Returns:
|
|
109
110
|
True if initialization successful
|
|
110
111
|
"""
|
|
111
112
|
if self._state != ServiceState.UNINITIALIZED:
|
|
112
113
|
self.logger.warning(f"Service {self.service_name} already initialized")
|
|
113
114
|
return self._state in (ServiceState.INITIALIZED, ServiceState.RUNNING)
|
|
114
|
-
|
|
115
|
+
|
|
115
116
|
self._transition_state(ServiceState.INITIALIZING)
|
|
116
117
|
self.logger.info(f"Initializing service: {self.service_name}")
|
|
117
|
-
|
|
118
|
+
|
|
118
119
|
try:
|
|
119
120
|
# Check dependencies
|
|
120
121
|
if not self._check_dependencies():
|
|
121
122
|
self._transition_state(ServiceState.ERROR)
|
|
122
123
|
return False
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
# Service-specific initialization
|
|
125
126
|
success = self._do_initialize()
|
|
126
|
-
|
|
127
|
+
|
|
127
128
|
if success:
|
|
128
129
|
self._transition_state(ServiceState.INITIALIZED)
|
|
129
|
-
self.logger.info(
|
|
130
|
+
self.logger.info(
|
|
131
|
+
f"Service {self.service_name} initialized successfully"
|
|
132
|
+
)
|
|
130
133
|
else:
|
|
131
134
|
self._transition_state(ServiceState.ERROR)
|
|
132
135
|
self.logger.error(f"Service {self.service_name} initialization failed")
|
|
133
|
-
|
|
136
|
+
|
|
134
137
|
return success
|
|
135
|
-
|
|
138
|
+
|
|
136
139
|
except Exception as e:
|
|
137
140
|
self._record_error("initialization", e)
|
|
138
141
|
self._transition_state(ServiceState.ERROR)
|
|
139
|
-
self.logger.error(
|
|
142
|
+
self.logger.error(
|
|
143
|
+
f"Service {self.service_name} initialization error: {e}", exc_info=True
|
|
144
|
+
)
|
|
140
145
|
return False
|
|
141
|
-
|
|
146
|
+
|
|
142
147
|
def start(self) -> bool:
|
|
143
148
|
"""
|
|
144
149
|
Start the service.
|
|
145
|
-
|
|
150
|
+
|
|
146
151
|
Returns:
|
|
147
152
|
True if start successful
|
|
148
153
|
"""
|
|
149
154
|
if self._state == ServiceState.RUNNING:
|
|
150
155
|
self.logger.warning(f"Service {self.service_name} already running")
|
|
151
156
|
return True
|
|
152
|
-
|
|
153
|
-
if self._state != ServiceState.INITIALIZED:
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
+
|
|
158
|
+
if self._state != ServiceState.INITIALIZED and not self.initialize():
|
|
159
|
+
return False
|
|
160
|
+
|
|
157
161
|
self._transition_state(ServiceState.STARTING)
|
|
158
162
|
self.logger.info(f"Starting service: {self.service_name}")
|
|
159
|
-
|
|
163
|
+
|
|
160
164
|
try:
|
|
161
165
|
success = self._do_start()
|
|
162
|
-
|
|
166
|
+
|
|
163
167
|
if success:
|
|
164
168
|
self._start_time = time.time()
|
|
165
169
|
self._transition_state(ServiceState.RUNNING)
|
|
@@ -167,32 +171,34 @@ class LifecycleServiceBase(LoggerMixin, ABC):
|
|
|
167
171
|
else:
|
|
168
172
|
self._transition_state(ServiceState.ERROR)
|
|
169
173
|
self.logger.error(f"Service {self.service_name} start failed")
|
|
170
|
-
|
|
174
|
+
|
|
171
175
|
return success
|
|
172
|
-
|
|
176
|
+
|
|
173
177
|
except Exception as e:
|
|
174
178
|
self._record_error("start", e)
|
|
175
179
|
self._transition_state(ServiceState.ERROR)
|
|
176
|
-
self.logger.error(
|
|
180
|
+
self.logger.error(
|
|
181
|
+
f"Service {self.service_name} start error: {e}", exc_info=True
|
|
182
|
+
)
|
|
177
183
|
return False
|
|
178
|
-
|
|
184
|
+
|
|
179
185
|
def stop(self) -> bool:
|
|
180
186
|
"""
|
|
181
187
|
Stop the service.
|
|
182
|
-
|
|
188
|
+
|
|
183
189
|
Returns:
|
|
184
190
|
True if stop successful
|
|
185
191
|
"""
|
|
186
192
|
if self._state == ServiceState.STOPPED:
|
|
187
193
|
self.logger.warning(f"Service {self.service_name} already stopped")
|
|
188
194
|
return True
|
|
189
|
-
|
|
195
|
+
|
|
190
196
|
self._transition_state(ServiceState.STOPPING)
|
|
191
197
|
self.logger.info(f"Stopping service: {self.service_name}")
|
|
192
|
-
|
|
198
|
+
|
|
193
199
|
try:
|
|
194
200
|
success = self._do_stop()
|
|
195
|
-
|
|
201
|
+
|
|
196
202
|
if success:
|
|
197
203
|
self._start_time = None
|
|
198
204
|
self._transition_state(ServiceState.STOPPED)
|
|
@@ -200,38 +206,39 @@ class LifecycleServiceBase(LoggerMixin, ABC):
|
|
|
200
206
|
else:
|
|
201
207
|
self._transition_state(ServiceState.ERROR)
|
|
202
208
|
self.logger.error(f"Service {self.service_name} stop failed")
|
|
203
|
-
|
|
209
|
+
|
|
204
210
|
return success
|
|
205
|
-
|
|
211
|
+
|
|
206
212
|
except Exception as e:
|
|
207
213
|
self._record_error("stop", e)
|
|
208
214
|
self._transition_state(ServiceState.ERROR)
|
|
209
|
-
self.logger.error(
|
|
215
|
+
self.logger.error(
|
|
216
|
+
f"Service {self.service_name} stop error: {e}", exc_info=True
|
|
217
|
+
)
|
|
210
218
|
return False
|
|
211
|
-
|
|
219
|
+
|
|
212
220
|
def restart(self) -> bool:
|
|
213
221
|
"""Restart the service."""
|
|
214
222
|
self.logger.info(f"Restarting service: {self.service_name}")
|
|
215
|
-
|
|
216
|
-
if self.is_running:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
223
|
+
|
|
224
|
+
if self.is_running and not self.stop():
|
|
225
|
+
return False
|
|
226
|
+
|
|
220
227
|
return self.start()
|
|
221
|
-
|
|
228
|
+
|
|
222
229
|
def health_check(self) -> Dict[str, Any]:
|
|
223
230
|
"""
|
|
224
231
|
Perform health check.
|
|
225
|
-
|
|
232
|
+
|
|
226
233
|
Returns:
|
|
227
234
|
Health status dictionary
|
|
228
235
|
"""
|
|
229
236
|
self._last_health_check = time.time()
|
|
230
|
-
|
|
237
|
+
|
|
231
238
|
try:
|
|
232
239
|
# Service-specific health check
|
|
233
240
|
service_health = self._do_health_check()
|
|
234
|
-
|
|
241
|
+
|
|
235
242
|
# Combine with base health info
|
|
236
243
|
health_status = {
|
|
237
244
|
"service": self.service_name,
|
|
@@ -242,76 +249,73 @@ class LifecycleServiceBase(LoggerMixin, ABC):
|
|
|
242
249
|
"dependencies": self._dependencies,
|
|
243
250
|
"dependents": self._dependents,
|
|
244
251
|
"last_check": self._last_health_check,
|
|
245
|
-
**service_health
|
|
252
|
+
**service_health,
|
|
246
253
|
}
|
|
247
|
-
|
|
254
|
+
|
|
248
255
|
self._health_status = health_status
|
|
249
256
|
return health_status
|
|
250
|
-
|
|
257
|
+
|
|
251
258
|
except Exception as e:
|
|
252
259
|
self._record_error("health_check", e)
|
|
253
260
|
return {
|
|
254
261
|
"service": self.service_name,
|
|
255
262
|
"state": self._state.value,
|
|
256
263
|
"healthy": False,
|
|
257
|
-
"error": str(e)
|
|
264
|
+
"error": str(e),
|
|
258
265
|
}
|
|
259
|
-
|
|
266
|
+
|
|
260
267
|
def _transition_state(self, new_state: ServiceState) -> None:
|
|
261
268
|
"""Transition to a new state."""
|
|
262
269
|
old_state = self._state
|
|
263
270
|
self._previous_state = old_state
|
|
264
271
|
self._state = new_state
|
|
265
|
-
|
|
272
|
+
|
|
266
273
|
# Record state transition
|
|
267
274
|
self._state_history.append((time.time(), old_state.value, new_state.value))
|
|
268
|
-
|
|
275
|
+
|
|
269
276
|
# Keep history bounded
|
|
270
277
|
if len(self._state_history) > 50:
|
|
271
278
|
self._state_history = self._state_history[-50:]
|
|
272
|
-
|
|
279
|
+
|
|
273
280
|
self.logger.debug(f"State transition: {old_state.value} -> {new_state.value}")
|
|
274
|
-
|
|
281
|
+
|
|
275
282
|
def _record_error(self, operation: str, error: Exception) -> None:
|
|
276
283
|
"""Record an error."""
|
|
277
284
|
error_record = {
|
|
278
285
|
"timestamp": time.time(),
|
|
279
286
|
"operation": operation,
|
|
280
287
|
"error": str(error),
|
|
281
|
-
"type": type(error).__name__
|
|
288
|
+
"type": type(error).__name__,
|
|
282
289
|
}
|
|
283
|
-
|
|
290
|
+
|
|
284
291
|
self._errors.append(error_record)
|
|
285
|
-
|
|
292
|
+
|
|
286
293
|
# Keep error list bounded
|
|
287
294
|
if len(self._errors) > self._max_errors:
|
|
288
|
-
self._errors = self._errors[-self._max_errors:]
|
|
289
|
-
|
|
295
|
+
self._errors = self._errors[-self._max_errors :]
|
|
296
|
+
|
|
290
297
|
def _check_dependencies(self) -> bool:
|
|
291
298
|
"""Check if all dependencies are satisfied."""
|
|
292
299
|
# This is a placeholder - in a real implementation,
|
|
293
300
|
# you would check with a service registry
|
|
294
301
|
return True
|
|
295
|
-
|
|
302
|
+
|
|
296
303
|
@abstractmethod
|
|
297
304
|
def _do_initialize(self) -> bool:
|
|
298
305
|
"""Service-specific initialization logic."""
|
|
299
|
-
|
|
300
|
-
|
|
306
|
+
|
|
301
307
|
@abstractmethod
|
|
302
308
|
def _do_start(self) -> bool:
|
|
303
309
|
"""Service-specific start logic."""
|
|
304
|
-
|
|
305
|
-
|
|
310
|
+
|
|
306
311
|
@abstractmethod
|
|
307
312
|
def _do_stop(self) -> bool:
|
|
308
313
|
"""Service-specific stop logic."""
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
|
|
311
315
|
def _do_health_check(self) -> Dict[str, Any]:
|
|
312
316
|
"""Service-specific health check logic."""
|
|
313
317
|
return {"healthy": True}
|
|
314
|
-
|
|
318
|
+
|
|
315
319
|
def __repr__(self) -> str:
|
|
316
320
|
"""String representation."""
|
|
317
321
|
return f"{self.__class__.__name__}(name={self.service_name}, state={self._state.value})"
|