claude-mpm 4.13.2__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_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +48 -17
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +227 -8
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/agentic-coder-optimizer.json +9 -2
- claude_mpm/agents/templates/api_qa.json +7 -1
- claude_mpm/agents/templates/clerk-ops.json +8 -1
- claude_mpm/agents/templates/code_analyzer.json +4 -1
- claude_mpm/agents/templates/dart_engineer.json +11 -1
- claude_mpm/agents/templates/data_engineer.json +11 -1
- claude_mpm/agents/templates/documentation.json +6 -1
- claude_mpm/agents/templates/engineer.json +18 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +8 -1
- claude_mpm/agents/templates/golang_engineer.json +11 -1
- claude_mpm/agents/templates/java_engineer.json +12 -2
- claude_mpm/agents/templates/local_ops_agent.json +1217 -6
- claude_mpm/agents/templates/nextjs_engineer.json +11 -1
- claude_mpm/agents/templates/ops.json +8 -1
- claude_mpm/agents/templates/php-engineer.json +11 -1
- claude_mpm/agents/templates/project_organizer.json +10 -3
- claude_mpm/agents/templates/prompt-engineer.json +5 -1
- claude_mpm/agents/templates/python_engineer.json +11 -1
- claude_mpm/agents/templates/qa.json +7 -1
- claude_mpm/agents/templates/react_engineer.json +11 -1
- claude_mpm/agents/templates/refactoring_engineer.json +8 -1
- claude_mpm/agents/templates/research.json +4 -1
- claude_mpm/agents/templates/ruby-engineer.json +11 -1
- claude_mpm/agents/templates/rust_engineer.json +11 -1
- claude_mpm/agents/templates/security.json +6 -1
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +6 -1
- claude_mpm/agents/templates/typescript_engineer.json +11 -1
- claude_mpm/agents/templates/vercel_ops_agent.json +8 -1
- claude_mpm/agents/templates/version_control.json +8 -1
- claude_mpm/agents/templates/web_qa.json +7 -1
- claude_mpm/agents/templates/web_ui.json +11 -1
- claude_mpm/cli/__init__.py +34 -706
- 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 +204 -148
- 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 +7 -9
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +294 -1788
- 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 +39 -25
- claude_mpm/cli/commands/mpm_init_handler.py +8 -3
- 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/base_parser.py +98 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- 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-help.md +3 -0
- 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/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/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/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/auto_config_manager.py +10 -11
- 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/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/interfaces/__init__.py +74 -2
- 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/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/models/__init__.py +33 -0
- claude_mpm/services/core/models/agent_config.py +12 -28
- 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/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 +36 -31
- 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/tools/external_mcp_services.py +71 -24
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/memory_hook_service.py +4 -1
- 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/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/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +2 -2
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/METADATA +117 -8
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/RECORD +238 -174
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- 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.13.2.dist-info → claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.13.2.dist-info → claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""Data models for configure command.
|
|
2
|
+
|
|
3
|
+
This module contains data classes used by the configure command for
|
|
4
|
+
agent metadata and configuration state management.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import List, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AgentConfig:
|
|
11
|
+
"""Simple agent configuration model."""
|
|
12
|
+
|
|
13
|
+
def __init__(
|
|
14
|
+
self, name: str, description: str = "", dependencies: Optional[List[str]] = None
|
|
15
|
+
):
|
|
16
|
+
self.name = name
|
|
17
|
+
self.description = description
|
|
18
|
+
self.dependencies = dependencies or []
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""Navigation and scope management for configure command.
|
|
2
|
+
|
|
3
|
+
WHY: Separate navigation, scope switching, and menu display logic from main
|
|
4
|
+
configure command to improve modularity. This handles the TUI interface
|
|
5
|
+
elements that guide users through the configuration system.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISIONS:
|
|
8
|
+
- Display header with version and scope info
|
|
9
|
+
- Main menu with numbered options and descriptions
|
|
10
|
+
- Scope switching between project and user configurations
|
|
11
|
+
- Launch integration to transition to Claude MPM run
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import os
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
|
|
17
|
+
from rich.box import ROUNDED
|
|
18
|
+
from rich.columns import Columns
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.panel import Panel
|
|
21
|
+
from rich.prompt import Prompt
|
|
22
|
+
from rich.table import Table
|
|
23
|
+
from rich.text import Text
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ConfigNavigation:
|
|
27
|
+
"""Handle scope switching and navigation for configure command.
|
|
28
|
+
|
|
29
|
+
This class manages:
|
|
30
|
+
- Header display with version and scope information
|
|
31
|
+
- Main menu rendering with options
|
|
32
|
+
- Scope switching (project ↔ user)
|
|
33
|
+
- Claude MPM launch integration
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
def __init__(self, console: Console, project_dir: Path):
|
|
37
|
+
"""Initialize navigation handler.
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
console: Rich console for output
|
|
41
|
+
project_dir: Current project directory
|
|
42
|
+
"""
|
|
43
|
+
self.console = console
|
|
44
|
+
self.project_dir = project_dir
|
|
45
|
+
self.current_scope = "project"
|
|
46
|
+
|
|
47
|
+
def display_header(self) -> None:
|
|
48
|
+
"""Display the TUI header with version and scope information.
|
|
49
|
+
|
|
50
|
+
Shows:
|
|
51
|
+
- Claude MPM branding and version
|
|
52
|
+
- Current configuration scope (project/user)
|
|
53
|
+
- Working directory
|
|
54
|
+
"""
|
|
55
|
+
self.console.clear()
|
|
56
|
+
|
|
57
|
+
# Get version for display
|
|
58
|
+
from claude_mpm import __version__
|
|
59
|
+
|
|
60
|
+
# Create header panel
|
|
61
|
+
header_text = Text()
|
|
62
|
+
header_text.append("Claude MPM ", style="bold blue")
|
|
63
|
+
header_text.append("Configuration Interface", style="bold")
|
|
64
|
+
header_text.append(f"\nv{__version__}", style="dim blue")
|
|
65
|
+
|
|
66
|
+
scope_text = Text(f"Scope: {self.current_scope.upper()}", style="bold blue")
|
|
67
|
+
dir_text = Text(f"Directory: {self.project_dir}", style="dim")
|
|
68
|
+
|
|
69
|
+
header_content = Columns([header_text], align="center")
|
|
70
|
+
subtitle_content = f"{scope_text} | {dir_text}"
|
|
71
|
+
|
|
72
|
+
header_panel = Panel(
|
|
73
|
+
header_content,
|
|
74
|
+
subtitle=subtitle_content,
|
|
75
|
+
box=ROUNDED,
|
|
76
|
+
style="blue",
|
|
77
|
+
padding=(1, 2),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
self.console.print(header_panel)
|
|
81
|
+
self.console.print()
|
|
82
|
+
|
|
83
|
+
def show_main_menu(self) -> str:
|
|
84
|
+
"""Show the main menu and get user choice.
|
|
85
|
+
|
|
86
|
+
Displays main configuration menu with options:
|
|
87
|
+
1. Agent Management
|
|
88
|
+
2. Skills Management
|
|
89
|
+
3. Template Editing
|
|
90
|
+
4. Behavior Files
|
|
91
|
+
5. Startup Configuration
|
|
92
|
+
6. Switch Scope
|
|
93
|
+
7. Version Info
|
|
94
|
+
l. Save & Launch
|
|
95
|
+
q. Quit
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
User's menu choice (lowercase, stripped)
|
|
99
|
+
"""
|
|
100
|
+
menu_items = [
|
|
101
|
+
("1", "Agent Management", "Enable/disable agents and customize settings"),
|
|
102
|
+
("2", "Skills Management", "Configure skills for agents"),
|
|
103
|
+
("3", "Template Editing", "Edit agent JSON templates"),
|
|
104
|
+
("4", "Behavior Files", "Manage identity and workflow configurations"),
|
|
105
|
+
(
|
|
106
|
+
"5",
|
|
107
|
+
"Startup Configuration",
|
|
108
|
+
"Configure MCP services and agents to start",
|
|
109
|
+
),
|
|
110
|
+
("6", "Switch Scope", f"Current: {self.current_scope}"),
|
|
111
|
+
("7", "Version Info", "Display MPM and Claude versions"),
|
|
112
|
+
("l", "Save & Launch", "Save all changes and start Claude MPM"),
|
|
113
|
+
("q", "Quit", "Exit without launching"),
|
|
114
|
+
]
|
|
115
|
+
|
|
116
|
+
table = Table(show_header=False, box=None, padding=(0, 2))
|
|
117
|
+
table.add_column("Key", style="bold blue", width=4) # Bolder shortcuts
|
|
118
|
+
table.add_column("Option", style="bold", width=24) # Wider for titles
|
|
119
|
+
table.add_column("Description", style="") # Use default terminal color
|
|
120
|
+
|
|
121
|
+
for key, option, desc in menu_items:
|
|
122
|
+
table.add_row(f"\\[{key}]", option, desc)
|
|
123
|
+
|
|
124
|
+
menu_panel = Panel(
|
|
125
|
+
table, title="[bold]Main Menu[/bold]", box=ROUNDED, style="green"
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
self.console.print(menu_panel)
|
|
129
|
+
self.console.print()
|
|
130
|
+
|
|
131
|
+
choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="q")
|
|
132
|
+
# Strip whitespace to handle leading/trailing spaces
|
|
133
|
+
return choice.strip().lower()
|
|
134
|
+
|
|
135
|
+
def switch_scope(self) -> None:
|
|
136
|
+
"""Switch between project and user scope.
|
|
137
|
+
|
|
138
|
+
Toggles current_scope between:
|
|
139
|
+
- "project": Project-level configuration (.claude-mpm in project dir)
|
|
140
|
+
- "user": User-level configuration (.claude-mpm in home dir)
|
|
141
|
+
"""
|
|
142
|
+
self.current_scope = "user" if self.current_scope == "project" else "project"
|
|
143
|
+
self.console.print(f"[green]Switched to {self.current_scope} scope[/green]")
|
|
144
|
+
Prompt.ask("Press Enter to continue")
|
|
145
|
+
|
|
146
|
+
def launch_claude_mpm(self) -> None:
|
|
147
|
+
"""Launch Claude MPM run command, replacing current process.
|
|
148
|
+
|
|
149
|
+
Uses os.execvp to replace the configure process with 'claude-mpm run',
|
|
150
|
+
providing a seamless transition from configuration to runtime.
|
|
151
|
+
|
|
152
|
+
If launch fails, displays instructions for manual launch.
|
|
153
|
+
"""
|
|
154
|
+
self.console.print("\n[bold cyan]═══ Launching Claude MPM ═══[/bold cyan]\n")
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
# Use execvp to replace the current process with claude-mpm run
|
|
158
|
+
# This ensures a clean transition from configurator to Claude MPM
|
|
159
|
+
os.execvp("claude-mpm", ["claude-mpm", "run"])
|
|
160
|
+
except Exception as e:
|
|
161
|
+
self.console.print(
|
|
162
|
+
f"[yellow]⚠ Could not launch Claude MPM automatically: {e}[/yellow]"
|
|
163
|
+
)
|
|
164
|
+
self.console.print(
|
|
165
|
+
"[cyan]→ Please run 'claude-mpm run' manually to start.[/cyan]"
|
|
166
|
+
)
|
|
167
|
+
Prompt.ask("\nPress Enter to exit")
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"""Path resolution utilities for configure command.
|
|
2
|
+
|
|
3
|
+
WHY: Centralizes path resolution logic for agent templates, configs, and system files.
|
|
4
|
+
Separates file system concerns from business logic.
|
|
5
|
+
|
|
6
|
+
DESIGN: Pure functions for path resolution without side effects (except mkdir).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def get_agent_template_path(
|
|
13
|
+
agent_name: str,
|
|
14
|
+
scope: str,
|
|
15
|
+
project_dir: Path,
|
|
16
|
+
templates_dir: Path,
|
|
17
|
+
) -> Path:
|
|
18
|
+
"""Get the path to an agent's template file.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
agent_name: Name of the agent
|
|
22
|
+
scope: Configuration scope ("project" or "user")
|
|
23
|
+
project_dir: Project directory path
|
|
24
|
+
templates_dir: System templates directory
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Path to the agent template file
|
|
28
|
+
"""
|
|
29
|
+
# First check for custom template in project/user config
|
|
30
|
+
if scope == "project":
|
|
31
|
+
config_dir = project_dir / ".claude-mpm" / "agents"
|
|
32
|
+
else:
|
|
33
|
+
config_dir = Path.home() / ".claude-mpm" / "agents"
|
|
34
|
+
|
|
35
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
36
|
+
custom_template = config_dir / f"{agent_name}.json"
|
|
37
|
+
|
|
38
|
+
# If custom template exists, return it
|
|
39
|
+
if custom_template.exists():
|
|
40
|
+
return custom_template
|
|
41
|
+
|
|
42
|
+
# Otherwise, look for the system template
|
|
43
|
+
# Handle various naming conventions
|
|
44
|
+
possible_names = [
|
|
45
|
+
f"{agent_name}.json",
|
|
46
|
+
f"{agent_name.replace('-', '_')}.json",
|
|
47
|
+
f"{agent_name}-agent.json",
|
|
48
|
+
f"{agent_name.replace('-', '_')}_agent.json",
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
for name in possible_names:
|
|
52
|
+
system_template = templates_dir / name
|
|
53
|
+
if system_template.exists():
|
|
54
|
+
return system_template
|
|
55
|
+
|
|
56
|
+
# Return the custom template path for new templates
|
|
57
|
+
return custom_template
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def get_config_directory(scope: str, project_dir: Path) -> Path:
|
|
61
|
+
"""Get configuration directory based on scope.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
scope: Configuration scope ("project" or "user")
|
|
65
|
+
project_dir: Project directory path
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Path to configuration directory
|
|
69
|
+
"""
|
|
70
|
+
if scope == "project":
|
|
71
|
+
return project_dir / ".claude-mpm"
|
|
72
|
+
return Path.home() / ".claude-mpm"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def get_agents_directory(scope: str, project_dir: Path) -> Path:
|
|
76
|
+
"""Get agents directory based on scope.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
scope: Configuration scope ("project" or "user")
|
|
80
|
+
project_dir: Project directory path
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Path to agents directory
|
|
84
|
+
"""
|
|
85
|
+
config_dir = get_config_directory(scope, project_dir)
|
|
86
|
+
agents_dir = config_dir / "agents"
|
|
87
|
+
agents_dir.mkdir(parents=True, exist_ok=True)
|
|
88
|
+
return agents_dir
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def get_behaviors_directory(scope: str, project_dir: Path) -> Path:
|
|
92
|
+
"""Get behaviors directory based on scope.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
scope: Configuration scope ("project" or "user")
|
|
96
|
+
project_dir: Project directory path
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Path to behaviors directory
|
|
100
|
+
"""
|
|
101
|
+
config_dir = get_config_directory(scope, project_dir)
|
|
102
|
+
behaviors_dir = config_dir / "behaviors"
|
|
103
|
+
behaviors_dir.mkdir(parents=True, exist_ok=True)
|
|
104
|
+
return behaviors_dir
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"""Configuration persistence and version management for configure command.
|
|
2
|
+
|
|
3
|
+
WHY: Separate configuration import/export and version display logic from main
|
|
4
|
+
configure command to improve modularity. This handles all file I/O for
|
|
5
|
+
configuration backups and version information display.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISIONS:
|
|
8
|
+
- Export/import configuration as JSON for portability
|
|
9
|
+
- Display version info for both MPM and Claude Code
|
|
10
|
+
- Support interactive and non-interactive modes
|
|
11
|
+
- Include validation for import operations
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import json
|
|
15
|
+
import subprocess
|
|
16
|
+
import sys
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
|
|
19
|
+
from rich.box import ROUNDED
|
|
20
|
+
from rich.console import Console
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
from rich.prompt import Prompt
|
|
23
|
+
|
|
24
|
+
from ..shared import CommandResult
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class ConfigPersistence:
|
|
28
|
+
"""Handle configuration import/export and version information display.
|
|
29
|
+
|
|
30
|
+
This class manages:
|
|
31
|
+
- Exporting configuration to JSON files
|
|
32
|
+
- Importing configuration from JSON files
|
|
33
|
+
- Displaying version information (MPM, Claude Code, Python)
|
|
34
|
+
- Both interactive and non-interactive display modes
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
console: Console,
|
|
40
|
+
version_service, # VersionService instance
|
|
41
|
+
agent_manager, # SimpleAgentManager instance (can be None for version operations)
|
|
42
|
+
get_template_path_fn, # Function to get template path
|
|
43
|
+
display_header_fn, # Function to display header
|
|
44
|
+
current_scope: str,
|
|
45
|
+
project_dir: Path,
|
|
46
|
+
):
|
|
47
|
+
"""Initialize persistence handler.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
console: Rich console for output
|
|
51
|
+
version_service: VersionService for version info
|
|
52
|
+
agent_manager: SimpleAgentManager for agent states (can be None for version operations)
|
|
53
|
+
get_template_path_fn: Function(agent_name) -> Path
|
|
54
|
+
display_header_fn: Function() -> None to display header
|
|
55
|
+
current_scope: Current configuration scope (project/user)
|
|
56
|
+
project_dir: Current project directory
|
|
57
|
+
"""
|
|
58
|
+
self.console = console
|
|
59
|
+
self.version_service = version_service
|
|
60
|
+
self.agent_manager = agent_manager
|
|
61
|
+
self._get_agent_template_path = get_template_path_fn
|
|
62
|
+
self._display_header = display_header_fn
|
|
63
|
+
self.current_scope = current_scope
|
|
64
|
+
self.project_dir = project_dir
|
|
65
|
+
|
|
66
|
+
def export_config(self, file_path: str) -> CommandResult:
|
|
67
|
+
"""Export configuration to a JSON file.
|
|
68
|
+
|
|
69
|
+
Exports:
|
|
70
|
+
- Current scope (project/user)
|
|
71
|
+
- Agent enabled/disabled states
|
|
72
|
+
- Template paths for each agent
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
file_path: Path to export configuration to
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
CommandResult indicating success or failure
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
# Gather all configuration
|
|
82
|
+
config_data = {"scope": self.current_scope, "agents": {}, "behaviors": {}}
|
|
83
|
+
|
|
84
|
+
# Get agent states
|
|
85
|
+
agents = self.agent_manager.discover_agents()
|
|
86
|
+
for agent in agents:
|
|
87
|
+
config_data["agents"][agent.name] = {
|
|
88
|
+
"enabled": self.agent_manager.is_agent_enabled(agent.name),
|
|
89
|
+
"template_path": str(self._get_agent_template_path(agent.name)),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
# Write to file
|
|
93
|
+
output_path = Path(file_path)
|
|
94
|
+
with output_path.open("w") as f:
|
|
95
|
+
json.dump(config_data, f, indent=2)
|
|
96
|
+
|
|
97
|
+
return CommandResult.success_result(
|
|
98
|
+
f"Configuration exported to {output_path}"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
except Exception as e:
|
|
102
|
+
return CommandResult.error_result(f"Failed to export configuration: {e}")
|
|
103
|
+
|
|
104
|
+
def import_config(self, file_path: str) -> CommandResult:
|
|
105
|
+
"""Import configuration from a JSON file.
|
|
106
|
+
|
|
107
|
+
Imports and applies:
|
|
108
|
+
- Agent enabled/disabled states
|
|
109
|
+
- (Future: behavior configurations)
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
file_path: Path to import configuration from
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
CommandResult indicating success or failure
|
|
116
|
+
"""
|
|
117
|
+
try:
|
|
118
|
+
input_path = Path(file_path)
|
|
119
|
+
if not input_path.exists():
|
|
120
|
+
return CommandResult.error_result(f"File not found: {file_path}")
|
|
121
|
+
|
|
122
|
+
with input_path.open() as f:
|
|
123
|
+
config_data = json.load(f)
|
|
124
|
+
|
|
125
|
+
# Apply agent states
|
|
126
|
+
if "agents" in config_data:
|
|
127
|
+
for agent_name, agent_config in config_data["agents"].items():
|
|
128
|
+
if "enabled" in agent_config:
|
|
129
|
+
self.agent_manager.set_agent_enabled(
|
|
130
|
+
agent_name, agent_config["enabled"]
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return CommandResult.success_result(
|
|
134
|
+
f"Configuration imported from {input_path}"
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
except Exception as e:
|
|
138
|
+
return CommandResult.error_result(f"Failed to import configuration: {e}")
|
|
139
|
+
|
|
140
|
+
def show_version_info(self) -> CommandResult:
|
|
141
|
+
"""Show version information in non-interactive mode.
|
|
142
|
+
|
|
143
|
+
Displays:
|
|
144
|
+
- Claude MPM version and build number
|
|
145
|
+
- Claude Code version (if available)
|
|
146
|
+
- Python version
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
CommandResult with version data
|
|
150
|
+
"""
|
|
151
|
+
mpm_version = self.version_service.get_version()
|
|
152
|
+
build_number = self.version_service.get_build_number()
|
|
153
|
+
|
|
154
|
+
data = {
|
|
155
|
+
"mpm_version": mpm_version,
|
|
156
|
+
"build_number": build_number,
|
|
157
|
+
"python_version": sys.version.split()[0],
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
# Try to get Claude version
|
|
161
|
+
try:
|
|
162
|
+
result = subprocess.run(
|
|
163
|
+
["claude", "--version"],
|
|
164
|
+
capture_output=True,
|
|
165
|
+
text=True,
|
|
166
|
+
timeout=5,
|
|
167
|
+
check=False,
|
|
168
|
+
)
|
|
169
|
+
if result.returncode == 0:
|
|
170
|
+
data["claude_version"] = result.stdout.strip()
|
|
171
|
+
except Exception:
|
|
172
|
+
data["claude_version"] = "Unknown"
|
|
173
|
+
|
|
174
|
+
# Print formatted output
|
|
175
|
+
self.console.print(
|
|
176
|
+
f"[bold]Claude MPM:[/bold] {mpm_version} (build {build_number})"
|
|
177
|
+
)
|
|
178
|
+
self.console.print(
|
|
179
|
+
f"[bold]Claude Code:[/bold] {data.get('claude_version', 'Unknown')}"
|
|
180
|
+
)
|
|
181
|
+
self.console.print(f"[bold]Python:[/bold] {data['python_version']}")
|
|
182
|
+
|
|
183
|
+
return CommandResult.success_result("Version information displayed", data=data)
|
|
184
|
+
|
|
185
|
+
def show_version_info_interactive(self) -> None:
|
|
186
|
+
"""Show version information in interactive mode with panel display.
|
|
187
|
+
|
|
188
|
+
Displays comprehensive version information in a formatted panel:
|
|
189
|
+
- Claude MPM version and build number
|
|
190
|
+
- Claude Code version with compatibility info
|
|
191
|
+
- Python version
|
|
192
|
+
- Current configuration scope and directory
|
|
193
|
+
"""
|
|
194
|
+
self.console.clear()
|
|
195
|
+
self._display_header()
|
|
196
|
+
|
|
197
|
+
# Get version information
|
|
198
|
+
mpm_version = self.version_service.get_version()
|
|
199
|
+
build_number = self.version_service.get_build_number()
|
|
200
|
+
|
|
201
|
+
# Try to get Claude Code version using the installer's method
|
|
202
|
+
claude_version = "Unknown"
|
|
203
|
+
try:
|
|
204
|
+
from ...hooks.claude_hooks.installer import HookInstaller
|
|
205
|
+
|
|
206
|
+
installer = HookInstaller()
|
|
207
|
+
detected_version = installer.get_claude_version()
|
|
208
|
+
if detected_version:
|
|
209
|
+
is_compatible, _ = installer.is_version_compatible()
|
|
210
|
+
claude_version = f"{detected_version} (Claude Code)"
|
|
211
|
+
if not is_compatible:
|
|
212
|
+
claude_version += (
|
|
213
|
+
f" - Monitoring requires {installer.MIN_CLAUDE_VERSION}+"
|
|
214
|
+
)
|
|
215
|
+
else:
|
|
216
|
+
# Fallback to direct subprocess call
|
|
217
|
+
result = subprocess.run(
|
|
218
|
+
["claude", "--version"],
|
|
219
|
+
capture_output=True,
|
|
220
|
+
text=True,
|
|
221
|
+
timeout=5,
|
|
222
|
+
check=False,
|
|
223
|
+
)
|
|
224
|
+
if result.returncode == 0:
|
|
225
|
+
claude_version = result.stdout.strip()
|
|
226
|
+
except Exception:
|
|
227
|
+
pass
|
|
228
|
+
|
|
229
|
+
# Create version panel
|
|
230
|
+
version_text = f"""
|
|
231
|
+
[bold cyan]Claude MPM[/bold cyan]
|
|
232
|
+
Version: {mpm_version}
|
|
233
|
+
Build: {build_number}
|
|
234
|
+
|
|
235
|
+
[bold cyan]Claude Code[/bold cyan]
|
|
236
|
+
Version: {claude_version}
|
|
237
|
+
|
|
238
|
+
[bold cyan]Python[/bold cyan]
|
|
239
|
+
Version: {sys.version.split()[0]}
|
|
240
|
+
|
|
241
|
+
[bold cyan]Configuration[/bold cyan]
|
|
242
|
+
Scope: {self.current_scope}
|
|
243
|
+
Directory: {self.project_dir}
|
|
244
|
+
"""
|
|
245
|
+
|
|
246
|
+
panel = Panel(
|
|
247
|
+
version_text.strip(),
|
|
248
|
+
title="[bold]Version Information[/bold]",
|
|
249
|
+
box=ROUNDED,
|
|
250
|
+
style="green",
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
self.console.print(panel)
|
|
254
|
+
Prompt.ask("\nPress Enter to continue")
|