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
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
"""
|
|
2
|
+
CLI Startup Functions
|
|
3
|
+
=====================
|
|
4
|
+
|
|
5
|
+
This module contains initialization functions that run on CLI startup,
|
|
6
|
+
including project registry, MCP configuration, and update checks.
|
|
7
|
+
|
|
8
|
+
Part of cli/__init__.py refactoring to reduce file size and improve modularity.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import os
|
|
12
|
+
import sys
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def setup_early_environment(argv):
|
|
16
|
+
"""
|
|
17
|
+
Set up early environment variables and logging suppression.
|
|
18
|
+
|
|
19
|
+
WHY: Some commands need special environment handling before any logging
|
|
20
|
+
or service initialization occurs.
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
argv: Command line arguments
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
Processed argv list
|
|
27
|
+
"""
|
|
28
|
+
# Disable telemetry and set cleanup flags early
|
|
29
|
+
os.environ.setdefault("DISABLE_TELEMETRY", "1")
|
|
30
|
+
os.environ.setdefault("CLAUDE_MPM_SKIP_CLEANUP", "0")
|
|
31
|
+
|
|
32
|
+
# EARLY CHECK: Suppress logging for configure command
|
|
33
|
+
if argv is None:
|
|
34
|
+
argv = sys.argv[1:]
|
|
35
|
+
if "configure" in argv or (len(argv) > 0 and argv[0] == "configure"):
|
|
36
|
+
import logging
|
|
37
|
+
|
|
38
|
+
logging.getLogger("claude_mpm").setLevel(logging.WARNING)
|
|
39
|
+
os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
|
|
40
|
+
|
|
41
|
+
return argv
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def should_skip_background_services(args, processed_argv):
|
|
45
|
+
"""
|
|
46
|
+
Determine if background services should be skipped for this command.
|
|
47
|
+
|
|
48
|
+
WHY: Some commands (help, version, configure, doctor) don't need
|
|
49
|
+
background services and should start faster.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
args: Parsed arguments
|
|
53
|
+
processed_argv: Processed command line arguments
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
bool: True if background services should be skipped
|
|
57
|
+
"""
|
|
58
|
+
skip_commands = ["--version", "-v", "--help", "-h"]
|
|
59
|
+
return any(cmd in (processed_argv or sys.argv[1:]) for cmd in skip_commands) or (
|
|
60
|
+
hasattr(args, "command")
|
|
61
|
+
and args.command in ["info", "doctor", "config", "mcp", "configure"]
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def setup_configure_command_environment(args):
|
|
66
|
+
"""
|
|
67
|
+
Set up special environment for configure command.
|
|
68
|
+
|
|
69
|
+
WHY: Configure command needs clean state without background services
|
|
70
|
+
and with suppressed logging.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
args: Parsed arguments
|
|
74
|
+
"""
|
|
75
|
+
if hasattr(args, "command") and args.command == "configure":
|
|
76
|
+
os.environ["CLAUDE_MPM_SKIP_CLEANUP"] = "1"
|
|
77
|
+
import logging
|
|
78
|
+
|
|
79
|
+
logging.getLogger("claude_mpm").setLevel(logging.WARNING)
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def discover_and_link_runtime_skills():
|
|
83
|
+
"""
|
|
84
|
+
Discover and link runtime skills from user/project directories.
|
|
85
|
+
|
|
86
|
+
WHY: Automatically discover and link skills added to .claude/skills/
|
|
87
|
+
without requiring manual configuration.
|
|
88
|
+
|
|
89
|
+
DESIGN DECISION: Failures are logged but don't block startup to ensure
|
|
90
|
+
claude-mpm remains functional even if skills discovery fails.
|
|
91
|
+
"""
|
|
92
|
+
try:
|
|
93
|
+
from ..cli.interactive.skills_wizard import (
|
|
94
|
+
discover_and_link_runtime_skills as discover_skills,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
discover_skills()
|
|
98
|
+
except Exception as e:
|
|
99
|
+
# Import logger here to avoid circular imports
|
|
100
|
+
from ..core.logger import get_logger
|
|
101
|
+
|
|
102
|
+
logger = get_logger("cli")
|
|
103
|
+
logger.debug(f"Failed to discover runtime skills: {e}")
|
|
104
|
+
# Continue execution - skills discovery failure shouldn't block startup
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def run_background_services():
|
|
108
|
+
"""
|
|
109
|
+
Initialize all background services on startup.
|
|
110
|
+
|
|
111
|
+
WHY: Centralizes all startup service initialization for cleaner main().
|
|
112
|
+
"""
|
|
113
|
+
initialize_project_registry()
|
|
114
|
+
check_mcp_auto_configuration()
|
|
115
|
+
verify_mcp_gateway_startup()
|
|
116
|
+
check_for_updates_async()
|
|
117
|
+
discover_and_link_runtime_skills()
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def setup_mcp_server_logging(args):
|
|
121
|
+
"""
|
|
122
|
+
Configure minimal logging for MCP server mode.
|
|
123
|
+
|
|
124
|
+
WHY: MCP server needs minimal stderr-only logging to avoid interfering
|
|
125
|
+
with stdout protocol communication.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
args: Parsed arguments
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
Configured logger
|
|
132
|
+
"""
|
|
133
|
+
import logging
|
|
134
|
+
|
|
135
|
+
from ..cli.utils import setup_logging
|
|
136
|
+
from ..constants import CLICommands
|
|
137
|
+
|
|
138
|
+
if (
|
|
139
|
+
args.command == CLICommands.MCP.value
|
|
140
|
+
and getattr(args, "mcp_command", None) == "start"
|
|
141
|
+
):
|
|
142
|
+
if not getattr(args, "test", False) and not getattr(
|
|
143
|
+
args, "instructions", False
|
|
144
|
+
):
|
|
145
|
+
# Production MCP mode - minimal logging
|
|
146
|
+
logging.basicConfig(
|
|
147
|
+
level=logging.ERROR,
|
|
148
|
+
format="%(message)s",
|
|
149
|
+
stream=sys.stderr,
|
|
150
|
+
force=True,
|
|
151
|
+
)
|
|
152
|
+
return logging.getLogger("claude_mpm")
|
|
153
|
+
# Test or instructions mode - normal logging
|
|
154
|
+
return setup_logging(args)
|
|
155
|
+
# Normal logging for all other commands
|
|
156
|
+
return setup_logging(args)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def initialize_project_registry():
|
|
160
|
+
"""
|
|
161
|
+
Initialize or update the project registry for the current session.
|
|
162
|
+
|
|
163
|
+
WHY: The project registry tracks all claude-mpm projects and their metadata
|
|
164
|
+
across sessions. This function ensures the current project is properly
|
|
165
|
+
registered and updates session information.
|
|
166
|
+
|
|
167
|
+
DESIGN DECISION: Registry failures are logged but don't prevent startup
|
|
168
|
+
to ensure claude-mpm remains functional even if registry operations fail.
|
|
169
|
+
"""
|
|
170
|
+
try:
|
|
171
|
+
from ..services.project.registry import ProjectRegistry
|
|
172
|
+
|
|
173
|
+
registry = ProjectRegistry()
|
|
174
|
+
registry.get_or_create_project_entry()
|
|
175
|
+
except Exception as e:
|
|
176
|
+
# Import logger here to avoid circular imports
|
|
177
|
+
from ..core.logger import get_logger
|
|
178
|
+
|
|
179
|
+
logger = get_logger("cli")
|
|
180
|
+
logger.debug(f"Failed to initialize project registry: {e}")
|
|
181
|
+
# Continue execution - registry failure shouldn't block startup
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def check_mcp_auto_configuration():
|
|
185
|
+
"""
|
|
186
|
+
Check and potentially auto-configure MCP for pipx installations.
|
|
187
|
+
|
|
188
|
+
WHY: Users installing via pipx should have MCP work out-of-the-box with
|
|
189
|
+
minimal friction. This function offers one-time auto-configuration with
|
|
190
|
+
user consent.
|
|
191
|
+
|
|
192
|
+
DESIGN DECISION: This is blocking but quick - it only runs once and has
|
|
193
|
+
a 10-second timeout. We want to catch users on first run for the best
|
|
194
|
+
experience.
|
|
195
|
+
"""
|
|
196
|
+
try:
|
|
197
|
+
from ..services.mcp_gateway.auto_configure import check_and_configure_mcp
|
|
198
|
+
|
|
199
|
+
# This function handles all the logic:
|
|
200
|
+
# - Checks if already configured
|
|
201
|
+
# - Checks if pipx installation
|
|
202
|
+
# - Checks if already asked before
|
|
203
|
+
# - Prompts user if needed
|
|
204
|
+
# - Configures if user agrees
|
|
205
|
+
check_and_configure_mcp()
|
|
206
|
+
|
|
207
|
+
except Exception as e:
|
|
208
|
+
# Non-critical - log but don't fail
|
|
209
|
+
from ..core.logger import get_logger
|
|
210
|
+
|
|
211
|
+
logger = get_logger("cli")
|
|
212
|
+
logger.debug(f"MCP auto-configuration check failed: {e}")
|
|
213
|
+
|
|
214
|
+
# Skip MCP service fixes for the doctor and configure commands
|
|
215
|
+
# The doctor command performs its own comprehensive MCP service check
|
|
216
|
+
# The configure command allows users to configure which services to enable
|
|
217
|
+
# Running both would cause duplicate checks and log messages (9 seconds apart)
|
|
218
|
+
if len(sys.argv) > 1 and sys.argv[1] in ("doctor", "configure"):
|
|
219
|
+
return
|
|
220
|
+
|
|
221
|
+
# Also ensure MCP services are properly configured in ~/.claude.json
|
|
222
|
+
# This fixes incorrect paths and adds missing services
|
|
223
|
+
try:
|
|
224
|
+
from ..core.logger import get_logger
|
|
225
|
+
from ..services.mcp_config_manager import MCPConfigManager
|
|
226
|
+
|
|
227
|
+
logger = get_logger("cli")
|
|
228
|
+
mcp_manager = MCPConfigManager()
|
|
229
|
+
|
|
230
|
+
# Fix any corrupted installations first
|
|
231
|
+
fix_success, fix_message = mcp_manager.fix_mcp_service_issues()
|
|
232
|
+
if fix_message and "Fixed:" in fix_message:
|
|
233
|
+
logger.info(f"MCP service fixes applied: {fix_message}")
|
|
234
|
+
|
|
235
|
+
# Ensure all services are configured correctly
|
|
236
|
+
config_success, config_message = mcp_manager.ensure_mcp_services_configured()
|
|
237
|
+
if config_message and "Added MCP services" in config_message:
|
|
238
|
+
logger.info(f"MCP services configured: {config_message}")
|
|
239
|
+
|
|
240
|
+
except Exception as e:
|
|
241
|
+
# Non-critical - log but don't fail
|
|
242
|
+
from ..core.logger import get_logger
|
|
243
|
+
|
|
244
|
+
logger = get_logger("cli")
|
|
245
|
+
logger.debug(f"MCP services configuration update failed: {e}")
|
|
246
|
+
|
|
247
|
+
|
|
248
|
+
def verify_mcp_gateway_startup():
|
|
249
|
+
"""
|
|
250
|
+
Verify MCP Gateway configuration on startup and pre-warm MCP services.
|
|
251
|
+
|
|
252
|
+
WHY: The MCP gateway should be automatically configured and verified on startup
|
|
253
|
+
to provide a seamless experience with diagnostic tools, file summarizer, and
|
|
254
|
+
ticket service. Pre-warming MCP services eliminates the 11.9s delay on first use.
|
|
255
|
+
|
|
256
|
+
DESIGN DECISION: This is non-blocking - failures are logged but don't prevent
|
|
257
|
+
startup to ensure claude-mpm remains functional even if MCP gateway has issues.
|
|
258
|
+
"""
|
|
259
|
+
# Quick verification of MCP services installation
|
|
260
|
+
try:
|
|
261
|
+
from ..core.logger import get_logger
|
|
262
|
+
from ..services.mcp_service_verifier import verify_mcp_services_on_startup
|
|
263
|
+
|
|
264
|
+
logger = get_logger("mcp_verify")
|
|
265
|
+
all_ok, message = verify_mcp_services_on_startup()
|
|
266
|
+
if not all_ok:
|
|
267
|
+
logger.warning(message)
|
|
268
|
+
except Exception:
|
|
269
|
+
# Non-critical - continue with startup
|
|
270
|
+
pass
|
|
271
|
+
|
|
272
|
+
try:
|
|
273
|
+
import asyncio
|
|
274
|
+
import time
|
|
275
|
+
|
|
276
|
+
from ..core.logger import get_logger
|
|
277
|
+
from ..services.mcp_gateway.core.startup_verification import (
|
|
278
|
+
is_mcp_gateway_configured,
|
|
279
|
+
verify_mcp_gateway_on_startup,
|
|
280
|
+
)
|
|
281
|
+
|
|
282
|
+
logger = get_logger("mcp_prewarm")
|
|
283
|
+
|
|
284
|
+
# Quick check first - if already configured, skip detailed verification
|
|
285
|
+
gateway_configured = is_mcp_gateway_configured()
|
|
286
|
+
|
|
287
|
+
# DISABLED: Pre-warming MCP servers can interfere with Claude Code's MCP management
|
|
288
|
+
# This was causing issues with MCP server initialization and stderr handling
|
|
289
|
+
# def run_pre_warming():
|
|
290
|
+
# loop = None
|
|
291
|
+
# try:
|
|
292
|
+
# start_time = time.time()
|
|
293
|
+
# loop = asyncio.new_event_loop()
|
|
294
|
+
# asyncio.set_event_loop(loop)
|
|
295
|
+
#
|
|
296
|
+
# # Pre-warm MCP servers (especially vector search)
|
|
297
|
+
# logger.info("Pre-warming MCP servers to eliminate startup delay...")
|
|
298
|
+
# loop.run_until_complete(pre_warm_mcp_servers())
|
|
299
|
+
#
|
|
300
|
+
# pre_warm_time = time.time() - start_time
|
|
301
|
+
# if pre_warm_time > 1.0:
|
|
302
|
+
# logger.info(f"MCP servers pre-warmed in {pre_warm_time:.2f}s")
|
|
303
|
+
|
|
304
|
+
# Dummy function to maintain structure
|
|
305
|
+
def run_pre_warming():
|
|
306
|
+
loop = None
|
|
307
|
+
try:
|
|
308
|
+
time.time()
|
|
309
|
+
loop = asyncio.new_event_loop()
|
|
310
|
+
asyncio.set_event_loop(loop)
|
|
311
|
+
|
|
312
|
+
# Also run gateway verification if needed
|
|
313
|
+
if not gateway_configured:
|
|
314
|
+
loop.run_until_complete(verify_mcp_gateway_on_startup())
|
|
315
|
+
|
|
316
|
+
except Exception as e:
|
|
317
|
+
# Non-blocking - log but don't fail
|
|
318
|
+
logger.debug(f"MCP pre-warming error (non-critical): {e}")
|
|
319
|
+
finally:
|
|
320
|
+
# Properly clean up event loop to prevent kqueue warnings
|
|
321
|
+
if loop is not None:
|
|
322
|
+
try:
|
|
323
|
+
# Cancel all running tasks
|
|
324
|
+
pending = asyncio.all_tasks(loop)
|
|
325
|
+
for task in pending:
|
|
326
|
+
task.cancel()
|
|
327
|
+
# Wait for tasks to complete cancellation
|
|
328
|
+
if pending:
|
|
329
|
+
loop.run_until_complete(
|
|
330
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
331
|
+
)
|
|
332
|
+
except Exception:
|
|
333
|
+
pass # Ignore cleanup errors
|
|
334
|
+
finally:
|
|
335
|
+
loop.close()
|
|
336
|
+
# Clear the event loop reference to help with cleanup
|
|
337
|
+
asyncio.set_event_loop(None)
|
|
338
|
+
|
|
339
|
+
# Run pre-warming in background thread
|
|
340
|
+
import threading
|
|
341
|
+
|
|
342
|
+
pre_warm_thread = threading.Thread(target=run_pre_warming, daemon=True)
|
|
343
|
+
pre_warm_thread.start()
|
|
344
|
+
|
|
345
|
+
return
|
|
346
|
+
|
|
347
|
+
# Run detailed verification in background if not configured
|
|
348
|
+
if not gateway_configured:
|
|
349
|
+
# Note: We don't await this to avoid blocking startup
|
|
350
|
+
def run_verification():
|
|
351
|
+
loop = None
|
|
352
|
+
try:
|
|
353
|
+
loop = asyncio.new_event_loop()
|
|
354
|
+
asyncio.set_event_loop(loop)
|
|
355
|
+
results = loop.run_until_complete(verify_mcp_gateway_on_startup())
|
|
356
|
+
|
|
357
|
+
# Log results but don't block
|
|
358
|
+
from ..core.logger import get_logger
|
|
359
|
+
|
|
360
|
+
logger = get_logger("cli")
|
|
361
|
+
|
|
362
|
+
if results.get("gateway_configured"):
|
|
363
|
+
logger.debug("MCP Gateway verification completed successfully")
|
|
364
|
+
else:
|
|
365
|
+
logger.debug("MCP Gateway verification completed with warnings")
|
|
366
|
+
|
|
367
|
+
except Exception as e:
|
|
368
|
+
from ..core.logger import get_logger
|
|
369
|
+
|
|
370
|
+
logger = get_logger("cli")
|
|
371
|
+
logger.debug(f"MCP Gateway verification failed: {e}")
|
|
372
|
+
finally:
|
|
373
|
+
# Properly clean up event loop to prevent kqueue warnings
|
|
374
|
+
if loop is not None:
|
|
375
|
+
try:
|
|
376
|
+
# Cancel all running tasks
|
|
377
|
+
pending = asyncio.all_tasks(loop)
|
|
378
|
+
for task in pending:
|
|
379
|
+
task.cancel()
|
|
380
|
+
# Wait for tasks to complete cancellation
|
|
381
|
+
if pending:
|
|
382
|
+
loop.run_until_complete(
|
|
383
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
384
|
+
)
|
|
385
|
+
except Exception:
|
|
386
|
+
pass # Ignore cleanup errors
|
|
387
|
+
finally:
|
|
388
|
+
loop.close()
|
|
389
|
+
# Clear the event loop reference to help with cleanup
|
|
390
|
+
asyncio.set_event_loop(None)
|
|
391
|
+
|
|
392
|
+
# Run in background thread to avoid blocking startup
|
|
393
|
+
import threading
|
|
394
|
+
|
|
395
|
+
verification_thread = threading.Thread(target=run_verification, daemon=True)
|
|
396
|
+
verification_thread.start()
|
|
397
|
+
|
|
398
|
+
except Exception as e:
|
|
399
|
+
# Import logger here to avoid circular imports
|
|
400
|
+
from ..core.logger import get_logger
|
|
401
|
+
|
|
402
|
+
logger = get_logger("cli")
|
|
403
|
+
logger.debug(f"Failed to start MCP Gateway verification: {e}")
|
|
404
|
+
# Continue execution - MCP gateway issues shouldn't block startup
|
|
405
|
+
|
|
406
|
+
|
|
407
|
+
def check_for_updates_async():
|
|
408
|
+
"""
|
|
409
|
+
Check for updates in background thread (non-blocking).
|
|
410
|
+
|
|
411
|
+
WHY: Users should be notified of new versions and have an easy way to upgrade
|
|
412
|
+
without manually checking PyPI/npm. This runs asynchronously on startup to avoid
|
|
413
|
+
blocking the CLI.
|
|
414
|
+
|
|
415
|
+
DESIGN DECISION: This is non-blocking and non-critical - failures are logged
|
|
416
|
+
but don't prevent startup. Only runs for pip/pipx/npm installations, skips
|
|
417
|
+
editable/development installations.
|
|
418
|
+
"""
|
|
419
|
+
|
|
420
|
+
def run_update_check():
|
|
421
|
+
"""Inner function to run in background thread."""
|
|
422
|
+
loop = None
|
|
423
|
+
try:
|
|
424
|
+
import asyncio
|
|
425
|
+
|
|
426
|
+
from ..core.logger import get_logger
|
|
427
|
+
from ..services.self_upgrade_service import SelfUpgradeService
|
|
428
|
+
|
|
429
|
+
logger = get_logger("upgrade_check")
|
|
430
|
+
|
|
431
|
+
# Create new event loop for this thread
|
|
432
|
+
loop = asyncio.new_event_loop()
|
|
433
|
+
asyncio.set_event_loop(loop)
|
|
434
|
+
|
|
435
|
+
# Create upgrade service and check for updates
|
|
436
|
+
upgrade_service = SelfUpgradeService()
|
|
437
|
+
|
|
438
|
+
# Skip for editable installs (development mode)
|
|
439
|
+
from ..services.self_upgrade_service import InstallationMethod
|
|
440
|
+
|
|
441
|
+
if upgrade_service.installation_method == InstallationMethod.EDITABLE:
|
|
442
|
+
logger.debug("Skipping version check for editable installation")
|
|
443
|
+
return
|
|
444
|
+
|
|
445
|
+
# Check and prompt for upgrade if available (non-blocking)
|
|
446
|
+
loop.run_until_complete(upgrade_service.check_and_prompt_on_startup())
|
|
447
|
+
|
|
448
|
+
except Exception as e:
|
|
449
|
+
# Non-critical - log but don't fail startup
|
|
450
|
+
try:
|
|
451
|
+
from ..core.logger import get_logger
|
|
452
|
+
|
|
453
|
+
logger = get_logger("upgrade_check")
|
|
454
|
+
logger.debug(f"Update check failed (non-critical): {e}")
|
|
455
|
+
except Exception:
|
|
456
|
+
pass # Avoid any errors in error handling
|
|
457
|
+
finally:
|
|
458
|
+
# Properly clean up event loop
|
|
459
|
+
if loop is not None:
|
|
460
|
+
try:
|
|
461
|
+
# Cancel all running tasks
|
|
462
|
+
pending = asyncio.all_tasks(loop)
|
|
463
|
+
for task in pending:
|
|
464
|
+
task.cancel()
|
|
465
|
+
# Wait for tasks to complete cancellation
|
|
466
|
+
if pending:
|
|
467
|
+
loop.run_until_complete(
|
|
468
|
+
asyncio.gather(*pending, return_exceptions=True)
|
|
469
|
+
)
|
|
470
|
+
except Exception:
|
|
471
|
+
pass # Ignore cleanup errors
|
|
472
|
+
finally:
|
|
473
|
+
loop.close()
|
|
474
|
+
# Clear the event loop reference to help with cleanup
|
|
475
|
+
asyncio.set_event_loop(None)
|
|
476
|
+
|
|
477
|
+
# Run update check in background thread to avoid blocking startup
|
|
478
|
+
import threading
|
|
479
|
+
|
|
480
|
+
update_check_thread = threading.Thread(target=run_update_check, daemon=True)
|
|
481
|
+
update_check_thread.start()
|
claude_mpm/cli/utils.py
CHANGED
|
@@ -6,9 +6,10 @@ Centralizing these functions reduces code duplication and provides a single plac
|
|
|
6
6
|
for common CLI operations.
|
|
7
7
|
"""
|
|
8
8
|
|
|
9
|
+
import difflib
|
|
9
10
|
import sys
|
|
10
11
|
from pathlib import Path
|
|
11
|
-
from typing import Optional
|
|
12
|
+
from typing import List, Optional
|
|
12
13
|
|
|
13
14
|
from ..core.logger import get_logger
|
|
14
15
|
|
|
@@ -207,3 +208,53 @@ def ensure_directories() -> None:
|
|
|
207
208
|
# Continue even if initialization fails
|
|
208
209
|
# The individual commands will handle missing directories as needed
|
|
209
210
|
pass
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def suggest_similar_commands(
|
|
214
|
+
invalid_command: str,
|
|
215
|
+
valid_commands: List[str],
|
|
216
|
+
cutoff: float = 0.6,
|
|
217
|
+
max_suggestions: int = 3,
|
|
218
|
+
) -> Optional[str]:
|
|
219
|
+
"""
|
|
220
|
+
Suggest similar commands for an invalid command using fuzzy matching.
|
|
221
|
+
|
|
222
|
+
WHY: Helps users quickly identify typos and discover correct command names
|
|
223
|
+
by suggesting the most similar valid commands. Uses stdlib difflib for
|
|
224
|
+
zero-dependency fuzzy matching.
|
|
225
|
+
|
|
226
|
+
DESIGN DECISION: Using difflib.get_close_matches provides good results for
|
|
227
|
+
typos and partial matches while being simple and lightweight (no external deps).
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
invalid_command: The invalid command the user typed
|
|
231
|
+
valid_commands: List of valid commands to match against
|
|
232
|
+
cutoff: Similarity threshold (0.0-1.0), default 0.6
|
|
233
|
+
max_suggestions: Maximum number of suggestions to return, default 3
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Formatted suggestion string or None if no good matches found
|
|
237
|
+
|
|
238
|
+
Examples:
|
|
239
|
+
>>> suggest_similar_commands("tickts", ["tickets", "run", "agents"])
|
|
240
|
+
"Did you mean 'tickets'?"
|
|
241
|
+
|
|
242
|
+
>>> suggest_similar_commands("mem", ["memory", "monitor", "mcp"])
|
|
243
|
+
"Did you mean one of these?\n memory\n monitor\n mcp"
|
|
244
|
+
|
|
245
|
+
>>> suggest_similar_commands("xyz", ["tickets", "run"])
|
|
246
|
+
None # No good matches
|
|
247
|
+
"""
|
|
248
|
+
# Use difflib to find close matches
|
|
249
|
+
matches = difflib.get_close_matches(
|
|
250
|
+
invalid_command, valid_commands, n=max_suggestions, cutoff=cutoff
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
if not matches:
|
|
254
|
+
return None
|
|
255
|
+
|
|
256
|
+
# Format suggestion message
|
|
257
|
+
if len(matches) == 1:
|
|
258
|
+
return f"Did you mean '{matches[0]}'?"
|
|
259
|
+
suggestions = "\n ".join(matches)
|
|
260
|
+
return f"Did you mean one of these?\n {suggestions}"
|