claude-mpm 4.1.0__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 +133 -58
- claude_mpm/agents/templates/web_ui.json +3 -3
- 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.0.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.0.dist-info/RECORD +0 -494
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.1.0.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
|
@@ -12,10 +12,12 @@ multiple installation strategies (pip, conda, source) to maximize success rate.
|
|
|
12
12
|
import re
|
|
13
13
|
import subprocess
|
|
14
14
|
import sys
|
|
15
|
+
import sysconfig
|
|
15
16
|
import time
|
|
16
17
|
from dataclasses import dataclass
|
|
17
18
|
from enum import Enum
|
|
18
|
-
from
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Dict, List, Optional, Tuple
|
|
19
21
|
|
|
20
22
|
from ..core.logger import get_logger
|
|
21
23
|
|
|
@@ -51,6 +53,9 @@ class RobustPackageInstaller:
|
|
|
51
53
|
WHY: This class handles the complexity of package installation in various
|
|
52
54
|
environments, network conditions, and Python versions. It ensures maximum
|
|
53
55
|
success rate while providing clear feedback on failures.
|
|
56
|
+
|
|
57
|
+
DECISION: Added PEP 668 detection and handling to work with externally managed
|
|
58
|
+
Python environments (like Homebrew's Python 3.13).
|
|
54
59
|
"""
|
|
55
60
|
|
|
56
61
|
def __init__(
|
|
@@ -75,6 +80,8 @@ class RobustPackageInstaller:
|
|
|
75
80
|
self.use_cache = use_cache
|
|
76
81
|
self.attempts: List[InstallAttempt] = []
|
|
77
82
|
self.success_cache: Dict[str, bool] = {}
|
|
83
|
+
self.is_pep668_managed = self._check_pep668_managed()
|
|
84
|
+
self.pep668_warning_shown = False
|
|
78
85
|
|
|
79
86
|
def install_package(
|
|
80
87
|
self, package_spec: str, strategies: Optional[List[InstallStrategy]] = None
|
|
@@ -178,24 +185,70 @@ class RobustPackageInstaller:
|
|
|
178
185
|
logger.debug(f"Running: {' '.join(cmd)}")
|
|
179
186
|
|
|
180
187
|
result = subprocess.run(
|
|
181
|
-
cmd, capture_output=True, text=True, timeout=self.timeout
|
|
188
|
+
cmd, capture_output=True, text=True, timeout=self.timeout, check=False
|
|
182
189
|
)
|
|
183
190
|
|
|
184
191
|
if result.returncode == 0:
|
|
185
192
|
# Verify installation
|
|
186
193
|
if self._verify_installation(package_spec):
|
|
187
194
|
return True, None
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
logger.debug(f"Installation failed: {error_msg}")
|
|
193
|
-
return False, error_msg
|
|
195
|
+
return False, "Package installed but verification failed"
|
|
196
|
+
error_msg = self._extract_error_message(result.stderr)
|
|
197
|
+
logger.debug(f"Installation failed: {error_msg}")
|
|
198
|
+
return False, error_msg
|
|
194
199
|
|
|
195
200
|
except subprocess.TimeoutExpired:
|
|
196
201
|
return False, f"Installation timed out after {self.timeout}s"
|
|
197
202
|
except Exception as e:
|
|
198
|
-
return False, f"Unexpected error: {
|
|
203
|
+
return False, f"Unexpected error: {e!s}"
|
|
204
|
+
|
|
205
|
+
def _check_pep668_managed(self) -> bool:
|
|
206
|
+
"""
|
|
207
|
+
Check if Python environment is PEP 668 externally managed.
|
|
208
|
+
|
|
209
|
+
WHY: PEP 668 prevents pip from installing packages into system Python
|
|
210
|
+
to avoid conflicts with system package managers (like Homebrew).
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
True if PEP 668 managed, False otherwise
|
|
214
|
+
"""
|
|
215
|
+
# Check for EXTERNALLY-MANAGED marker file
|
|
216
|
+
stdlib_path = sysconfig.get_path("stdlib")
|
|
217
|
+
marker_file = Path(stdlib_path) / "EXTERNALLY-MANAGED"
|
|
218
|
+
|
|
219
|
+
if marker_file.exists():
|
|
220
|
+
logger.debug(f"PEP 668 EXTERNALLY-MANAGED marker found at {marker_file}")
|
|
221
|
+
return True
|
|
222
|
+
|
|
223
|
+
# Also check parent directory (some Python installations place it there)
|
|
224
|
+
parent_marker = marker_file.parent.parent / "EXTERNALLY-MANAGED"
|
|
225
|
+
if parent_marker.exists():
|
|
226
|
+
logger.debug(f"PEP 668 EXTERNALLY-MANAGED marker found at {parent_marker}")
|
|
227
|
+
return True
|
|
228
|
+
|
|
229
|
+
return False
|
|
230
|
+
|
|
231
|
+
def _show_pep668_warning(self) -> None:
|
|
232
|
+
"""
|
|
233
|
+
Show warning about PEP 668 managed environment.
|
|
234
|
+
|
|
235
|
+
WHY: Users should understand why we're bypassing PEP 668 restrictions
|
|
236
|
+
and be encouraged to use virtual environments as best practice.
|
|
237
|
+
"""
|
|
238
|
+
if not self.pep668_warning_shown:
|
|
239
|
+
logger.warning(
|
|
240
|
+
"⚠️ PEP 668 MANAGED ENVIRONMENT DETECTED\n"
|
|
241
|
+
"Your Python installation is marked as externally managed (PEP 668).\n"
|
|
242
|
+
"This typically means you're using a system Python managed by Homebrew, apt, etc.\n"
|
|
243
|
+
"\n"
|
|
244
|
+
"Installing packages with --break-system-packages --user flags...\n"
|
|
245
|
+
"\n"
|
|
246
|
+
"RECOMMENDED: Use a virtual environment instead:\n"
|
|
247
|
+
" python -m venv .venv\n"
|
|
248
|
+
" source .venv/bin/activate # On Windows: .venv\\Scripts\\activate\n"
|
|
249
|
+
" pip install claude-mpm\n"
|
|
250
|
+
)
|
|
251
|
+
self.pep668_warning_shown = True
|
|
199
252
|
|
|
200
253
|
def _build_install_command(
|
|
201
254
|
self, package_spec: str, strategy: InstallStrategy
|
|
@@ -203,6 +256,9 @@ class RobustPackageInstaller:
|
|
|
203
256
|
"""
|
|
204
257
|
Build the installation command for a given strategy.
|
|
205
258
|
|
|
259
|
+
WHY: PEP 668 support added to handle externally managed Python
|
|
260
|
+
environments by adding appropriate flags when needed.
|
|
261
|
+
|
|
206
262
|
Args:
|
|
207
263
|
package_spec: Package specification
|
|
208
264
|
strategy: Installation strategy
|
|
@@ -212,22 +268,32 @@ class RobustPackageInstaller:
|
|
|
212
268
|
"""
|
|
213
269
|
base_cmd = [sys.executable, "-m", "pip", "install"]
|
|
214
270
|
|
|
271
|
+
# Add PEP 668 bypass flags if needed
|
|
272
|
+
if self.is_pep668_managed:
|
|
273
|
+
self._show_pep668_warning()
|
|
274
|
+
# Add flags to bypass PEP 668 restrictions
|
|
275
|
+
base_cmd.extend(["--break-system-packages", "--user"])
|
|
276
|
+
logger.debug(
|
|
277
|
+
"Added --break-system-packages --user flags for PEP 668 environment"
|
|
278
|
+
)
|
|
279
|
+
|
|
215
280
|
# Add cache control
|
|
216
281
|
if not self.use_cache:
|
|
217
282
|
base_cmd.append("--no-cache-dir")
|
|
218
283
|
|
|
219
284
|
if strategy == InstallStrategy.PIP:
|
|
220
|
-
return base_cmd
|
|
285
|
+
return [*base_cmd, package_spec]
|
|
221
286
|
|
|
222
|
-
|
|
223
|
-
return base_cmd
|
|
287
|
+
if strategy == InstallStrategy.PIP_NO_DEPS:
|
|
288
|
+
return [*base_cmd, "--no-deps", package_spec]
|
|
224
289
|
|
|
225
|
-
|
|
226
|
-
return base_cmd
|
|
290
|
+
if strategy == InstallStrategy.PIP_UPGRADE:
|
|
291
|
+
return [*base_cmd, "--upgrade", package_spec]
|
|
227
292
|
|
|
228
|
-
|
|
293
|
+
if strategy == InstallStrategy.PIP_INDEX_URL:
|
|
229
294
|
# Try alternative index (PyPI mirror)
|
|
230
|
-
return
|
|
295
|
+
return [
|
|
296
|
+
*base_cmd,
|
|
231
297
|
"--index-url",
|
|
232
298
|
"https://pypi.org/simple",
|
|
233
299
|
"--extra-index-url",
|
|
@@ -235,8 +301,7 @@ class RobustPackageInstaller:
|
|
|
235
301
|
package_spec,
|
|
236
302
|
]
|
|
237
303
|
|
|
238
|
-
|
|
239
|
-
return base_cmd + [package_spec]
|
|
304
|
+
return [*base_cmd, package_spec]
|
|
240
305
|
|
|
241
306
|
def _extract_package_name(self, package_spec: str) -> str:
|
|
242
307
|
"""
|
|
@@ -433,9 +498,8 @@ class RobustPackageInstaller:
|
|
|
433
498
|
|
|
434
499
|
# Format error message
|
|
435
500
|
if len(errors) == 1:
|
|
436
|
-
return
|
|
437
|
-
|
|
438
|
-
return f"Multiple errors: {' | '.join(errors)}"
|
|
501
|
+
return next(iter(errors))
|
|
502
|
+
return f"Multiple errors: {' | '.join(errors)}"
|
|
439
503
|
|
|
440
504
|
def install_packages(
|
|
441
505
|
self, packages: List[str], parallel: bool = False
|
|
@@ -463,9 +527,8 @@ class RobustPackageInstaller:
|
|
|
463
527
|
if success:
|
|
464
528
|
logger.info("Batch installation successful")
|
|
465
529
|
return packages, [], {}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
logger.info("Falling back to individual installation...")
|
|
530
|
+
logger.warning(f"Batch installation failed: {error}")
|
|
531
|
+
logger.info("Falling back to individual installation...")
|
|
469
532
|
|
|
470
533
|
# Install packages individually
|
|
471
534
|
for i, package in enumerate(packages, 1):
|
|
@@ -492,13 +555,22 @@ class RobustPackageInstaller:
|
|
|
492
555
|
Tuple of (success, error_message)
|
|
493
556
|
"""
|
|
494
557
|
try:
|
|
495
|
-
cmd = [sys.executable, "-m", "pip", "install"]
|
|
558
|
+
cmd = [sys.executable, "-m", "pip", "install"]
|
|
559
|
+
|
|
560
|
+
# Add PEP 668 bypass flags if needed
|
|
561
|
+
if self.is_pep668_managed:
|
|
562
|
+
self._show_pep668_warning()
|
|
563
|
+
cmd.extend(["--break-system-packages", "--user"])
|
|
564
|
+
logger.debug("Added PEP 668 flags for batch installation")
|
|
565
|
+
|
|
566
|
+
cmd.extend(packages)
|
|
496
567
|
|
|
497
568
|
result = subprocess.run(
|
|
498
569
|
cmd,
|
|
499
570
|
capture_output=True,
|
|
500
571
|
text=True,
|
|
501
|
-
timeout=self.timeout * 2,
|
|
572
|
+
timeout=self.timeout * 2,
|
|
573
|
+
check=False, # Longer timeout for batch
|
|
502
574
|
)
|
|
503
575
|
|
|
504
576
|
if result.returncode == 0:
|
|
@@ -506,16 +578,14 @@ class RobustPackageInstaller:
|
|
|
506
578
|
all_verified = all(self._verify_installation(pkg) for pkg in packages)
|
|
507
579
|
if all_verified:
|
|
508
580
|
return True, None
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
error_msg = self._extract_error_message(result.stderr)
|
|
513
|
-
return False, error_msg
|
|
581
|
+
return False, "Some packages failed verification"
|
|
582
|
+
error_msg = self._extract_error_message(result.stderr)
|
|
583
|
+
return False, error_msg
|
|
514
584
|
|
|
515
585
|
except subprocess.TimeoutExpired:
|
|
516
|
-
return False,
|
|
586
|
+
return False, "Batch installation timed out"
|
|
517
587
|
except Exception as e:
|
|
518
|
-
return False, f"Batch installation error: {
|
|
588
|
+
return False, f"Batch installation error: {e!s}"
|
|
519
589
|
|
|
520
590
|
def get_report(self) -> str:
|
|
521
591
|
"""
|
|
@@ -529,6 +599,13 @@ class RobustPackageInstaller:
|
|
|
529
599
|
lines.append("INSTALLATION REPORT")
|
|
530
600
|
lines.append("=" * 60)
|
|
531
601
|
|
|
602
|
+
# Add PEP 668 status
|
|
603
|
+
if self.is_pep668_managed:
|
|
604
|
+
lines.append("")
|
|
605
|
+
lines.append("⚠️ PEP 668 Managed Environment: YES")
|
|
606
|
+
lines.append(" Installations used --break-system-packages --user flags")
|
|
607
|
+
lines.append(" Consider using a virtual environment for better isolation")
|
|
608
|
+
|
|
532
609
|
# Summary
|
|
533
610
|
total_attempts = len(self.attempts)
|
|
534
611
|
successful = sum(1 for a in self.attempts if a.success)
|
|
@@ -7,12 +7,12 @@ with proper error handling, timeouts, and process cleanup.
|
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
9
|
import asyncio
|
|
10
|
+
import contextlib
|
|
10
11
|
import logging
|
|
11
12
|
import shlex
|
|
12
|
-
import signal
|
|
13
13
|
import subprocess
|
|
14
14
|
import time
|
|
15
|
-
from typing import Any, Dict, List, Optional
|
|
15
|
+
from typing import Any, Dict, List, Optional
|
|
16
16
|
|
|
17
17
|
import psutil
|
|
18
18
|
|
|
@@ -122,6 +122,7 @@ def run_subprocess(
|
|
|
122
122
|
cwd=cwd,
|
|
123
123
|
env=env,
|
|
124
124
|
**kwargs,
|
|
125
|
+
check=False,
|
|
125
126
|
)
|
|
126
127
|
|
|
127
128
|
return SubprocessResult(
|
|
@@ -229,16 +230,14 @@ def terminate_process_tree(pid: int, timeout: float = 5.0) -> int:
|
|
|
229
230
|
|
|
230
231
|
# Get all child processes recursively
|
|
231
232
|
children = parent.children(recursive=True)
|
|
232
|
-
processes = [parent
|
|
233
|
+
processes = [parent, *children]
|
|
233
234
|
|
|
234
235
|
terminated_count = 0
|
|
235
236
|
|
|
236
237
|
# First, try graceful termination
|
|
237
238
|
for process in processes:
|
|
238
|
-
|
|
239
|
+
with contextlib.suppress(psutil.NoSuchProcess):
|
|
239
240
|
process.terminate()
|
|
240
|
-
except psutil.NoSuchProcess:
|
|
241
|
-
pass
|
|
242
241
|
|
|
243
242
|
# Wait for processes to terminate gracefully
|
|
244
243
|
gone, alive = psutil.wait_procs(processes, timeout=timeout)
|
|
@@ -26,17 +26,14 @@ from datetime import datetime
|
|
|
26
26
|
from pathlib import Path
|
|
27
27
|
from typing import Any, Dict, List, Optional, Tuple
|
|
28
28
|
|
|
29
|
-
import jsonschema
|
|
30
29
|
from jsonschema import Draft7Validator, ValidationError, validate
|
|
31
30
|
|
|
32
31
|
from claude_mpm.config.paths import paths
|
|
33
32
|
from claude_mpm.core.constants import (
|
|
34
|
-
ComplexityMetrics,
|
|
35
33
|
ErrorMessages,
|
|
36
34
|
ResourceLimits,
|
|
37
35
|
SystemLimits,
|
|
38
36
|
TimeoutConfig,
|
|
39
|
-
ValidationRules,
|
|
40
37
|
)
|
|
41
38
|
|
|
42
39
|
logger = logging.getLogger(__name__)
|
|
@@ -105,7 +102,7 @@ class AgentValidator:
|
|
|
105
102
|
if not self.schema_path.is_file():
|
|
106
103
|
raise ValueError(f"Schema path is not a file: {self.schema_path}")
|
|
107
104
|
|
|
108
|
-
with open(self.schema_path
|
|
105
|
+
with open(self.schema_path) as f:
|
|
109
106
|
return json.load(f)
|
|
110
107
|
except Exception as e:
|
|
111
108
|
logger.error(f"Failed to load schema from {self.schema_path}: {e}")
|
|
@@ -130,7 +127,7 @@ class AgentValidator:
|
|
|
130
127
|
|
|
131
128
|
# Check if model contains tier name
|
|
132
129
|
model_lower = model.lower()
|
|
133
|
-
for tier in
|
|
130
|
+
for tier in ("opus", "sonnet", "haiku"):
|
|
134
131
|
if tier in model_lower:
|
|
135
132
|
return tier
|
|
136
133
|
|
|
@@ -395,7 +392,7 @@ class AgentValidator:
|
|
|
395
392
|
max_size = SystemLimits.MAX_AGENT_CONFIG_SIZE
|
|
396
393
|
if file_size > max_size:
|
|
397
394
|
raise ValueError(ErrorMessages.FILE_TOO_LARGE.format(limit=max_size))
|
|
398
|
-
with open(file_path
|
|
395
|
+
with open(file_path) as f:
|
|
399
396
|
agent_data = json.load(f)
|
|
400
397
|
|
|
401
398
|
result = self.validate_agent(agent_data)
|