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
|
@@ -11,11 +11,96 @@ and reduce duplication across command parsers.
|
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import argparse
|
|
14
|
+
import sys
|
|
14
15
|
from typing import List, Optional
|
|
15
16
|
|
|
16
17
|
from ...constants import CLICommands, CLIPrefix, LogLevel
|
|
17
18
|
|
|
18
19
|
|
|
20
|
+
class SuggestingArgumentParser(argparse.ArgumentParser):
|
|
21
|
+
"""
|
|
22
|
+
Custom ArgumentParser that suggests similar commands on error.
|
|
23
|
+
|
|
24
|
+
WHY: Provides better user experience by suggesting corrections for typos
|
|
25
|
+
and invalid commands instead of just showing an error message.
|
|
26
|
+
|
|
27
|
+
DESIGN DECISION: Extends ArgumentParser.error() to add suggestions before
|
|
28
|
+
exiting. This catches all parser errors including invalid subcommands and
|
|
29
|
+
invalid options.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def error(self, message: str) -> None:
|
|
33
|
+
"""
|
|
34
|
+
Override error method to add command suggestions.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
message: Error message from argparse
|
|
38
|
+
"""
|
|
39
|
+
from ..utils import suggest_similar_commands
|
|
40
|
+
|
|
41
|
+
# Try to extract the invalid command/option from the error message
|
|
42
|
+
invalid_value = None
|
|
43
|
+
valid_choices = []
|
|
44
|
+
|
|
45
|
+
# Handle invalid subcommand errors
|
|
46
|
+
# Format: "argument COMMAND: invalid choice: 'tickts' (choose from ...)"
|
|
47
|
+
if "invalid choice:" in message:
|
|
48
|
+
try:
|
|
49
|
+
# Extract the invalid choice
|
|
50
|
+
parts = message.split("invalid choice: '")
|
|
51
|
+
if len(parts) > 1:
|
|
52
|
+
invalid_value = parts[1].split("'")[0]
|
|
53
|
+
|
|
54
|
+
# Extract valid choices
|
|
55
|
+
if "(choose from" in message:
|
|
56
|
+
choices_part = message.split("(choose from")[1]
|
|
57
|
+
# Remove trailing parenthesis and split
|
|
58
|
+
choices_str = choices_part.rstrip(")")
|
|
59
|
+
# Parse choices - they may be quoted or unquoted
|
|
60
|
+
valid_choices = [
|
|
61
|
+
c.strip().strip("'\"")
|
|
62
|
+
for c in choices_str.split(",")
|
|
63
|
+
if c.strip()
|
|
64
|
+
]
|
|
65
|
+
except (IndexError, ValueError):
|
|
66
|
+
pass
|
|
67
|
+
|
|
68
|
+
# Handle unrecognized arguments (invalid options)
|
|
69
|
+
# Format: "unrecognized arguments: --verbos"
|
|
70
|
+
elif "unrecognized arguments:" in message:
|
|
71
|
+
try:
|
|
72
|
+
parts = message.split("unrecognized arguments:")
|
|
73
|
+
if len(parts) > 1:
|
|
74
|
+
invalid_value = parts[1].strip().split()[0]
|
|
75
|
+
|
|
76
|
+
# Get common options from parser
|
|
77
|
+
valid_choices = []
|
|
78
|
+
for action in self._actions:
|
|
79
|
+
for option in action.option_strings:
|
|
80
|
+
valid_choices.append(option)
|
|
81
|
+
except (IndexError, ValueError):
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
# Build error message with suggestions
|
|
85
|
+
from rich.console import Console
|
|
86
|
+
|
|
87
|
+
console = Console(stderr=True)
|
|
88
|
+
|
|
89
|
+
console.print(f"\n[red]Error:[/red] {message}\n", style="bold")
|
|
90
|
+
|
|
91
|
+
# Add suggestions if we found valid choices
|
|
92
|
+
if invalid_value and valid_choices:
|
|
93
|
+
suggestion = suggest_similar_commands(invalid_value, valid_choices)
|
|
94
|
+
if suggestion:
|
|
95
|
+
console.print(f"[yellow]{suggestion}[/yellow]\n")
|
|
96
|
+
|
|
97
|
+
# Show help hint
|
|
98
|
+
console.print(f"[dim]Run '{self.prog} --help' for usage information.[/dim]\n")
|
|
99
|
+
|
|
100
|
+
# Exit with error code
|
|
101
|
+
sys.exit(2)
|
|
102
|
+
|
|
103
|
+
|
|
19
104
|
def _get_enhanced_version(base_version: str) -> str:
|
|
20
105
|
"""
|
|
21
106
|
Get enhanced version string with build number if available.
|
|
@@ -111,15 +196,18 @@ def create_main_parser(
|
|
|
111
196
|
WHY: This creates the foundation parser that other modules will extend
|
|
112
197
|
with their specific subcommands and arguments.
|
|
113
198
|
|
|
199
|
+
DESIGN DECISION: Uses SuggestingArgumentParser to provide helpful suggestions
|
|
200
|
+
for typos and invalid commands, improving user experience.
|
|
201
|
+
|
|
114
202
|
Args:
|
|
115
203
|
prog_name: The program name to use
|
|
116
204
|
version: The version string to display
|
|
117
205
|
|
|
118
206
|
Returns:
|
|
119
|
-
Configured
|
|
207
|
+
Configured SuggestingArgumentParser instance ready for subparser addition
|
|
120
208
|
"""
|
|
121
|
-
# Main parser
|
|
122
|
-
parser =
|
|
209
|
+
# Main parser with suggestion support
|
|
210
|
+
parser = SuggestingArgumentParser(
|
|
123
211
|
prog=prog_name,
|
|
124
212
|
description=f"Claude Multi-Agent Project Manager v{version} - Orchestrate Claude with agent delegation and ticket tracking",
|
|
125
213
|
epilog="By default, runs an orchestrated Claude session. Use 'claude-mpm' for interactive mode or 'claude-mpm -i \"prompt\"' for non-interactive mode.\n\nTo pass arguments to Claude CLI, use -- separator: claude-mpm run -- --model sonnet --temperature 0.1",
|
|
@@ -336,6 +424,13 @@ def create_parser(
|
|
|
336
424
|
except ImportError:
|
|
337
425
|
pass
|
|
338
426
|
|
|
427
|
+
try:
|
|
428
|
+
from .local_deploy_parser import add_local_deploy_arguments
|
|
429
|
+
|
|
430
|
+
add_local_deploy_arguments(subparsers)
|
|
431
|
+
except ImportError:
|
|
432
|
+
pass
|
|
433
|
+
|
|
339
434
|
try:
|
|
340
435
|
from .mcp_parser import add_mcp_subparser
|
|
341
436
|
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Local Deploy parser module for claude-mpm CLI.
|
|
3
|
+
|
|
4
|
+
WHY: Provides argument parsing for local deployment management commands.
|
|
5
|
+
Extracted from the monolithic parser.py for better organization.
|
|
6
|
+
|
|
7
|
+
DESIGN DECISION: Supports multiple subcommands (start, stop, restart, status, etc.)
|
|
8
|
+
with command-specific arguments for comprehensive process management.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def add_local_deploy_arguments(subparsers) -> None:
|
|
15
|
+
"""
|
|
16
|
+
Add local-deploy command and its subcommands to the parser.
|
|
17
|
+
|
|
18
|
+
WHY: Provides a comprehensive CLI for managing local development deployments
|
|
19
|
+
with process monitoring, health checks, and auto-restart capabilities.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
subparsers: The subparsers object to add commands to
|
|
23
|
+
"""
|
|
24
|
+
# Main local-deploy command
|
|
25
|
+
local_deploy_parser = subparsers.add_parser(
|
|
26
|
+
"local-deploy",
|
|
27
|
+
help="Manage local development deployments with process monitoring",
|
|
28
|
+
description=(
|
|
29
|
+
"Manage local development deployments with comprehensive process management, "
|
|
30
|
+
"health monitoring, and auto-restart capabilities."
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Create subparsers for local-deploy subcommands
|
|
35
|
+
local_deploy_subparsers = local_deploy_parser.add_subparsers(
|
|
36
|
+
dest="local_deploy_command",
|
|
37
|
+
help="Local deployment commands",
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# ===== START command =====
|
|
41
|
+
start_parser = local_deploy_subparsers.add_parser(
|
|
42
|
+
"start",
|
|
43
|
+
help="Start a new local deployment",
|
|
44
|
+
description="Start a new local deployment with process monitoring and optional auto-restart",
|
|
45
|
+
)
|
|
46
|
+
start_parser.add_argument(
|
|
47
|
+
"--command",
|
|
48
|
+
"-c",
|
|
49
|
+
required=True,
|
|
50
|
+
help="Command to execute (e.g., 'npm run dev' or 'python manage.py runserver')",
|
|
51
|
+
)
|
|
52
|
+
start_parser.add_argument(
|
|
53
|
+
"--working-directory",
|
|
54
|
+
"-d",
|
|
55
|
+
type=Path,
|
|
56
|
+
help="Working directory for the process (default: current directory)",
|
|
57
|
+
)
|
|
58
|
+
start_parser.add_argument(
|
|
59
|
+
"--port",
|
|
60
|
+
"-p",
|
|
61
|
+
type=int,
|
|
62
|
+
help="Port number for the deployment",
|
|
63
|
+
)
|
|
64
|
+
start_parser.add_argument(
|
|
65
|
+
"--auto-find-port",
|
|
66
|
+
action="store_true",
|
|
67
|
+
default=True,
|
|
68
|
+
help="Automatically find alternative port if specified port is unavailable (default: enabled)",
|
|
69
|
+
)
|
|
70
|
+
start_parser.add_argument(
|
|
71
|
+
"--no-auto-find-port",
|
|
72
|
+
action="store_false",
|
|
73
|
+
dest="auto_find_port",
|
|
74
|
+
help="Disable automatic port finding",
|
|
75
|
+
)
|
|
76
|
+
start_parser.add_argument(
|
|
77
|
+
"--auto-restart",
|
|
78
|
+
action="store_true",
|
|
79
|
+
help="Enable automatic restart on crashes",
|
|
80
|
+
)
|
|
81
|
+
start_parser.add_argument(
|
|
82
|
+
"--log-file",
|
|
83
|
+
type=Path,
|
|
84
|
+
help="Path to log file for monitoring error patterns",
|
|
85
|
+
)
|
|
86
|
+
start_parser.add_argument(
|
|
87
|
+
"--env",
|
|
88
|
+
"-e",
|
|
89
|
+
action="append",
|
|
90
|
+
help="Environment variables in KEY=VALUE format (can be specified multiple times)",
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# ===== STOP command =====
|
|
94
|
+
stop_parser = local_deploy_subparsers.add_parser(
|
|
95
|
+
"stop",
|
|
96
|
+
help="Stop a running deployment",
|
|
97
|
+
description="Stop a running deployment with graceful shutdown",
|
|
98
|
+
)
|
|
99
|
+
stop_parser.add_argument(
|
|
100
|
+
"deployment_id",
|
|
101
|
+
help="Deployment ID to stop",
|
|
102
|
+
)
|
|
103
|
+
stop_parser.add_argument(
|
|
104
|
+
"--timeout",
|
|
105
|
+
"-t",
|
|
106
|
+
type=int,
|
|
107
|
+
default=10,
|
|
108
|
+
help="Timeout in seconds for graceful shutdown (default: 10)",
|
|
109
|
+
)
|
|
110
|
+
stop_parser.add_argument(
|
|
111
|
+
"--force",
|
|
112
|
+
"-f",
|
|
113
|
+
action="store_true",
|
|
114
|
+
help="Force kill immediately without graceful shutdown",
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# ===== RESTART command =====
|
|
118
|
+
restart_parser = local_deploy_subparsers.add_parser(
|
|
119
|
+
"restart",
|
|
120
|
+
help="Restart a deployment",
|
|
121
|
+
description="Restart a deployment with the same configuration",
|
|
122
|
+
)
|
|
123
|
+
restart_parser.add_argument(
|
|
124
|
+
"deployment_id",
|
|
125
|
+
help="Deployment ID to restart",
|
|
126
|
+
)
|
|
127
|
+
restart_parser.add_argument(
|
|
128
|
+
"--timeout",
|
|
129
|
+
"-t",
|
|
130
|
+
type=int,
|
|
131
|
+
default=10,
|
|
132
|
+
help="Timeout in seconds for graceful shutdown (default: 10)",
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# ===== STATUS command =====
|
|
136
|
+
status_parser = local_deploy_subparsers.add_parser(
|
|
137
|
+
"status",
|
|
138
|
+
help="Show comprehensive deployment status",
|
|
139
|
+
description="Show comprehensive status including process info, health, and restart history",
|
|
140
|
+
)
|
|
141
|
+
status_parser.add_argument(
|
|
142
|
+
"deployment_id",
|
|
143
|
+
help="Deployment ID to check",
|
|
144
|
+
)
|
|
145
|
+
status_parser.add_argument(
|
|
146
|
+
"--json",
|
|
147
|
+
action="store_true",
|
|
148
|
+
help="Output status in JSON format",
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# ===== HEALTH command =====
|
|
152
|
+
health_parser = local_deploy_subparsers.add_parser(
|
|
153
|
+
"health",
|
|
154
|
+
help="Show health status",
|
|
155
|
+
description="Show health check status including HTTP, process, and resource checks",
|
|
156
|
+
)
|
|
157
|
+
health_parser.add_argument(
|
|
158
|
+
"deployment_id",
|
|
159
|
+
help="Deployment ID to check",
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# ===== LIST command =====
|
|
163
|
+
list_parser = local_deploy_subparsers.add_parser(
|
|
164
|
+
"list",
|
|
165
|
+
help="List all deployments",
|
|
166
|
+
description="List all local deployments with their status",
|
|
167
|
+
)
|
|
168
|
+
list_parser.add_argument(
|
|
169
|
+
"--status",
|
|
170
|
+
"-s",
|
|
171
|
+
choices=["running", "stopped", "crashed", "stopping"],
|
|
172
|
+
help="Filter deployments by status",
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# ===== MONITOR command =====
|
|
176
|
+
monitor_parser = local_deploy_subparsers.add_parser(
|
|
177
|
+
"monitor",
|
|
178
|
+
help="Live monitoring dashboard",
|
|
179
|
+
description="Display live monitoring dashboard for a deployment",
|
|
180
|
+
)
|
|
181
|
+
monitor_parser.add_argument(
|
|
182
|
+
"deployment_id",
|
|
183
|
+
help="Deployment ID to monitor",
|
|
184
|
+
)
|
|
185
|
+
monitor_parser.add_argument(
|
|
186
|
+
"--refresh",
|
|
187
|
+
"-r",
|
|
188
|
+
type=int,
|
|
189
|
+
default=2,
|
|
190
|
+
help="Refresh interval in seconds (default: 2)",
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
# ===== HISTORY command =====
|
|
194
|
+
history_parser = local_deploy_subparsers.add_parser(
|
|
195
|
+
"history",
|
|
196
|
+
help="Show restart history",
|
|
197
|
+
description="Show restart history and statistics for a deployment",
|
|
198
|
+
)
|
|
199
|
+
history_parser.add_argument(
|
|
200
|
+
"deployment_id",
|
|
201
|
+
help="Deployment ID to check",
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# ===== ENABLE-AUTO-RESTART command =====
|
|
205
|
+
enable_auto_restart_parser = local_deploy_subparsers.add_parser(
|
|
206
|
+
"enable-auto-restart",
|
|
207
|
+
help="Enable auto-restart for a deployment",
|
|
208
|
+
description="Enable automatic restart on crashes for a deployment",
|
|
209
|
+
)
|
|
210
|
+
enable_auto_restart_parser.add_argument(
|
|
211
|
+
"deployment_id",
|
|
212
|
+
help="Deployment ID to enable auto-restart for",
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# ===== DISABLE-AUTO-RESTART command =====
|
|
216
|
+
disable_auto_restart_parser = local_deploy_subparsers.add_parser(
|
|
217
|
+
"disable-auto-restart",
|
|
218
|
+
help="Disable auto-restart for a deployment",
|
|
219
|
+
description="Disable automatic restart on crashes for a deployment",
|
|
220
|
+
)
|
|
221
|
+
disable_auto_restart_parser.add_argument(
|
|
222
|
+
"deployment_id",
|
|
223
|
+
help="Deployment ID to disable auto-restart for",
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
__all__ = ["add_local_deploy_arguments"]
|
|
@@ -7,6 +7,8 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
7
7
|
|
|
8
8
|
import yaml
|
|
9
9
|
|
|
10
|
+
from claude_mpm.core.enums import OutputFormat
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
class OutputFormatter:
|
|
12
14
|
"""Handles formatting output in different formats."""
|
|
@@ -104,13 +106,13 @@ class OutputFormatter:
|
|
|
104
106
|
return str(data)
|
|
105
107
|
|
|
106
108
|
|
|
107
|
-
def format_output(data: Any, format_type: str =
|
|
109
|
+
def format_output(data: Any, format_type: str = OutputFormat.TEXT, **kwargs) -> str:
|
|
108
110
|
"""
|
|
109
111
|
Format data according to the specified format.
|
|
110
112
|
|
|
111
113
|
Args:
|
|
112
114
|
data: Data to format
|
|
113
|
-
format_type: Output format (
|
|
115
|
+
format_type: Output format (use OutputFormat enum or string)
|
|
114
116
|
**kwargs: Additional formatting options
|
|
115
117
|
|
|
116
118
|
Returns:
|
|
@@ -118,20 +120,23 @@ def format_output(data: Any, format_type: str = "text", **kwargs) -> str:
|
|
|
118
120
|
"""
|
|
119
121
|
formatter = OutputFormatter()
|
|
120
122
|
|
|
121
|
-
|
|
123
|
+
# Convert to string for comparison (handles both enum and string inputs)
|
|
124
|
+
fmt = str(format_type).lower()
|
|
125
|
+
|
|
126
|
+
if fmt == OutputFormat.JSON:
|
|
122
127
|
return formatter.format_json(data, **kwargs)
|
|
123
|
-
if
|
|
128
|
+
if fmt == OutputFormat.YAML:
|
|
124
129
|
return formatter.format_yaml(data)
|
|
125
|
-
if
|
|
130
|
+
if fmt == OutputFormat.TABLE:
|
|
126
131
|
return formatter.format_table(data, **kwargs)
|
|
127
|
-
if
|
|
132
|
+
if fmt == OutputFormat.TEXT:
|
|
128
133
|
return formatter.format_text(data)
|
|
129
134
|
# Fallback to text format
|
|
130
135
|
return formatter.format_text(data)
|
|
131
136
|
|
|
132
137
|
|
|
133
138
|
def format_success_message(
|
|
134
|
-
message: str, data: Any = None, format_type: str =
|
|
139
|
+
message: str, data: Any = None, format_type: str = OutputFormat.TEXT
|
|
135
140
|
) -> str:
|
|
136
141
|
"""
|
|
137
142
|
Format a success message with optional data.
|
|
@@ -139,12 +144,13 @@ def format_success_message(
|
|
|
139
144
|
Args:
|
|
140
145
|
message: Success message
|
|
141
146
|
data: Optional data to include
|
|
142
|
-
format_type: Output format
|
|
147
|
+
format_type: Output format (use OutputFormat enum or string)
|
|
143
148
|
|
|
144
149
|
Returns:
|
|
145
150
|
Formatted success message
|
|
146
151
|
"""
|
|
147
|
-
|
|
152
|
+
fmt = str(format_type).lower()
|
|
153
|
+
if fmt in (OutputFormat.JSON, OutputFormat.YAML):
|
|
148
154
|
result = {"success": True, "message": message}
|
|
149
155
|
if data is not None:
|
|
150
156
|
result["data"] = data
|
|
@@ -158,7 +164,7 @@ def format_success_message(
|
|
|
158
164
|
|
|
159
165
|
|
|
160
166
|
def format_error_message(
|
|
161
|
-
message: str, details: Any = None, format_type: str =
|
|
167
|
+
message: str, details: Any = None, format_type: str = OutputFormat.TEXT
|
|
162
168
|
) -> str:
|
|
163
169
|
"""
|
|
164
170
|
Format an error message with optional details.
|
|
@@ -166,12 +172,13 @@ def format_error_message(
|
|
|
166
172
|
Args:
|
|
167
173
|
message: Error message
|
|
168
174
|
details: Optional error details
|
|
169
|
-
format_type: Output format
|
|
175
|
+
format_type: Output format (use OutputFormat enum or string)
|
|
170
176
|
|
|
171
177
|
Returns:
|
|
172
178
|
Formatted error message
|
|
173
179
|
"""
|
|
174
|
-
|
|
180
|
+
fmt = str(format_type).lower()
|
|
181
|
+
if fmt in (OutputFormat.JSON, OutputFormat.YAML):
|
|
175
182
|
result = {"success": False, "error": message}
|
|
176
183
|
if details is not None:
|
|
177
184
|
result["details"] = details
|
|
@@ -187,7 +194,7 @@ def format_error_message(
|
|
|
187
194
|
def format_list_output(
|
|
188
195
|
items: List[Any],
|
|
189
196
|
title: Optional[str] = None,
|
|
190
|
-
format_type: str =
|
|
197
|
+
format_type: str = OutputFormat.TEXT,
|
|
191
198
|
headers: Optional[List[str]] = None,
|
|
192
199
|
) -> str:
|
|
193
200
|
"""
|
|
@@ -196,29 +203,31 @@ def format_list_output(
|
|
|
196
203
|
Args:
|
|
197
204
|
items: List of items to format
|
|
198
205
|
title: Optional title for the list
|
|
199
|
-
format_type: Output format
|
|
206
|
+
format_type: Output format (use OutputFormat enum or string)
|
|
200
207
|
headers: Optional headers for table format
|
|
201
208
|
|
|
202
209
|
Returns:
|
|
203
210
|
Formatted list output
|
|
204
211
|
"""
|
|
212
|
+
fmt = str(format_type).lower()
|
|
213
|
+
|
|
205
214
|
if not items:
|
|
206
215
|
empty_msg = f"No {title.lower() if title else 'items'} found"
|
|
207
|
-
if
|
|
216
|
+
if fmt in (OutputFormat.JSON, OutputFormat.YAML):
|
|
208
217
|
return format_output({"items": [], "message": empty_msg}, format_type)
|
|
209
218
|
return empty_msg
|
|
210
219
|
|
|
211
|
-
if
|
|
220
|
+
if fmt in (OutputFormat.JSON, OutputFormat.YAML):
|
|
212
221
|
result = {"items": items}
|
|
213
222
|
if title:
|
|
214
223
|
result["title"] = title
|
|
215
224
|
return format_output(result, format_type)
|
|
216
225
|
|
|
217
|
-
if
|
|
226
|
+
if fmt == OutputFormat.TABLE:
|
|
218
227
|
output = ""
|
|
219
228
|
if title:
|
|
220
229
|
output += f"{title}\n{'=' * len(title)}\n\n"
|
|
221
|
-
output += format_output(items,
|
|
230
|
+
output += format_output(items, OutputFormat.TABLE, headers=headers)
|
|
222
231
|
return output
|
|
223
232
|
|
|
224
233
|
# Text format
|
|
@@ -228,5 +237,5 @@ def format_list_output(
|
|
|
228
237
|
lines.append("=" * len(title))
|
|
229
238
|
lines.append("")
|
|
230
239
|
|
|
231
|
-
lines.append(format_output(items,
|
|
240
|
+
lines.append(format_output(items, OutputFormat.TEXT))
|
|
232
241
|
return "\n".join(lines)
|