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
claude_mpm/core/hook_manager.py
CHANGED
|
@@ -12,6 +12,7 @@ WHY this is needed:
|
|
|
12
12
|
- Ensures consistent event streaming to Socket.IO dashboard
|
|
13
13
|
"""
|
|
14
14
|
|
|
15
|
+
import contextlib
|
|
15
16
|
import json
|
|
16
17
|
import os
|
|
17
18
|
import queue
|
|
@@ -22,7 +23,6 @@ from datetime import datetime
|
|
|
22
23
|
from typing import Any, Dict, Optional
|
|
23
24
|
|
|
24
25
|
from ..core.logger import get_logger
|
|
25
|
-
from .config_constants import ConfigConstants
|
|
26
26
|
from .hook_performance_config import get_hook_performance_config
|
|
27
27
|
from .unified_paths import get_package_root
|
|
28
28
|
|
|
@@ -45,14 +45,16 @@ class HookManager:
|
|
|
45
45
|
# Initialize background hook processing for async execution
|
|
46
46
|
self.performance_config = get_hook_performance_config()
|
|
47
47
|
queue_config = self.performance_config.get_queue_config()
|
|
48
|
-
self.hook_queue = queue.Queue(maxsize=queue_config[
|
|
48
|
+
self.hook_queue = queue.Queue(maxsize=queue_config["maxsize"])
|
|
49
49
|
self.background_thread = None
|
|
50
50
|
self.shutdown_event = threading.Event()
|
|
51
51
|
|
|
52
52
|
# Start background processing if hook handler is available
|
|
53
53
|
if self.hook_handler_path:
|
|
54
54
|
self._start_background_processor()
|
|
55
|
-
self.logger.debug(
|
|
55
|
+
self.logger.debug(
|
|
56
|
+
f"Hook handler found with async processing: {self.hook_handler_path}"
|
|
57
|
+
)
|
|
56
58
|
else:
|
|
57
59
|
self.logger.debug("Hook handler not found - hooks will be skipped")
|
|
58
60
|
|
|
@@ -68,6 +70,7 @@ class HookManager:
|
|
|
68
70
|
|
|
69
71
|
def _start_background_processor(self):
|
|
70
72
|
"""Start background thread to process hooks asynchronously."""
|
|
73
|
+
|
|
71
74
|
def process_hooks():
|
|
72
75
|
"""Background thread function to process hook queue."""
|
|
73
76
|
while not self.shutdown_event.is_set():
|
|
@@ -88,9 +91,7 @@ class HookManager:
|
|
|
88
91
|
self.logger.error(f"Hook processing error: {e}")
|
|
89
92
|
|
|
90
93
|
self.background_thread = threading.Thread(
|
|
91
|
-
target=process_hooks,
|
|
92
|
-
name="hook-processor",
|
|
93
|
-
daemon=True
|
|
94
|
+
target=process_hooks, name="hook-processor", daemon=True
|
|
94
95
|
)
|
|
95
96
|
self.background_thread.start()
|
|
96
97
|
self.logger.debug("Started background hook processor thread")
|
|
@@ -98,14 +99,14 @@ class HookManager:
|
|
|
98
99
|
def _execute_hook_sync(self, hook_data: Dict[str, Any]):
|
|
99
100
|
"""Execute a single hook synchronously in the background thread."""
|
|
100
101
|
try:
|
|
101
|
-
hook_type = hook_data[
|
|
102
|
-
event_data = hook_data[
|
|
102
|
+
hook_type = hook_data["hook_type"]
|
|
103
|
+
event_data = hook_data["event_data"]
|
|
103
104
|
|
|
104
105
|
# Create the hook event
|
|
105
106
|
hook_event = {
|
|
106
107
|
"hook_event_name": hook_type,
|
|
107
108
|
"session_id": self.session_id,
|
|
108
|
-
"timestamp": hook_data.get(
|
|
109
|
+
"timestamp": hook_data.get("timestamp", datetime.utcnow().isoformat()),
|
|
109
110
|
**event_data,
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -121,6 +122,7 @@ class HookManager:
|
|
|
121
122
|
capture_output=True,
|
|
122
123
|
env=env,
|
|
123
124
|
timeout=self.performance_config.background_timeout,
|
|
125
|
+
check=False,
|
|
124
126
|
)
|
|
125
127
|
|
|
126
128
|
if result.returncode != 0:
|
|
@@ -129,7 +131,9 @@ class HookManager:
|
|
|
129
131
|
self.logger.debug(f"Hook stderr: {result.stderr}")
|
|
130
132
|
|
|
131
133
|
except subprocess.TimeoutExpired:
|
|
132
|
-
self.logger.debug(
|
|
134
|
+
self.logger.debug(
|
|
135
|
+
f"Hook {hook_data.get('hook_type', 'unknown')} timed out in background"
|
|
136
|
+
)
|
|
133
137
|
except Exception as e:
|
|
134
138
|
self.logger.debug(f"Background hook execution error: {e}")
|
|
135
139
|
|
|
@@ -138,10 +142,8 @@ class HookManager:
|
|
|
138
142
|
if self.background_thread and self.background_thread.is_alive():
|
|
139
143
|
self.shutdown_event.set()
|
|
140
144
|
# Signal shutdown by putting None in queue
|
|
141
|
-
|
|
145
|
+
with contextlib.suppress(queue.Full):
|
|
142
146
|
self.hook_queue.put_nowait(None)
|
|
143
|
-
except queue.Full:
|
|
144
|
-
pass
|
|
145
147
|
|
|
146
148
|
# Wait for thread to finish
|
|
147
149
|
self.background_thread.join(timeout=2.0)
|
|
@@ -157,15 +159,14 @@ class HookManager:
|
|
|
157
159
|
|
|
158
160
|
if hook_handler.exists():
|
|
159
161
|
return hook_handler
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return None
|
|
162
|
+
self.logger.warning(f"Hook handler not found at: {hook_handler}")
|
|
163
|
+
return None
|
|
163
164
|
except Exception as e:
|
|
164
165
|
self.logger.error(f"Error finding hook handler: {e}")
|
|
165
166
|
return None
|
|
166
167
|
|
|
167
168
|
def trigger_pre_tool_hook(
|
|
168
|
-
self, tool_name: str, tool_args: Dict[str, Any] = None
|
|
169
|
+
self, tool_name: str, tool_args: Optional[Dict[str, Any]] = None
|
|
169
170
|
) -> bool:
|
|
170
171
|
"""Trigger PreToolUse hook event.
|
|
171
172
|
|
|
@@ -247,14 +248,16 @@ class HookManager:
|
|
|
247
248
|
try:
|
|
248
249
|
# Queue hook for background processing
|
|
249
250
|
hook_data = {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
251
|
+
"hook_type": hook_type,
|
|
252
|
+
"event_data": event_data,
|
|
253
|
+
"timestamp": datetime.utcnow().isoformat(),
|
|
253
254
|
}
|
|
254
255
|
|
|
255
256
|
# Try to queue without blocking
|
|
256
257
|
self.hook_queue.put_nowait(hook_data)
|
|
257
|
-
self.logger.debug(
|
|
258
|
+
self.logger.debug(
|
|
259
|
+
f"Successfully queued {hook_type} hook for background processing"
|
|
260
|
+
)
|
|
258
261
|
return True
|
|
259
262
|
|
|
260
263
|
except queue.Full:
|
|
@@ -276,6 +279,7 @@ def get_hook_manager() -> HookManager:
|
|
|
276
279
|
_hook_manager = HookManager()
|
|
277
280
|
# Register cleanup on exit
|
|
278
281
|
import atexit
|
|
282
|
+
|
|
279
283
|
atexit.register(_cleanup_hook_manager)
|
|
280
284
|
return _hook_manager
|
|
281
285
|
|
|
@@ -290,7 +294,7 @@ def _cleanup_hook_manager():
|
|
|
290
294
|
|
|
291
295
|
def trigger_tool_hooks(
|
|
292
296
|
tool_name: str,
|
|
293
|
-
tool_args: Dict[str, Any] = None,
|
|
297
|
+
tool_args: Optional[Dict[str, Any]] = None,
|
|
294
298
|
result: Any = None,
|
|
295
299
|
exit_code: int = 0,
|
|
296
300
|
):
|
|
@@ -10,72 +10,83 @@ from typing import Dict, Optional
|
|
|
10
10
|
|
|
11
11
|
class HookPerformanceConfig:
|
|
12
12
|
"""Configuration for hook performance optimization."""
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
def __init__(self):
|
|
15
15
|
"""Initialize hook performance configuration from environment."""
|
|
16
16
|
self._load_config()
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
def _load_config(self):
|
|
19
19
|
"""Load configuration from environment variables."""
|
|
20
20
|
# Performance mode - disables all hooks for maximum speed
|
|
21
|
-
self.performance_mode =
|
|
22
|
-
|
|
21
|
+
self.performance_mode = (
|
|
22
|
+
os.getenv("CLAUDE_MPM_PERFORMANCE_MODE", "false").lower() == "true"
|
|
23
|
+
)
|
|
24
|
+
|
|
23
25
|
# Individual hook type controls
|
|
24
|
-
self.enable_pre_tool_hooks =
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
self.
|
|
28
|
-
|
|
26
|
+
self.enable_pre_tool_hooks = (
|
|
27
|
+
os.getenv("CLAUDE_MPM_HOOKS_PRE_TOOL", "true").lower() == "true"
|
|
28
|
+
)
|
|
29
|
+
self.enable_post_tool_hooks = (
|
|
30
|
+
os.getenv("CLAUDE_MPM_HOOKS_POST_TOOL", "true").lower() == "true"
|
|
31
|
+
)
|
|
32
|
+
self.enable_user_prompt_hooks = (
|
|
33
|
+
os.getenv("CLAUDE_MPM_HOOKS_USER_PROMPT", "true").lower() == "true"
|
|
34
|
+
)
|
|
35
|
+
self.enable_delegation_hooks = (
|
|
36
|
+
os.getenv("CLAUDE_MPM_HOOKS_DELEGATION", "true").lower() == "true"
|
|
37
|
+
)
|
|
38
|
+
|
|
29
39
|
# Background processing settings
|
|
30
|
-
self.queue_size = int(os.getenv(
|
|
31
|
-
self.background_timeout = float(os.getenv(
|
|
32
|
-
|
|
40
|
+
self.queue_size = int(os.getenv("CLAUDE_MPM_HOOK_QUEUE_SIZE", "1000"))
|
|
41
|
+
self.background_timeout = float(os.getenv("CLAUDE_MPM_HOOK_BG_TIMEOUT", "2.0"))
|
|
42
|
+
|
|
33
43
|
# Batching settings (for future implementation)
|
|
34
|
-
self.enable_batching =
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
44
|
+
self.enable_batching = (
|
|
45
|
+
os.getenv("CLAUDE_MPM_HOOK_BATCHING", "false").lower() == "true"
|
|
46
|
+
)
|
|
47
|
+
self.batch_size = int(os.getenv("CLAUDE_MPM_HOOK_BATCH_SIZE", "10"))
|
|
48
|
+
self.batch_timeout_ms = int(
|
|
49
|
+
os.getenv("CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS", "100")
|
|
50
|
+
)
|
|
51
|
+
|
|
38
52
|
def is_hook_enabled(self, hook_type: str) -> bool:
|
|
39
53
|
"""Check if a specific hook type is enabled.
|
|
40
|
-
|
|
54
|
+
|
|
41
55
|
Args:
|
|
42
56
|
hook_type: Type of hook (PreToolUse, PostToolUse, UserPromptSubmit, etc.)
|
|
43
|
-
|
|
57
|
+
|
|
44
58
|
Returns:
|
|
45
59
|
bool: True if hook should be processed
|
|
46
60
|
"""
|
|
47
61
|
if self.performance_mode:
|
|
48
62
|
return False
|
|
49
|
-
|
|
63
|
+
|
|
50
64
|
hook_type_lower = hook_type.lower()
|
|
51
|
-
|
|
52
|
-
if
|
|
65
|
+
|
|
66
|
+
if "pretool" in hook_type_lower or "pre_tool" in hook_type_lower:
|
|
53
67
|
return self.enable_pre_tool_hooks
|
|
54
|
-
|
|
68
|
+
if "posttool" in hook_type_lower or "post_tool" in hook_type_lower:
|
|
55
69
|
return self.enable_post_tool_hooks
|
|
56
|
-
|
|
70
|
+
if "userprompt" in hook_type_lower or "user_prompt" in hook_type_lower:
|
|
57
71
|
return self.enable_user_prompt_hooks
|
|
58
|
-
|
|
72
|
+
if "delegation" in hook_type_lower:
|
|
59
73
|
return self.enable_delegation_hooks
|
|
60
|
-
|
|
74
|
+
|
|
61
75
|
# Default to enabled for unknown hook types
|
|
62
76
|
return True
|
|
63
|
-
|
|
77
|
+
|
|
64
78
|
def get_queue_config(self) -> Dict[str, int]:
|
|
65
79
|
"""Get queue configuration for background processing."""
|
|
66
|
-
return {
|
|
67
|
-
|
|
68
|
-
'timeout': self.background_timeout
|
|
69
|
-
}
|
|
70
|
-
|
|
80
|
+
return {"maxsize": self.queue_size, "timeout": self.background_timeout}
|
|
81
|
+
|
|
71
82
|
def get_batch_config(self) -> Dict[str, any]:
|
|
72
83
|
"""Get batching configuration (for future use)."""
|
|
73
84
|
return {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
85
|
+
"enabled": self.enable_batching,
|
|
86
|
+
"batch_size": self.batch_size,
|
|
87
|
+
"timeout_ms": self.batch_timeout_ms,
|
|
77
88
|
}
|
|
78
|
-
|
|
89
|
+
|
|
79
90
|
def print_config(self) -> str:
|
|
80
91
|
"""Return a string representation of current configuration."""
|
|
81
92
|
config_lines = [
|
|
@@ -106,11 +117,11 @@ def get_hook_performance_config() -> HookPerformanceConfig:
|
|
|
106
117
|
|
|
107
118
|
def set_performance_mode(enabled: bool):
|
|
108
119
|
"""Enable or disable performance mode programmatically.
|
|
109
|
-
|
|
120
|
+
|
|
110
121
|
Args:
|
|
111
122
|
enabled: True to enable performance mode (disable all hooks)
|
|
112
123
|
"""
|
|
113
|
-
os.environ[
|
|
124
|
+
os.environ["CLAUDE_MPM_PERFORMANCE_MODE"] = "true" if enabled else "false"
|
|
114
125
|
# Reload configuration
|
|
115
126
|
global _hook_config
|
|
116
127
|
_hook_config = None
|
|
@@ -123,14 +134,14 @@ def is_performance_mode() -> bool:
|
|
|
123
134
|
|
|
124
135
|
# Environment variable documentation for users
|
|
125
136
|
ENVIRONMENT_VARIABLES = {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
137
|
+
"CLAUDE_MPM_PERFORMANCE_MODE": 'Set to "true" to disable all hooks for maximum performance',
|
|
138
|
+
"CLAUDE_MPM_HOOKS_PRE_TOOL": 'Set to "false" to disable pre-tool hooks',
|
|
139
|
+
"CLAUDE_MPM_HOOKS_POST_TOOL": 'Set to "false" to disable post-tool hooks',
|
|
140
|
+
"CLAUDE_MPM_HOOKS_USER_PROMPT": 'Set to "false" to disable user prompt hooks',
|
|
141
|
+
"CLAUDE_MPM_HOOKS_DELEGATION": 'Set to "false" to disable delegation hooks',
|
|
142
|
+
"CLAUDE_MPM_HOOK_QUEUE_SIZE": "Maximum number of hooks in background queue (default: 1000)",
|
|
143
|
+
"CLAUDE_MPM_HOOK_BG_TIMEOUT": "Timeout for background hook processing in seconds (default: 2.0)",
|
|
144
|
+
"CLAUDE_MPM_HOOK_BATCHING": 'Set to "true" to enable hook batching (experimental)',
|
|
145
|
+
"CLAUDE_MPM_HOOK_BATCH_SIZE": "Number of hooks to batch together (default: 10)",
|
|
146
|
+
"CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS": "Batch timeout in milliseconds (default: 100)",
|
|
136
147
|
}
|
|
@@ -199,7 +199,7 @@ class InjectableService(BaseService, ABC):
|
|
|
199
199
|
deps = []
|
|
200
200
|
annotations = getattr(self.__class__, "__annotations__", {})
|
|
201
201
|
|
|
202
|
-
for attr_name,
|
|
202
|
+
for attr_name, _attr_type in annotations.items():
|
|
203
203
|
if hasattr(self, attr_name) and not attr_name.startswith("_"):
|
|
204
204
|
deps.append(
|
|
205
205
|
f"{attr_name}={getattr(self, attr_name).__class__.__name__}"
|
|
@@ -4,11 +4,10 @@ This module provides the InteractiveSession class that manages Claude's interact
|
|
|
4
4
|
with proper separation of concerns and reduced complexity.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
+
import contextlib
|
|
7
8
|
import os
|
|
8
9
|
import subprocess
|
|
9
|
-
import sys
|
|
10
10
|
import uuid
|
|
11
|
-
from datetime import datetime
|
|
12
11
|
from typing import Any, Dict, Optional, Tuple
|
|
13
12
|
|
|
14
13
|
from claude_mpm.core.logger import get_logger
|
|
@@ -134,7 +133,6 @@ class InteractiveSession:
|
|
|
134
133
|
|
|
135
134
|
# Deploy project-specific agents
|
|
136
135
|
self.runner.deploy_project_agents_to_claude()
|
|
137
|
-
|
|
138
136
|
|
|
139
137
|
# Build command
|
|
140
138
|
cmd = self._build_claude_command()
|
|
@@ -186,8 +184,7 @@ class InteractiveSession:
|
|
|
186
184
|
# Launch using selected method
|
|
187
185
|
if self.runner.launch_method == "subprocess":
|
|
188
186
|
return self._launch_subprocess_mode(cmd, env)
|
|
189
|
-
|
|
190
|
-
return self._launch_exec_mode(cmd, env)
|
|
187
|
+
return self._launch_exec_mode(cmd, env)
|
|
191
188
|
|
|
192
189
|
except FileNotFoundError as e:
|
|
193
190
|
self._handle_launch_error("FileNotFoundError", e)
|
|
@@ -206,7 +203,11 @@ class InteractiveSession:
|
|
|
206
203
|
return self._attempt_fallback_launch(environment)
|
|
207
204
|
|
|
208
205
|
def process_interactive_command(self, prompt: str) -> Optional[bool]:
|
|
209
|
-
"""Process special interactive commands
|
|
206
|
+
"""Process special interactive commands.
|
|
207
|
+
|
|
208
|
+
NOTE: As of v4.1.2, MPM slash commands are deployed as markdown files
|
|
209
|
+
to ~/.claude/commands and handled directly by Claude Code.
|
|
210
|
+
This method is kept for potential future use with non-Claude commands.
|
|
210
211
|
|
|
211
212
|
Args:
|
|
212
213
|
prompt: User input command
|
|
@@ -214,21 +215,7 @@ class InteractiveSession:
|
|
|
214
215
|
Returns:
|
|
215
216
|
Optional[bool]: True if handled, False if error, None if not a special command
|
|
216
217
|
"""
|
|
217
|
-
#
|
|
218
|
-
parts = prompt.strip().split()
|
|
219
|
-
if not parts:
|
|
220
|
-
return None
|
|
221
|
-
|
|
222
|
-
command = parts[0]
|
|
223
|
-
args = parts[1:]
|
|
224
|
-
|
|
225
|
-
# Check for special commands
|
|
226
|
-
if command == "/agents":
|
|
227
|
-
return self._show_available_agents()
|
|
228
|
-
elif command == "/mpm-doctor":
|
|
229
|
-
return self._run_doctor_diagnostics(args)
|
|
230
|
-
|
|
231
|
-
# Not a special command
|
|
218
|
+
# Currently no commands are intercepted - all MPM commands are handled by Claude Code
|
|
232
219
|
return None
|
|
233
220
|
|
|
234
221
|
def cleanup_interactive_session(self) -> None:
|
|
@@ -239,10 +226,8 @@ class InteractiveSession:
|
|
|
239
226
|
try:
|
|
240
227
|
# Restore original directory
|
|
241
228
|
if self.original_cwd and os.path.exists(self.original_cwd):
|
|
242
|
-
|
|
229
|
+
with contextlib.suppress(OSError):
|
|
243
230
|
os.chdir(self.original_cwd)
|
|
244
|
-
except OSError:
|
|
245
|
-
pass
|
|
246
231
|
|
|
247
232
|
# Close WebSocket if connected
|
|
248
233
|
if self.runner.websocket_server:
|
|
@@ -307,7 +292,7 @@ class InteractiveSession:
|
|
|
307
292
|
def _display_welcome_message(self) -> None:
|
|
308
293
|
"""Display the interactive session welcome message."""
|
|
309
294
|
version_str = self.runner._get_version()
|
|
310
|
-
|
|
295
|
+
|
|
311
296
|
# Get output style status
|
|
312
297
|
output_style_info = self._get_output_style_info()
|
|
313
298
|
|
|
@@ -320,40 +305,47 @@ class InteractiveSession:
|
|
|
320
305
|
print(f"\033[32m│\033[0m {output_style_info:<49}\033[32m│\033[0m")
|
|
321
306
|
print("\033[32m│ │\033[0m")
|
|
322
307
|
print(
|
|
323
|
-
"\033[32m│\033[0m Commands:
|
|
308
|
+
"\033[32m│\033[0m MPM Commands (via Claude Code): \033[32m│\033[0m"
|
|
309
|
+
)
|
|
310
|
+
print(
|
|
311
|
+
"\033[32m│\033[0m /mpm - MPM overview and help \033[32m│\033[0m"
|
|
324
312
|
)
|
|
325
313
|
print(
|
|
326
|
-
"\033[32m│\033[0m /agents
|
|
314
|
+
"\033[32m│\033[0m /mpm-agents - Show available agents \033[32m│\033[0m"
|
|
327
315
|
)
|
|
328
316
|
print(
|
|
329
|
-
"\033[32m│\033[0m /mpm-doctor
|
|
317
|
+
"\033[32m│\033[0m /mpm-doctor - Run diagnostic checks \033[32m│\033[0m"
|
|
330
318
|
)
|
|
319
|
+
print(
|
|
320
|
+
"\033[32m│\033[0m Type / for autocomplete in Claude Code \033[32m│\033[0m"
|
|
321
|
+
)
|
|
322
|
+
|
|
331
323
|
print("\033[32m╰───────────────────────────────────────────────────╯\033[0m")
|
|
332
324
|
print("") # Add blank line after box
|
|
333
|
-
|
|
334
|
-
|
|
325
|
+
|
|
335
326
|
def _get_output_style_info(self) -> Optional[str]:
|
|
336
327
|
"""Get output style status for display."""
|
|
337
328
|
try:
|
|
338
329
|
# Check if output style manager is available through framework loader
|
|
339
|
-
if
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
330
|
+
if (
|
|
331
|
+
hasattr(self.runner, "framework_loader")
|
|
332
|
+
and self.runner.framework_loader
|
|
333
|
+
) and hasattr(self.runner.framework_loader, "output_style_manager"):
|
|
334
|
+
osm = self.runner.framework_loader.output_style_manager
|
|
335
|
+
if osm:
|
|
336
|
+
if osm.claude_version and osm.supports_output_styles():
|
|
337
|
+
# Check if claude-mpm style is active
|
|
338
|
+
settings_file = osm.settings_file
|
|
339
|
+
if settings_file.exists():
|
|
340
|
+
import json
|
|
341
|
+
|
|
342
|
+
settings = json.loads(settings_file.read_text())
|
|
343
|
+
active_style = settings.get("activeOutputStyle")
|
|
344
|
+
if active_style == "claude-mpm":
|
|
345
|
+
return "Output Style: claude-mpm ✅"
|
|
346
|
+
return f"Output Style: {active_style or 'none'}"
|
|
347
|
+
return "Output Style: Available"
|
|
348
|
+
return "Output Style: Injected (legacy)"
|
|
357
349
|
except Exception:
|
|
358
350
|
pass
|
|
359
351
|
return None
|
|
@@ -365,7 +357,9 @@ class InteractiveSession:
|
|
|
365
357
|
|
|
366
358
|
if has_resume:
|
|
367
359
|
# When resuming, use minimal command to avoid interfering with conversation selection
|
|
368
|
-
self.logger.info(
|
|
360
|
+
self.logger.info(
|
|
361
|
+
"🔄 Resume mode detected - using minimal Claude command to preserve conversation selection"
|
|
362
|
+
)
|
|
369
363
|
cmd = ["claude"]
|
|
370
364
|
|
|
371
365
|
# Add only the claude_args (which includes --resume)
|
|
@@ -374,26 +368,25 @@ class InteractiveSession:
|
|
|
374
368
|
self.logger.info(f"Resume command: {cmd}")
|
|
375
369
|
|
|
376
370
|
return cmd
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
cmd = ["claude", "--model", "opus", "--dangerously-skip-permissions"]
|
|
371
|
+
# Normal mode - full command with all claude-mpm enhancements
|
|
372
|
+
cmd = ["claude", "--model", "opus", "--dangerously-skip-permissions"]
|
|
380
373
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
374
|
+
# Add custom arguments
|
|
375
|
+
if self.runner.claude_args:
|
|
376
|
+
# Enhanced debug logging for --resume flag verification
|
|
377
|
+
self.logger.debug(f"Raw claude_args received: {self.runner.claude_args}")
|
|
378
|
+
cmd.extend(self.runner.claude_args)
|
|
386
379
|
|
|
387
|
-
|
|
388
|
-
|
|
380
|
+
# Add system instructions
|
|
381
|
+
from claude_mpm.core.claude_runner import create_simple_context
|
|
389
382
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
383
|
+
system_prompt = self.runner._create_system_prompt()
|
|
384
|
+
if system_prompt and system_prompt != create_simple_context():
|
|
385
|
+
cmd.extend(["--append-system-prompt", system_prompt])
|
|
393
386
|
|
|
394
387
|
# Final command verification
|
|
395
388
|
# self.logger.info(f"Final Claude command built: {' '.join(cmd)}")
|
|
396
|
-
|
|
389
|
+
|
|
397
390
|
# Explicit --resume flag verification
|
|
398
391
|
if "--resume" in cmd:
|
|
399
392
|
self.logger.info("✅ VERIFIED: --resume flag IS included in final command")
|
|
@@ -520,7 +513,9 @@ class InteractiveSession:
|
|
|
520
513
|
cmd = environment["command"]
|
|
521
514
|
env = environment["environment"]
|
|
522
515
|
|
|
523
|
-
result = subprocess.run(
|
|
516
|
+
result = subprocess.run(
|
|
517
|
+
cmd, stdin=None, stdout=None, stderr=None, env=env, check=False
|
|
518
|
+
)
|
|
524
519
|
|
|
525
520
|
if result.returncode == 0:
|
|
526
521
|
if self.runner.project_logger:
|
|
@@ -530,9 +525,8 @@ class InteractiveSession:
|
|
|
530
525
|
component="session",
|
|
531
526
|
)
|
|
532
527
|
return True
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
return False
|
|
528
|
+
print(f"⚠️ Claude exited with code {result.returncode}")
|
|
529
|
+
return False
|
|
536
530
|
|
|
537
531
|
except FileNotFoundError:
|
|
538
532
|
print("❌ Fallback failed: Claude CLI not found in PATH")
|
|
@@ -546,88 +540,3 @@ class InteractiveSession:
|
|
|
546
540
|
except Exception as e:
|
|
547
541
|
print(f"❌ Fallback failed with unexpected error: {e}")
|
|
548
542
|
return False
|
|
549
|
-
|
|
550
|
-
def _show_available_agents(self) -> bool:
|
|
551
|
-
"""Show available agents in the system."""
|
|
552
|
-
try:
|
|
553
|
-
from claude_mpm.cli.utils import get_agent_versions_display
|
|
554
|
-
|
|
555
|
-
agent_versions = get_agent_versions_display()
|
|
556
|
-
|
|
557
|
-
if agent_versions:
|
|
558
|
-
print(agent_versions)
|
|
559
|
-
else:
|
|
560
|
-
print("No deployed agents found")
|
|
561
|
-
print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
|
|
562
|
-
|
|
563
|
-
return True
|
|
564
|
-
|
|
565
|
-
except ImportError:
|
|
566
|
-
print("Error: CLI module not available")
|
|
567
|
-
return False
|
|
568
|
-
except Exception as e:
|
|
569
|
-
print(f"Error getting agent versions: {e}")
|
|
570
|
-
return False
|
|
571
|
-
|
|
572
|
-
def _run_doctor_diagnostics(self, args: list) -> bool:
|
|
573
|
-
"""Run doctor diagnostics from interactive mode.
|
|
574
|
-
|
|
575
|
-
Args:
|
|
576
|
-
args: Command arguments (e.g., ['--verbose'])
|
|
577
|
-
|
|
578
|
-
Returns:
|
|
579
|
-
bool: True if successful, False otherwise
|
|
580
|
-
"""
|
|
581
|
-
try:
|
|
582
|
-
from claude_mpm.services.diagnostics import DiagnosticRunner, DoctorReporter
|
|
583
|
-
|
|
584
|
-
# Parse arguments
|
|
585
|
-
verbose = "--verbose" in args or "-v" in args
|
|
586
|
-
no_color = "--no-color" in args
|
|
587
|
-
|
|
588
|
-
# Print header
|
|
589
|
-
print("\n" + "="*60)
|
|
590
|
-
print("Claude MPM Doctor Report")
|
|
591
|
-
print("="*60)
|
|
592
|
-
|
|
593
|
-
# Create diagnostic runner
|
|
594
|
-
runner = DiagnosticRunner(verbose=verbose)
|
|
595
|
-
|
|
596
|
-
# Run diagnostics
|
|
597
|
-
try:
|
|
598
|
-
summary = runner.run_diagnostics()
|
|
599
|
-
except KeyboardInterrupt:
|
|
600
|
-
print("\nDiagnostics interrupted by user")
|
|
601
|
-
return False
|
|
602
|
-
except Exception as e:
|
|
603
|
-
print(f"\n❌ Diagnostic failed: {str(e)}")
|
|
604
|
-
if verbose:
|
|
605
|
-
import traceback
|
|
606
|
-
traceback.print_exc()
|
|
607
|
-
return False
|
|
608
|
-
|
|
609
|
-
# Create reporter
|
|
610
|
-
reporter = DoctorReporter(
|
|
611
|
-
use_color=not no_color,
|
|
612
|
-
verbose=verbose
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
# Display results in terminal format
|
|
616
|
-
reporter.report(summary, format="terminal")
|
|
617
|
-
|
|
618
|
-
# Return based on status
|
|
619
|
-
if summary.error_count > 0:
|
|
620
|
-
return False
|
|
621
|
-
|
|
622
|
-
return True
|
|
623
|
-
|
|
624
|
-
except ImportError as e:
|
|
625
|
-
print(f"Error: Diagnostics module not available: {e}")
|
|
626
|
-
print("Please ensure claude-mpm is properly installed")
|
|
627
|
-
return False
|
|
628
|
-
except Exception as e:
|
|
629
|
-
print(f"Error running diagnostics: {e}")
|
|
630
|
-
if "--verbose" in args or "-v" in args:
|
|
631
|
-
import traceback
|
|
632
|
-
traceback.print_exc()
|
|
633
|
-
return False
|