claude-mpm 4.7.4__py3-none-any.whl → 4.18.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/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +106 -1
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +4 -1
- claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
- claude_mpm/agents/templates/api_qa.json +11 -2
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +12 -2
- claude_mpm/agents/templates/code_analyzer.json +8 -2
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +15 -2
- claude_mpm/agents/templates/data_engineer.json +15 -2
- claude_mpm/agents/templates/documentation.json +10 -2
- claude_mpm/agents/templates/engineer.json +21 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +4 -1
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/local_ops_agent.json +1227 -6
- claude_mpm/agents/templates/memory_manager.json +4 -1
- claude_mpm/agents/templates/nextjs_engineer.json +141 -133
- claude_mpm/agents/templates/ops.json +12 -2
- claude_mpm/agents/templates/php-engineer.json +270 -174
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +240 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +14 -4
- claude_mpm/agents/templates/prompt-engineer.json +13 -2
- claude_mpm/agents/templates/python_engineer.json +174 -81
- claude_mpm/agents/templates/qa.json +11 -2
- claude_mpm/agents/templates/react_engineer.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +12 -2
- claude_mpm/agents/templates/research.json +34 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +129 -192
- claude_mpm/agents/templates/rust_engineer.json +270 -0
- claude_mpm/agents/templates/security.json +10 -2
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +10 -2
- claude_mpm/agents/templates/typescript_engineer.json +116 -125
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
- claude_mpm/agents/templates/version_control.json +12 -2
- claude_mpm/agents/templates/web_qa.json +11 -2
- claude_mpm/agents/templates/web_ui.json +15 -2
- claude_mpm/cli/__init__.py +34 -614
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +235 -148
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +419 -1571
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +585 -196
- claude_mpm/cli/commands/mpm_init_handler.py +37 -3
- claude_mpm/cli/commands/search.py +170 -4
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agents_parser.py +9 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +110 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +75 -1
- claude_mpm/commands/mpm-auto-configure.md +217 -0
- claude_mpm/commands/mpm-help.md +163 -0
- claude_mpm/commands/mpm-init.md +148 -3
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/log_manager.py +2 -0
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +20 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +37 -12
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +568 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/core/models/__init__.py +79 -0
- claude_mpm/services/core/models/agent_config.py +381 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/main.py +30 -0
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/failure_tracker.py +563 -0
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/self_upgrade_service.py +342 -0
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/storage/state_storage.py +15 -15
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +40 -20
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +129 -12
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +295 -193
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -8,6 +8,8 @@ from pathlib import Path
|
|
|
8
8
|
|
|
9
9
|
from rich.console import Console
|
|
10
10
|
|
|
11
|
+
from claude_mpm.core.enums import OperationResult
|
|
12
|
+
|
|
11
13
|
console = Console()
|
|
12
14
|
|
|
13
15
|
|
|
@@ -25,6 +27,39 @@ def manage_mpm_init(args):
|
|
|
25
27
|
# Import the command implementation
|
|
26
28
|
from .mpm_init import MPMInitCommand
|
|
27
29
|
|
|
30
|
+
# Handle context subcommands
|
|
31
|
+
subcommand = getattr(args, "subcommand", None)
|
|
32
|
+
|
|
33
|
+
if subcommand in ("context", "resume"):
|
|
34
|
+
# Show deprecation warning for 'resume'
|
|
35
|
+
if subcommand == "resume":
|
|
36
|
+
console.print(
|
|
37
|
+
"[yellow]⚠️ Warning: 'resume' is deprecated. Use 'context' instead.[/yellow]"
|
|
38
|
+
)
|
|
39
|
+
console.print("[dim]Run: claude-mpm mpm-init context[/dim]\n")
|
|
40
|
+
|
|
41
|
+
# Get project path
|
|
42
|
+
project_path = (
|
|
43
|
+
Path(args.project_path) if hasattr(args, "project_path") else Path.cwd()
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
# Create command instance
|
|
47
|
+
command = MPMInitCommand(project_path)
|
|
48
|
+
|
|
49
|
+
# Handle context with optional session ID and days
|
|
50
|
+
result = command.handle_context(
|
|
51
|
+
session_id=getattr(args, "session_id", None),
|
|
52
|
+
days=getattr(args, "days", 7),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Return appropriate exit code
|
|
56
|
+
if result.get("status") in (
|
|
57
|
+
OperationResult.SUCCESS,
|
|
58
|
+
OperationResult.CONTEXT_READY,
|
|
59
|
+
):
|
|
60
|
+
return 0
|
|
61
|
+
return 1
|
|
62
|
+
|
|
28
63
|
# Handle special flags
|
|
29
64
|
if getattr(args, "list_templates", False):
|
|
30
65
|
# List available templates
|
|
@@ -55,7 +90,6 @@ def manage_mpm_init(args):
|
|
|
55
90
|
"framework": getattr(args, "framework", None),
|
|
56
91
|
"force": getattr(args, "force", False),
|
|
57
92
|
"verbose": getattr(args, "verbose", False),
|
|
58
|
-
"use_venv": getattr(args, "use_venv", False),
|
|
59
93
|
"ast_analysis": getattr(args, "ast_analysis", True),
|
|
60
94
|
"update_mode": getattr(args, "update", False),
|
|
61
95
|
"review_only": getattr(args, "review", False),
|
|
@@ -73,9 +107,9 @@ def manage_mpm_init(args):
|
|
|
73
107
|
result = command.initialize_project(**init_params)
|
|
74
108
|
|
|
75
109
|
# Return appropriate exit code
|
|
76
|
-
if result.get("status") ==
|
|
110
|
+
if result.get("status") == OperationResult.SUCCESS:
|
|
77
111
|
return 0
|
|
78
|
-
if result.get("status") ==
|
|
112
|
+
if result.get("status") == OperationResult.CANCELLED:
|
|
79
113
|
return 130 # User cancelled
|
|
80
114
|
return 1 # Error
|
|
81
115
|
|
|
@@ -16,8 +16,7 @@ from rich.panel import Panel
|
|
|
16
16
|
from rich.syntax import Syntax
|
|
17
17
|
from rich.table import Table
|
|
18
18
|
|
|
19
|
-
from claude_mpm.
|
|
20
|
-
from claude_mpm.services.service_container import get_service_container
|
|
19
|
+
from claude_mpm.services.core.service_container import get_global_container
|
|
21
20
|
|
|
22
21
|
console = Console()
|
|
23
22
|
|
|
@@ -27,8 +26,9 @@ class MCPSearchInterface:
|
|
|
27
26
|
|
|
28
27
|
def __init__(self):
|
|
29
28
|
"""Initialize the search interface."""
|
|
30
|
-
self.container =
|
|
29
|
+
self.container = get_global_container()
|
|
31
30
|
self.mcp_gateway = None
|
|
31
|
+
self.vector_search_available = False
|
|
32
32
|
|
|
33
33
|
async def initialize(self):
|
|
34
34
|
"""Initialize the MCP gateway connection."""
|
|
@@ -39,10 +39,127 @@ class MCPSearchInterface:
|
|
|
39
39
|
if not self.mcp_gateway:
|
|
40
40
|
self.mcp_gateway = MCPGatewayService()
|
|
41
41
|
await self.mcp_gateway.initialize()
|
|
42
|
+
|
|
43
|
+
# Check if vector search is available
|
|
44
|
+
self.vector_search_available = await self._check_vector_search_available()
|
|
45
|
+
|
|
42
46
|
except Exception as e:
|
|
43
47
|
console.print(f"[red]Failed to initialize MCP gateway: {e}[/red]")
|
|
44
48
|
raise
|
|
45
49
|
|
|
50
|
+
async def _check_vector_search_available(self) -> bool:
|
|
51
|
+
"""Check if mcp-vector-search is available and offer installation if not."""
|
|
52
|
+
import importlib.util
|
|
53
|
+
|
|
54
|
+
# Check if package is installed
|
|
55
|
+
spec = importlib.util.find_spec("mcp_vector_search")
|
|
56
|
+
if spec is not None:
|
|
57
|
+
return True
|
|
58
|
+
|
|
59
|
+
# Package not found - offer installation
|
|
60
|
+
console.print("\n[yellow]⚠️ mcp-vector-search not found[/yellow]")
|
|
61
|
+
console.print("This package enables semantic code search (optional feature).")
|
|
62
|
+
console.print("\nInstallation options:")
|
|
63
|
+
console.print(" 1. Install via pip (recommended for this project)")
|
|
64
|
+
console.print(" 2. Install via pipx (isolated, system-wide)")
|
|
65
|
+
console.print(" 3. Skip (use traditional grep/glob instead)")
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
choice = input("\nChoose option (1/2/3) [3]: ").strip() or "3"
|
|
69
|
+
|
|
70
|
+
if choice == "1":
|
|
71
|
+
return await self._install_via_pip()
|
|
72
|
+
if choice == "2":
|
|
73
|
+
return await self._install_via_pipx()
|
|
74
|
+
console.print(
|
|
75
|
+
"[dim]Continuing with fallback search methods (grep/glob)[/dim]"
|
|
76
|
+
)
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
except (EOFError, KeyboardInterrupt):
|
|
80
|
+
console.print("\n[dim]Installation cancelled, using fallback methods[/dim]")
|
|
81
|
+
return False
|
|
82
|
+
|
|
83
|
+
async def _install_via_pip(self) -> bool:
|
|
84
|
+
"""Install mcp-vector-search via pip."""
|
|
85
|
+
import subprocess
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
console.print("\n[cyan]📦 Installing mcp-vector-search via pip...[/cyan]")
|
|
89
|
+
result = subprocess.run(
|
|
90
|
+
[sys.executable, "-m", "pip", "install", "mcp-vector-search"],
|
|
91
|
+
capture_output=True,
|
|
92
|
+
text=True,
|
|
93
|
+
timeout=120,
|
|
94
|
+
check=False,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
if result.returncode == 0:
|
|
98
|
+
console.print(
|
|
99
|
+
"[green]✓ Successfully installed mcp-vector-search[/green]"
|
|
100
|
+
)
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
error_msg = result.stderr.strip() if result.stderr else "Unknown error"
|
|
104
|
+
console.print(f"[red]✗ Installation failed: {error_msg}[/red]")
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
except subprocess.TimeoutExpired:
|
|
108
|
+
console.print("[red]✗ Installation timed out[/red]")
|
|
109
|
+
return False
|
|
110
|
+
except Exception as e:
|
|
111
|
+
console.print(f"[red]✗ Installation error: {e}[/red]")
|
|
112
|
+
return False
|
|
113
|
+
|
|
114
|
+
async def _install_via_pipx(self) -> bool:
|
|
115
|
+
"""Install mcp-vector-search via pipx."""
|
|
116
|
+
import subprocess
|
|
117
|
+
|
|
118
|
+
try:
|
|
119
|
+
# Check if pipx is available
|
|
120
|
+
pipx_check = subprocess.run(
|
|
121
|
+
["pipx", "--version"],
|
|
122
|
+
capture_output=True,
|
|
123
|
+
text=True,
|
|
124
|
+
timeout=5,
|
|
125
|
+
check=False,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
if pipx_check.returncode != 0:
|
|
129
|
+
console.print("[red]✗ pipx is not installed[/red]")
|
|
130
|
+
console.print("Install pipx first: python -m pip install pipx")
|
|
131
|
+
return False
|
|
132
|
+
|
|
133
|
+
console.print("\n[cyan]📦 Installing mcp-vector-search via pipx...[/cyan]")
|
|
134
|
+
result = subprocess.run(
|
|
135
|
+
["pipx", "install", "mcp-vector-search"],
|
|
136
|
+
capture_output=True,
|
|
137
|
+
text=True,
|
|
138
|
+
timeout=120,
|
|
139
|
+
check=False,
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
if result.returncode == 0:
|
|
143
|
+
console.print(
|
|
144
|
+
"[green]✓ Successfully installed mcp-vector-search[/green]"
|
|
145
|
+
)
|
|
146
|
+
return True
|
|
147
|
+
|
|
148
|
+
error_msg = result.stderr.strip() if result.stderr else "Unknown error"
|
|
149
|
+
console.print(f"[red]✗ Installation failed: {error_msg}[/red]")
|
|
150
|
+
return False
|
|
151
|
+
|
|
152
|
+
except FileNotFoundError:
|
|
153
|
+
console.print("[red]✗ pipx command not found[/red]")
|
|
154
|
+
console.print("Install pipx first: python -m pip install pipx")
|
|
155
|
+
return False
|
|
156
|
+
except subprocess.TimeoutExpired:
|
|
157
|
+
console.print("[red]✗ Installation timed out[/red]")
|
|
158
|
+
return False
|
|
159
|
+
except Exception as e:
|
|
160
|
+
console.print(f"[red]✗ Installation error: {e}[/red]")
|
|
161
|
+
return False
|
|
162
|
+
|
|
46
163
|
async def search_code(
|
|
47
164
|
self,
|
|
48
165
|
query: str,
|
|
@@ -125,6 +242,12 @@ class MCPSearchInterface:
|
|
|
125
242
|
if not self.mcp_gateway:
|
|
126
243
|
await self.initialize()
|
|
127
244
|
|
|
245
|
+
# Check if vector search is available
|
|
246
|
+
if not self.vector_search_available:
|
|
247
|
+
return {
|
|
248
|
+
"error": "mcp-vector-search is not available. Use traditional grep/glob tools instead, or run command again to install."
|
|
249
|
+
}
|
|
250
|
+
|
|
128
251
|
try:
|
|
129
252
|
return await self.mcp_gateway.call_tool(tool_name, params)
|
|
130
253
|
except Exception as e:
|
|
@@ -196,7 +319,6 @@ def display_search_results(results: Dict[str, Any], output_format: str = "rich")
|
|
|
196
319
|
@click.option("--focus", multiple=True, help="Focus areas (with --context)")
|
|
197
320
|
@click.option("--force", is_flag=True, help="Force reindexing (with --index)")
|
|
198
321
|
@click.option("--json", "output_json", is_flag=True, help="Output results as JSON")
|
|
199
|
-
@handle_async_errors
|
|
200
322
|
async def search_command(
|
|
201
323
|
query: Optional[str],
|
|
202
324
|
similar: Optional[str],
|
|
@@ -228,8 +350,24 @@ async def search_command(
|
|
|
228
350
|
output_format = "json" if output_json else "rich"
|
|
229
351
|
|
|
230
352
|
try:
|
|
353
|
+
# Show first-time usage tips if vector search is available
|
|
354
|
+
if search.vector_search_available and not (index or status):
|
|
355
|
+
console.print(
|
|
356
|
+
"\n[dim]💡 Tip: Vector search provides semantic code understanding.[/dim]"
|
|
357
|
+
)
|
|
358
|
+
console.print(
|
|
359
|
+
"[dim] Run with --index first to index your project.[/dim]\n"
|
|
360
|
+
)
|
|
361
|
+
|
|
231
362
|
# Handle different operation modes
|
|
232
363
|
if index:
|
|
364
|
+
if not search.vector_search_available:
|
|
365
|
+
console.print("[red]✗ mcp-vector-search is required for indexing[/red]")
|
|
366
|
+
console.print(
|
|
367
|
+
"[dim]Install it or use traditional grep/glob for search[/dim]"
|
|
368
|
+
)
|
|
369
|
+
sys.exit(1)
|
|
370
|
+
|
|
233
371
|
console.print("[cyan]Indexing project...[/cyan]")
|
|
234
372
|
result = await search.index_project(
|
|
235
373
|
force=force, file_extensions=list(extensions) if extensions else None
|
|
@@ -239,10 +377,23 @@ async def search_command(
|
|
|
239
377
|
display_search_results(result, output_format)
|
|
240
378
|
|
|
241
379
|
elif status:
|
|
380
|
+
if not search.vector_search_available:
|
|
381
|
+
console.print(
|
|
382
|
+
"[red]✗ mcp-vector-search is required for status check[/red]"
|
|
383
|
+
)
|
|
384
|
+
console.print("[dim]Install it to use vector search features[/dim]")
|
|
385
|
+
sys.exit(1)
|
|
386
|
+
|
|
242
387
|
result = await search.get_status()
|
|
243
388
|
display_search_results(result, output_format)
|
|
244
389
|
|
|
245
390
|
elif similar:
|
|
391
|
+
if not search.vector_search_available:
|
|
392
|
+
console.print("[yellow]⚠️ Vector search not available[/yellow]")
|
|
393
|
+
console.print("[dim]Similarity search requires mcp-vector-search[/dim]")
|
|
394
|
+
console.print("[dim]Falling back to basic file search...[/dim]")
|
|
395
|
+
sys.exit(1)
|
|
396
|
+
|
|
246
397
|
result = await search.search_similar(
|
|
247
398
|
file_path=similar,
|
|
248
399
|
function_name=function,
|
|
@@ -252,6 +403,12 @@ async def search_command(
|
|
|
252
403
|
display_search_results(result, output_format)
|
|
253
404
|
|
|
254
405
|
elif context:
|
|
406
|
+
if not search.vector_search_available:
|
|
407
|
+
console.print("[yellow]⚠️ Vector search not available[/yellow]")
|
|
408
|
+
console.print("[dim]Context search requires mcp-vector-search[/dim]")
|
|
409
|
+
console.print("[dim]Try using grep for text-based search instead[/dim]")
|
|
410
|
+
sys.exit(1)
|
|
411
|
+
|
|
255
412
|
result = await search.search_context(
|
|
256
413
|
description=context,
|
|
257
414
|
focus_areas=list(focus) if focus else None,
|
|
@@ -260,6 +417,15 @@ async def search_command(
|
|
|
260
417
|
display_search_results(result, output_format)
|
|
261
418
|
|
|
262
419
|
elif query:
|
|
420
|
+
if not search.vector_search_available:
|
|
421
|
+
console.print("[yellow]⚠️ Vector search not available[/yellow]")
|
|
422
|
+
console.print("[dim]Code search requires mcp-vector-search[/dim]")
|
|
423
|
+
console.print(
|
|
424
|
+
"\n[cyan]Alternative: Use grep for pattern matching:[/cyan]"
|
|
425
|
+
)
|
|
426
|
+
console.print(f" grep -r '{query}' .")
|
|
427
|
+
sys.exit(1)
|
|
428
|
+
|
|
263
429
|
result = await search.search_code(
|
|
264
430
|
query=query,
|
|
265
431
|
limit=limit,
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Upgrade command implementation for claude-mpm.
|
|
3
|
+
|
|
4
|
+
WHY: This module provides a manual upgrade command that allows users to check
|
|
5
|
+
for and install the latest version of claude-mpm without waiting for the
|
|
6
|
+
automatic startup check.
|
|
7
|
+
|
|
8
|
+
DESIGN DECISIONS:
|
|
9
|
+
- Use BaseCommand for consistent CLI patterns
|
|
10
|
+
- Leverage SelfUpgradeService for upgrade functionality
|
|
11
|
+
- Support multiple installation methods (pip, pipx, npm)
|
|
12
|
+
- Skip editable/development installations (must upgrade manually)
|
|
13
|
+
- Provide clear feedback on available updates and upgrade progress
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import asyncio
|
|
17
|
+
|
|
18
|
+
from ..shared import BaseCommand, CommandResult
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class UpgradeCommand(BaseCommand):
|
|
22
|
+
"""Upgrade command using shared utilities."""
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
super().__init__("upgrade")
|
|
26
|
+
|
|
27
|
+
def validate_args(self, args) -> str:
|
|
28
|
+
"""Validate command arguments."""
|
|
29
|
+
# Upgrade command doesn't require specific validation
|
|
30
|
+
return None
|
|
31
|
+
|
|
32
|
+
def run(self, args) -> CommandResult:
|
|
33
|
+
"""Execute the upgrade command."""
|
|
34
|
+
try:
|
|
35
|
+
from ...services.self_upgrade_service import (
|
|
36
|
+
InstallationMethod,
|
|
37
|
+
SelfUpgradeService,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# Create upgrade service
|
|
41
|
+
upgrade_service = SelfUpgradeService()
|
|
42
|
+
|
|
43
|
+
# Check installation method
|
|
44
|
+
if upgrade_service.installation_method == InstallationMethod.EDITABLE:
|
|
45
|
+
self.logger.info(
|
|
46
|
+
"Editable installation detected - upgrade must be done manually"
|
|
47
|
+
)
|
|
48
|
+
print("\n⚠️ Editable Installation Detected")
|
|
49
|
+
print(
|
|
50
|
+
"\nYou are running claude-mpm from an editable installation (development mode)."
|
|
51
|
+
)
|
|
52
|
+
print("To upgrade, run:")
|
|
53
|
+
print(" cd /path/to/claude-mpm")
|
|
54
|
+
print(" git pull")
|
|
55
|
+
print(" pip install -e .")
|
|
56
|
+
return CommandResult.success_result(
|
|
57
|
+
"Upgrade information provided for editable installation"
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Check for updates
|
|
61
|
+
print("\n🔍 Checking for updates...")
|
|
62
|
+
loop = asyncio.new_event_loop()
|
|
63
|
+
asyncio.set_event_loop(loop)
|
|
64
|
+
try:
|
|
65
|
+
update_info = loop.run_until_complete(
|
|
66
|
+
upgrade_service.check_for_update()
|
|
67
|
+
)
|
|
68
|
+
finally:
|
|
69
|
+
loop.close()
|
|
70
|
+
|
|
71
|
+
if not update_info or not update_info.get("update_available"):
|
|
72
|
+
print(
|
|
73
|
+
f"\n✅ You are already on the latest version (v{upgrade_service.current_version})"
|
|
74
|
+
)
|
|
75
|
+
return CommandResult.success_result("Already on latest version")
|
|
76
|
+
|
|
77
|
+
# Display update information
|
|
78
|
+
current = update_info["current"]
|
|
79
|
+
latest = update_info["latest"]
|
|
80
|
+
method = update_info.get("installation_method", "unknown")
|
|
81
|
+
|
|
82
|
+
print("\n🎉 New version available!")
|
|
83
|
+
print(f" Current: v{current}")
|
|
84
|
+
print(f" Latest: v{latest}")
|
|
85
|
+
print(f" Installation method: {method}")
|
|
86
|
+
|
|
87
|
+
# Check if --yes flag is set for non-interactive upgrade
|
|
88
|
+
force_upgrade = getattr(args, "yes", False) or getattr(args, "force", False)
|
|
89
|
+
|
|
90
|
+
if not force_upgrade:
|
|
91
|
+
# Prompt user for confirmation
|
|
92
|
+
if not upgrade_service.prompt_for_upgrade(update_info):
|
|
93
|
+
print("\n⏸️ Upgrade cancelled by user")
|
|
94
|
+
return CommandResult.success_result("Upgrade cancelled by user")
|
|
95
|
+
|
|
96
|
+
# Perform upgrade
|
|
97
|
+
success, message = upgrade_service.perform_upgrade(update_info)
|
|
98
|
+
print(f"\n{message}")
|
|
99
|
+
|
|
100
|
+
if success:
|
|
101
|
+
# Restart after successful upgrade
|
|
102
|
+
upgrade_service.restart_after_upgrade()
|
|
103
|
+
# Note: This line won't be reached as restart replaces process
|
|
104
|
+
return CommandResult.success_result(f"Upgraded to v{latest}")
|
|
105
|
+
return CommandResult.error_result("Upgrade failed")
|
|
106
|
+
|
|
107
|
+
except Exception as e:
|
|
108
|
+
self.logger.error(f"Error during upgrade: {e}", exc_info=True)
|
|
109
|
+
return CommandResult.error_result(f"Error during upgrade: {e}")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def add_upgrade_parser(subparsers):
|
|
113
|
+
"""
|
|
114
|
+
Add upgrade command parser.
|
|
115
|
+
|
|
116
|
+
WHY: This command helps users check for and install the latest version of
|
|
117
|
+
claude-mpm without waiting for the automatic startup check.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
subparsers: The subparser action object to add the upgrade command to
|
|
121
|
+
"""
|
|
122
|
+
parser = subparsers.add_parser(
|
|
123
|
+
"upgrade",
|
|
124
|
+
help="Check for and install latest claude-mpm version",
|
|
125
|
+
description="Check for updates and upgrade claude-mpm to the latest version from PyPI/npm",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
parser.add_argument(
|
|
129
|
+
"-y",
|
|
130
|
+
"--yes",
|
|
131
|
+
action="store_true",
|
|
132
|
+
help="Skip confirmation prompt and upgrade immediately if available",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
parser.add_argument(
|
|
136
|
+
"--force",
|
|
137
|
+
action="store_true",
|
|
138
|
+
help="Force upgrade even if already on latest version (alias for --yes)",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return parser
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def upgrade(args):
|
|
145
|
+
"""
|
|
146
|
+
Main entry point for upgrade command.
|
|
147
|
+
|
|
148
|
+
This function maintains backward compatibility while using the new BaseCommand pattern.
|
|
149
|
+
"""
|
|
150
|
+
command = UpgradeCommand()
|
|
151
|
+
result = command.execute(args)
|
|
152
|
+
return result.exit_code
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Command Executor
|
|
3
|
+
====================
|
|
4
|
+
|
|
5
|
+
This module handles command execution routing and argument preparation.
|
|
6
|
+
|
|
7
|
+
Part of cli/__init__.py refactoring to reduce file size and improve modularity.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from ..constants import CLICommands
|
|
11
|
+
from .commands import (
|
|
12
|
+
aggregate_command,
|
|
13
|
+
cleanup_memory,
|
|
14
|
+
manage_agent_manager,
|
|
15
|
+
manage_agents,
|
|
16
|
+
manage_config,
|
|
17
|
+
manage_configure,
|
|
18
|
+
manage_debug,
|
|
19
|
+
manage_mcp,
|
|
20
|
+
manage_memory,
|
|
21
|
+
manage_monitor,
|
|
22
|
+
manage_tickets,
|
|
23
|
+
run_doctor,
|
|
24
|
+
run_session,
|
|
25
|
+
show_info,
|
|
26
|
+
)
|
|
27
|
+
from .commands.analyze_code import manage_analyze_code
|
|
28
|
+
from .commands.dashboard import manage_dashboard
|
|
29
|
+
from .commands.upgrade import upgrade
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def ensure_run_attributes(args):
|
|
33
|
+
"""
|
|
34
|
+
Ensure run command attributes exist when defaulting to run.
|
|
35
|
+
|
|
36
|
+
WHY: When no command is specified, we default to 'run' but the args object
|
|
37
|
+
won't have run-specific attributes from the subparser. This function ensures
|
|
38
|
+
they exist with sensible defaults.
|
|
39
|
+
|
|
40
|
+
Args:
|
|
41
|
+
args: Parsed arguments object to update
|
|
42
|
+
"""
|
|
43
|
+
# Set defaults for run command attributes
|
|
44
|
+
args.no_tickets = getattr(args, "no_tickets", False)
|
|
45
|
+
args.no_hooks = getattr(args, "no_hooks", False)
|
|
46
|
+
args.intercept_commands = getattr(args, "intercept_commands", False)
|
|
47
|
+
args.input = getattr(args, "input", None)
|
|
48
|
+
args.non_interactive = getattr(args, "non_interactive", False)
|
|
49
|
+
args.no_native_agents = getattr(args, "no_native_agents", False)
|
|
50
|
+
|
|
51
|
+
# Handle claude_args - if --resume flag is set, add it to claude_args
|
|
52
|
+
claude_args = getattr(args, "claude_args", [])
|
|
53
|
+
if getattr(args, "resume", False):
|
|
54
|
+
# Add --resume to claude_args if not already present
|
|
55
|
+
if "--resume" not in claude_args:
|
|
56
|
+
claude_args = ["--resume", *claude_args]
|
|
57
|
+
args.claude_args = claude_args
|
|
58
|
+
|
|
59
|
+
args.launch_method = getattr(args, "launch_method", "exec")
|
|
60
|
+
args.websocket = getattr(args, "websocket", False)
|
|
61
|
+
args.websocket_port = getattr(args, "websocket_port", 8765)
|
|
62
|
+
# CRITICAL: Include mpm_resume attribute for session resumption
|
|
63
|
+
args.mpm_resume = getattr(args, "mpm_resume", None)
|
|
64
|
+
# Also include monitor and force attributes
|
|
65
|
+
args.monitor = getattr(args, "monitor", False)
|
|
66
|
+
args.force = getattr(args, "force", False)
|
|
67
|
+
args.reload_agents = getattr(args, "reload_agents", False)
|
|
68
|
+
# Include dependency checking attributes
|
|
69
|
+
args.check_dependencies = getattr(args, "check_dependencies", True)
|
|
70
|
+
args.force_check_dependencies = getattr(args, "force_check_dependencies", False)
|
|
71
|
+
args.no_prompt = getattr(args, "no_prompt", False)
|
|
72
|
+
args.force_prompt = getattr(args, "force_prompt", False)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def execute_command(command: str, args) -> int:
|
|
76
|
+
"""
|
|
77
|
+
Execute the specified command.
|
|
78
|
+
|
|
79
|
+
WHY: This function maps command names to their implementations, providing
|
|
80
|
+
a single place to manage command routing. Experimental commands are imported
|
|
81
|
+
lazily to avoid loading unnecessary code.
|
|
82
|
+
|
|
83
|
+
DESIGN DECISION: run_guarded is imported only when needed to maintain
|
|
84
|
+
separation between stable and experimental features. Command suggestions
|
|
85
|
+
are provided for unknown commands to improve user experience.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
command: The command name to execute
|
|
89
|
+
args: Parsed command line arguments
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
Exit code from the command
|
|
93
|
+
"""
|
|
94
|
+
# Handle experimental run-guarded command separately with lazy import
|
|
95
|
+
if command == "run-guarded":
|
|
96
|
+
# Lazy import to avoid loading experimental code unless needed
|
|
97
|
+
from .commands.run_guarded import execute_run_guarded
|
|
98
|
+
|
|
99
|
+
result = execute_run_guarded(args)
|
|
100
|
+
return result if result is not None else 0
|
|
101
|
+
|
|
102
|
+
# Handle mpm-init command with lazy import
|
|
103
|
+
if command == "mpm-init":
|
|
104
|
+
# Lazy import to avoid loading unless needed
|
|
105
|
+
from .commands.mpm_init_handler import manage_mpm_init
|
|
106
|
+
|
|
107
|
+
result = manage_mpm_init(args)
|
|
108
|
+
return result if result is not None else 0
|
|
109
|
+
|
|
110
|
+
# Handle uninstall command with lazy import
|
|
111
|
+
if command == "uninstall":
|
|
112
|
+
# Lazy import to avoid loading unless needed
|
|
113
|
+
from .commands.uninstall import UninstallCommand
|
|
114
|
+
|
|
115
|
+
cmd = UninstallCommand()
|
|
116
|
+
result = cmd.execute(args)
|
|
117
|
+
# Convert CommandResult to exit code
|
|
118
|
+
return result.exit_code if result else 0
|
|
119
|
+
|
|
120
|
+
# Handle verify command with lazy import
|
|
121
|
+
if command == "verify":
|
|
122
|
+
# Lazy import to avoid loading unless needed
|
|
123
|
+
from .commands.verify import handle_verify
|
|
124
|
+
|
|
125
|
+
result = handle_verify(args)
|
|
126
|
+
return result if result is not None else 0
|
|
127
|
+
|
|
128
|
+
# Handle auto-configure command with lazy import
|
|
129
|
+
if command == "auto-configure":
|
|
130
|
+
# Lazy import to avoid loading unless needed
|
|
131
|
+
from .commands.auto_configure import AutoConfigureCommand
|
|
132
|
+
|
|
133
|
+
cmd = AutoConfigureCommand()
|
|
134
|
+
result = cmd.run(args)
|
|
135
|
+
# Convert CommandResult to exit code
|
|
136
|
+
return result.exit_code if result else 0
|
|
137
|
+
|
|
138
|
+
# Handle local-deploy command with lazy import
|
|
139
|
+
if command == "local-deploy":
|
|
140
|
+
# Lazy import to avoid loading unless needed
|
|
141
|
+
from .commands.local_deploy import LocalDeployCommand
|
|
142
|
+
|
|
143
|
+
cmd = LocalDeployCommand()
|
|
144
|
+
result = cmd.run(args)
|
|
145
|
+
# Convert CommandResult to exit code
|
|
146
|
+
return result.exit_code if result else 0
|
|
147
|
+
|
|
148
|
+
# Map stable commands to their implementations
|
|
149
|
+
command_map = {
|
|
150
|
+
CLICommands.RUN.value: run_session,
|
|
151
|
+
# CLICommands.RUN_GUARDED.value is handled above
|
|
152
|
+
CLICommands.TICKETS.value: manage_tickets,
|
|
153
|
+
CLICommands.INFO.value: show_info,
|
|
154
|
+
CLICommands.AGENTS.value: manage_agents,
|
|
155
|
+
CLICommands.AGENT_MANAGER.value: manage_agent_manager,
|
|
156
|
+
CLICommands.MEMORY.value: manage_memory,
|
|
157
|
+
CLICommands.MONITOR.value: manage_monitor,
|
|
158
|
+
CLICommands.DASHBOARD.value: manage_dashboard,
|
|
159
|
+
CLICommands.CONFIG.value: manage_config,
|
|
160
|
+
CLICommands.CONFIGURE.value: manage_configure,
|
|
161
|
+
CLICommands.AGGREGATE.value: aggregate_command,
|
|
162
|
+
CLICommands.ANALYZE_CODE.value: manage_analyze_code,
|
|
163
|
+
CLICommands.CLEANUP.value: cleanup_memory,
|
|
164
|
+
CLICommands.MCP.value: manage_mcp,
|
|
165
|
+
CLICommands.DOCTOR.value: run_doctor,
|
|
166
|
+
CLICommands.UPGRADE.value: upgrade,
|
|
167
|
+
"debug": manage_debug, # Add debug command
|
|
168
|
+
"mpm-init": None, # Will be handled separately with lazy import
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# Execute command if found
|
|
172
|
+
if command in command_map:
|
|
173
|
+
result = command_map[command](args)
|
|
174
|
+
# Commands may return None (success) or an exit code
|
|
175
|
+
return result if result is not None else 0
|
|
176
|
+
|
|
177
|
+
# Unknown command - provide suggestions
|
|
178
|
+
from rich.console import Console
|
|
179
|
+
|
|
180
|
+
from .utils import suggest_similar_commands
|
|
181
|
+
|
|
182
|
+
console = Console(stderr=True)
|
|
183
|
+
|
|
184
|
+
console.print(f"\n[red]Error:[/red] Unknown command: {command}\n", style="bold")
|
|
185
|
+
|
|
186
|
+
# Get all valid commands for suggestions
|
|
187
|
+
all_commands = [
|
|
188
|
+
*command_map.keys(),
|
|
189
|
+
"run-guarded",
|
|
190
|
+
"uninstall",
|
|
191
|
+
"verify",
|
|
192
|
+
"auto-configure",
|
|
193
|
+
"local-deploy",
|
|
194
|
+
]
|
|
195
|
+
|
|
196
|
+
suggestion = suggest_similar_commands(command, all_commands)
|
|
197
|
+
if suggestion:
|
|
198
|
+
console.print(f"[yellow]{suggestion}[/yellow]\n")
|
|
199
|
+
|
|
200
|
+
console.print("[dim]Run 'claude-mpm --help' for usage information.[/dim]\n")
|
|
201
|
+
|
|
202
|
+
return 1
|