claude-mpm 4.0.29__py3-none-any.whl → 4.0.31__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/agents/BASE_AGENT_TEMPLATE.md +48 -3
- claude_mpm/agents/BASE_PM.md +20 -15
- claude_mpm/agents/INSTRUCTIONS.md +12 -2
- claude_mpm/agents/templates/documentation.json +16 -3
- claude_mpm/agents/templates/engineer.json +19 -5
- claude_mpm/agents/templates/ops.json +19 -5
- claude_mpm/agents/templates/qa.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +25 -7
- claude_mpm/agents/templates/research.json +19 -5
- claude_mpm/cli/__init__.py +2 -0
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_manager.py +10 -6
- claude_mpm/cli/commands/agents.py +2 -1
- claude_mpm/cli/commands/cleanup.py +1 -1
- claude_mpm/cli/commands/doctor.py +209 -0
- claude_mpm/cli/commands/mcp.py +3 -3
- claude_mpm/cli/commands/mcp_install_commands.py +12 -30
- claude_mpm/cli/commands/mcp_server_commands.py +9 -9
- claude_mpm/cli/commands/run.py +31 -2
- claude_mpm/cli/commands/run_config_checker.py +1 -1
- claude_mpm/cli/parsers/agent_manager_parser.py +3 -3
- claude_mpm/cli/parsers/base_parser.py +5 -1
- claude_mpm/cli/parsers/mcp_parser.py +1 -1
- claude_mpm/cli/parsers/run_parser.py +1 -1
- claude_mpm/cli/startup_logging.py +463 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/claude_runner.py +78 -0
- claude_mpm/core/framework_loader.py +45 -11
- claude_mpm/core/interactive_session.py +82 -3
- claude_mpm/core/output_style_manager.py +6 -6
- claude_mpm/core/unified_paths.py +128 -0
- claude_mpm/scripts/mcp_server.py +2 -2
- claude_mpm/services/agents/deployment/agent_validator.py +1 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +69 -1
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +2 -2
- claude_mpm/services/diagnostics/__init__.py +18 -0
- claude_mpm/services/diagnostics/checks/__init__.py +30 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +319 -0
- claude_mpm/services/diagnostics/checks/base_check.py +64 -0
- claude_mpm/services/diagnostics/checks/claude_desktop_check.py +283 -0
- claude_mpm/services/diagnostics/checks/common_issues_check.py +354 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +300 -0
- claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +255 -0
- claude_mpm/services/diagnostics/checks/mcp_check.py +315 -0
- claude_mpm/services/diagnostics/checks/monitor_check.py +282 -0
- claude_mpm/services/diagnostics/checks/startup_log_check.py +322 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +247 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +283 -0
- claude_mpm/services/diagnostics/models.py +120 -0
- claude_mpm/services/mcp_gateway/core/interfaces.py +1 -1
- claude_mpm/services/mcp_gateway/main.py +1 -1
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +3 -3
- claude_mpm/services/mcp_gateway/server/stdio_handler.py +1 -1
- claude_mpm/services/mcp_gateway/server/stdio_server.py +3 -3
- claude_mpm/services/mcp_gateway/tools/ticket_tools.py +2 -2
- claude_mpm/services/socketio/handlers/registry.py +39 -7
- claude_mpm/services/socketio/server/core.py +72 -22
- claude_mpm/validation/frontmatter_validator.py +1 -1
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/METADATA +4 -1
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/RECORD +65 -48
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/WHEEL +0 -0
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.0.29.dist-info → claude_mpm-4.0.31.dist-info}/top_level.txt +0 -0
|
@@ -206,7 +206,7 @@ class InteractiveSession:
|
|
|
206
206
|
return self._attempt_fallback_launch(environment)
|
|
207
207
|
|
|
208
208
|
def process_interactive_command(self, prompt: str) -> Optional[bool]:
|
|
209
|
-
"""Process special interactive commands like /agents.
|
|
209
|
+
"""Process special interactive commands like /agents and /mpm-doctor.
|
|
210
210
|
|
|
211
211
|
Args:
|
|
212
212
|
prompt: User input command
|
|
@@ -214,9 +214,19 @@ class InteractiveSession:
|
|
|
214
214
|
Returns:
|
|
215
215
|
Optional[bool]: True if handled, False if error, None if not a special command
|
|
216
216
|
"""
|
|
217
|
+
# Parse command and arguments
|
|
218
|
+
parts = prompt.strip().split()
|
|
219
|
+
if not parts:
|
|
220
|
+
return None
|
|
221
|
+
|
|
222
|
+
command = parts[0]
|
|
223
|
+
args = parts[1:]
|
|
224
|
+
|
|
217
225
|
# Check for special commands
|
|
218
|
-
if
|
|
226
|
+
if command == "/agents":
|
|
219
227
|
return self._show_available_agents()
|
|
228
|
+
elif command == "/mpm-doctor":
|
|
229
|
+
return self._run_doctor_diagnostics(args)
|
|
220
230
|
|
|
221
231
|
# Not a special command
|
|
222
232
|
return None
|
|
@@ -310,7 +320,13 @@ class InteractiveSession:
|
|
|
310
320
|
print(f"\033[32m│\033[0m {output_style_info:<49}\033[32m│\033[0m")
|
|
311
321
|
print("\033[32m│ │\033[0m")
|
|
312
322
|
print(
|
|
313
|
-
"\033[32m│\033[0m
|
|
323
|
+
"\033[32m│\033[0m Commands: \033[32m│\033[0m"
|
|
324
|
+
)
|
|
325
|
+
print(
|
|
326
|
+
"\033[32m│\033[0m /agents - Show available agents \033[32m│\033[0m"
|
|
327
|
+
)
|
|
328
|
+
print(
|
|
329
|
+
"\033[32m│\033[0m /mpm-doctor - Run diagnostic checks \033[32m│\033[0m"
|
|
314
330
|
)
|
|
315
331
|
print("\033[32m╰───────────────────────────────────────────────────╯\033[0m")
|
|
316
332
|
print("") # Add blank line after box
|
|
@@ -552,3 +568,66 @@ class InteractiveSession:
|
|
|
552
568
|
except Exception as e:
|
|
553
569
|
print(f"Error getting agent versions: {e}")
|
|
554
570
|
return False
|
|
571
|
+
|
|
572
|
+
def _run_doctor_diagnostics(self, args: list) -> bool:
|
|
573
|
+
"""Run doctor diagnostics from interactive mode.
|
|
574
|
+
|
|
575
|
+
Args:
|
|
576
|
+
args: Command arguments (e.g., ['--verbose'])
|
|
577
|
+
|
|
578
|
+
Returns:
|
|
579
|
+
bool: True if successful, False otherwise
|
|
580
|
+
"""
|
|
581
|
+
try:
|
|
582
|
+
from claude_mpm.services.diagnostics import DiagnosticRunner, DoctorReporter
|
|
583
|
+
|
|
584
|
+
# Parse arguments
|
|
585
|
+
verbose = "--verbose" in args or "-v" in args
|
|
586
|
+
no_color = "--no-color" in args
|
|
587
|
+
|
|
588
|
+
# Print header
|
|
589
|
+
print("\n" + "="*60)
|
|
590
|
+
print("Claude MPM Doctor Report")
|
|
591
|
+
print("="*60)
|
|
592
|
+
|
|
593
|
+
# Create diagnostic runner
|
|
594
|
+
runner = DiagnosticRunner(verbose=verbose)
|
|
595
|
+
|
|
596
|
+
# Run diagnostics
|
|
597
|
+
try:
|
|
598
|
+
summary = runner.run_diagnostics()
|
|
599
|
+
except KeyboardInterrupt:
|
|
600
|
+
print("\nDiagnostics interrupted by user")
|
|
601
|
+
return False
|
|
602
|
+
except Exception as e:
|
|
603
|
+
print(f"\n❌ Diagnostic failed: {str(e)}")
|
|
604
|
+
if verbose:
|
|
605
|
+
import traceback
|
|
606
|
+
traceback.print_exc()
|
|
607
|
+
return False
|
|
608
|
+
|
|
609
|
+
# Create reporter
|
|
610
|
+
reporter = DoctorReporter(
|
|
611
|
+
use_color=not no_color,
|
|
612
|
+
verbose=verbose
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
# Display results in terminal format
|
|
616
|
+
reporter.report(summary, format="terminal")
|
|
617
|
+
|
|
618
|
+
# Return based on status
|
|
619
|
+
if summary.error_count > 0:
|
|
620
|
+
return False
|
|
621
|
+
|
|
622
|
+
return True
|
|
623
|
+
|
|
624
|
+
except ImportError as e:
|
|
625
|
+
print(f"Error: Diagnostics module not available: {e}")
|
|
626
|
+
print("Please ensure claude-mpm is properly installed")
|
|
627
|
+
return False
|
|
628
|
+
except Exception as e:
|
|
629
|
+
print(f"Error running diagnostics: {e}")
|
|
630
|
+
if "--verbose" in args or "-v" in args:
|
|
631
|
+
import traceback
|
|
632
|
+
traceback.print_exc()
|
|
633
|
+
return False
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
This module handles:
|
|
4
4
|
1. Claude version detection
|
|
5
5
|
2. Output style extraction from framework instructions
|
|
6
|
-
3. One-time deployment to Claude
|
|
6
|
+
3. One-time deployment to Claude Code >= 1.0.83 at startup
|
|
7
7
|
4. Fallback injection for older versions
|
|
8
8
|
|
|
9
9
|
The output style is set once at startup and not monitored or enforced after that.
|
|
@@ -41,7 +41,7 @@ class OutputStyleManager:
|
|
|
41
41
|
|
|
42
42
|
def _detect_claude_version(self) -> Optional[str]:
|
|
43
43
|
"""
|
|
44
|
-
Detect Claude
|
|
44
|
+
Detect Claude Code version by running 'claude --version'.
|
|
45
45
|
|
|
46
46
|
Returns:
|
|
47
47
|
Version string (e.g., "1.0.82") or None if Claude not found
|
|
@@ -73,7 +73,7 @@ class OutputStyleManager:
|
|
|
73
73
|
return None
|
|
74
74
|
|
|
75
75
|
except FileNotFoundError:
|
|
76
|
-
self.logger.info("Claude
|
|
76
|
+
self.logger.info("Claude Code not found in PATH")
|
|
77
77
|
return None
|
|
78
78
|
except subprocess.TimeoutExpired:
|
|
79
79
|
self.logger.warning("Claude version check timed out")
|
|
@@ -116,7 +116,7 @@ class OutputStyleManager:
|
|
|
116
116
|
|
|
117
117
|
def supports_output_styles(self) -> bool:
|
|
118
118
|
"""
|
|
119
|
-
Check if Claude
|
|
119
|
+
Check if Claude Code supports output styles (>= 1.0.83).
|
|
120
120
|
|
|
121
121
|
Returns:
|
|
122
122
|
True if Claude version >= 1.0.83, False otherwise
|
|
@@ -324,7 +324,7 @@ class OutputStyleManager:
|
|
|
324
324
|
|
|
325
325
|
def deploy_output_style(self, content: str) -> bool:
|
|
326
326
|
"""
|
|
327
|
-
Deploy output style to Claude
|
|
327
|
+
Deploy output style to Claude Code if version >= 1.0.83.
|
|
328
328
|
Deploys the style file and activates it once.
|
|
329
329
|
|
|
330
330
|
Args:
|
|
@@ -356,7 +356,7 @@ class OutputStyleManager:
|
|
|
356
356
|
|
|
357
357
|
def _activate_output_style(self) -> bool:
|
|
358
358
|
"""
|
|
359
|
-
Update Claude
|
|
359
|
+
Update Claude Code settings to activate the claude-mpm output style.
|
|
360
360
|
Sets activeOutputStyle to "claude-mpm" once at startup.
|
|
361
361
|
|
|
362
362
|
Returns:
|
claude_mpm/core/unified_paths.py
CHANGED
|
@@ -641,6 +641,128 @@ class UnifiedPathManager:
|
|
|
641
641
|
if src_dir.exists() and str(src_dir) not in sys.path:
|
|
642
642
|
sys.path.insert(0, str(src_dir))
|
|
643
643
|
|
|
644
|
+
def get_executable_path(self) -> Optional[Path]:
|
|
645
|
+
"""Get the path to the claude-mpm executable for the current deployment context.
|
|
646
|
+
|
|
647
|
+
This method provides deployment-context-aware executable path detection,
|
|
648
|
+
particularly useful for MCP server configuration.
|
|
649
|
+
|
|
650
|
+
Returns:
|
|
651
|
+
Path to executable or None if not found
|
|
652
|
+
"""
|
|
653
|
+
import shutil
|
|
654
|
+
|
|
655
|
+
# Try standard which first
|
|
656
|
+
which_result = shutil.which("claude-mpm")
|
|
657
|
+
if which_result:
|
|
658
|
+
return Path(which_result)
|
|
659
|
+
|
|
660
|
+
# Enhanced detection based on deployment context
|
|
661
|
+
if self._deployment_context == DeploymentContext.PIPX_INSTALL:
|
|
662
|
+
return self._find_pipx_executable()
|
|
663
|
+
elif self._deployment_context in (DeploymentContext.DEVELOPMENT, DeploymentContext.EDITABLE_INSTALL):
|
|
664
|
+
return self._find_development_executable()
|
|
665
|
+
elif self._deployment_context == DeploymentContext.PIP_INSTALL:
|
|
666
|
+
return self._find_pip_executable()
|
|
667
|
+
|
|
668
|
+
return None
|
|
669
|
+
|
|
670
|
+
def _find_pipx_executable(self) -> Optional[Path]:
|
|
671
|
+
"""Find claude-mpm executable in pipx installation."""
|
|
672
|
+
try:
|
|
673
|
+
import claude_mpm
|
|
674
|
+
module_path = Path(claude_mpm.__file__).parent
|
|
675
|
+
|
|
676
|
+
if "pipx" not in str(module_path):
|
|
677
|
+
return None
|
|
678
|
+
|
|
679
|
+
# Common pipx executable locations
|
|
680
|
+
home = Path.home()
|
|
681
|
+
pipx_paths = [
|
|
682
|
+
home / ".local" / "bin" / "claude-mpm",
|
|
683
|
+
home / ".local" / "share" / "pipx" / "venvs" / "claude-mpm" / "bin" / "claude-mpm",
|
|
684
|
+
]
|
|
685
|
+
|
|
686
|
+
# Windows paths
|
|
687
|
+
if sys.platform == "win32":
|
|
688
|
+
pipx_paths.extend([
|
|
689
|
+
home / "AppData" / "Local" / "pipx" / "bin" / "claude-mpm.exe",
|
|
690
|
+
home / ".local" / "bin" / "claude-mpm.exe",
|
|
691
|
+
])
|
|
692
|
+
|
|
693
|
+
for path in pipx_paths:
|
|
694
|
+
if path.exists():
|
|
695
|
+
logger.debug(f"Found pipx executable: {path}")
|
|
696
|
+
return path
|
|
697
|
+
|
|
698
|
+
# Try to derive from module path
|
|
699
|
+
# Navigate up from module to find venv, then to bin
|
|
700
|
+
venv_path = module_path
|
|
701
|
+
for _ in range(5): # Prevent infinite loops
|
|
702
|
+
if venv_path.name == "claude-mpm" and (venv_path / "pyvenv.cfg").exists():
|
|
703
|
+
# Found the venv directory
|
|
704
|
+
bin_dir = venv_path / ("Scripts" if sys.platform == "win32" else "bin")
|
|
705
|
+
exe_name = "claude-mpm.exe" if sys.platform == "win32" else "claude-mpm"
|
|
706
|
+
exe_path = bin_dir / exe_name
|
|
707
|
+
|
|
708
|
+
if exe_path.exists():
|
|
709
|
+
logger.debug(f"Found pipx executable via module path: {exe_path}")
|
|
710
|
+
return exe_path
|
|
711
|
+
break
|
|
712
|
+
|
|
713
|
+
if venv_path == venv_path.parent:
|
|
714
|
+
break
|
|
715
|
+
venv_path = venv_path.parent
|
|
716
|
+
|
|
717
|
+
except Exception as e:
|
|
718
|
+
logger.debug(f"Error finding pipx executable: {e}")
|
|
719
|
+
|
|
720
|
+
return None
|
|
721
|
+
|
|
722
|
+
def _find_development_executable(self) -> Optional[Path]:
|
|
723
|
+
"""Find claude-mpm executable in development installation."""
|
|
724
|
+
# For development, prefer the script in the project
|
|
725
|
+
scripts_dir = self.get_scripts_dir()
|
|
726
|
+
dev_executable = scripts_dir / "claude-mpm"
|
|
727
|
+
|
|
728
|
+
if dev_executable.exists():
|
|
729
|
+
return dev_executable
|
|
730
|
+
|
|
731
|
+
# Check if we're in a development venv
|
|
732
|
+
if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
|
|
733
|
+
venv_bin = Path(sys.prefix) / ("Scripts" if sys.platform == "win32" else "bin")
|
|
734
|
+
venv_executable = venv_bin / "claude-mpm"
|
|
735
|
+
if venv_executable.exists():
|
|
736
|
+
return venv_executable
|
|
737
|
+
|
|
738
|
+
return None
|
|
739
|
+
|
|
740
|
+
def _find_pip_executable(self) -> Optional[Path]:
|
|
741
|
+
"""Find claude-mpm executable in pip installation."""
|
|
742
|
+
# For pip installs, check the current Python environment
|
|
743
|
+
if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix):
|
|
744
|
+
# In a virtual environment
|
|
745
|
+
venv_bin = Path(sys.prefix) / ("Scripts" if sys.platform == "win32" else "bin")
|
|
746
|
+
venv_executable = venv_bin / "claude-mpm"
|
|
747
|
+
if venv_executable.exists():
|
|
748
|
+
return venv_executable
|
|
749
|
+
|
|
750
|
+
# Check system-wide installation
|
|
751
|
+
try:
|
|
752
|
+
import site
|
|
753
|
+
for site_dir in site.getsitepackages():
|
|
754
|
+
# Look for installed scripts
|
|
755
|
+
site_path = Path(site_dir)
|
|
756
|
+
scripts_dir = site_path.parent / ("Scripts" if sys.platform == "win32" else "bin")
|
|
757
|
+
if scripts_dir.exists():
|
|
758
|
+
exe_path = scripts_dir / "claude-mpm"
|
|
759
|
+
if exe_path.exists():
|
|
760
|
+
return exe_path
|
|
761
|
+
except Exception as e:
|
|
762
|
+
logger.debug(f"Error finding pip executable: {e}")
|
|
763
|
+
|
|
764
|
+
return None
|
|
765
|
+
|
|
644
766
|
|
|
645
767
|
# ============================================================================
|
|
646
768
|
# Singleton Instance and Convenience Functions
|
|
@@ -701,6 +823,11 @@ def get_package_resource_path(resource_path: str) -> Path:
|
|
|
701
823
|
return get_path_manager().get_package_resource_path(resource_path)
|
|
702
824
|
|
|
703
825
|
|
|
826
|
+
def get_executable_path() -> Optional[Path]:
|
|
827
|
+
"""Get the claude-mpm executable path for the current deployment context."""
|
|
828
|
+
return get_path_manager().get_executable_path()
|
|
829
|
+
|
|
830
|
+
|
|
704
831
|
# ============================================================================
|
|
705
832
|
# Export All Public Symbols
|
|
706
833
|
# ============================================================================
|
|
@@ -719,4 +846,5 @@ __all__ = [
|
|
|
719
846
|
"get_config_dir",
|
|
720
847
|
"find_file_upwards",
|
|
721
848
|
"get_package_resource_path",
|
|
849
|
+
"get_executable_path",
|
|
722
850
|
]
|
claude_mpm/scripts/mcp_server.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""MCP Server launcher script for Claude
|
|
2
|
+
"""MCP Server launcher script for Claude Code.
|
|
3
3
|
|
|
4
|
-
This script launches the MCP gateway server for Claude
|
|
4
|
+
This script launches the MCP gateway server for Claude Code integration.
|
|
5
5
|
It handles proper Python path setup and error reporting to stderr.
|
|
6
6
|
"""
|
|
7
7
|
|
|
@@ -363,6 +363,10 @@ class MultiSourceAgentDeploymentService:
|
|
|
363
363
|
source_match = re.search(r'^source:\s*(.+)$', deployed_content, re.MULTILINE)
|
|
364
364
|
if source_match:
|
|
365
365
|
deployed_source = source_match.group(1).strip()
|
|
366
|
+
|
|
367
|
+
# If source is still unknown, try to infer it from deployment context
|
|
368
|
+
if deployed_source == "unknown":
|
|
369
|
+
deployed_source = self._infer_agent_source_from_context(agent_name, deployed_agents_dir)
|
|
366
370
|
except Exception as e:
|
|
367
371
|
self.logger.warning(f"Error reading deployed agent '{agent_name}': {e}")
|
|
368
372
|
comparison_results["needs_update"].append(agent_name)
|
|
@@ -438,4 +442,68 @@ class MultiSourceAgentDeploymentService:
|
|
|
438
442
|
f"{downgrade['template_version']}"
|
|
439
443
|
)
|
|
440
444
|
|
|
441
|
-
return comparison_results
|
|
445
|
+
return comparison_results
|
|
446
|
+
|
|
447
|
+
def _infer_agent_source_from_context(self, agent_name: str, deployed_agents_dir: Path) -> str:
|
|
448
|
+
"""Infer the source of a deployed agent when source metadata is missing.
|
|
449
|
+
|
|
450
|
+
This method attempts to determine the agent source based on:
|
|
451
|
+
1. Deployment context (development vs pipx)
|
|
452
|
+
2. Agent naming patterns
|
|
453
|
+
3. Known system agents
|
|
454
|
+
|
|
455
|
+
Args:
|
|
456
|
+
agent_name: Name of the agent
|
|
457
|
+
deployed_agents_dir: Directory where agent is deployed
|
|
458
|
+
|
|
459
|
+
Returns:
|
|
460
|
+
Inferred source string (system/project/user)
|
|
461
|
+
"""
|
|
462
|
+
# List of known system agents that ship with claude-mpm
|
|
463
|
+
system_agents = {
|
|
464
|
+
"pm", "engineer", "qa", "research", "documentation", "ops",
|
|
465
|
+
"security", "web-ui", "api-qa", "version-control"
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
# If this is a known system agent, it's from system
|
|
469
|
+
if agent_name in system_agents:
|
|
470
|
+
return "system"
|
|
471
|
+
|
|
472
|
+
# Check deployment context
|
|
473
|
+
from ....core.unified_paths import get_path_manager
|
|
474
|
+
path_manager = get_path_manager()
|
|
475
|
+
|
|
476
|
+
# If deployed_agents_dir is under user home/.claude/agents, check context
|
|
477
|
+
user_claude_dir = Path.home() / ".claude" / "agents"
|
|
478
|
+
if deployed_agents_dir == user_claude_dir:
|
|
479
|
+
# Check if we're in development mode
|
|
480
|
+
try:
|
|
481
|
+
from ....core.unified_paths import DeploymentContext, PathContext
|
|
482
|
+
deployment_context = PathContext.detect_deployment_context()
|
|
483
|
+
|
|
484
|
+
if deployment_context in (DeploymentContext.DEVELOPMENT, DeploymentContext.EDITABLE_INSTALL):
|
|
485
|
+
# In development mode, unknown agents are likely system agents being tested
|
|
486
|
+
return "system"
|
|
487
|
+
elif deployment_context == DeploymentContext.PIPX_INSTALL:
|
|
488
|
+
# In pipx mode, unknown agents could be system agents
|
|
489
|
+
# Check if agent follows system naming patterns
|
|
490
|
+
if agent_name.count('-') <= 2 and len(agent_name) <= 20:
|
|
491
|
+
return "system"
|
|
492
|
+
except Exception:
|
|
493
|
+
pass
|
|
494
|
+
|
|
495
|
+
# Check if deployed to project-specific directory
|
|
496
|
+
try:
|
|
497
|
+
project_root = path_manager.project_root
|
|
498
|
+
if str(deployed_agents_dir).startswith(str(project_root)):
|
|
499
|
+
return "project"
|
|
500
|
+
except Exception:
|
|
501
|
+
pass
|
|
502
|
+
|
|
503
|
+
# Default inference based on naming patterns
|
|
504
|
+
# System agents typically have simple names
|
|
505
|
+
if '-' not in agent_name or agent_name.count('-') <= 1:
|
|
506
|
+
return "system"
|
|
507
|
+
|
|
508
|
+
# Complex names are more likely to be user/project agents
|
|
509
|
+
return "user"
|
|
@@ -53,8 +53,8 @@ class SystemInstructionsDeployer:
|
|
|
53
53
|
framework_files = [
|
|
54
54
|
(
|
|
55
55
|
"INSTRUCTIONS.md",
|
|
56
|
-
"
|
|
57
|
-
), # INSTRUCTIONS.md
|
|
56
|
+
"INSTRUCTIONS.md",
|
|
57
|
+
), # Keep INSTRUCTIONS.md as is - NEVER rename to CLAUDE.md
|
|
58
58
|
("WORKFLOW.md", "WORKFLOW.md"),
|
|
59
59
|
("MEMORY.md", "MEMORY.md"),
|
|
60
60
|
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Diagnostic service for claude-mpm health checks.
|
|
3
|
+
|
|
4
|
+
WHY: Provide a comprehensive diagnostic tool to help users identify and fix
|
|
5
|
+
common issues with their claude-mpm installation and configuration.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISIONS:
|
|
8
|
+
- Modular check system for easy extension
|
|
9
|
+
- Interface-based design for consistency
|
|
10
|
+
- Clear status levels (ok, warning, error)
|
|
11
|
+
- Actionable fix suggestions
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from .diagnostic_runner import DiagnosticRunner
|
|
15
|
+
from .doctor_reporter import DoctorReporter
|
|
16
|
+
from .models import DiagnosticResult, DiagnosticStatus
|
|
17
|
+
|
|
18
|
+
__all__ = ["DiagnosticRunner", "DoctorReporter", "DiagnosticResult", "DiagnosticStatus"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Diagnostic checks for claude-mpm doctor command.
|
|
3
|
+
|
|
4
|
+
WHY: Modular checks allow for easy extension and testing of individual
|
|
5
|
+
diagnostic components.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .agent_check import AgentCheck
|
|
9
|
+
from .base_check import BaseDiagnosticCheck
|
|
10
|
+
from .claude_desktop_check import ClaudeDesktopCheck
|
|
11
|
+
from .common_issues_check import CommonIssuesCheck
|
|
12
|
+
from .configuration_check import ConfigurationCheck
|
|
13
|
+
from .filesystem_check import FilesystemCheck
|
|
14
|
+
from .installation_check import InstallationCheck
|
|
15
|
+
from .mcp_check import MCPCheck
|
|
16
|
+
from .monitor_check import MonitorCheck
|
|
17
|
+
from .startup_log_check import StartupLogCheck
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"BaseDiagnosticCheck",
|
|
21
|
+
"InstallationCheck",
|
|
22
|
+
"ConfigurationCheck",
|
|
23
|
+
"ClaudeDesktopCheck",
|
|
24
|
+
"AgentCheck",
|
|
25
|
+
"MCPCheck",
|
|
26
|
+
"MonitorCheck",
|
|
27
|
+
"FilesystemCheck",
|
|
28
|
+
"CommonIssuesCheck",
|
|
29
|
+
"StartupLogCheck",
|
|
30
|
+
]
|