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
|
@@ -29,11 +29,9 @@ class MemoryHookService(BaseService, MemoryHookInterface):
|
|
|
29
29
|
|
|
30
30
|
async def _initialize(self) -> None:
|
|
31
31
|
"""Initialize the service. No special initialization needed."""
|
|
32
|
-
pass
|
|
33
32
|
|
|
34
33
|
async def _cleanup(self) -> None:
|
|
35
34
|
"""Cleanup service resources. No cleanup needed."""
|
|
36
|
-
pass
|
|
37
35
|
|
|
38
36
|
def register_memory_hooks(self):
|
|
39
37
|
"""Register memory-related hooks with the hook service.
|
|
@@ -144,68 +142,86 @@ class MemoryHookService(BaseService, MemoryHookInterface):
|
|
|
144
142
|
"""
|
|
145
143
|
try:
|
|
146
144
|
from claude_mpm.hooks.base_hook import HookResult
|
|
147
|
-
|
|
145
|
+
|
|
148
146
|
# Extract agent_id and response from context
|
|
149
147
|
agent_id = None
|
|
150
148
|
response_text = None
|
|
151
|
-
|
|
149
|
+
|
|
152
150
|
# Try to get agent_id from various possible locations in context
|
|
153
|
-
if hasattr(context,
|
|
151
|
+
if hasattr(context, "data") and context.data:
|
|
154
152
|
data = context.data
|
|
155
|
-
|
|
153
|
+
|
|
156
154
|
# Check for agent_id in various locations
|
|
157
155
|
if isinstance(data, dict):
|
|
158
156
|
# Try direct agent_id field
|
|
159
|
-
agent_id = data.get(
|
|
160
|
-
|
|
157
|
+
agent_id = data.get("agent_id")
|
|
158
|
+
|
|
161
159
|
# Try agent_type field
|
|
162
160
|
if not agent_id:
|
|
163
|
-
agent_id = data.get(
|
|
164
|
-
|
|
161
|
+
agent_id = data.get("agent_type")
|
|
162
|
+
|
|
165
163
|
# Try subagent_type (for Task delegations)
|
|
166
164
|
if not agent_id:
|
|
167
|
-
agent_id = data.get(
|
|
168
|
-
|
|
165
|
+
agent_id = data.get("subagent_type")
|
|
166
|
+
|
|
169
167
|
# Try tool_parameters for Task delegations
|
|
170
|
-
if not agent_id and
|
|
171
|
-
params = data.get(
|
|
168
|
+
if not agent_id and "tool_parameters" in data:
|
|
169
|
+
params = data.get("tool_parameters", {})
|
|
172
170
|
if isinstance(params, dict):
|
|
173
|
-
agent_id = params.get(
|
|
174
|
-
|
|
171
|
+
agent_id = params.get("subagent_type")
|
|
172
|
+
|
|
175
173
|
# Extract response text
|
|
176
|
-
response_text =
|
|
177
|
-
|
|
174
|
+
response_text = (
|
|
175
|
+
data.get("response") or data.get("result") or data.get("output")
|
|
176
|
+
)
|
|
177
|
+
|
|
178
178
|
# If response_text is a dict, try to get text from it
|
|
179
179
|
if isinstance(response_text, dict):
|
|
180
|
-
response_text =
|
|
181
|
-
|
|
180
|
+
response_text = (
|
|
181
|
+
response_text.get("text")
|
|
182
|
+
or response_text.get("content")
|
|
183
|
+
or str(response_text)
|
|
184
|
+
)
|
|
185
|
+
|
|
182
186
|
# Default to PM if no agent_id found
|
|
183
187
|
if not agent_id:
|
|
184
188
|
agent_id = "PM"
|
|
185
189
|
self.logger.debug("No agent_id found in context, defaulting to PM")
|
|
186
|
-
|
|
190
|
+
|
|
187
191
|
# Only process if we have response text
|
|
188
192
|
if response_text and isinstance(response_text, str):
|
|
189
193
|
self.logger.debug(f"Processing memory extraction for agent: {agent_id}")
|
|
190
|
-
|
|
194
|
+
|
|
191
195
|
# Import and use the memory manager
|
|
192
|
-
from claude_mpm.services.agents.memory.agent_memory_manager import
|
|
193
|
-
|
|
196
|
+
from claude_mpm.services.agents.memory.agent_memory_manager import (
|
|
197
|
+
get_memory_manager,
|
|
198
|
+
)
|
|
199
|
+
|
|
194
200
|
try:
|
|
195
201
|
memory_manager = get_memory_manager()
|
|
196
|
-
|
|
202
|
+
|
|
197
203
|
# Extract and update memory
|
|
198
|
-
success = memory_manager.extract_and_update_memory(
|
|
199
|
-
|
|
204
|
+
success = memory_manager.extract_and_update_memory(
|
|
205
|
+
agent_id, response_text
|
|
206
|
+
)
|
|
207
|
+
|
|
200
208
|
if success:
|
|
201
|
-
self.logger.info(
|
|
209
|
+
self.logger.info(
|
|
210
|
+
f"Successfully extracted and saved memories for {agent_id}"
|
|
211
|
+
)
|
|
202
212
|
else:
|
|
203
|
-
self.logger.debug(
|
|
204
|
-
|
|
213
|
+
self.logger.debug(
|
|
214
|
+
f"No memories found to extract for {agent_id}"
|
|
215
|
+
)
|
|
216
|
+
|
|
205
217
|
except Exception as mem_error:
|
|
206
|
-
self.logger.warning(
|
|
218
|
+
self.logger.warning(
|
|
219
|
+
f"Failed to extract/save memories for {agent_id}: {mem_error}"
|
|
220
|
+
)
|
|
207
221
|
else:
|
|
208
|
-
self.logger.debug(
|
|
222
|
+
self.logger.debug(
|
|
223
|
+
"No response text found in context for memory extraction"
|
|
224
|
+
)
|
|
209
225
|
|
|
210
226
|
return HookResult(success=True, data=context.data, modified=False)
|
|
211
227
|
|
|
@@ -291,5 +307,3 @@ class MemoryHookService(BaseService, MemoryHookInterface):
|
|
|
291
307
|
"total_hooks": len(self.registered_hooks),
|
|
292
308
|
"status": "active" if self.registered_hooks else "inactive",
|
|
293
309
|
}
|
|
294
|
-
|
|
295
|
-
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
WHY: The Monitor UI needs its own build tracking separate from the main MPM build
|
|
4
4
|
number to track UI-specific changes and deployments independently.
|
|
5
5
|
|
|
6
|
-
DESIGN DECISION:
|
|
6
|
+
DESIGN DECISION:
|
|
7
7
|
- Uses atomic file operations for thread-safe build number management
|
|
8
8
|
- Stores build number in MONITOR_BUILD file at project root
|
|
9
9
|
- Formats as 4-digit zero-padded strings (0001, 0002, etc.)
|
|
@@ -11,7 +11,6 @@ DESIGN DECISION:
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import asyncio
|
|
14
|
-
import fcntl
|
|
15
14
|
import json
|
|
16
15
|
import os
|
|
17
16
|
import tempfile
|
|
@@ -24,67 +23,68 @@ from claude_mpm.core.logger import get_logger
|
|
|
24
23
|
|
|
25
24
|
class MonitorBuildService(BaseService):
|
|
26
25
|
"""Service for managing Monitor UI build numbers.
|
|
27
|
-
|
|
26
|
+
|
|
28
27
|
WHY: Separate build tracking allows the Monitor UI to evolve independently
|
|
29
28
|
of the main MPM framework, enabling rapid UI iterations without affecting
|
|
30
29
|
core framework versioning.
|
|
31
30
|
"""
|
|
32
|
-
|
|
31
|
+
|
|
33
32
|
# Default values
|
|
34
33
|
DEFAULT_BUILD_NUMBER = 1
|
|
35
34
|
DEFAULT_VERSION = "1.0.0"
|
|
36
35
|
BUILD_FILE_NAME = "MONITOR_BUILD"
|
|
37
|
-
|
|
36
|
+
|
|
38
37
|
def __init__(self):
|
|
39
38
|
"""Initialize the monitor build service."""
|
|
40
39
|
super().__init__(name="monitor_build_service")
|
|
41
40
|
self.logger = get_logger(self.__class__.__name__)
|
|
42
|
-
|
|
41
|
+
|
|
43
42
|
# Determine build file location
|
|
44
43
|
self._build_file_path = self._get_build_file_path()
|
|
45
|
-
|
|
44
|
+
|
|
46
45
|
# Cache for build info to reduce file I/O
|
|
47
46
|
self._cached_build_info: Optional[Dict[str, Any]] = None
|
|
48
47
|
self._cache_lock = asyncio.Lock()
|
|
49
|
-
|
|
48
|
+
|
|
50
49
|
def _get_build_file_path(self) -> Path:
|
|
51
50
|
"""Get the path to the MONITOR_BUILD file.
|
|
52
|
-
|
|
51
|
+
|
|
53
52
|
WHY: Centralizes build file location logic, checking multiple
|
|
54
53
|
possible locations to support different installation scenarios.
|
|
55
|
-
|
|
54
|
+
|
|
56
55
|
Returns:
|
|
57
56
|
Path to the MONITOR_BUILD file
|
|
58
57
|
"""
|
|
59
58
|
# Try project root first (development)
|
|
60
59
|
try:
|
|
61
60
|
from claude_mpm.config.paths import paths
|
|
61
|
+
|
|
62
62
|
build_file = paths.project_root / self.BUILD_FILE_NAME
|
|
63
63
|
if build_file.parent.exists():
|
|
64
64
|
return build_file
|
|
65
65
|
except ImportError:
|
|
66
66
|
pass
|
|
67
|
-
|
|
67
|
+
|
|
68
68
|
# Fallback to package root
|
|
69
69
|
package_root = Path(__file__).parent.parent.parent
|
|
70
70
|
return package_root / self.BUILD_FILE_NAME
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
async def _initialize(self) -> None:
|
|
73
73
|
"""Initialize the service and ensure build file exists.
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
WHY: Ensures the build file exists with default values on first run,
|
|
76
76
|
preventing errors and providing a clean starting point.
|
|
77
77
|
"""
|
|
78
78
|
await self._ensure_build_file_exists()
|
|
79
79
|
await self._load_build_info()
|
|
80
|
-
|
|
80
|
+
|
|
81
81
|
async def _cleanup(self) -> None:
|
|
82
82
|
"""Cleanup service resources."""
|
|
83
83
|
self._cached_build_info = None
|
|
84
|
-
|
|
84
|
+
|
|
85
85
|
async def _ensure_build_file_exists(self) -> None:
|
|
86
86
|
"""Ensure the MONITOR_BUILD file exists with default values.
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
WHY: Atomic file creation prevents race conditions when multiple
|
|
89
89
|
processes might try to create the file simultaneously.
|
|
90
90
|
"""
|
|
@@ -92,17 +92,17 @@ class MonitorBuildService(BaseService):
|
|
|
92
92
|
default_info = {
|
|
93
93
|
"build_number": self.DEFAULT_BUILD_NUMBER,
|
|
94
94
|
"version": self.DEFAULT_VERSION,
|
|
95
|
-
"last_updated": None
|
|
95
|
+
"last_updated": None,
|
|
96
96
|
}
|
|
97
97
|
await self._write_build_info(default_info)
|
|
98
98
|
self.logger.info(f"Created MONITOR_BUILD file at {self._build_file_path}")
|
|
99
|
-
|
|
99
|
+
|
|
100
100
|
async def _load_build_info(self) -> Dict[str, Any]:
|
|
101
101
|
"""Load build information from file.
|
|
102
|
-
|
|
102
|
+
|
|
103
103
|
WHY: Centralizes file reading with error handling and caching
|
|
104
104
|
to improve performance and reliability.
|
|
105
|
-
|
|
105
|
+
|
|
106
106
|
Returns:
|
|
107
107
|
Dictionary with build information
|
|
108
108
|
"""
|
|
@@ -110,7 +110,7 @@ class MonitorBuildService(BaseService):
|
|
|
110
110
|
try:
|
|
111
111
|
if self._build_file_path.exists():
|
|
112
112
|
content = self._build_file_path.read_text().strip()
|
|
113
|
-
|
|
113
|
+
|
|
114
114
|
# Try to parse as JSON first
|
|
115
115
|
try:
|
|
116
116
|
self._cached_build_info = json.loads(content)
|
|
@@ -121,95 +121,94 @@ class MonitorBuildService(BaseService):
|
|
|
121
121
|
self._cached_build_info = {
|
|
122
122
|
"build_number": build_num,
|
|
123
123
|
"version": self.DEFAULT_VERSION,
|
|
124
|
-
"last_updated": None
|
|
124
|
+
"last_updated": None,
|
|
125
125
|
}
|
|
126
126
|
except ValueError:
|
|
127
127
|
# Invalid content, use defaults
|
|
128
128
|
self._cached_build_info = {
|
|
129
129
|
"build_number": self.DEFAULT_BUILD_NUMBER,
|
|
130
130
|
"version": self.DEFAULT_VERSION,
|
|
131
|
-
"last_updated": None
|
|
131
|
+
"last_updated": None,
|
|
132
132
|
}
|
|
133
133
|
else:
|
|
134
134
|
self._cached_build_info = {
|
|
135
135
|
"build_number": self.DEFAULT_BUILD_NUMBER,
|
|
136
136
|
"version": self.DEFAULT_VERSION,
|
|
137
|
-
"last_updated": None
|
|
137
|
+
"last_updated": None,
|
|
138
138
|
}
|
|
139
139
|
except Exception as e:
|
|
140
140
|
self.logger.error(f"Error loading build info: {e}")
|
|
141
141
|
self._cached_build_info = {
|
|
142
142
|
"build_number": self.DEFAULT_BUILD_NUMBER,
|
|
143
143
|
"version": self.DEFAULT_VERSION,
|
|
144
|
-
"last_updated": None
|
|
144
|
+
"last_updated": None,
|
|
145
145
|
}
|
|
146
|
-
|
|
146
|
+
|
|
147
147
|
return self._cached_build_info
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
async def _write_build_info(self, info: Dict[str, Any]) -> None:
|
|
150
150
|
"""Write build information to file atomically.
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
WHY: Atomic writes prevent file corruption if the process is
|
|
153
153
|
interrupted during the write operation.
|
|
154
|
-
|
|
154
|
+
|
|
155
155
|
Args:
|
|
156
156
|
info: Build information dictionary
|
|
157
157
|
"""
|
|
158
158
|
# Add timestamp
|
|
159
159
|
from datetime import datetime
|
|
160
|
+
|
|
160
161
|
info["last_updated"] = datetime.utcnow().isoformat()
|
|
161
|
-
|
|
162
|
+
|
|
162
163
|
# Write atomically using temp file and rename
|
|
163
164
|
temp_fd, temp_path = tempfile.mkstemp(
|
|
164
|
-
dir=self._build_file_path.parent,
|
|
165
|
-
prefix=".monitor_build_",
|
|
166
|
-
suffix=".tmp"
|
|
165
|
+
dir=self._build_file_path.parent, prefix=".monitor_build_", suffix=".tmp"
|
|
167
166
|
)
|
|
168
|
-
|
|
167
|
+
|
|
169
168
|
try:
|
|
170
169
|
# Write JSON content
|
|
171
|
-
with os.fdopen(temp_fd,
|
|
170
|
+
with os.fdopen(temp_fd, "w") as f:
|
|
172
171
|
json.dump(info, f, indent=2)
|
|
173
|
-
|
|
172
|
+
|
|
174
173
|
# Atomic rename
|
|
175
174
|
Path(temp_path).replace(self._build_file_path)
|
|
176
|
-
|
|
175
|
+
|
|
177
176
|
# Update cache
|
|
178
177
|
async with self._cache_lock:
|
|
179
178
|
self._cached_build_info = info
|
|
180
|
-
|
|
179
|
+
|
|
181
180
|
except Exception as e:
|
|
182
181
|
# Clean up temp file on error
|
|
183
182
|
Path(temp_path).unlink(missing_ok=True)
|
|
184
183
|
raise e
|
|
185
|
-
|
|
184
|
+
|
|
186
185
|
async def get_build_number(self) -> int:
|
|
187
186
|
"""Get the current monitor build number.
|
|
188
|
-
|
|
187
|
+
|
|
189
188
|
Returns:
|
|
190
189
|
Current build number as integer
|
|
191
190
|
"""
|
|
192
191
|
info = await self._load_build_info()
|
|
193
192
|
return info.get("build_number", self.DEFAULT_BUILD_NUMBER)
|
|
194
|
-
|
|
193
|
+
|
|
195
194
|
async def get_formatted_build_number(self) -> str:
|
|
196
195
|
"""Get the current build number as a 4-digit string.
|
|
197
|
-
|
|
196
|
+
|
|
198
197
|
WHY: Consistent 4-digit formatting ensures proper sorting
|
|
199
198
|
and display alignment in the UI.
|
|
200
|
-
|
|
199
|
+
|
|
201
200
|
Returns:
|
|
202
201
|
Build number as 4-digit zero-padded string
|
|
203
202
|
"""
|
|
204
203
|
build_num = await self.get_build_number()
|
|
205
204
|
return f"{build_num:04d}"
|
|
206
|
-
|
|
205
|
+
|
|
207
206
|
async def increment_build_number(self) -> int:
|
|
208
207
|
"""Increment and return the new build number.
|
|
209
|
-
|
|
208
|
+
|
|
210
209
|
WHY: Atomic increment operation ensures no build numbers are
|
|
211
210
|
skipped or duplicated even with concurrent access.
|
|
212
|
-
|
|
211
|
+
|
|
213
212
|
Returns:
|
|
214
213
|
New build number after incrementing
|
|
215
214
|
"""
|
|
@@ -217,22 +216,22 @@ class MonitorBuildService(BaseService):
|
|
|
217
216
|
new_build = info.get("build_number", self.DEFAULT_BUILD_NUMBER) + 1
|
|
218
217
|
info["build_number"] = new_build
|
|
219
218
|
await self._write_build_info(info)
|
|
220
|
-
|
|
219
|
+
|
|
221
220
|
self.logger.info(f"Monitor build number incremented to {new_build:04d}")
|
|
222
221
|
return new_build
|
|
223
|
-
|
|
222
|
+
|
|
224
223
|
async def get_monitor_version(self) -> str:
|
|
225
224
|
"""Get the monitor UI version.
|
|
226
|
-
|
|
225
|
+
|
|
227
226
|
Returns:
|
|
228
227
|
Monitor UI semantic version string
|
|
229
228
|
"""
|
|
230
229
|
info = await self._load_build_info()
|
|
231
230
|
return info.get("version", self.DEFAULT_VERSION)
|
|
232
|
-
|
|
231
|
+
|
|
233
232
|
async def set_monitor_version(self, version: str) -> None:
|
|
234
233
|
"""Set the monitor UI version.
|
|
235
|
-
|
|
234
|
+
|
|
236
235
|
Args:
|
|
237
236
|
version: New semantic version string
|
|
238
237
|
"""
|
|
@@ -240,67 +239,72 @@ class MonitorBuildService(BaseService):
|
|
|
240
239
|
info["version"] = version
|
|
241
240
|
await self._write_build_info(info)
|
|
242
241
|
self.logger.info(f"Monitor version updated to {version}")
|
|
243
|
-
|
|
242
|
+
|
|
244
243
|
async def get_full_version_string(self) -> str:
|
|
245
244
|
"""Get the full version string for display.
|
|
246
|
-
|
|
245
|
+
|
|
247
246
|
WHY: Combines semantic version with build number for complete
|
|
248
247
|
version identification in the UI.
|
|
249
|
-
|
|
248
|
+
|
|
250
249
|
Returns:
|
|
251
250
|
Full version string (e.g., "v1.0.0-0001")
|
|
252
251
|
"""
|
|
253
252
|
version = await self.get_monitor_version()
|
|
254
253
|
build = await self.get_formatted_build_number()
|
|
255
254
|
return f"v{version}-{build}"
|
|
256
|
-
|
|
255
|
+
|
|
257
256
|
async def get_build_info(self) -> Dict[str, Any]:
|
|
258
257
|
"""Get complete build information.
|
|
259
|
-
|
|
258
|
+
|
|
260
259
|
WHY: Provides all build metadata in a single call for
|
|
261
260
|
efficient transmission to the UI via SocketIO.
|
|
262
|
-
|
|
261
|
+
|
|
263
262
|
Returns:
|
|
264
263
|
Dictionary with all build information
|
|
265
264
|
"""
|
|
266
265
|
info = await self._load_build_info()
|
|
267
|
-
|
|
266
|
+
|
|
268
267
|
# Get MPM version info
|
|
269
268
|
mpm_version = "unknown"
|
|
270
269
|
mpm_build = "unknown"
|
|
271
|
-
|
|
270
|
+
|
|
272
271
|
try:
|
|
273
272
|
from claude_mpm.services.version_service import VersionService
|
|
273
|
+
|
|
274
274
|
version_service = VersionService()
|
|
275
275
|
version_info = version_service.get_version_info()
|
|
276
276
|
mpm_version = version_info.get("base_version", "unknown")
|
|
277
277
|
mpm_build = version_info.get("build_number", "unknown")
|
|
278
278
|
except Exception as e:
|
|
279
279
|
self.logger.debug(f"Could not get MPM version info: {e}")
|
|
280
|
-
|
|
280
|
+
|
|
281
281
|
return {
|
|
282
282
|
"monitor": {
|
|
283
283
|
"version": info.get("version", self.DEFAULT_VERSION),
|
|
284
284
|
"build": info.get("build_number", self.DEFAULT_BUILD_NUMBER),
|
|
285
285
|
"formatted_build": f"{info.get('build_number', self.DEFAULT_BUILD_NUMBER):04d}",
|
|
286
286
|
"full_version": await self.get_full_version_string(),
|
|
287
|
-
"last_updated": info.get("last_updated")
|
|
287
|
+
"last_updated": info.get("last_updated"),
|
|
288
288
|
},
|
|
289
289
|
"mpm": {
|
|
290
290
|
"version": mpm_version,
|
|
291
291
|
"build": mpm_build,
|
|
292
|
-
"full_version":
|
|
293
|
-
|
|
292
|
+
"full_version": (
|
|
293
|
+
f"v{mpm_version}-build.{mpm_build}"
|
|
294
|
+
if mpm_build != "unknown"
|
|
295
|
+
else f"v{mpm_version}"
|
|
296
|
+
),
|
|
297
|
+
},
|
|
294
298
|
}
|
|
295
|
-
|
|
299
|
+
|
|
296
300
|
# Synchronous convenience methods for non-async contexts
|
|
297
|
-
|
|
301
|
+
|
|
298
302
|
def get_build_number_sync(self) -> int:
|
|
299
303
|
"""Synchronous version of get_build_number.
|
|
300
|
-
|
|
304
|
+
|
|
301
305
|
WHY: Some contexts (like SocketIO handlers) may not support
|
|
302
306
|
async operations directly.
|
|
303
|
-
|
|
307
|
+
|
|
304
308
|
Returns:
|
|
305
309
|
Current build number as integer
|
|
306
310
|
"""
|
|
@@ -309,13 +313,13 @@ class MonitorBuildService(BaseService):
|
|
|
309
313
|
return loop.run_until_complete(self.get_build_number())
|
|
310
314
|
finally:
|
|
311
315
|
loop.close()
|
|
312
|
-
|
|
316
|
+
|
|
313
317
|
def get_build_info_sync(self) -> Dict[str, Any]:
|
|
314
318
|
"""Synchronous version of get_build_info.
|
|
315
|
-
|
|
319
|
+
|
|
316
320
|
WHY: SocketIO connection handlers often need synchronous
|
|
317
321
|
access to build information.
|
|
318
|
-
|
|
322
|
+
|
|
319
323
|
Returns:
|
|
320
324
|
Dictionary with all build information
|
|
321
325
|
"""
|
|
@@ -332,14 +336,14 @@ _monitor_build_service: Optional[MonitorBuildService] = None
|
|
|
332
336
|
|
|
333
337
|
def get_monitor_build_service() -> MonitorBuildService:
|
|
334
338
|
"""Get or create the global monitor build service instance.
|
|
335
|
-
|
|
339
|
+
|
|
336
340
|
WHY: Singleton pattern ensures consistent build number management
|
|
337
341
|
across the application.
|
|
338
|
-
|
|
342
|
+
|
|
339
343
|
Returns:
|
|
340
344
|
The global MonitorBuildService instance
|
|
341
345
|
"""
|
|
342
346
|
global _monitor_build_service
|
|
343
347
|
if _monitor_build_service is None:
|
|
344
348
|
_monitor_build_service = MonitorBuildService()
|
|
345
|
-
return _monitor_build_service
|
|
349
|
+
return _monitor_build_service
|