claude-mpm 4.1.1__py3-none-any.whl → 4.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/BUILD_NUMBER +1 -1
- claude_mpm/VERSION +1 -1
- claude_mpm/__main__.py +1 -1
- claude_mpm/agents/BASE_PM.md +74 -46
- claude_mpm/agents/INSTRUCTIONS.md +11 -153
- claude_mpm/agents/WORKFLOW.md +61 -321
- claude_mpm/agents/__init__.py +11 -11
- claude_mpm/agents/agent_loader.py +23 -20
- claude_mpm/agents/agent_loader_integration.py +1 -1
- claude_mpm/agents/agents_metadata.py +27 -0
- claude_mpm/agents/async_agent_loader.py +5 -8
- claude_mpm/agents/base_agent_loader.py +36 -25
- claude_mpm/agents/frontmatter_validator.py +6 -6
- claude_mpm/agents/schema/agent_schema.json +1 -1
- claude_mpm/agents/system_agent_config.py +9 -9
- claude_mpm/agents/templates/api_qa.json +47 -2
- claude_mpm/agents/templates/engineer.json +33 -11
- claude_mpm/agents/templates/imagemagick.json +256 -0
- claude_mpm/agents/templates/qa.json +41 -2
- claude_mpm/agents/templates/ticketing.json +5 -5
- claude_mpm/agents/templates/web_qa.json +50 -2
- claude_mpm/cli/__init__.py +51 -46
- claude_mpm/cli/__main__.py +1 -1
- claude_mpm/cli/commands/__init__.py +10 -12
- claude_mpm/cli/commands/agent_manager.py +186 -181
- claude_mpm/cli/commands/agents.py +648 -1098
- claude_mpm/cli/commands/aggregate.py +30 -29
- claude_mpm/cli/commands/cleanup.py +50 -44
- claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
- claude_mpm/cli/commands/config.py +162 -127
- claude_mpm/cli/commands/doctor.py +52 -62
- claude_mpm/cli/commands/info.py +37 -25
- claude_mpm/cli/commands/mcp.py +3 -7
- claude_mpm/cli/commands/mcp_command_router.py +14 -18
- claude_mpm/cli/commands/mcp_install_commands.py +28 -23
- claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
- claude_mpm/cli/commands/mcp_server_commands.py +23 -17
- claude_mpm/cli/commands/memory.py +339 -967
- claude_mpm/cli/commands/monitor.py +117 -88
- claude_mpm/cli/commands/run.py +233 -542
- claude_mpm/cli/commands/socketio_monitor.py +17 -19
- claude_mpm/cli/commands/tickets.py +92 -92
- claude_mpm/cli/parser.py +1 -5
- claude_mpm/cli/parsers/__init__.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
- claude_mpm/cli/parsers/agents_parser.py +2 -3
- claude_mpm/cli/parsers/base_parser.py +7 -5
- claude_mpm/cli/parsers/mcp_parser.py +4 -2
- claude_mpm/cli/parsers/monitor_parser.py +26 -18
- claude_mpm/cli/shared/__init__.py +10 -10
- claude_mpm/cli/shared/argument_patterns.py +57 -71
- claude_mpm/cli/shared/base_command.py +61 -53
- claude_mpm/cli/shared/error_handling.py +62 -58
- claude_mpm/cli/shared/output_formatters.py +78 -77
- claude_mpm/cli/startup_logging.py +280 -172
- claude_mpm/cli/utils.py +10 -11
- claude_mpm/cli_module/__init__.py +1 -1
- claude_mpm/cli_module/args.py +1 -1
- claude_mpm/cli_module/migration_example.py +5 -5
- claude_mpm/config/__init__.py +9 -9
- claude_mpm/config/agent_config.py +15 -14
- claude_mpm/config/experimental_features.py +4 -4
- claude_mpm/config/paths.py +0 -1
- claude_mpm/config/socketio_config.py +5 -6
- claude_mpm/constants.py +1 -2
- claude_mpm/core/__init__.py +8 -8
- claude_mpm/core/agent_name_normalizer.py +1 -1
- claude_mpm/core/agent_registry.py +22 -29
- claude_mpm/core/agent_session_manager.py +3 -3
- claude_mpm/core/base_service.py +7 -15
- claude_mpm/core/cache.py +4 -6
- claude_mpm/core/claude_runner.py +85 -113
- claude_mpm/core/config.py +43 -28
- claude_mpm/core/config_aliases.py +0 -9
- claude_mpm/core/config_constants.py +52 -30
- claude_mpm/core/constants.py +0 -1
- claude_mpm/core/container.py +18 -27
- claude_mpm/core/exceptions.py +2 -2
- claude_mpm/core/factories.py +10 -12
- claude_mpm/core/framework_loader.py +500 -680
- claude_mpm/core/hook_manager.py +26 -22
- claude_mpm/core/hook_performance_config.py +58 -47
- claude_mpm/core/injectable_service.py +1 -1
- claude_mpm/core/interactive_session.py +61 -152
- claude_mpm/core/interfaces.py +1 -100
- claude_mpm/core/lazy.py +5 -5
- claude_mpm/core/log_manager.py +587 -0
- claude_mpm/core/logger.py +125 -8
- claude_mpm/core/logging_config.py +15 -17
- claude_mpm/core/minimal_framework_loader.py +5 -8
- claude_mpm/core/oneshot_session.py +15 -33
- claude_mpm/core/optimized_agent_loader.py +4 -6
- claude_mpm/core/optimized_startup.py +2 -1
- claude_mpm/core/output_style_manager.py +147 -106
- claude_mpm/core/pm_hook_interceptor.py +0 -1
- claude_mpm/core/service_registry.py +11 -8
- claude_mpm/core/session_manager.py +1 -2
- claude_mpm/core/shared/__init__.py +1 -1
- claude_mpm/core/shared/config_loader.py +101 -97
- claude_mpm/core/shared/path_resolver.py +72 -68
- claude_mpm/core/shared/singleton_manager.py +56 -50
- claude_mpm/core/socketio_pool.py +26 -6
- claude_mpm/core/tool_access_control.py +4 -5
- claude_mpm/core/typing_utils.py +50 -59
- claude_mpm/core/unified_agent_registry.py +14 -19
- claude_mpm/core/unified_config.py +4 -6
- claude_mpm/core/unified_paths.py +197 -109
- claude_mpm/dashboard/open_dashboard.py +2 -4
- claude_mpm/experimental/cli_enhancements.py +51 -36
- claude_mpm/generators/agent_profile_generator.py +2 -4
- claude_mpm/hooks/base_hook.py +1 -2
- claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
- claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
- claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
- claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
- claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
- claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
- claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
- claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
- claude_mpm/hooks/memory_integration_hook.py +5 -5
- claude_mpm/hooks/tool_call_interceptor.py +1 -1
- claude_mpm/hooks/validation_hooks.py +4 -4
- claude_mpm/init.py +4 -9
- claude_mpm/models/__init__.py +2 -2
- claude_mpm/models/agent_session.py +11 -14
- claude_mpm/scripts/mcp_server.py +20 -11
- claude_mpm/scripts/mcp_wrapper.py +5 -5
- claude_mpm/scripts/mpm_doctor.py +321 -0
- claude_mpm/scripts/socketio_daemon.py +28 -25
- claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
- claude_mpm/scripts/socketio_server_manager.py +116 -95
- claude_mpm/services/__init__.py +49 -49
- claude_mpm/services/agent_capabilities_service.py +12 -18
- claude_mpm/services/agents/__init__.py +22 -22
- claude_mpm/services/agents/agent_builder.py +140 -119
- claude_mpm/services/agents/deployment/__init__.py +3 -3
- claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
- claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
- claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
- claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
- claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
- claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
- claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
- claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
- claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
- claude_mpm/services/agents/deployment/agent_validator.py +0 -1
- claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
- claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
- claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
- claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
- claude_mpm/services/agents/deployment/config/__init__.py +1 -1
- claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
- claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
- claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
- claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
- claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
- claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
- claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
- claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
- claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
- claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
- claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
- claude_mpm/services/agents/deployment/results/__init__.py +1 -1
- claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
- claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
- claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
- claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
- claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
- claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
- claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
- claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
- claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
- claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
- claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
- claude_mpm/services/agents/loading/__init__.py +1 -1
- claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
- claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
- claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
- claude_mpm/services/agents/management/__init__.py +1 -1
- claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
- claude_mpm/services/agents/management/agent_management_service.py +5 -9
- claude_mpm/services/agents/memory/__init__.py +4 -4
- claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
- claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
- claude_mpm/services/agents/memory/content_manager.py +44 -38
- claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
- claude_mpm/services/agents/memory/memory_file_service.py +103 -0
- claude_mpm/services/agents/memory/memory_format_service.py +201 -0
- claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
- claude_mpm/services/agents/memory/template_generator.py +4 -6
- claude_mpm/services/agents/registry/__init__.py +11 -7
- claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
- claude_mpm/services/agents/registry/modification_tracker.py +3 -6
- claude_mpm/services/async_session_logger.py +1 -2
- claude_mpm/services/claude_session_logger.py +1 -2
- claude_mpm/services/cli/__init__.py +18 -0
- claude_mpm/services/cli/agent_cleanup_service.py +407 -0
- claude_mpm/services/cli/agent_dependency_service.py +395 -0
- claude_mpm/services/cli/agent_listing_service.py +463 -0
- claude_mpm/services/cli/agent_output_formatter.py +605 -0
- claude_mpm/services/cli/agent_validation_service.py +589 -0
- claude_mpm/services/cli/dashboard_launcher.py +424 -0
- claude_mpm/services/cli/memory_crud_service.py +617 -0
- claude_mpm/services/cli/memory_output_formatter.py +604 -0
- claude_mpm/services/cli/session_manager.py +513 -0
- claude_mpm/services/cli/socketio_manager.py +498 -0
- claude_mpm/services/cli/startup_checker.py +370 -0
- claude_mpm/services/command_deployment_service.py +173 -0
- claude_mpm/services/command_handler_service.py +20 -22
- claude_mpm/services/core/__init__.py +25 -25
- claude_mpm/services/core/base.py +0 -5
- claude_mpm/services/core/cache_manager.py +311 -0
- claude_mpm/services/core/interfaces/__init__.py +32 -32
- claude_mpm/services/core/interfaces/agent.py +0 -21
- claude_mpm/services/core/interfaces/communication.py +0 -27
- claude_mpm/services/core/interfaces/infrastructure.py +0 -56
- claude_mpm/services/core/interfaces/service.py +0 -29
- claude_mpm/services/core/memory_manager.py +637 -0
- claude_mpm/services/core/path_resolver.py +498 -0
- claude_mpm/services/core/service_container.py +520 -0
- claude_mpm/services/core/service_interfaces.py +436 -0
- claude_mpm/services/diagnostics/__init__.py +1 -1
- claude_mpm/services/diagnostics/checks/__init__.py +6 -6
- claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
- claude_mpm/services/diagnostics/checks/base_check.py +12 -16
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
- claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
- claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
- claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
- claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
- claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
- claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
- claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
- claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
- claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
- claude_mpm/services/diagnostics/models.py +21 -19
- claude_mpm/services/event_aggregator.py +10 -17
- claude_mpm/services/event_bus/__init__.py +1 -1
- claude_mpm/services/event_bus/config.py +54 -35
- claude_mpm/services/event_bus/event_bus.py +76 -71
- claude_mpm/services/event_bus/relay.py +74 -64
- claude_mpm/services/events/__init__.py +11 -11
- claude_mpm/services/events/consumers/__init__.py +3 -3
- claude_mpm/services/events/consumers/dead_letter.py +71 -63
- claude_mpm/services/events/consumers/logging.py +39 -37
- claude_mpm/services/events/consumers/metrics.py +56 -57
- claude_mpm/services/events/consumers/socketio.py +82 -81
- claude_mpm/services/events/core.py +110 -99
- claude_mpm/services/events/interfaces.py +56 -72
- claude_mpm/services/events/producers/__init__.py +1 -1
- claude_mpm/services/events/producers/hook.py +38 -38
- claude_mpm/services/events/producers/system.py +46 -44
- claude_mpm/services/exceptions.py +81 -80
- claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
- claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
- claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
- claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
- claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
- claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
- claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
- claude_mpm/services/hook_service.py +6 -9
- claude_mpm/services/infrastructure/__init__.py +1 -1
- claude_mpm/services/infrastructure/context_preservation.py +8 -12
- claude_mpm/services/infrastructure/monitoring.py +21 -23
- claude_mpm/services/mcp_gateway/__init__.py +37 -37
- claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
- claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
- claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
- claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
- claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
- claude_mpm/services/mcp_gateway/core/base.py +0 -3
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
- claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
- claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
- claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
- claude_mpm/services/mcp_gateway/main.py +2 -1
- claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
- claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
- claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
- claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
- claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
- claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
- claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
- claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
- claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
- claude_mpm/services/memory/__init__.py +3 -3
- claude_mpm/services/memory/builder.py +3 -6
- claude_mpm/services/memory/cache/__init__.py +1 -1
- claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
- claude_mpm/services/memory/cache/simple_cache.py +1 -1
- claude_mpm/services/memory/indexed_memory.py +5 -7
- claude_mpm/services/memory/optimizer.py +7 -10
- claude_mpm/services/memory/router.py +8 -9
- claude_mpm/services/memory_hook_service.py +48 -34
- claude_mpm/services/monitor_build_service.py +77 -73
- claude_mpm/services/port_manager.py +130 -108
- claude_mpm/services/project/analyzer.py +12 -10
- claude_mpm/services/project/registry.py +11 -11
- claude_mpm/services/recovery_manager.py +10 -19
- claude_mpm/services/response_tracker.py +0 -1
- claude_mpm/services/runner_configuration_service.py +19 -20
- claude_mpm/services/session_management_service.py +7 -11
- claude_mpm/services/shared/__init__.py +1 -1
- claude_mpm/services/shared/async_service_base.py +58 -50
- claude_mpm/services/shared/config_service_base.py +73 -67
- claude_mpm/services/shared/lifecycle_service_base.py +82 -78
- claude_mpm/services/shared/manager_base.py +94 -82
- claude_mpm/services/shared/service_factory.py +96 -98
- claude_mpm/services/socketio/__init__.py +3 -3
- claude_mpm/services/socketio/client_proxy.py +5 -5
- claude_mpm/services/socketio/event_normalizer.py +199 -181
- claude_mpm/services/socketio/handlers/__init__.py +3 -3
- claude_mpm/services/socketio/handlers/base.py +5 -4
- claude_mpm/services/socketio/handlers/connection.py +163 -136
- claude_mpm/services/socketio/handlers/file.py +13 -14
- claude_mpm/services/socketio/handlers/git.py +12 -7
- claude_mpm/services/socketio/handlers/hook.py +49 -44
- claude_mpm/services/socketio/handlers/memory.py +0 -1
- claude_mpm/services/socketio/handlers/project.py +0 -1
- claude_mpm/services/socketio/handlers/registry.py +37 -19
- claude_mpm/services/socketio/migration_utils.py +98 -84
- claude_mpm/services/socketio/server/__init__.py +1 -1
- claude_mpm/services/socketio/server/broadcaster.py +81 -87
- claude_mpm/services/socketio/server/core.py +65 -54
- claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
- claude_mpm/services/socketio/server/main.py +64 -38
- claude_mpm/services/socketio_client_manager.py +10 -12
- claude_mpm/services/subprocess_launcher_service.py +4 -7
- claude_mpm/services/system_instructions_service.py +13 -14
- claude_mpm/services/ticket_manager.py +2 -2
- claude_mpm/services/utility_service.py +5 -13
- claude_mpm/services/version_control/__init__.py +16 -16
- claude_mpm/services/version_control/branch_strategy.py +5 -8
- claude_mpm/services/version_control/conflict_resolution.py +9 -23
- claude_mpm/services/version_control/git_operations.py +5 -7
- claude_mpm/services/version_control/semantic_versioning.py +16 -17
- claude_mpm/services/version_control/version_parser.py +13 -18
- claude_mpm/services/version_service.py +10 -11
- claude_mpm/storage/__init__.py +1 -1
- claude_mpm/storage/state_storage.py +22 -28
- claude_mpm/utils/__init__.py +6 -6
- claude_mpm/utils/agent_dependency_loader.py +47 -33
- claude_mpm/utils/config_manager.py +11 -14
- claude_mpm/utils/dependency_cache.py +1 -1
- claude_mpm/utils/dependency_manager.py +13 -17
- claude_mpm/utils/dependency_strategies.py +8 -10
- claude_mpm/utils/environment_context.py +3 -9
- claude_mpm/utils/error_handler.py +3 -13
- claude_mpm/utils/file_utils.py +1 -1
- claude_mpm/utils/path_operations.py +8 -12
- claude_mpm/utils/robust_installer.py +110 -33
- claude_mpm/utils/subprocess_utils.py +5 -6
- claude_mpm/validation/agent_validator.py +3 -6
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
- claude_mpm-4.1.3.dist-info/RECORD +528 -0
- claude_mpm/cli/commands/run_config_checker.py +0 -160
- claude_mpm-4.1.1.dist-info/RECORD +0 -494
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"""Subagent response processing service for Claude hook handler.
|
|
2
|
+
|
|
3
|
+
This service handles:
|
|
4
|
+
- SubagentStop event processing
|
|
5
|
+
- Structured response extraction
|
|
6
|
+
- Response tracking and correlation
|
|
7
|
+
- Memory field processing
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
import json
|
|
11
|
+
import os
|
|
12
|
+
import re
|
|
13
|
+
import sys
|
|
14
|
+
from datetime import datetime
|
|
15
|
+
from typing import Optional, Tuple
|
|
16
|
+
|
|
17
|
+
# Debug mode is enabled by default for better visibility into hook processing
|
|
18
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "true").lower() != "false"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class SubagentResponseProcessor:
|
|
22
|
+
"""Processes subagent responses and extracts structured data."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, state_manager, response_tracking_manager, connection_manager):
|
|
25
|
+
"""Initialize the subagent response processor.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
state_manager: StateManagerService instance
|
|
29
|
+
response_tracking_manager: ResponseTrackingManager instance
|
|
30
|
+
connection_manager: ConnectionManagerService instance
|
|
31
|
+
"""
|
|
32
|
+
self.state_manager = state_manager
|
|
33
|
+
self.response_tracking_manager = response_tracking_manager
|
|
34
|
+
self.connection_manager = connection_manager
|
|
35
|
+
|
|
36
|
+
def process_subagent_stop(self, event: dict):
|
|
37
|
+
"""Handle subagent stop events with improved agent type detection.
|
|
38
|
+
|
|
39
|
+
WHY comprehensive subagent stop capture:
|
|
40
|
+
- Provides visibility into subagent lifecycle and delegation patterns
|
|
41
|
+
- Captures agent type, ID, reason, and results for analysis
|
|
42
|
+
- Enables tracking of delegation success/failure patterns
|
|
43
|
+
- Useful for understanding subagent performance and reliability
|
|
44
|
+
"""
|
|
45
|
+
# Enhanced debug logging for session correlation
|
|
46
|
+
session_id = event.get("session_id", "")
|
|
47
|
+
if DEBUG:
|
|
48
|
+
print(
|
|
49
|
+
f" - session_id: {session_id[:16] if session_id else 'None'}...",
|
|
50
|
+
file=sys.stderr,
|
|
51
|
+
)
|
|
52
|
+
print(f" - event keys: {list(event.keys())}", file=sys.stderr)
|
|
53
|
+
print(
|
|
54
|
+
f" - delegation_requests size: {len(self.state_manager.delegation_requests)}",
|
|
55
|
+
file=sys.stderr,
|
|
56
|
+
)
|
|
57
|
+
# Show all stored session IDs for comparison
|
|
58
|
+
all_sessions = list(self.state_manager.delegation_requests.keys())
|
|
59
|
+
if all_sessions:
|
|
60
|
+
print(" - Stored sessions (first 16 chars):", file=sys.stderr)
|
|
61
|
+
for sid in all_sessions[:10]: # Show up to 10
|
|
62
|
+
print(
|
|
63
|
+
f" - {sid[:16]}... (agent: {self.state_manager.delegation_requests[sid].get('agent_type', 'unknown')})",
|
|
64
|
+
file=sys.stderr,
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
print(" - No stored sessions in delegation_requests!", file=sys.stderr)
|
|
68
|
+
|
|
69
|
+
# Get agent type and other basic info
|
|
70
|
+
agent_type, agent_id, reason = self._extract_basic_info(event, session_id)
|
|
71
|
+
|
|
72
|
+
# Always log SubagentStop events for debugging
|
|
73
|
+
if DEBUG or agent_type != "unknown":
|
|
74
|
+
print(
|
|
75
|
+
f"Hook handler: Processing SubagentStop - agent: '{agent_type}', session: '{session_id}', reason: '{reason}'",
|
|
76
|
+
file=sys.stderr,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Get working directory and git branch
|
|
80
|
+
working_dir = event.get("cwd", "")
|
|
81
|
+
git_branch = (
|
|
82
|
+
self.state_manager.get_git_branch(working_dir) if working_dir else "Unknown"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
# Try to extract structured response from output if available
|
|
86
|
+
output = event.get("output", "")
|
|
87
|
+
structured_response = self._extract_structured_response(output, agent_type)
|
|
88
|
+
|
|
89
|
+
# Track agent response
|
|
90
|
+
self._track_response(
|
|
91
|
+
event,
|
|
92
|
+
session_id,
|
|
93
|
+
agent_type,
|
|
94
|
+
reason,
|
|
95
|
+
working_dir,
|
|
96
|
+
git_branch,
|
|
97
|
+
output,
|
|
98
|
+
structured_response,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Build subagent stop data for event emission
|
|
102
|
+
subagent_stop_data = self._build_subagent_stop_data(
|
|
103
|
+
event,
|
|
104
|
+
session_id,
|
|
105
|
+
agent_type,
|
|
106
|
+
agent_id,
|
|
107
|
+
reason,
|
|
108
|
+
working_dir,
|
|
109
|
+
git_branch,
|
|
110
|
+
structured_response,
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
# Debug log the processed data
|
|
114
|
+
if DEBUG:
|
|
115
|
+
print(
|
|
116
|
+
f"SubagentStop processed data: agent_type='{agent_type}', session_id='{session_id}'",
|
|
117
|
+
file=sys.stderr,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Emit to /hook namespace with high priority
|
|
121
|
+
self.connection_manager.emit_event("/hook", "subagent_stop", subagent_stop_data)
|
|
122
|
+
|
|
123
|
+
def _extract_basic_info(self, event: dict, session_id: str) -> Tuple[str, str, str]:
|
|
124
|
+
"""Extract basic info from the event."""
|
|
125
|
+
# First try to get agent type from our tracking
|
|
126
|
+
agent_type = (
|
|
127
|
+
self.state_manager.get_delegation_agent_type(session_id)
|
|
128
|
+
if session_id
|
|
129
|
+
else "unknown"
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# Fall back to event data if tracking didn't have it
|
|
133
|
+
if agent_type == "unknown":
|
|
134
|
+
agent_type = event.get("agent_type", event.get("subagent_type", "unknown"))
|
|
135
|
+
|
|
136
|
+
agent_id = event.get("agent_id", event.get("subagent_id", ""))
|
|
137
|
+
reason = event.get("reason", event.get("stop_reason", "unknown"))
|
|
138
|
+
|
|
139
|
+
# Try to infer agent type from other fields if still unknown
|
|
140
|
+
if agent_type == "unknown" and "task" in event:
|
|
141
|
+
task_desc = str(event.get("task", "")).lower()
|
|
142
|
+
if "research" in task_desc:
|
|
143
|
+
agent_type = "research"
|
|
144
|
+
elif "engineer" in task_desc or "code" in task_desc:
|
|
145
|
+
agent_type = "engineer"
|
|
146
|
+
elif "pm" in task_desc or "project" in task_desc:
|
|
147
|
+
agent_type = "pm"
|
|
148
|
+
|
|
149
|
+
return agent_type, agent_id, reason
|
|
150
|
+
|
|
151
|
+
def _extract_structured_response(
|
|
152
|
+
self, output: str, agent_type: str
|
|
153
|
+
) -> Optional[dict]:
|
|
154
|
+
"""Extract structured JSON response from output."""
|
|
155
|
+
if not output:
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
try:
|
|
159
|
+
json_match = re.search(r"```json\s*(\{.*?\})\s*```", str(output), re.DOTALL)
|
|
160
|
+
if json_match:
|
|
161
|
+
structured_response = json.loads(json_match.group(1))
|
|
162
|
+
if DEBUG:
|
|
163
|
+
print(
|
|
164
|
+
f"Extracted structured response from {agent_type} agent in SubagentStop",
|
|
165
|
+
file=sys.stderr,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# Log if MEMORIES field is present
|
|
169
|
+
if structured_response.get("MEMORIES") and DEBUG:
|
|
170
|
+
memories_count = len(structured_response["MEMORIES"])
|
|
171
|
+
print(
|
|
172
|
+
f"Agent {agent_type} returned MEMORIES field with {memories_count} items",
|
|
173
|
+
file=sys.stderr,
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
return structured_response
|
|
177
|
+
except (json.JSONDecodeError, AttributeError):
|
|
178
|
+
pass # No structured response, that's okay
|
|
179
|
+
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
def _track_response(
|
|
183
|
+
self,
|
|
184
|
+
event: dict,
|
|
185
|
+
session_id: str,
|
|
186
|
+
agent_type: str,
|
|
187
|
+
reason: str,
|
|
188
|
+
working_dir: str,
|
|
189
|
+
git_branch: str,
|
|
190
|
+
output: str,
|
|
191
|
+
structured_response: Optional[dict],
|
|
192
|
+
):
|
|
193
|
+
"""Track the agent response if response tracking is enabled."""
|
|
194
|
+
if DEBUG:
|
|
195
|
+
print(
|
|
196
|
+
f" - response_tracking_enabled: {self.response_tracking_manager.response_tracking_enabled}",
|
|
197
|
+
file=sys.stderr,
|
|
198
|
+
)
|
|
199
|
+
print(
|
|
200
|
+
f" - response_tracker exists: {self.response_tracking_manager.response_tracker is not None}",
|
|
201
|
+
file=sys.stderr,
|
|
202
|
+
)
|
|
203
|
+
print(
|
|
204
|
+
f" - session_id: {session_id[:16] if session_id else 'None'}...",
|
|
205
|
+
file=sys.stderr,
|
|
206
|
+
)
|
|
207
|
+
print(f" - agent_type: {agent_type}", file=sys.stderr)
|
|
208
|
+
print(f" - reason: {reason}", file=sys.stderr)
|
|
209
|
+
|
|
210
|
+
if (
|
|
211
|
+
self.response_tracking_manager.response_tracking_enabled
|
|
212
|
+
and self.response_tracking_manager.response_tracker
|
|
213
|
+
):
|
|
214
|
+
try:
|
|
215
|
+
# Get the original request data (with fuzzy matching fallback)
|
|
216
|
+
request_info = self.state_manager.find_matching_request(session_id)
|
|
217
|
+
|
|
218
|
+
if DEBUG:
|
|
219
|
+
print(
|
|
220
|
+
f" - request_info present: {bool(request_info)}",
|
|
221
|
+
file=sys.stderr,
|
|
222
|
+
)
|
|
223
|
+
if request_info:
|
|
224
|
+
print(
|
|
225
|
+
" - ✅ Found request data for response tracking",
|
|
226
|
+
file=sys.stderr,
|
|
227
|
+
)
|
|
228
|
+
print(
|
|
229
|
+
f" - stored agent_type: {request_info.get('agent_type')}",
|
|
230
|
+
file=sys.stderr,
|
|
231
|
+
)
|
|
232
|
+
print(
|
|
233
|
+
f" - request keys: {list(request_info.get('request', {}).keys())}",
|
|
234
|
+
file=sys.stderr,
|
|
235
|
+
)
|
|
236
|
+
else:
|
|
237
|
+
print(
|
|
238
|
+
f" - ❌ No request data found for session {session_id[:16]}...",
|
|
239
|
+
file=sys.stderr,
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
if request_info:
|
|
243
|
+
# Use the output as the response
|
|
244
|
+
response_text = (
|
|
245
|
+
str(output)
|
|
246
|
+
if output
|
|
247
|
+
else f"Agent {agent_type} completed with reason: {reason}"
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
# Get the original request
|
|
251
|
+
original_request = request_info.get("request", {})
|
|
252
|
+
prompt = original_request.get("prompt", "")
|
|
253
|
+
description = original_request.get("description", "")
|
|
254
|
+
|
|
255
|
+
# Combine prompt and description
|
|
256
|
+
full_request = prompt
|
|
257
|
+
if description and description != prompt:
|
|
258
|
+
if full_request:
|
|
259
|
+
full_request += f"\n\nDescription: {description}"
|
|
260
|
+
else:
|
|
261
|
+
full_request = description
|
|
262
|
+
|
|
263
|
+
if not full_request:
|
|
264
|
+
full_request = f"Task delegation to {agent_type} agent"
|
|
265
|
+
|
|
266
|
+
# Prepare metadata
|
|
267
|
+
metadata = {
|
|
268
|
+
"exit_code": event.get("exit_code", 0),
|
|
269
|
+
"success": reason in ["completed", "finished", "done"],
|
|
270
|
+
"has_error": reason
|
|
271
|
+
in ["error", "timeout", "failed", "blocked"],
|
|
272
|
+
"duration_ms": event.get("duration_ms"),
|
|
273
|
+
"working_directory": working_dir,
|
|
274
|
+
"git_branch": git_branch,
|
|
275
|
+
"timestamp": datetime.now().isoformat(),
|
|
276
|
+
"event_type": "subagent_stop",
|
|
277
|
+
"reason": reason,
|
|
278
|
+
"original_request_timestamp": request_info.get("timestamp"),
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
# Add structured response if available
|
|
282
|
+
if structured_response:
|
|
283
|
+
metadata["structured_response"] = structured_response
|
|
284
|
+
metadata["task_completed"] = structured_response.get(
|
|
285
|
+
"task_completed", False
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
# Check for MEMORIES field and process if present
|
|
289
|
+
if structured_response.get("MEMORIES") and DEBUG:
|
|
290
|
+
memories = structured_response["MEMORIES"]
|
|
291
|
+
print(
|
|
292
|
+
f"Found MEMORIES field in {agent_type} response with {len(memories)} items",
|
|
293
|
+
file=sys.stderr,
|
|
294
|
+
)
|
|
295
|
+
# The memory will be processed by extract_and_update_memory
|
|
296
|
+
# which is called by the memory hook service
|
|
297
|
+
|
|
298
|
+
# Track the response
|
|
299
|
+
file_path = (
|
|
300
|
+
self.response_tracking_manager.response_tracker.track_response(
|
|
301
|
+
agent_name=agent_type,
|
|
302
|
+
request=full_request,
|
|
303
|
+
response=response_text,
|
|
304
|
+
session_id=session_id,
|
|
305
|
+
metadata=metadata,
|
|
306
|
+
)
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
if file_path and DEBUG:
|
|
310
|
+
print(
|
|
311
|
+
f"✅ Tracked {agent_type} agent response on SubagentStop: {file_path.name}",
|
|
312
|
+
file=sys.stderr,
|
|
313
|
+
)
|
|
314
|
+
|
|
315
|
+
# Clean up the request data
|
|
316
|
+
self.state_manager.remove_request(session_id)
|
|
317
|
+
|
|
318
|
+
elif DEBUG:
|
|
319
|
+
print(
|
|
320
|
+
f"No request data for SubagentStop session {session_id[:8]}..., agent: {agent_type}",
|
|
321
|
+
file=sys.stderr,
|
|
322
|
+
)
|
|
323
|
+
|
|
324
|
+
except Exception as e:
|
|
325
|
+
if DEBUG:
|
|
326
|
+
print(
|
|
327
|
+
f"❌ Failed to track response on SubagentStop: {e}",
|
|
328
|
+
file=sys.stderr,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
def _build_subagent_stop_data(
|
|
332
|
+
self,
|
|
333
|
+
event: dict,
|
|
334
|
+
session_id: str,
|
|
335
|
+
agent_type: str,
|
|
336
|
+
agent_id: str,
|
|
337
|
+
reason: str,
|
|
338
|
+
working_dir: str,
|
|
339
|
+
git_branch: str,
|
|
340
|
+
structured_response: Optional[dict],
|
|
341
|
+
) -> dict:
|
|
342
|
+
"""Build the subagent stop data for event emission."""
|
|
343
|
+
subagent_stop_data = {
|
|
344
|
+
"agent_type": agent_type,
|
|
345
|
+
"agent_id": agent_id,
|
|
346
|
+
"reason": reason,
|
|
347
|
+
"session_id": session_id,
|
|
348
|
+
"working_directory": working_dir,
|
|
349
|
+
"git_branch": git_branch,
|
|
350
|
+
"timestamp": datetime.now().isoformat(),
|
|
351
|
+
"is_successful_completion": reason in ["completed", "finished", "done"],
|
|
352
|
+
"is_error_termination": reason in ["error", "timeout", "failed", "blocked"],
|
|
353
|
+
"is_delegation_related": agent_type
|
|
354
|
+
in ["research", "engineer", "pm", "ops", "qa", "documentation", "security"],
|
|
355
|
+
"has_results": bool(event.get("results") or event.get("output")),
|
|
356
|
+
"duration_context": event.get("duration_ms"),
|
|
357
|
+
"hook_event_name": "SubagentStop", # Explicitly set for dashboard
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
# Add structured response data if available
|
|
361
|
+
if structured_response:
|
|
362
|
+
subagent_stop_data["structured_response"] = {
|
|
363
|
+
"task_completed": structured_response.get("task_completed", False),
|
|
364
|
+
"instructions": structured_response.get("instructions", ""),
|
|
365
|
+
"results": structured_response.get("results", ""),
|
|
366
|
+
"files_modified": structured_response.get("files_modified", []),
|
|
367
|
+
"tools_used": structured_response.get("tools_used", []),
|
|
368
|
+
"remember": structured_response.get("remember"),
|
|
369
|
+
"MEMORIES": structured_response.get(
|
|
370
|
+
"MEMORIES"
|
|
371
|
+
), # Complete memory replacement
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return subagent_stop_data
|
|
@@ -5,8 +5,6 @@ This module provides utilities for analyzing tool usage, extracting parameters,
|
|
|
5
5
|
and assessing security risks.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
from typing import Any, Dict, List
|
|
9
|
-
|
|
10
8
|
|
|
11
9
|
def extract_tool_parameters(tool_name: str, tool_input: dict) -> dict:
|
|
12
10
|
"""Extract relevant parameters based on tool type.
|
|
@@ -99,7 +97,7 @@ def extract_tool_parameters(tool_name: str, tool_input: dict) -> dict:
|
|
|
99
97
|
"has_in_progress": any(t.get("status") == "in_progress" for t in todos),
|
|
100
98
|
"has_pending": any(t.get("status") == "pending" for t in todos),
|
|
101
99
|
"has_completed": any(t.get("status") == "completed" for t in todos),
|
|
102
|
-
"priorities": list(
|
|
100
|
+
"priorities": list({t.get("priority", "medium") for t in todos}),
|
|
103
101
|
}
|
|
104
102
|
)
|
|
105
103
|
|
|
@@ -144,18 +142,17 @@ def classify_tool_operation(tool_name: str, tool_input: dict) -> str:
|
|
|
144
142
|
"""Classify the type of operation being performed."""
|
|
145
143
|
if tool_name in ["Read", "LS", "Glob", "Grep", "NotebookRead"]:
|
|
146
144
|
return "read"
|
|
147
|
-
|
|
145
|
+
if tool_name in ["Write", "Edit", "MultiEdit", "NotebookEdit"]:
|
|
148
146
|
return "write"
|
|
149
|
-
|
|
147
|
+
if tool_name == "Bash":
|
|
150
148
|
return "execute"
|
|
151
|
-
|
|
149
|
+
if tool_name in ["WebFetch", "WebSearch"]:
|
|
152
150
|
return "network"
|
|
153
|
-
|
|
151
|
+
if tool_name == "TodoWrite":
|
|
154
152
|
return "task_management"
|
|
155
|
-
|
|
153
|
+
if tool_name == "Task":
|
|
156
154
|
return "delegation"
|
|
157
|
-
|
|
158
|
-
return "other"
|
|
155
|
+
return "other"
|
|
159
156
|
|
|
160
157
|
|
|
161
158
|
def assess_security_risk(tool_name: str, tool_input: dict) -> str:
|
|
@@ -174,21 +171,18 @@ def assess_security_risk(tool_name: str, tool_input: dict) -> str:
|
|
|
174
171
|
]
|
|
175
172
|
if any(pattern in command for pattern in dangerous_patterns):
|
|
176
173
|
return "high"
|
|
177
|
-
|
|
174
|
+
if any(word in command for word in ["install", "delete", "format", "kill"]):
|
|
178
175
|
return "medium"
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
elif tool_name in ["Write", "Edit", "MultiEdit"]:
|
|
176
|
+
return "low"
|
|
177
|
+
if tool_name in ["Write", "Edit", "MultiEdit"]:
|
|
182
178
|
file_path = tool_input.get("file_path", "")
|
|
183
179
|
# Check for system file modifications
|
|
184
180
|
if any(path in file_path for path in ["/etc/", "/usr/", "/var/", "/sys/"]):
|
|
185
181
|
return "high"
|
|
186
|
-
|
|
182
|
+
if file_path.startswith("/"):
|
|
187
183
|
return "medium"
|
|
188
|
-
else:
|
|
189
|
-
return "low"
|
|
190
|
-
else:
|
|
191
184
|
return "low"
|
|
185
|
+
return "low"
|
|
192
186
|
|
|
193
187
|
|
|
194
188
|
def extract_tool_results(event: dict) -> dict:
|
|
@@ -13,7 +13,7 @@ agent outputs because:
|
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
15
|
import re
|
|
16
|
-
from typing import
|
|
16
|
+
from typing import Dict, List
|
|
17
17
|
|
|
18
18
|
from claude_mpm.core.config import Config
|
|
19
19
|
from claude_mpm.core.logger import get_logger
|
|
@@ -162,7 +162,7 @@ INSTRUCTIONS: Review your memory above before proceeding. Apply learned patterns
|
|
|
162
162
|
success=True,
|
|
163
163
|
data=context.data,
|
|
164
164
|
modified=False,
|
|
165
|
-
error=f"Memory injection failed: {
|
|
165
|
+
error=f"Memory injection failed: {e!s}",
|
|
166
166
|
)
|
|
167
167
|
|
|
168
168
|
|
|
@@ -319,7 +319,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
|
|
|
319
319
|
success=True,
|
|
320
320
|
data=context.data,
|
|
321
321
|
modified=False,
|
|
322
|
-
error=f"Learning extraction failed: {
|
|
322
|
+
error=f"Learning extraction failed: {e!s}",
|
|
323
323
|
)
|
|
324
324
|
|
|
325
325
|
def _extract_learnings(self, text: str) -> Dict[str, List[str]]:
|
|
@@ -339,7 +339,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
|
|
|
339
339
|
Returns:
|
|
340
340
|
Dictionary mapping learning types to lists of extracted learnings
|
|
341
341
|
"""
|
|
342
|
-
learnings = {learning_type: [] for learning_type in self.type_mapping
|
|
342
|
+
learnings = {learning_type: [] for learning_type in self.type_mapping}
|
|
343
343
|
seen_learnings = set() # Avoid duplicates
|
|
344
344
|
|
|
345
345
|
# Pattern to find memory blocks with multiple trigger phrases
|
|
@@ -394,7 +394,7 @@ class MemoryPostDelegationHook(PostDelegationHook):
|
|
|
394
394
|
f"Unsupported learning type: {learning_type}. Supported types: {list(self.type_mapping.keys())}"
|
|
395
395
|
)
|
|
396
396
|
else:
|
|
397
|
-
logger.debug(
|
|
397
|
+
logger.debug("Invalid memory block format - missing Type or Content")
|
|
398
398
|
|
|
399
399
|
# Log summary of extracted learnings
|
|
400
400
|
total_learnings = sum(len(items) for items in learnings.values())
|
|
@@ -6,7 +6,7 @@ from datetime import datetime
|
|
|
6
6
|
from typing import Any, Dict, List, Optional
|
|
7
7
|
|
|
8
8
|
from claude_mpm.core.logger import get_logger
|
|
9
|
-
from claude_mpm.hooks.base_hook import BaseHook, HookContext,
|
|
9
|
+
from claude_mpm.hooks.base_hook import BaseHook, HookContext, HookType
|
|
10
10
|
|
|
11
11
|
logger = get_logger(__name__)
|
|
12
12
|
|
|
@@ -61,7 +61,7 @@ class ValidationHooks:
|
|
|
61
61
|
result.is_valid = False
|
|
62
62
|
except Exception as e:
|
|
63
63
|
logger.error(f"Pre-load hook failed: {e}")
|
|
64
|
-
result.warnings.append(f"Pre-load hook failed: {
|
|
64
|
+
result.warnings.append(f"Pre-load hook failed: {e!s}")
|
|
65
65
|
|
|
66
66
|
return result
|
|
67
67
|
|
|
@@ -79,7 +79,7 @@ class ValidationHooks:
|
|
|
79
79
|
result.warnings.extend(hook_result.warnings)
|
|
80
80
|
except Exception as e:
|
|
81
81
|
logger.error(f"Post-load hook failed: {e}")
|
|
82
|
-
result.warnings.append(f"Post-load hook failed: {
|
|
82
|
+
result.warnings.append(f"Post-load hook failed: {e!s}")
|
|
83
83
|
|
|
84
84
|
return result
|
|
85
85
|
|
|
@@ -107,7 +107,7 @@ class ValidationHooks:
|
|
|
107
107
|
result.is_valid = False
|
|
108
108
|
except Exception as e:
|
|
109
109
|
logger.error(f"Pre-execute hook failed: {e}")
|
|
110
|
-
result.warnings.append(f"Pre-execute hook failed: {
|
|
110
|
+
result.warnings.append(f"Pre-execute hook failed: {e!s}")
|
|
111
111
|
|
|
112
112
|
return result
|
|
113
113
|
|
|
@@ -118,7 +118,7 @@ async def validate_agent_dependencies(profile_path: Path) -> ValidationResult:
|
|
|
118
118
|
result = ValidationResult(is_valid=True)
|
|
119
119
|
|
|
120
120
|
try:
|
|
121
|
-
with open(profile_path
|
|
121
|
+
with open(profile_path) as f:
|
|
122
122
|
profile_data = yaml.safe_load(f)
|
|
123
123
|
|
|
124
124
|
# Check for circular dependencies
|
claude_mpm/init.py
CHANGED
|
@@ -8,7 +8,8 @@ Handles creation of necessary directories and configuration files.
|
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
10
|
import shutil
|
|
11
|
-
|
|
11
|
+
import sys
|
|
12
|
+
from typing import Dict, Optional
|
|
12
13
|
|
|
13
14
|
import yaml
|
|
14
15
|
|
|
@@ -142,12 +143,10 @@ class ProjectInitializer:
|
|
|
142
143
|
|
|
143
144
|
# Log successful creation with details
|
|
144
145
|
self.logger.info(f"Initialized project directory at {self.project_dir}")
|
|
145
|
-
self.logger.debug(
|
|
146
|
+
self.logger.debug("Created directories: agents, config, responses, logs")
|
|
146
147
|
|
|
147
148
|
# Print appropriate message to console for visibility during startup
|
|
148
149
|
# BUT: Don't print to stdout when running MCP server (interferes with JSON-RPC)
|
|
149
|
-
import sys
|
|
150
|
-
|
|
151
150
|
is_mcp_mode = "mcp" in sys.argv and "start" in sys.argv
|
|
152
151
|
|
|
153
152
|
if not is_mcp_mode:
|
|
@@ -216,8 +215,6 @@ class ProjectInitializer:
|
|
|
216
215
|
|
|
217
216
|
if migrated_count > 0:
|
|
218
217
|
# Don't print to stdout when running MCP server
|
|
219
|
-
import sys
|
|
220
|
-
|
|
221
218
|
is_mcp_mode = "mcp" in sys.argv and "start" in sys.argv
|
|
222
219
|
if not is_mcp_mode:
|
|
223
220
|
print(
|
|
@@ -254,7 +251,7 @@ class ProjectInitializer:
|
|
|
254
251
|
"""
|
|
255
252
|
try:
|
|
256
253
|
# Read existing JSON configuration
|
|
257
|
-
with open(old_file
|
|
254
|
+
with open(old_file) as f:
|
|
258
255
|
config = json.load(f)
|
|
259
256
|
|
|
260
257
|
# Write as YAML
|
|
@@ -327,8 +324,6 @@ class ProjectInitializer:
|
|
|
327
324
|
dependencies = {}
|
|
328
325
|
|
|
329
326
|
# Check Python version
|
|
330
|
-
import sys
|
|
331
|
-
|
|
332
327
|
dependencies["python"] = sys.version_info >= (3, 8)
|
|
333
328
|
|
|
334
329
|
# Check Claude CLI
|
claude_mpm/models/__init__.py
CHANGED
|
@@ -12,7 +12,6 @@ chronological order for session replay and analysis.
|
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
|
-
import os
|
|
16
15
|
from dataclasses import asdict, dataclass, field
|
|
17
16
|
from datetime import datetime
|
|
18
17
|
from enum import Enum
|
|
@@ -241,29 +240,28 @@ class AgentSession:
|
|
|
241
240
|
# Check event type patterns
|
|
242
241
|
if "prompt" in event_type.lower() or event_type == "user_input":
|
|
243
242
|
return EventCategory.PROMPT
|
|
244
|
-
|
|
243
|
+
if "delegation" in event_type.lower() or event_type == "Task":
|
|
245
244
|
return EventCategory.DELEGATION
|
|
246
|
-
|
|
245
|
+
if "tool" in event_type.lower() or event_type in [
|
|
247
246
|
"PreToolUse",
|
|
248
247
|
"PostToolUse",
|
|
249
248
|
]:
|
|
250
249
|
return EventCategory.TOOL
|
|
251
|
-
|
|
250
|
+
if (
|
|
252
251
|
"file" in event_type.lower()
|
|
253
252
|
or "write" in event_type.lower()
|
|
254
253
|
or "read" in event_type.lower()
|
|
255
254
|
):
|
|
256
255
|
return EventCategory.FILE
|
|
257
|
-
|
|
256
|
+
if "todo" in event_type.lower():
|
|
258
257
|
return EventCategory.TODO
|
|
259
|
-
|
|
258
|
+
if "response" in event_type.lower() or event_type in ["Stop", "SubagentStop"]:
|
|
260
259
|
return EventCategory.RESPONSE
|
|
261
|
-
|
|
260
|
+
if "memory" in event_type.lower():
|
|
262
261
|
return EventCategory.MEMORY
|
|
263
|
-
|
|
262
|
+
if "status" in event_type.lower() or "session" in event_type.lower():
|
|
264
263
|
return EventCategory.STATUS
|
|
265
|
-
|
|
266
|
-
return EventCategory.SYSTEM
|
|
264
|
+
return EventCategory.SYSTEM
|
|
267
265
|
|
|
268
266
|
def _process_event(self, event: SessionEvent):
|
|
269
267
|
"""Process specific event types to update session state.
|
|
@@ -376,9 +374,8 @@ class AgentSession:
|
|
|
376
374
|
self.active_delegation.todos_modified.append(data["todos"])
|
|
377
375
|
|
|
378
376
|
# Track memory updates
|
|
379
|
-
elif event.category == EventCategory.MEMORY:
|
|
380
|
-
|
|
381
|
-
self.active_delegation.memory_updates.append(data)
|
|
377
|
+
elif event.category == EventCategory.MEMORY and self.active_delegation:
|
|
378
|
+
self.active_delegation.memory_updates.append(data)
|
|
382
379
|
|
|
383
380
|
def finalize(self):
|
|
384
381
|
"""Finalize the session by calculating final metrics.
|
|
@@ -534,6 +531,6 @@ class AgentSession:
|
|
|
534
531
|
|
|
535
532
|
WHY: Enables analysis of historical sessions.
|
|
536
533
|
"""
|
|
537
|
-
with open(filepath,
|
|
534
|
+
with open(filepath, encoding="utf-8") as f:
|
|
538
535
|
data = json.load(f)
|
|
539
536
|
return cls.from_dict(data)
|