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
|
@@ -27,21 +27,20 @@ Implements error handling and user guidance patterns from awesome-claude-code.
|
|
|
27
27
|
|
|
28
28
|
import logging
|
|
29
29
|
import sys
|
|
30
|
-
from typing import Any, Dict, List, Optional
|
|
31
30
|
|
|
32
31
|
import click
|
|
33
32
|
|
|
34
|
-
from claude_mpm.hooks.validation_hooks import
|
|
33
|
+
from claude_mpm.hooks.validation_hooks import ValidationHooks
|
|
35
34
|
from claude_mpm.utils.error_handler import (
|
|
36
35
|
ErrorContext,
|
|
37
36
|
MPMError,
|
|
38
37
|
handle_errors,
|
|
39
|
-
suggest_setup_fix,
|
|
40
38
|
)
|
|
41
39
|
from claude_mpm.validation import AgentValidator, ValidationResult
|
|
42
40
|
|
|
43
41
|
logger = logging.getLogger(__name__)
|
|
44
42
|
|
|
43
|
+
|
|
45
44
|
class CLIContext:
|
|
46
45
|
"""Enhanced CLI context with validation and error handling."""
|
|
47
46
|
|
|
@@ -55,12 +54,14 @@ class CLIContext:
|
|
|
55
54
|
def setup_logging(self, debug: bool = False) -> None:
|
|
56
55
|
"""Setup logging based on debug flag."""
|
|
57
56
|
level = logging.DEBUG if debug else logging.INFO
|
|
58
|
-
format_str =
|
|
57
|
+
format_str = (
|
|
58
|
+
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
59
|
+
if debug
|
|
60
|
+
else "%(message)s"
|
|
61
|
+
)
|
|
59
62
|
|
|
60
63
|
logging.basicConfig(
|
|
61
|
-
level=level,
|
|
62
|
-
format=format_str,
|
|
63
|
-
handlers=[logging.StreamHandler(sys.stdout)]
|
|
64
|
+
level=level, format=format_str, handlers=[logging.StreamHandler(sys.stdout)]
|
|
64
65
|
)
|
|
65
66
|
self.debug = debug
|
|
66
67
|
|
|
@@ -78,9 +79,9 @@ class CLIContext:
|
|
|
78
79
|
|
|
79
80
|
# Check required directories
|
|
80
81
|
required_dirs = [
|
|
81
|
-
Path.home() /
|
|
82
|
-
Path.home() /
|
|
83
|
-
Path.home() /
|
|
82
|
+
Path.home() / ".claude-mpm",
|
|
83
|
+
Path.home() / ".claude-mpm" / "profiles",
|
|
84
|
+
Path.home() / ".claude-mpm" / "logs",
|
|
84
85
|
]
|
|
85
86
|
|
|
86
87
|
for dir_path in required_dirs:
|
|
@@ -94,8 +95,9 @@ class CLIContext:
|
|
|
94
95
|
|
|
95
96
|
return all_passed
|
|
96
97
|
|
|
97
|
-
def handle_validation_result(
|
|
98
|
-
|
|
98
|
+
def handle_validation_result(
|
|
99
|
+
self, result: ValidationResult, operation: str = "operation"
|
|
100
|
+
) -> None:
|
|
99
101
|
"""Handle validation results with user-friendly output."""
|
|
100
102
|
if result.is_valid:
|
|
101
103
|
if result.warnings:
|
|
@@ -116,13 +118,14 @@ class CLIContext:
|
|
|
116
118
|
|
|
117
119
|
sys.exit(1)
|
|
118
120
|
|
|
121
|
+
|
|
119
122
|
def create_enhanced_cli() -> click.Group:
|
|
120
123
|
"""Create enhanced CLI with better error handling."""
|
|
121
124
|
cli_context = CLIContext()
|
|
122
125
|
|
|
123
126
|
@click.group()
|
|
124
|
-
@click.option(
|
|
125
|
-
@click.option(
|
|
127
|
+
@click.option("--debug", is_flag=True, help="Enable debug logging")
|
|
128
|
+
@click.option("--dry-run", is_flag=True, help="Run without making changes")
|
|
126
129
|
@click.pass_context
|
|
127
130
|
def cli(ctx, debug: bool, dry_run: bool):
|
|
128
131
|
"""Enhanced claude-mpm CLI with validation and error handling."""
|
|
@@ -131,6 +134,7 @@ def create_enhanced_cli() -> click.Group:
|
|
|
131
134
|
cli_context.dry_run = dry_run
|
|
132
135
|
|
|
133
136
|
if debug:
|
|
137
|
+
print("🐛 Debug mode enabled")
|
|
134
138
|
|
|
135
139
|
if dry_run:
|
|
136
140
|
print("🏃 Dry-run mode enabled")
|
|
@@ -154,7 +158,7 @@ def create_enhanced_cli() -> click.Group:
|
|
|
154
158
|
sys.exit(1)
|
|
155
159
|
|
|
156
160
|
@cli.command()
|
|
157
|
-
@click.argument(
|
|
161
|
+
@click.argument("profile_path", type=click.Path(exists=True))
|
|
158
162
|
@click.pass_context
|
|
159
163
|
@handle_errors(MPMError)
|
|
160
164
|
async def validate_profile(ctx, profile_path: str):
|
|
@@ -167,14 +171,16 @@ def create_enhanced_cli() -> click.Group:
|
|
|
167
171
|
# Run pre-load validation
|
|
168
172
|
result = await cli_ctx.validation_hooks.run_pre_load_validation(profile)
|
|
169
173
|
|
|
170
|
-
cli_ctx.handle_validation_result(
|
|
174
|
+
cli_ctx.handle_validation_result(
|
|
175
|
+
result, f"Profile validation for {profile.name}"
|
|
176
|
+
)
|
|
171
177
|
|
|
172
178
|
if result.is_valid and result.locked_fields:
|
|
173
179
|
print(f"\n🔒 Locked fields: {', '.join(result.locked_fields)}")
|
|
174
180
|
|
|
175
181
|
@cli.command()
|
|
176
|
-
@click.option(
|
|
177
|
-
@click.option(
|
|
182
|
+
@click.option("--profile", "-p", help="Agent profile to load")
|
|
183
|
+
@click.option("--task", "-t", help="Task to execute")
|
|
178
184
|
@click.pass_context
|
|
179
185
|
@handle_errors(MPMError)
|
|
180
186
|
async def run_agent(ctx, profile: str, task: str):
|
|
@@ -189,8 +195,8 @@ def create_enhanced_cli() -> click.Group:
|
|
|
189
195
|
if not profile_path.exists():
|
|
190
196
|
# Try default locations
|
|
191
197
|
default_locations = [
|
|
192
|
-
Path.home() /
|
|
193
|
-
Path.cwd() /
|
|
198
|
+
Path.home() / ".claude-mpm" / "profiles" / f"{profile}.yaml",
|
|
199
|
+
Path.cwd() / "agents" / f"{profile}.yaml",
|
|
194
200
|
]
|
|
195
201
|
|
|
196
202
|
for location in default_locations:
|
|
@@ -200,24 +206,26 @@ def create_enhanced_cli() -> click.Group:
|
|
|
200
206
|
else:
|
|
201
207
|
raise MPMError(
|
|
202
208
|
f"Profile '{profile}' not found",
|
|
203
|
-
details={
|
|
209
|
+
details={"searched_locations": [str(p) for p in default_locations]},
|
|
204
210
|
suggestions=[
|
|
205
211
|
"Check the profile name",
|
|
206
212
|
"Use 'mpm list-profiles' to see available profiles",
|
|
207
|
-
"Create a new profile with 'mpm create-profile'"
|
|
208
|
-
]
|
|
213
|
+
"Create a new profile with 'mpm create-profile'",
|
|
214
|
+
],
|
|
209
215
|
)
|
|
210
216
|
|
|
211
217
|
# Run validation
|
|
212
218
|
print(f"🔍 Validating profile: {profile_path.name}")
|
|
213
|
-
validation_result = await cli_ctx.validation_hooks.run_pre_load_validation(
|
|
219
|
+
validation_result = await cli_ctx.validation_hooks.run_pre_load_validation(
|
|
220
|
+
profile_path
|
|
221
|
+
)
|
|
214
222
|
|
|
215
223
|
if not validation_result.is_valid:
|
|
216
224
|
cli_ctx.handle_validation_result(validation_result, "Profile validation")
|
|
217
225
|
return
|
|
218
226
|
|
|
219
227
|
# Validate task
|
|
220
|
-
print(
|
|
228
|
+
print("🔍 Validating task...")
|
|
221
229
|
task_result = await cli_ctx.validation_hooks.run_pre_execute_validation(
|
|
222
230
|
profile_path.stem, task
|
|
223
231
|
)
|
|
@@ -242,14 +250,14 @@ def create_enhanced_cli() -> click.Group:
|
|
|
242
250
|
cli_ctx = ctx.obj
|
|
243
251
|
|
|
244
252
|
profile_locations = [
|
|
245
|
-
Path.home() /
|
|
246
|
-
Path.cwd() /
|
|
253
|
+
Path.home() / ".claude-mpm" / "profiles",
|
|
254
|
+
Path.cwd() / "agents",
|
|
247
255
|
]
|
|
248
256
|
|
|
249
257
|
all_profiles = []
|
|
250
258
|
for location in profile_locations:
|
|
251
259
|
if location.exists():
|
|
252
|
-
profiles = list(location.glob(
|
|
260
|
+
profiles = list(location.glob("*.yaml")) + list(location.glob("*.yml"))
|
|
253
261
|
all_profiles.extend(profiles)
|
|
254
262
|
|
|
255
263
|
if not all_profiles:
|
|
@@ -265,9 +273,9 @@ def create_enhanced_cli() -> click.Group:
|
|
|
265
273
|
print(f" {status} {profile.stem} ({profile})")
|
|
266
274
|
|
|
267
275
|
@cli.command()
|
|
268
|
-
@click.argument(
|
|
269
|
-
@click.option(
|
|
270
|
-
@click.option(
|
|
276
|
+
@click.argument("name")
|
|
277
|
+
@click.option("--role", "-r", required=True, help="Agent role")
|
|
278
|
+
@click.option("--category", "-c", default="analysis", help="Agent category")
|
|
271
279
|
@click.pass_context
|
|
272
280
|
def create_profile(ctx, name: str, role: str, category: str):
|
|
273
281
|
"""Create a new agent profile from template."""
|
|
@@ -285,34 +293,41 @@ def create_enhanced_cli() -> click.Group:
|
|
|
285
293
|
profile_content = generator.generate_profile(config)
|
|
286
294
|
|
|
287
295
|
# Save profile
|
|
288
|
-
profile_dir = Path.home() /
|
|
296
|
+
profile_dir = Path.home() / ".claude-mpm" / "profiles"
|
|
289
297
|
profile_dir.mkdir(parents=True, exist_ok=True)
|
|
290
298
|
|
|
291
299
|
profile_path = profile_dir / f"{name.lower().replace(' ', '_')}.yaml"
|
|
292
300
|
|
|
293
|
-
if profile_path.exists() and not click.confirm(
|
|
301
|
+
if profile_path.exists() and not click.confirm(
|
|
302
|
+
f"Profile {profile_path} exists. Overwrite?"
|
|
303
|
+
):
|
|
294
304
|
print("Aborted")
|
|
295
305
|
return
|
|
296
306
|
|
|
297
307
|
if cli_ctx.dry_run:
|
|
298
308
|
print(f"\n🏃 Dry-run mode - would create {profile_path}:")
|
|
299
309
|
print("---")
|
|
300
|
-
print(
|
|
310
|
+
print(
|
|
311
|
+
profile_content[:500] + "..."
|
|
312
|
+
if len(profile_content) > 500
|
|
313
|
+
else profile_content
|
|
314
|
+
)
|
|
301
315
|
print("---")
|
|
302
316
|
else:
|
|
303
317
|
profile_path.write_text(profile_content)
|
|
304
318
|
print(f"✅ Created profile: {profile_path}")
|
|
305
319
|
|
|
306
320
|
# Generate documentation
|
|
307
|
-
doc_path = profile_path.with_suffix(
|
|
321
|
+
doc_path = profile_path.with_suffix(".md")
|
|
308
322
|
doc_content = generator.generate_agent_documentation(config)
|
|
309
323
|
doc_path.write_text(doc_content)
|
|
310
324
|
print(f"📝 Created documentation: {doc_path}")
|
|
311
325
|
|
|
312
326
|
return cli
|
|
313
327
|
|
|
328
|
+
|
|
314
329
|
# Export the enhanced CLI
|
|
315
330
|
enhanced_cli = create_enhanced_cli()
|
|
316
331
|
|
|
317
|
-
if __name__ ==
|
|
332
|
+
if __name__ == "__main__":
|
|
318
333
|
enhanced_cli()
|
|
@@ -29,7 +29,7 @@ class AgentProfileGenerator:
|
|
|
29
29
|
if not self.template_path.exists():
|
|
30
30
|
raise FileNotFoundError(f"Template not found: {self.template_path}")
|
|
31
31
|
|
|
32
|
-
with open(self.template_path
|
|
32
|
+
with open(self.template_path) as f:
|
|
33
33
|
return yaml.safe_load(f)
|
|
34
34
|
|
|
35
35
|
def generate_profile(self, config: Dict[str, Any]) -> str:
|
|
@@ -46,9 +46,7 @@ class AgentProfileGenerator:
|
|
|
46
46
|
result = self._replace_placeholders(template_str, config)
|
|
47
47
|
|
|
48
48
|
# Clean up any remaining placeholders
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return result
|
|
49
|
+
return re.sub(r"\{\{[^}]+\}\}", "", result)
|
|
52
50
|
|
|
53
51
|
def _replace_placeholders(self, template: str, values: Dict[str, Any]) -> str:
|
|
54
52
|
"""Replace template placeholders with actual values."""
|
claude_mpm/hooks/base_hook.py
CHANGED
|
@@ -6,7 +6,7 @@ from abc import ABC, abstractmethod
|
|
|
6
6
|
from dataclasses import dataclass
|
|
7
7
|
from datetime import datetime
|
|
8
8
|
from enum import Enum
|
|
9
|
-
from typing import Any, Dict,
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
@@ -75,7 +75,6 @@ class BaseHook(ABC):
|
|
|
75
75
|
Returns:
|
|
76
76
|
HookResult with execution results
|
|
77
77
|
"""
|
|
78
|
-
pass
|
|
79
78
|
|
|
80
79
|
async def async_execute(self, context: HookContext) -> HookResult:
|
|
81
80
|
"""Async version of execute. Override for async hooks."""
|
|
@@ -59,8 +59,7 @@ class SocketIOConnectionPool:
|
|
|
59
59
|
client = conn["client"]
|
|
60
60
|
if self._is_connection_alive(client):
|
|
61
61
|
return client
|
|
62
|
-
|
|
63
|
-
self.connections.remove(conn)
|
|
62
|
+
self.connections.remove(conn)
|
|
64
63
|
|
|
65
64
|
if len(self.connections) < self.max_connections:
|
|
66
65
|
client = self._create_connection(port)
|
|
@@ -82,7 +81,7 @@ class SocketIOConnectionPool:
|
|
|
82
81
|
|
|
83
82
|
def _create_connection(self, port: int) -> Optional[Any]:
|
|
84
83
|
"""Create a new Socket.IO connection with persistent keep-alive.
|
|
85
|
-
|
|
84
|
+
|
|
86
85
|
WHY persistent connections:
|
|
87
86
|
- Maintains connection throughout handler lifecycle
|
|
88
87
|
- Automatic reconnection on disconnect
|
|
@@ -100,32 +99,38 @@ class SocketIOConnectionPool:
|
|
|
100
99
|
logger=False,
|
|
101
100
|
engineio_logger=False,
|
|
102
101
|
)
|
|
103
|
-
|
|
102
|
+
|
|
104
103
|
# Set up event handlers for connection lifecycle
|
|
105
|
-
@client.on(
|
|
104
|
+
@client.on("connect")
|
|
106
105
|
def on_connect():
|
|
107
106
|
pass # Connection established
|
|
108
|
-
|
|
109
|
-
@client.on(
|
|
107
|
+
|
|
108
|
+
@client.on("disconnect")
|
|
110
109
|
def on_disconnect():
|
|
111
110
|
pass # Will automatically try to reconnect
|
|
112
|
-
|
|
111
|
+
|
|
113
112
|
client.connect(
|
|
114
113
|
f"http://localhost:{port}",
|
|
115
114
|
wait=True, # Wait for connection to establish
|
|
116
115
|
wait_timeout=NetworkConfig.SOCKET_WAIT_TIMEOUT,
|
|
117
|
-
transports=[
|
|
116
|
+
transports=[
|
|
117
|
+
"websocket",
|
|
118
|
+
"polling",
|
|
119
|
+
], # Try WebSocket first, fall back to polling
|
|
118
120
|
)
|
|
119
|
-
|
|
121
|
+
|
|
120
122
|
if client.connected:
|
|
121
123
|
# Send a keep-alive ping to establish the connection
|
|
122
124
|
try:
|
|
123
|
-
client.emit(
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
125
|
+
client.emit(
|
|
126
|
+
"ping",
|
|
127
|
+
{
|
|
128
|
+
"type": "system",
|
|
129
|
+
"subtype": "ping",
|
|
130
|
+
"timestamp": time.time(),
|
|
131
|
+
"source": "connection_pool",
|
|
132
|
+
},
|
|
133
|
+
)
|
|
129
134
|
except:
|
|
130
135
|
pass # Ignore ping errors
|
|
131
136
|
return client
|
|
@@ -135,7 +140,7 @@ class SocketIOConnectionPool:
|
|
|
135
140
|
|
|
136
141
|
def _is_connection_alive(self, client: Any) -> bool:
|
|
137
142
|
"""Check if a connection is still alive.
|
|
138
|
-
|
|
143
|
+
|
|
139
144
|
WHY enhanced check:
|
|
140
145
|
- Verifies actual connection state
|
|
141
146
|
- Attempts to ping server for liveness check
|
|
@@ -144,21 +149,24 @@ class SocketIOConnectionPool:
|
|
|
144
149
|
try:
|
|
145
150
|
if not client:
|
|
146
151
|
return False
|
|
147
|
-
|
|
152
|
+
|
|
148
153
|
# Check basic connection state
|
|
149
154
|
if not client.connected:
|
|
150
155
|
return False
|
|
151
|
-
|
|
156
|
+
|
|
152
157
|
# Try a quick ping to verify connection is truly alive
|
|
153
158
|
# This helps detect zombie connections
|
|
154
159
|
try:
|
|
155
160
|
# Just emit a ping, don't wait for response (faster)
|
|
156
|
-
client.emit(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
161
|
+
client.emit(
|
|
162
|
+
"ping",
|
|
163
|
+
{
|
|
164
|
+
"type": "system",
|
|
165
|
+
"subtype": "ping",
|
|
166
|
+
"timestamp": time.time(),
|
|
167
|
+
"source": "connection_pool",
|
|
168
|
+
},
|
|
169
|
+
)
|
|
162
170
|
return True
|
|
163
171
|
except:
|
|
164
172
|
# If ping fails, connection might be dead
|
|
@@ -176,7 +184,7 @@ class SocketIOConnectionPool:
|
|
|
176
184
|
|
|
177
185
|
def _cleanup_dead_connections(self) -> None:
|
|
178
186
|
"""Remove dead connections from the pool and attempt reconnection.
|
|
179
|
-
|
|
187
|
+
|
|
180
188
|
WHY proactive reconnection:
|
|
181
189
|
- Maintains pool health
|
|
182
190
|
- Ensures connections are ready when needed
|
|
@@ -202,3 +210,41 @@ class SocketIOConnectionPool:
|
|
|
202
210
|
for conn in self.connections:
|
|
203
211
|
self._close_connection(conn.get("client"))
|
|
204
212
|
self.connections.clear()
|
|
213
|
+
|
|
214
|
+
def emit(self, event: str, data: Dict[str, Any]) -> bool:
|
|
215
|
+
"""Emit an event through the connection pool.
|
|
216
|
+
|
|
217
|
+
This method provides backward compatibility for the deprecated
|
|
218
|
+
connection pool. It attempts to send events directly to the
|
|
219
|
+
Socket.IO server.
|
|
220
|
+
|
|
221
|
+
Args:
|
|
222
|
+
event: Event name (e.g., "claude_event")
|
|
223
|
+
data: Event data dictionary
|
|
224
|
+
|
|
225
|
+
Returns:
|
|
226
|
+
bool: True if event was sent successfully
|
|
227
|
+
"""
|
|
228
|
+
if not SOCKETIO_AVAILABLE:
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
# Try multiple ports in the range
|
|
232
|
+
for port in range(
|
|
233
|
+
NetworkConfig.SOCKETIO_PORT_RANGE[0],
|
|
234
|
+
NetworkConfig.SOCKETIO_PORT_RANGE[1] + 1,
|
|
235
|
+
):
|
|
236
|
+
client = self.get_connection(port)
|
|
237
|
+
if client:
|
|
238
|
+
try:
|
|
239
|
+
# Emit the event
|
|
240
|
+
client.emit(event, data)
|
|
241
|
+
return True
|
|
242
|
+
except Exception:
|
|
243
|
+
# Try next port
|
|
244
|
+
continue
|
|
245
|
+
|
|
246
|
+
return False
|
|
247
|
+
|
|
248
|
+
def cleanup(self) -> None:
|
|
249
|
+
"""Cleanup all connections (alias for close_all)."""
|
|
250
|
+
self.close_all()
|