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
|
@@ -5,253 +5,265 @@ Base class for manager-style services to reduce duplication.
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from typing import Any, Dict, List, Optional, Set, TypeVar
|
|
7
7
|
|
|
8
|
-
from ...core.mixins import LoggerMixin
|
|
9
8
|
from .config_service_base import ConfigServiceBase
|
|
10
9
|
|
|
11
|
-
T = TypeVar(
|
|
10
|
+
T = TypeVar("T")
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class ManagerBase(ConfigServiceBase, ABC):
|
|
15
14
|
"""
|
|
16
15
|
Base class for manager-style services.
|
|
17
|
-
|
|
16
|
+
|
|
18
17
|
Provides common patterns for services that manage collections of items:
|
|
19
18
|
- Item registration and discovery
|
|
20
19
|
- Lifecycle management
|
|
21
20
|
- Caching and indexing
|
|
22
21
|
- Validation and filtering
|
|
23
22
|
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
|
|
24
|
+
def __init__(
|
|
25
|
+
self,
|
|
26
|
+
manager_name: str,
|
|
27
|
+
config: Optional[Dict[str, Any]] = None,
|
|
28
|
+
config_section: Optional[str] = None,
|
|
29
|
+
):
|
|
29
30
|
"""
|
|
30
31
|
Initialize manager.
|
|
31
|
-
|
|
32
|
+
|
|
32
33
|
Args:
|
|
33
34
|
manager_name: Name of the manager
|
|
34
35
|
config: Configuration dictionary
|
|
35
36
|
config_section: Configuration section name
|
|
36
37
|
"""
|
|
37
38
|
super().__init__(manager_name, config, config_section)
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
# Item storage
|
|
40
41
|
self._items: Dict[str, T] = {}
|
|
41
42
|
self._item_metadata: Dict[str, Dict[str, Any]] = {}
|
|
42
|
-
|
|
43
|
+
|
|
43
44
|
# Indexing
|
|
44
45
|
self._indexes: Dict[str, Dict[Any, Set[str]]] = {}
|
|
45
|
-
|
|
46
|
+
|
|
46
47
|
# State tracking
|
|
47
48
|
self._initialized = False
|
|
48
49
|
self._last_scan_time: Optional[float] = None
|
|
49
|
-
|
|
50
|
+
|
|
50
51
|
# Configuration
|
|
51
52
|
self._auto_scan = self.get_config_value("auto_scan", True, config_type=bool)
|
|
52
|
-
self._cache_enabled = self.get_config_value(
|
|
53
|
+
self._cache_enabled = self.get_config_value(
|
|
54
|
+
"cache_enabled", True, config_type=bool
|
|
55
|
+
)
|
|
53
56
|
self._max_items = self.get_config_value("max_items", 1000, config_type=int)
|
|
54
|
-
|
|
57
|
+
|
|
55
58
|
@property
|
|
56
59
|
def item_count(self) -> int:
|
|
57
60
|
"""Get number of managed items."""
|
|
58
61
|
return len(self._items)
|
|
59
|
-
|
|
62
|
+
|
|
60
63
|
@property
|
|
61
64
|
def is_initialized(self) -> bool:
|
|
62
65
|
"""Check if manager is initialized."""
|
|
63
66
|
return self._initialized
|
|
64
|
-
|
|
67
|
+
|
|
65
68
|
def initialize(self) -> bool:
|
|
66
69
|
"""
|
|
67
70
|
Initialize the manager.
|
|
68
|
-
|
|
71
|
+
|
|
69
72
|
Returns:
|
|
70
73
|
True if initialization successful
|
|
71
74
|
"""
|
|
72
75
|
if self._initialized:
|
|
73
76
|
self.logger.warning(f"Manager {self.service_name} already initialized")
|
|
74
77
|
return True
|
|
75
|
-
|
|
78
|
+
|
|
76
79
|
self.logger.info(f"Initializing manager: {self.service_name}")
|
|
77
|
-
|
|
80
|
+
|
|
78
81
|
try:
|
|
79
82
|
# Manager-specific initialization
|
|
80
83
|
success = self._do_initialize()
|
|
81
|
-
|
|
84
|
+
|
|
82
85
|
if success:
|
|
83
86
|
# Perform initial scan if auto-scan enabled
|
|
84
87
|
if self._auto_scan:
|
|
85
88
|
self.scan_items()
|
|
86
|
-
|
|
89
|
+
|
|
87
90
|
self._initialized = True
|
|
88
|
-
self.logger.info(
|
|
91
|
+
self.logger.info(
|
|
92
|
+
f"Manager {self.service_name} initialized successfully"
|
|
93
|
+
)
|
|
89
94
|
else:
|
|
90
95
|
self.logger.error(f"Manager {self.service_name} initialization failed")
|
|
91
|
-
|
|
96
|
+
|
|
92
97
|
return success
|
|
93
|
-
|
|
98
|
+
|
|
94
99
|
except Exception as e:
|
|
95
|
-
self.logger.error(
|
|
100
|
+
self.logger.error(
|
|
101
|
+
f"Manager {self.service_name} initialization error: {e}", exc_info=True
|
|
102
|
+
)
|
|
96
103
|
return False
|
|
97
|
-
|
|
98
|
-
def register_item(
|
|
104
|
+
|
|
105
|
+
def register_item(
|
|
106
|
+
self, item_id: str, item: T, metadata: Optional[Dict[str, Any]] = None
|
|
107
|
+
) -> bool:
|
|
99
108
|
"""
|
|
100
109
|
Register an item.
|
|
101
|
-
|
|
110
|
+
|
|
102
111
|
Args:
|
|
103
112
|
item_id: Unique identifier for the item
|
|
104
113
|
item: The item to register
|
|
105
114
|
metadata: Optional metadata for the item
|
|
106
|
-
|
|
115
|
+
|
|
107
116
|
Returns:
|
|
108
117
|
True if registration successful
|
|
109
118
|
"""
|
|
110
119
|
if not self._initialized:
|
|
111
120
|
self.logger.warning("Manager not initialized")
|
|
112
121
|
return False
|
|
113
|
-
|
|
122
|
+
|
|
114
123
|
# Check item limit
|
|
115
124
|
if len(self._items) >= self._max_items:
|
|
116
125
|
self.logger.warning(f"Maximum items ({self._max_items}) reached")
|
|
117
126
|
return False
|
|
118
|
-
|
|
127
|
+
|
|
119
128
|
# Validate item
|
|
120
129
|
if not self._validate_item(item_id, item):
|
|
121
130
|
return False
|
|
122
|
-
|
|
131
|
+
|
|
123
132
|
# Store item
|
|
124
133
|
self._items[item_id] = item
|
|
125
134
|
self._item_metadata[item_id] = metadata or {}
|
|
126
|
-
|
|
135
|
+
|
|
127
136
|
# Update indexes
|
|
128
137
|
self._update_indexes(item_id, item, metadata)
|
|
129
|
-
|
|
138
|
+
|
|
130
139
|
self.logger.debug(f"Registered item: {item_id}")
|
|
131
140
|
return True
|
|
132
|
-
|
|
141
|
+
|
|
133
142
|
def unregister_item(self, item_id: str) -> bool:
|
|
134
143
|
"""
|
|
135
144
|
Unregister an item.
|
|
136
|
-
|
|
145
|
+
|
|
137
146
|
Args:
|
|
138
147
|
item_id: Identifier of item to unregister
|
|
139
|
-
|
|
148
|
+
|
|
140
149
|
Returns:
|
|
141
150
|
True if unregistration successful
|
|
142
151
|
"""
|
|
143
152
|
if item_id not in self._items:
|
|
144
153
|
self.logger.warning(f"Item not found: {item_id}")
|
|
145
154
|
return False
|
|
146
|
-
|
|
155
|
+
|
|
147
156
|
# Remove from storage
|
|
148
157
|
item = self._items.pop(item_id)
|
|
149
158
|
metadata = self._item_metadata.pop(item_id, {})
|
|
150
|
-
|
|
159
|
+
|
|
151
160
|
# Update indexes
|
|
152
161
|
self._remove_from_indexes(item_id, item, metadata)
|
|
153
|
-
|
|
162
|
+
|
|
154
163
|
self.logger.debug(f"Unregistered item: {item_id}")
|
|
155
164
|
return True
|
|
156
|
-
|
|
165
|
+
|
|
157
166
|
def get_item(self, item_id: str) -> Optional[T]:
|
|
158
167
|
"""Get item by ID."""
|
|
159
168
|
return self._items.get(item_id)
|
|
160
|
-
|
|
169
|
+
|
|
161
170
|
def get_item_metadata(self, item_id: str) -> Dict[str, Any]:
|
|
162
171
|
"""Get item metadata."""
|
|
163
172
|
return self._item_metadata.get(item_id, {})
|
|
164
|
-
|
|
173
|
+
|
|
165
174
|
def list_items(self, filter_func=None) -> List[str]:
|
|
166
175
|
"""
|
|
167
176
|
List item IDs.
|
|
168
|
-
|
|
177
|
+
|
|
169
178
|
Args:
|
|
170
179
|
filter_func: Optional filter function
|
|
171
|
-
|
|
180
|
+
|
|
172
181
|
Returns:
|
|
173
182
|
List of item IDs
|
|
174
183
|
"""
|
|
175
184
|
if filter_func is None:
|
|
176
185
|
return list(self._items.keys())
|
|
177
|
-
|
|
186
|
+
|
|
178
187
|
return [
|
|
179
|
-
item_id
|
|
188
|
+
item_id
|
|
189
|
+
for item_id, item in self._items.items()
|
|
180
190
|
if filter_func(item_id, item, self._item_metadata.get(item_id, {}))
|
|
181
191
|
]
|
|
182
|
-
|
|
192
|
+
|
|
183
193
|
def find_items(self, **criteria) -> List[str]:
|
|
184
194
|
"""
|
|
185
195
|
Find items by criteria using indexes.
|
|
186
|
-
|
|
196
|
+
|
|
187
197
|
Args:
|
|
188
198
|
**criteria: Search criteria
|
|
189
|
-
|
|
199
|
+
|
|
190
200
|
Returns:
|
|
191
201
|
List of matching item IDs
|
|
192
202
|
"""
|
|
193
203
|
if not criteria:
|
|
194
204
|
return self.list_items()
|
|
195
|
-
|
|
205
|
+
|
|
196
206
|
# Use indexes if available
|
|
197
207
|
result_sets = []
|
|
198
208
|
for key, value in criteria.items():
|
|
199
209
|
if key in self._indexes and value in self._indexes[key]:
|
|
200
210
|
result_sets.append(self._indexes[key][value])
|
|
201
|
-
|
|
211
|
+
|
|
202
212
|
if result_sets:
|
|
203
213
|
# Intersection of all criteria
|
|
204
214
|
result = result_sets[0]
|
|
205
215
|
for result_set in result_sets[1:]:
|
|
206
216
|
result = result.intersection(result_set)
|
|
207
217
|
return list(result)
|
|
208
|
-
|
|
218
|
+
|
|
209
219
|
# Fallback to linear search
|
|
210
220
|
return self.list_items(
|
|
211
221
|
lambda item_id, item, metadata: all(
|
|
212
222
|
metadata.get(key) == value for key, value in criteria.items()
|
|
213
223
|
)
|
|
214
224
|
)
|
|
215
|
-
|
|
225
|
+
|
|
216
226
|
def scan_items(self) -> int:
|
|
217
227
|
"""
|
|
218
228
|
Scan for items and update registry.
|
|
219
|
-
|
|
229
|
+
|
|
220
230
|
Returns:
|
|
221
231
|
Number of items found
|
|
222
232
|
"""
|
|
223
233
|
import time
|
|
224
|
-
|
|
234
|
+
|
|
225
235
|
self.logger.info(f"Scanning for items: {self.service_name}")
|
|
226
236
|
start_time = time.time()
|
|
227
|
-
|
|
237
|
+
|
|
228
238
|
try:
|
|
229
239
|
# Manager-specific scanning
|
|
230
240
|
found_items = self._do_scan_items()
|
|
231
|
-
|
|
241
|
+
|
|
232
242
|
# Update scan time
|
|
233
243
|
self._last_scan_time = time.time()
|
|
234
|
-
|
|
244
|
+
|
|
235
245
|
scan_duration = self._last_scan_time - start_time
|
|
236
|
-
self.logger.info(
|
|
237
|
-
|
|
246
|
+
self.logger.info(
|
|
247
|
+
f"Scan completed: found {found_items} items in {scan_duration:.2f}s"
|
|
248
|
+
)
|
|
249
|
+
|
|
238
250
|
return found_items
|
|
239
|
-
|
|
251
|
+
|
|
240
252
|
except Exception as e:
|
|
241
253
|
self.logger.error(f"Scan failed: {e}", exc_info=True)
|
|
242
254
|
return 0
|
|
243
|
-
|
|
255
|
+
|
|
244
256
|
def clear_items(self) -> None:
|
|
245
257
|
"""Clear all items."""
|
|
246
258
|
self.logger.info(f"Clearing all items: {self.service_name}")
|
|
247
259
|
self._items.clear()
|
|
248
260
|
self._item_metadata.clear()
|
|
249
261
|
self._indexes.clear()
|
|
250
|
-
|
|
262
|
+
|
|
251
263
|
def get_status(self) -> Dict[str, Any]:
|
|
252
264
|
"""
|
|
253
265
|
Get manager status.
|
|
254
|
-
|
|
266
|
+
|
|
255
267
|
Returns:
|
|
256
268
|
Status dictionary
|
|
257
269
|
"""
|
|
@@ -263,41 +275,41 @@ class ManagerBase(ConfigServiceBase, ABC):
|
|
|
263
275
|
"auto_scan": self._auto_scan,
|
|
264
276
|
"cache_enabled": self._cache_enabled,
|
|
265
277
|
"last_scan_time": self._last_scan_time,
|
|
266
|
-
"indexes": list(self._indexes.keys())
|
|
278
|
+
"indexes": list(self._indexes.keys()),
|
|
267
279
|
}
|
|
268
|
-
|
|
280
|
+
|
|
269
281
|
def _create_index(self, index_name: str) -> None:
|
|
270
282
|
"""Create an index for fast lookups."""
|
|
271
283
|
if index_name not in self._indexes:
|
|
272
284
|
self._indexes[index_name] = {}
|
|
273
285
|
self.logger.debug(f"Created index: {index_name}")
|
|
274
|
-
|
|
286
|
+
|
|
275
287
|
def _update_indexes(self, item_id: str, item: T, metadata: Dict[str, Any]) -> None:
|
|
276
288
|
"""Update indexes for an item."""
|
|
277
289
|
# Manager-specific index updates
|
|
278
290
|
self._do_update_indexes(item_id, item, metadata)
|
|
279
|
-
|
|
280
|
-
def _remove_from_indexes(
|
|
291
|
+
|
|
292
|
+
def _remove_from_indexes(
|
|
293
|
+
self, item_id: str, item: T, metadata: Dict[str, Any]
|
|
294
|
+
) -> None:
|
|
281
295
|
"""Remove item from indexes."""
|
|
282
|
-
for
|
|
283
|
-
for
|
|
296
|
+
for _index_name, index in self._indexes.items():
|
|
297
|
+
for _value, item_set in index.items():
|
|
284
298
|
item_set.discard(item_id)
|
|
285
|
-
|
|
299
|
+
|
|
286
300
|
@abstractmethod
|
|
287
301
|
def _do_initialize(self) -> bool:
|
|
288
302
|
"""Manager-specific initialization logic."""
|
|
289
|
-
|
|
290
|
-
|
|
303
|
+
|
|
291
304
|
@abstractmethod
|
|
292
305
|
def _validate_item(self, item_id: str, item: T) -> bool:
|
|
293
306
|
"""Validate an item before registration."""
|
|
294
|
-
|
|
295
|
-
|
|
307
|
+
|
|
296
308
|
@abstractmethod
|
|
297
309
|
def _do_scan_items(self) -> int:
|
|
298
310
|
"""Manager-specific item scanning logic."""
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
311
|
+
|
|
312
|
+
def _do_update_indexes(
|
|
313
|
+
self, item_id: str, item: T, metadata: Dict[str, Any]
|
|
314
|
+
) -> None:
|
|
302
315
|
"""Manager-specific index update logic."""
|
|
303
|
-
pass
|