claude-mpm 4.7.4__py3-none-any.whl ā 4.18.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_AGENT_TEMPLATE.md +118 -0
- claude_mpm/agents/BASE_ENGINEER.md +286 -0
- claude_mpm/agents/BASE_PM.md +106 -1
- claude_mpm/agents/OUTPUT_STYLE.md +329 -11
- claude_mpm/agents/PM_INSTRUCTIONS.md +397 -459
- claude_mpm/agents/agent_loader.py +17 -5
- claude_mpm/agents/frontmatter_validator.py +284 -253
- claude_mpm/agents/templates/README.md +465 -0
- claude_mpm/agents/templates/agent-manager.json +4 -1
- claude_mpm/agents/templates/agentic-coder-optimizer.json +13 -3
- claude_mpm/agents/templates/api_qa.json +11 -2
- claude_mpm/agents/templates/circuit_breakers.md +638 -0
- claude_mpm/agents/templates/clerk-ops.json +12 -2
- claude_mpm/agents/templates/code_analyzer.json +8 -2
- claude_mpm/agents/templates/content-agent.json +358 -0
- claude_mpm/agents/templates/dart_engineer.json +15 -2
- claude_mpm/agents/templates/data_engineer.json +15 -2
- claude_mpm/agents/templates/documentation.json +10 -2
- claude_mpm/agents/templates/engineer.json +21 -1
- claude_mpm/agents/templates/gcp_ops_agent.json +12 -2
- claude_mpm/agents/templates/git_file_tracking.md +584 -0
- claude_mpm/agents/templates/golang_engineer.json +270 -0
- claude_mpm/agents/templates/imagemagick.json +4 -1
- claude_mpm/agents/templates/java_engineer.json +346 -0
- claude_mpm/agents/templates/local_ops_agent.json +1227 -6
- claude_mpm/agents/templates/memory_manager.json +4 -1
- claude_mpm/agents/templates/nextjs_engineer.json +141 -133
- claude_mpm/agents/templates/ops.json +12 -2
- claude_mpm/agents/templates/php-engineer.json +270 -174
- claude_mpm/agents/templates/pm_examples.md +474 -0
- claude_mpm/agents/templates/pm_red_flags.md +240 -0
- claude_mpm/agents/templates/product_owner.json +338 -0
- claude_mpm/agents/templates/project_organizer.json +14 -4
- claude_mpm/agents/templates/prompt-engineer.json +13 -2
- claude_mpm/agents/templates/python_engineer.json +174 -81
- claude_mpm/agents/templates/qa.json +11 -2
- claude_mpm/agents/templates/react_engineer.json +16 -3
- claude_mpm/agents/templates/refactoring_engineer.json +12 -2
- claude_mpm/agents/templates/research.json +34 -21
- claude_mpm/agents/templates/response_format.md +583 -0
- claude_mpm/agents/templates/ruby-engineer.json +129 -192
- claude_mpm/agents/templates/rust_engineer.json +270 -0
- claude_mpm/agents/templates/security.json +10 -2
- claude_mpm/agents/templates/svelte-engineer.json +225 -0
- claude_mpm/agents/templates/ticketing.json +10 -2
- claude_mpm/agents/templates/typescript_engineer.json +116 -125
- claude_mpm/agents/templates/validation_templates.md +312 -0
- claude_mpm/agents/templates/vercel_ops_agent.json +12 -2
- claude_mpm/agents/templates/version_control.json +12 -2
- claude_mpm/agents/templates/web_qa.json +11 -2
- claude_mpm/agents/templates/web_ui.json +15 -2
- claude_mpm/cli/__init__.py +34 -614
- claude_mpm/cli/commands/agent_manager.py +25 -12
- claude_mpm/cli/commands/agent_state_manager.py +186 -0
- claude_mpm/cli/commands/agents.py +235 -148
- claude_mpm/cli/commands/agents_detect.py +380 -0
- claude_mpm/cli/commands/agents_recommend.py +309 -0
- claude_mpm/cli/commands/aggregate.py +7 -3
- claude_mpm/cli/commands/analyze.py +9 -4
- claude_mpm/cli/commands/analyze_code.py +7 -2
- claude_mpm/cli/commands/auto_configure.py +570 -0
- claude_mpm/cli/commands/config.py +47 -13
- claude_mpm/cli/commands/configure.py +419 -1571
- claude_mpm/cli/commands/configure_agent_display.py +261 -0
- claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
- claude_mpm/cli/commands/configure_hook_manager.py +225 -0
- claude_mpm/cli/commands/configure_models.py +18 -0
- claude_mpm/cli/commands/configure_navigation.py +167 -0
- claude_mpm/cli/commands/configure_paths.py +104 -0
- claude_mpm/cli/commands/configure_persistence.py +254 -0
- claude_mpm/cli/commands/configure_startup_manager.py +646 -0
- claude_mpm/cli/commands/configure_template_editor.py +497 -0
- claude_mpm/cli/commands/configure_validators.py +73 -0
- claude_mpm/cli/commands/local_deploy.py +537 -0
- claude_mpm/cli/commands/memory.py +54 -20
- claude_mpm/cli/commands/mpm_init.py +585 -196
- claude_mpm/cli/commands/mpm_init_handler.py +37 -3
- claude_mpm/cli/commands/search.py +170 -4
- claude_mpm/cli/commands/upgrade.py +152 -0
- claude_mpm/cli/executor.py +202 -0
- claude_mpm/cli/helpers.py +105 -0
- claude_mpm/cli/interactive/__init__.py +3 -0
- claude_mpm/cli/interactive/skills_wizard.py +491 -0
- claude_mpm/cli/parsers/__init__.py +7 -1
- claude_mpm/cli/parsers/agents_parser.py +9 -0
- claude_mpm/cli/parsers/auto_configure_parser.py +245 -0
- claude_mpm/cli/parsers/base_parser.py +110 -3
- claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
- claude_mpm/cli/parsers/mpm_init_parser.py +65 -5
- claude_mpm/cli/shared/output_formatters.py +28 -19
- claude_mpm/cli/startup.py +481 -0
- claude_mpm/cli/utils.py +52 -1
- claude_mpm/commands/mpm-agents-detect.md +168 -0
- claude_mpm/commands/mpm-agents-recommend.md +214 -0
- claude_mpm/commands/mpm-agents.md +75 -1
- claude_mpm/commands/mpm-auto-configure.md +217 -0
- claude_mpm/commands/mpm-help.md +163 -0
- claude_mpm/commands/mpm-init.md +148 -3
- claude_mpm/commands/mpm-version.md +113 -0
- claude_mpm/commands/mpm.md +1 -0
- claude_mpm/config/agent_config.py +2 -2
- claude_mpm/config/model_config.py +428 -0
- claude_mpm/constants.py +1 -0
- claude_mpm/core/base_service.py +13 -12
- claude_mpm/core/enums.py +452 -0
- claude_mpm/core/factories.py +1 -1
- claude_mpm/core/instruction_reinforcement_hook.py +2 -1
- claude_mpm/core/interactive_session.py +9 -3
- claude_mpm/core/log_manager.py +2 -0
- claude_mpm/core/logging_config.py +6 -2
- claude_mpm/core/oneshot_session.py +8 -4
- claude_mpm/core/optimized_agent_loader.py +3 -3
- claude_mpm/core/output_style_manager.py +12 -192
- claude_mpm/core/service_registry.py +5 -1
- claude_mpm/core/types.py +2 -9
- claude_mpm/core/typing_utils.py +7 -6
- claude_mpm/dashboard/static/js/dashboard.js +0 -14
- claude_mpm/dashboard/templates/index.html +3 -41
- claude_mpm/hooks/__init__.py +20 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +4 -2
- claude_mpm/hooks/claude_hooks/response_tracking.py +35 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +23 -2
- claude_mpm/hooks/failure_learning/__init__.py +60 -0
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +235 -0
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +217 -0
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +286 -0
- claude_mpm/hooks/instruction_reinforcement.py +7 -2
- claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
- claude_mpm/hooks/kuzu_memory_hook.py +37 -12
- claude_mpm/hooks/kuzu_response_hook.py +183 -0
- claude_mpm/models/resume_log.py +340 -0
- claude_mpm/services/agents/__init__.py +18 -5
- claude_mpm/services/agents/auto_config_manager.py +796 -0
- claude_mpm/services/agents/deployment/agent_configuration_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_record_service.py +1 -1
- claude_mpm/services/agents/deployment/agent_validator.py +17 -1
- claude_mpm/services/agents/deployment/async_agent_deployment.py +1 -1
- claude_mpm/services/agents/deployment/interface_adapter.py +3 -2
- claude_mpm/services/agents/deployment/local_template_deployment.py +1 -1
- claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +7 -6
- claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +7 -16
- claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +4 -3
- claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +5 -3
- claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +6 -5
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +9 -6
- claude_mpm/services/agents/deployment/validation/__init__.py +3 -1
- claude_mpm/services/agents/deployment/validation/validation_result.py +1 -9
- claude_mpm/services/agents/local_template_manager.py +1 -1
- claude_mpm/services/agents/memory/agent_memory_manager.py +5 -2
- claude_mpm/services/agents/observers.py +547 -0
- claude_mpm/services/agents/recommender.py +568 -0
- claude_mpm/services/agents/registry/modification_tracker.py +5 -2
- claude_mpm/services/command_handler_service.py +11 -5
- claude_mpm/services/core/__init__.py +33 -1
- claude_mpm/services/core/interfaces/__init__.py +90 -3
- claude_mpm/services/core/interfaces/agent.py +184 -0
- claude_mpm/services/core/interfaces/health.py +172 -0
- claude_mpm/services/core/interfaces/model.py +281 -0
- claude_mpm/services/core/interfaces/process.py +372 -0
- claude_mpm/services/core/interfaces/project.py +121 -0
- claude_mpm/services/core/interfaces/restart.py +307 -0
- claude_mpm/services/core/interfaces/stability.py +260 -0
- claude_mpm/services/core/memory_manager.py +11 -24
- claude_mpm/services/core/models/__init__.py +79 -0
- claude_mpm/services/core/models/agent_config.py +381 -0
- claude_mpm/services/core/models/health.py +162 -0
- claude_mpm/services/core/models/process.py +235 -0
- claude_mpm/services/core/models/restart.py +302 -0
- claude_mpm/services/core/models/stability.py +264 -0
- claude_mpm/services/core/models/toolchain.py +306 -0
- claude_mpm/services/core/path_resolver.py +23 -7
- claude_mpm/services/diagnostics/__init__.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_check.py +25 -24
- claude_mpm/services/diagnostics/checks/claude_code_check.py +24 -23
- claude_mpm/services/diagnostics/checks/common_issues_check.py +25 -24
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -23
- claude_mpm/services/diagnostics/checks/filesystem_check.py +18 -17
- claude_mpm/services/diagnostics/checks/installation_check.py +30 -29
- claude_mpm/services/diagnostics/checks/instructions_check.py +20 -19
- claude_mpm/services/diagnostics/checks/mcp_check.py +50 -36
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +38 -33
- claude_mpm/services/diagnostics/checks/monitor_check.py +23 -22
- claude_mpm/services/diagnostics/checks/startup_log_check.py +9 -8
- claude_mpm/services/diagnostics/diagnostic_runner.py +6 -5
- claude_mpm/services/diagnostics/doctor_reporter.py +28 -25
- claude_mpm/services/diagnostics/models.py +19 -24
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -1
- claude_mpm/services/infrastructure/monitoring/aggregator.py +12 -12
- claude_mpm/services/infrastructure/monitoring/base.py +5 -13
- claude_mpm/services/infrastructure/monitoring/network.py +7 -6
- claude_mpm/services/infrastructure/monitoring/process.py +13 -12
- claude_mpm/services/infrastructure/monitoring/resources.py +7 -6
- claude_mpm/services/infrastructure/monitoring/service.py +16 -15
- claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
- claude_mpm/services/local_ops/__init__.py +163 -0
- claude_mpm/services/local_ops/crash_detector.py +257 -0
- claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
- claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
- claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
- claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
- claude_mpm/services/local_ops/health_manager.py +430 -0
- claude_mpm/services/local_ops/log_monitor.py +396 -0
- claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
- claude_mpm/services/local_ops/process_manager.py +595 -0
- claude_mpm/services/local_ops/resource_monitor.py +331 -0
- claude_mpm/services/local_ops/restart_manager.py +401 -0
- claude_mpm/services/local_ops/restart_policy.py +387 -0
- claude_mpm/services/local_ops/state_manager.py +372 -0
- claude_mpm/services/local_ops/unified_manager.py +600 -0
- claude_mpm/services/mcp_config_manager.py +9 -4
- claude_mpm/services/mcp_gateway/core/__init__.py +1 -2
- claude_mpm/services/mcp_gateway/core/base.py +18 -31
- claude_mpm/services/mcp_gateway/main.py +30 -0
- claude_mpm/services/mcp_gateway/tools/external_mcp_services.py +206 -32
- claude_mpm/services/mcp_gateway/tools/health_check_tool.py +30 -28
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +25 -5
- claude_mpm/services/mcp_service_verifier.py +1 -1
- claude_mpm/services/memory/failure_tracker.py +563 -0
- claude_mpm/services/memory_hook_service.py +165 -4
- claude_mpm/services/model/__init__.py +147 -0
- claude_mpm/services/model/base_provider.py +365 -0
- claude_mpm/services/model/claude_provider.py +412 -0
- claude_mpm/services/model/model_router.py +453 -0
- claude_mpm/services/model/ollama_provider.py +415 -0
- claude_mpm/services/monitor/daemon_manager.py +3 -2
- claude_mpm/services/monitor/handlers/dashboard.py +2 -1
- claude_mpm/services/monitor/handlers/hooks.py +2 -1
- claude_mpm/services/monitor/management/lifecycle.py +3 -2
- claude_mpm/services/monitor/server.py +2 -1
- claude_mpm/services/project/__init__.py +23 -0
- claude_mpm/services/project/detection_strategies.py +719 -0
- claude_mpm/services/project/toolchain_analyzer.py +581 -0
- claude_mpm/services/self_upgrade_service.py +342 -0
- claude_mpm/services/session_management_service.py +3 -2
- claude_mpm/services/session_manager.py +205 -1
- claude_mpm/services/shared/async_service_base.py +16 -27
- claude_mpm/services/shared/lifecycle_service_base.py +1 -14
- claude_mpm/services/socketio/handlers/__init__.py +5 -2
- claude_mpm/services/socketio/handlers/hook.py +13 -2
- claude_mpm/services/socketio/handlers/registry.py +4 -2
- claude_mpm/services/socketio/server/main.py +10 -8
- claude_mpm/services/subprocess_launcher_service.py +14 -5
- claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +6 -5
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +8 -7
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +7 -6
- claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +5 -4
- claude_mpm/services/unified/config_strategies/validation_strategy.py +13 -9
- claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +10 -3
- claude_mpm/services/unified/deployment_strategies/local.py +6 -5
- claude_mpm/services/unified/deployment_strategies/utils.py +6 -5
- claude_mpm/services/unified/deployment_strategies/vercel.py +7 -6
- claude_mpm/services/unified/interfaces.py +3 -1
- claude_mpm/services/unified/unified_analyzer.py +14 -10
- claude_mpm/services/unified/unified_config.py +2 -1
- claude_mpm/services/unified/unified_deployment.py +9 -4
- claude_mpm/services/version_service.py +104 -1
- claude_mpm/skills/__init__.py +21 -0
- claude_mpm/skills/bundled/__init__.py +6 -0
- claude_mpm/skills/bundled/api-documentation.md +393 -0
- claude_mpm/skills/bundled/async-testing.md +571 -0
- claude_mpm/skills/bundled/code-review.md +143 -0
- claude_mpm/skills/bundled/database-migration.md +199 -0
- claude_mpm/skills/bundled/docker-containerization.md +194 -0
- claude_mpm/skills/bundled/express-local-dev.md +1429 -0
- claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
- claude_mpm/skills/bundled/git-workflow.md +414 -0
- claude_mpm/skills/bundled/imagemagick.md +204 -0
- claude_mpm/skills/bundled/json-data-handling.md +223 -0
- claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
- claude_mpm/skills/bundled/pdf.md +141 -0
- claude_mpm/skills/bundled/performance-profiling.md +567 -0
- claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
- claude_mpm/skills/bundled/security-scanning.md +327 -0
- claude_mpm/skills/bundled/systematic-debugging.md +473 -0
- claude_mpm/skills/bundled/test-driven-development.md +378 -0
- claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
- claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
- claude_mpm/skills/bundled/xlsx.md +157 -0
- claude_mpm/skills/registry.py +286 -0
- claude_mpm/skills/skill_manager.py +310 -0
- claude_mpm/storage/state_storage.py +15 -15
- claude_mpm/tools/code_tree_analyzer.py +177 -141
- claude_mpm/tools/code_tree_events.py +4 -2
- claude_mpm/utils/agent_dependency_loader.py +40 -20
- claude_mpm/utils/display_helper.py +260 -0
- claude_mpm/utils/git_analyzer.py +407 -0
- claude_mpm/utils/robust_installer.py +73 -19
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/METADATA +129 -12
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/RECORD +295 -193
- claude_mpm/dashboard/static/css/code-tree.css +0 -1639
- claude_mpm/dashboard/static/index-hub-backup.html +0 -713
- claude_mpm/dashboard/static/js/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/js/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/js/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/js/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/js/components/code-tree.js +0 -5869
- claude_mpm/dashboard/static/js/components/code-viewer.js +0 -1386
- claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +0 -425
- claude_mpm/hooks/claude_hooks/hook_handler_original.py +0 -1041
- claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +0 -347
- claude_mpm/services/agents/deployment/agent_lifecycle_manager_refactored.py +0 -575
- claude_mpm/services/project/analyzer_refactored.py +0 -450
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/WHEEL +0 -0
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.7.4.dist-info ā claude_mpm-4.18.2.dist-info}/top_level.txt +0 -0
|
@@ -16,6 +16,7 @@ import json
|
|
|
16
16
|
import sys
|
|
17
17
|
from typing import Optional
|
|
18
18
|
|
|
19
|
+
from ...core.enums import OutputFormat
|
|
19
20
|
from ...core.logger import get_logger
|
|
20
21
|
from ...services.event_aggregator import (
|
|
21
22
|
aggregator_status,
|
|
@@ -110,7 +111,10 @@ def aggregate_command(args):
|
|
|
110
111
|
result = command.execute(args)
|
|
111
112
|
|
|
112
113
|
# Print result if structured output format is requested
|
|
113
|
-
if hasattr(args, "format") and args.format in
|
|
114
|
+
if hasattr(args, "format") and str(args.format).lower() in (
|
|
115
|
+
OutputFormat.JSON,
|
|
116
|
+
OutputFormat.YAML,
|
|
117
|
+
):
|
|
114
118
|
command.print_result(result, args)
|
|
115
119
|
|
|
116
120
|
return result.exit_code
|
|
@@ -407,7 +411,7 @@ def export_command_legacy(args):
|
|
|
407
411
|
output_path = Path(f"session_{session.session_id[:8]}_export.json")
|
|
408
412
|
|
|
409
413
|
# Export based on format
|
|
410
|
-
if args.format ==
|
|
414
|
+
if str(args.format).lower() == OutputFormat.JSON:
|
|
411
415
|
# Full JSON export
|
|
412
416
|
with output_path.open("w") as f:
|
|
413
417
|
json.dump(session.to_dict(), f, indent=2)
|
|
@@ -529,7 +533,7 @@ def add_aggregate_parser(subparsers):
|
|
|
529
533
|
"--format",
|
|
530
534
|
"-f",
|
|
531
535
|
choices=["json", "summary", "events"],
|
|
532
|
-
default=
|
|
536
|
+
default=OutputFormat.JSON,
|
|
533
537
|
help="Export format (default: json)",
|
|
534
538
|
)
|
|
535
539
|
|
|
@@ -23,6 +23,7 @@ from datetime import datetime, timezone
|
|
|
23
23
|
from pathlib import Path
|
|
24
24
|
from typing import Dict, List, Optional
|
|
25
25
|
|
|
26
|
+
from ...core.enums import OutputFormat
|
|
26
27
|
from ...core.logging_config import get_logger
|
|
27
28
|
from ...services.cli.session_manager import SessionManager
|
|
28
29
|
from ..shared import BaseCommand, CommandResult
|
|
@@ -132,7 +133,11 @@ class AnalyzeCommand(BaseCommand):
|
|
|
132
133
|
self._save_output(output, args.output)
|
|
133
134
|
|
|
134
135
|
return CommandResult.success_result(
|
|
135
|
-
message=
|
|
136
|
+
message=(
|
|
137
|
+
output
|
|
138
|
+
if str(args.format).lower() == OutputFormat.TEXT
|
|
139
|
+
else "Analysis completed"
|
|
140
|
+
),
|
|
136
141
|
data=result_data,
|
|
137
142
|
)
|
|
138
143
|
|
|
@@ -422,7 +427,7 @@ class AnalyzeCommand(BaseCommand):
|
|
|
422
427
|
Returns:
|
|
423
428
|
Formatted output string
|
|
424
429
|
"""
|
|
425
|
-
if format_type ==
|
|
430
|
+
if str(format_type).lower() == OutputFormat.JSON:
|
|
426
431
|
result_data["diagrams"] = diagrams
|
|
427
432
|
return json.dumps(result_data, indent=2)
|
|
428
433
|
|
|
@@ -516,7 +521,7 @@ def analyze_command(args):
|
|
|
516
521
|
result = command.run(args)
|
|
517
522
|
|
|
518
523
|
if result.success:
|
|
519
|
-
if args.format ==
|
|
524
|
+
if str(args.format).lower() == OutputFormat.JSON:
|
|
520
525
|
print(json.dumps(result.data, indent=2))
|
|
521
526
|
else:
|
|
522
527
|
print(result.message)
|
|
@@ -540,7 +545,7 @@ if __name__ == "__main__":
|
|
|
540
545
|
parser.add_argument("--focus", nargs="+")
|
|
541
546
|
parser.add_argument("--session-id", type=str)
|
|
542
547
|
parser.add_argument("--no-session", action="store_true")
|
|
543
|
-
parser.add_argument("--format", default=
|
|
548
|
+
parser.add_argument("--format", default=OutputFormat.TEXT)
|
|
544
549
|
parser.add_argument("--output", type=Path)
|
|
545
550
|
parser.add_argument("--verbose", action="store_true")
|
|
546
551
|
|
|
@@ -37,6 +37,7 @@ except ImportError:
|
|
|
37
37
|
RICH_AVAILABLE = False
|
|
38
38
|
Console = None
|
|
39
39
|
|
|
40
|
+
from ...core.enums import OutputFormat
|
|
40
41
|
from ...core.logging_config import get_logger
|
|
41
42
|
from ...tools.code_tree_analyzer import CodeTreeAnalyzer
|
|
42
43
|
from ...tools.code_tree_builder import CodeTreeBuilder
|
|
@@ -73,7 +74,11 @@ class AnalyzeCodeCommand(BaseCommand):
|
|
|
73
74
|
return f"Path is not a directory: {path}"
|
|
74
75
|
|
|
75
76
|
# Validate output format
|
|
76
|
-
if args.output and args.output not in (
|
|
77
|
+
if args.output and str(args.output).lower() not in (
|
|
78
|
+
OutputFormat.JSON,
|
|
79
|
+
"tree",
|
|
80
|
+
"stats",
|
|
81
|
+
):
|
|
77
82
|
return f"Invalid output format: {args.output}"
|
|
78
83
|
|
|
79
84
|
return None
|
|
@@ -123,7 +128,7 @@ class AnalyzeCodeCommand(BaseCommand):
|
|
|
123
128
|
)
|
|
124
129
|
|
|
125
130
|
# Handle output format
|
|
126
|
-
if args.output ==
|
|
131
|
+
if str(args.output).lower() == OutputFormat.JSON:
|
|
127
132
|
# Output JSON to stdout
|
|
128
133
|
json.dump(analysis_result, sys.stdout, indent=2, default=str)
|
|
129
134
|
sys.stdout.write("\n")
|
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Auto-Configuration CLI Command for Claude MPM Framework
|
|
3
|
+
========================================================
|
|
4
|
+
|
|
5
|
+
WHY: This module provides a user-friendly CLI interface for the auto-configuration
|
|
6
|
+
feature, allowing users to automatically configure agents based on detected toolchain.
|
|
7
|
+
|
|
8
|
+
DESIGN DECISION: Uses rich for beautiful terminal output, implements interactive
|
|
9
|
+
confirmation, and provides comprehensive error handling. Supports both interactive
|
|
10
|
+
and non-interactive modes for flexibility.
|
|
11
|
+
|
|
12
|
+
Part of TSK-0054: Auto-Configuration Feature - Phase 5
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
import json
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import Optional
|
|
18
|
+
|
|
19
|
+
try:
|
|
20
|
+
from rich.console import Console
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
from rich.progress import BarColumn, Progress, SpinnerColumn, TextColumn
|
|
23
|
+
from rich.table import Table
|
|
24
|
+
|
|
25
|
+
RICH_AVAILABLE = True
|
|
26
|
+
except ImportError:
|
|
27
|
+
RICH_AVAILABLE = False
|
|
28
|
+
|
|
29
|
+
from ...core.enums import OperationResult
|
|
30
|
+
from ...services.agents.auto_config_manager import AutoConfigManagerService
|
|
31
|
+
from ...services.agents.observers import NullObserver
|
|
32
|
+
from ...services.core.models.agent_config import ConfigurationResult
|
|
33
|
+
from ..shared import BaseCommand, CommandResult
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class RichProgressObserver(NullObserver):
|
|
37
|
+
"""
|
|
38
|
+
Observer that displays deployment progress using Rich.
|
|
39
|
+
|
|
40
|
+
WHY: Extends NullObserver to inherit all required abstract method
|
|
41
|
+
implementations while overriding only the methods needed for
|
|
42
|
+
Rich console output.
|
|
43
|
+
"""
|
|
44
|
+
|
|
45
|
+
def __init__(self, console: "Console"):
|
|
46
|
+
"""Initialize the observer.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
console: Rich console for output
|
|
50
|
+
"""
|
|
51
|
+
self.console = console
|
|
52
|
+
self.progress = None
|
|
53
|
+
self.task_id = None
|
|
54
|
+
|
|
55
|
+
def on_agent_deployment_started(
|
|
56
|
+
self, agent_id: str, agent_name: str, index: int, total: int
|
|
57
|
+
) -> None:
|
|
58
|
+
"""Called when agent deployment starts."""
|
|
59
|
+
if not self.progress:
|
|
60
|
+
self.progress = Progress(
|
|
61
|
+
SpinnerColumn(),
|
|
62
|
+
TextColumn("[progress.description]{task.description}"),
|
|
63
|
+
BarColumn(),
|
|
64
|
+
TextColumn("[progress.percentage]{task.percentage:>3.0f}%"),
|
|
65
|
+
console=self.console,
|
|
66
|
+
)
|
|
67
|
+
self.progress.start()
|
|
68
|
+
|
|
69
|
+
self.task_id = self.progress.add_task(f"Deploying {agent_name}...", total=100)
|
|
70
|
+
|
|
71
|
+
def on_agent_deployment_progress(
|
|
72
|
+
self, agent_id: str, progress: int, message: str = ""
|
|
73
|
+
) -> None:
|
|
74
|
+
"""Called when deployment makes progress."""
|
|
75
|
+
if self.progress and self.task_id is not None:
|
|
76
|
+
self.progress.update(self.task_id, completed=progress)
|
|
77
|
+
|
|
78
|
+
def on_agent_deployment_completed(
|
|
79
|
+
self, agent_id: str, agent_name: str, success: bool, error: str | None = None
|
|
80
|
+
) -> None:
|
|
81
|
+
"""Called when agent deployment completes."""
|
|
82
|
+
if self.progress and self.task_id is not None:
|
|
83
|
+
if success:
|
|
84
|
+
self.progress.update(self.task_id, completed=100)
|
|
85
|
+
self.console.print(f"ā
{agent_name} deployed successfully")
|
|
86
|
+
else:
|
|
87
|
+
error_msg = f": {error}" if error else ""
|
|
88
|
+
self.console.print(f"ā {agent_name} deployment failed{error_msg}")
|
|
89
|
+
|
|
90
|
+
def on_deployment_completed(
|
|
91
|
+
self, success_count: int, failure_count: int, duration_ms: float
|
|
92
|
+
) -> None:
|
|
93
|
+
"""Called when all deployments complete."""
|
|
94
|
+
if self.progress:
|
|
95
|
+
self.progress.stop()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class AutoConfigureCommand(BaseCommand):
|
|
99
|
+
"""
|
|
100
|
+
Handle auto-configuration CLI commands.
|
|
101
|
+
|
|
102
|
+
This command provides a user-friendly interface for automatically configuring
|
|
103
|
+
agents based on detected project toolchain.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def __init__(self):
|
|
107
|
+
"""Initialize the auto-configure command."""
|
|
108
|
+
super().__init__("auto-configure")
|
|
109
|
+
self.console = Console() if RICH_AVAILABLE else None
|
|
110
|
+
self._auto_config_manager = None
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def auto_config_manager(self) -> AutoConfigManagerService:
|
|
114
|
+
"""Get auto-configuration manager (lazy loaded)."""
|
|
115
|
+
if self._auto_config_manager is None:
|
|
116
|
+
from ...services.agents.auto_config_manager import (
|
|
117
|
+
AutoConfigManagerService,
|
|
118
|
+
)
|
|
119
|
+
from ...services.agents.recommender import AgentRecommenderService
|
|
120
|
+
from ...services.agents.registry import AgentRegistry
|
|
121
|
+
from ...services.project.toolchain_analyzer import (
|
|
122
|
+
ToolchainAnalyzerService,
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Initialize services with dependency injection
|
|
126
|
+
toolchain_analyzer = ToolchainAnalyzerService()
|
|
127
|
+
agent_registry = AgentRegistry()
|
|
128
|
+
agent_recommender = AgentRecommenderService()
|
|
129
|
+
|
|
130
|
+
# Get deployment service
|
|
131
|
+
try:
|
|
132
|
+
from ...services.agents.deployment import AgentDeploymentService
|
|
133
|
+
|
|
134
|
+
agent_deployment = AgentDeploymentService()
|
|
135
|
+
except ImportError:
|
|
136
|
+
agent_deployment = None
|
|
137
|
+
|
|
138
|
+
self._auto_config_manager = AutoConfigManagerService(
|
|
139
|
+
toolchain_analyzer=toolchain_analyzer,
|
|
140
|
+
agent_recommender=agent_recommender,
|
|
141
|
+
agent_registry=agent_registry,
|
|
142
|
+
agent_deployment=agent_deployment,
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return self._auto_config_manager
|
|
146
|
+
|
|
147
|
+
def validate_args(self, args) -> Optional[str]:
|
|
148
|
+
"""Validate command arguments."""
|
|
149
|
+
# Validate project path
|
|
150
|
+
project_path = (
|
|
151
|
+
Path(args.project_path)
|
|
152
|
+
if hasattr(args, "project_path") and args.project_path
|
|
153
|
+
else Path.cwd()
|
|
154
|
+
)
|
|
155
|
+
if not project_path.exists():
|
|
156
|
+
return f"Project path does not exist: {project_path}"
|
|
157
|
+
|
|
158
|
+
# Validate min_confidence range
|
|
159
|
+
if hasattr(args, "min_confidence") and args.min_confidence:
|
|
160
|
+
if not 0.0 <= args.min_confidence <= 1.0:
|
|
161
|
+
return "min_confidence must be between 0.0 and 1.0"
|
|
162
|
+
|
|
163
|
+
return None
|
|
164
|
+
|
|
165
|
+
def run(self, args) -> CommandResult:
|
|
166
|
+
"""
|
|
167
|
+
Execute auto-configuration command.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
CommandResult with success status and exit code
|
|
171
|
+
"""
|
|
172
|
+
try:
|
|
173
|
+
# Setup logging
|
|
174
|
+
self.setup_logging(args)
|
|
175
|
+
|
|
176
|
+
# Validate arguments
|
|
177
|
+
error = self.validate_args(args)
|
|
178
|
+
if error:
|
|
179
|
+
return CommandResult.error_result(error)
|
|
180
|
+
|
|
181
|
+
# Get configuration options
|
|
182
|
+
project_path = (
|
|
183
|
+
Path(args.project_path)
|
|
184
|
+
if hasattr(args, "project_path") and args.project_path
|
|
185
|
+
else Path.cwd()
|
|
186
|
+
)
|
|
187
|
+
min_confidence = (
|
|
188
|
+
args.min_confidence
|
|
189
|
+
if hasattr(args, "min_confidence") and args.min_confidence
|
|
190
|
+
else 0.8
|
|
191
|
+
)
|
|
192
|
+
dry_run = (
|
|
193
|
+
args.preview or args.dry_run if hasattr(args, "preview") else False
|
|
194
|
+
)
|
|
195
|
+
skip_confirmation = args.yes if hasattr(args, "yes") and args.yes else False
|
|
196
|
+
json_output = args.json if hasattr(args, "json") and args.json else False
|
|
197
|
+
|
|
198
|
+
# Run preview or full configuration
|
|
199
|
+
if dry_run or args.preview if hasattr(args, "preview") else False:
|
|
200
|
+
return self._run_preview(project_path, min_confidence, json_output)
|
|
201
|
+
return self._run_full_configuration(
|
|
202
|
+
project_path, min_confidence, skip_confirmation, json_output
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
except KeyboardInterrupt:
|
|
206
|
+
if self.console:
|
|
207
|
+
self.console.print("\n\nā Operation cancelled by user")
|
|
208
|
+
else:
|
|
209
|
+
print("\n\nOperation cancelled by user")
|
|
210
|
+
return CommandResult.error_result("Operation cancelled", exit_code=130)
|
|
211
|
+
|
|
212
|
+
except Exception as e:
|
|
213
|
+
self.logger.exception("Auto-configuration failed")
|
|
214
|
+
error_msg = f"Auto-configuration failed: {e!s}"
|
|
215
|
+
if self.console:
|
|
216
|
+
self.console.print(f"\nā {error_msg}")
|
|
217
|
+
else:
|
|
218
|
+
print(f"\n{error_msg}")
|
|
219
|
+
return CommandResult.error_result(error_msg)
|
|
220
|
+
|
|
221
|
+
def _run_preview(
|
|
222
|
+
self, project_path: Path, min_confidence: float, json_output: bool
|
|
223
|
+
) -> CommandResult:
|
|
224
|
+
"""Run configuration preview without deploying."""
|
|
225
|
+
# Show analysis spinner
|
|
226
|
+
if self.console and not json_output:
|
|
227
|
+
with self.console.status("[bold green]Analyzing project toolchain..."):
|
|
228
|
+
preview = self.auto_config_manager.preview_configuration(
|
|
229
|
+
project_path, min_confidence
|
|
230
|
+
)
|
|
231
|
+
else:
|
|
232
|
+
preview = self.auto_config_manager.preview_configuration(
|
|
233
|
+
project_path, min_confidence
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
# Output results
|
|
237
|
+
if json_output:
|
|
238
|
+
return self._output_preview_json(preview)
|
|
239
|
+
return self._display_preview(preview)
|
|
240
|
+
|
|
241
|
+
def _run_full_configuration(
|
|
242
|
+
self,
|
|
243
|
+
project_path: Path,
|
|
244
|
+
min_confidence: float,
|
|
245
|
+
skip_confirmation: bool,
|
|
246
|
+
json_output: bool,
|
|
247
|
+
) -> CommandResult:
|
|
248
|
+
"""Run full auto-configuration with deployment."""
|
|
249
|
+
# Get preview first
|
|
250
|
+
if self.console and not json_output:
|
|
251
|
+
with self.console.status("[bold green]Analyzing project toolchain..."):
|
|
252
|
+
preview = self.auto_config_manager.preview_configuration(
|
|
253
|
+
project_path, min_confidence
|
|
254
|
+
)
|
|
255
|
+
else:
|
|
256
|
+
preview = self.auto_config_manager.preview_configuration(
|
|
257
|
+
project_path, min_confidence
|
|
258
|
+
)
|
|
259
|
+
|
|
260
|
+
# Display preview (unless JSON output)
|
|
261
|
+
if not json_output:
|
|
262
|
+
self._display_preview(preview)
|
|
263
|
+
|
|
264
|
+
# Ask for confirmation (unless skipped)
|
|
265
|
+
if not skip_confirmation and not json_output:
|
|
266
|
+
if not self._confirm_deployment(preview):
|
|
267
|
+
if self.console:
|
|
268
|
+
self.console.print("\nā Operation cancelled by user")
|
|
269
|
+
else:
|
|
270
|
+
print("\nOperation cancelled by user")
|
|
271
|
+
return CommandResult.error_result("Operation cancelled", exit_code=0)
|
|
272
|
+
|
|
273
|
+
# Execute configuration
|
|
274
|
+
import asyncio
|
|
275
|
+
|
|
276
|
+
observer = RichProgressObserver(self.console) if self.console else None
|
|
277
|
+
result = asyncio.run(
|
|
278
|
+
self.auto_config_manager.auto_configure(
|
|
279
|
+
project_path,
|
|
280
|
+
confirmation_required=False, # Already confirmed above
|
|
281
|
+
dry_run=False,
|
|
282
|
+
min_confidence=min_confidence,
|
|
283
|
+
observer=observer,
|
|
284
|
+
)
|
|
285
|
+
)
|
|
286
|
+
|
|
287
|
+
# Output results
|
|
288
|
+
if json_output:
|
|
289
|
+
return self._output_result_json(result)
|
|
290
|
+
return self._display_result(result)
|
|
291
|
+
|
|
292
|
+
def _display_preview(self, preview) -> CommandResult:
|
|
293
|
+
"""Display configuration preview with Rich formatting."""
|
|
294
|
+
if not self.console:
|
|
295
|
+
# Fallback to plain text
|
|
296
|
+
return self._display_preview_plain(preview)
|
|
297
|
+
|
|
298
|
+
# Display detected toolchain
|
|
299
|
+
self.console.print("\nš Detected Toolchain:", style="bold blue")
|
|
300
|
+
if preview.detected_toolchain and preview.detected_toolchain.components:
|
|
301
|
+
toolchain_table = Table(show_header=True, header_style="bold")
|
|
302
|
+
toolchain_table.add_column("Component", style="cyan")
|
|
303
|
+
toolchain_table.add_column("Version", style="yellow")
|
|
304
|
+
toolchain_table.add_column("Confidence", style="green")
|
|
305
|
+
|
|
306
|
+
for component in preview.detected_toolchain.components:
|
|
307
|
+
confidence_pct = int(component.confidence * 100)
|
|
308
|
+
bar = "ā" * (confidence_pct // 10) + "ā" * (10 - confidence_pct // 10)
|
|
309
|
+
confidence_str = f"{bar} {confidence_pct}%"
|
|
310
|
+
|
|
311
|
+
toolchain_table.add_row(
|
|
312
|
+
(
|
|
313
|
+
component.type.value
|
|
314
|
+
if hasattr(component.type, "value")
|
|
315
|
+
else str(component.type)
|
|
316
|
+
),
|
|
317
|
+
component.version or "Unknown",
|
|
318
|
+
confidence_str,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
self.console.print(toolchain_table)
|
|
322
|
+
else:
|
|
323
|
+
self.console.print(" No toolchain detected", style="yellow")
|
|
324
|
+
|
|
325
|
+
# Display recommended agents
|
|
326
|
+
self.console.print("\nš¤ Recommended Agents:", style="bold blue")
|
|
327
|
+
if preview.recommendations:
|
|
328
|
+
for rec in preview.recommendations:
|
|
329
|
+
confidence_pct = int(rec.confidence * 100)
|
|
330
|
+
icon = "ā" if rec.confidence >= 0.8 else "ā"
|
|
331
|
+
self.console.print(
|
|
332
|
+
f" {icon} [bold]{rec.agent_id}[/bold] ({confidence_pct}% confidence)"
|
|
333
|
+
)
|
|
334
|
+
self.console.print(f" Reason: {rec.reasoning}", style="dim")
|
|
335
|
+
else:
|
|
336
|
+
self.console.print(" No agents recommended", style="yellow")
|
|
337
|
+
|
|
338
|
+
# Display validation issues
|
|
339
|
+
if preview.validation_result and preview.validation_result.issues:
|
|
340
|
+
self.console.print("\nā ļø Validation Issues:", style="bold yellow")
|
|
341
|
+
for issue in preview.validation_result.issues:
|
|
342
|
+
severity_icon = {"error": "ā", "warning": "ā ļø", "info": "ā¹ļø"}.get(
|
|
343
|
+
(
|
|
344
|
+
issue.severity.value
|
|
345
|
+
if hasattr(issue.severity, "value")
|
|
346
|
+
else str(issue.severity)
|
|
347
|
+
),
|
|
348
|
+
"ā¢",
|
|
349
|
+
)
|
|
350
|
+
self.console.print(f" {severity_icon} {issue.message}", style="yellow")
|
|
351
|
+
|
|
352
|
+
return CommandResult.success_result()
|
|
353
|
+
|
|
354
|
+
def _display_preview_plain(self, preview) -> CommandResult:
|
|
355
|
+
"""Display preview in plain text (fallback when Rich not available)."""
|
|
356
|
+
print("\nDetected Toolchain:")
|
|
357
|
+
if preview.detected_toolchain and preview.detected_toolchain.components:
|
|
358
|
+
for component in preview.detected_toolchain.components:
|
|
359
|
+
confidence_pct = int(component.confidence * 100)
|
|
360
|
+
print(f" - {component.type}: {component.version} ({confidence_pct}%)")
|
|
361
|
+
else:
|
|
362
|
+
print(" No toolchain detected")
|
|
363
|
+
|
|
364
|
+
print("\nRecommended Agents:")
|
|
365
|
+
if preview.recommendations:
|
|
366
|
+
for rec in preview.recommendations:
|
|
367
|
+
confidence_pct = int(rec.confidence * 100)
|
|
368
|
+
print(f" - {rec.agent_id} ({confidence_pct}%)")
|
|
369
|
+
print(f" Reason: {rec.reasoning}")
|
|
370
|
+
else:
|
|
371
|
+
print(" No agents recommended")
|
|
372
|
+
|
|
373
|
+
if preview.validation_result and preview.validation_result.issues:
|
|
374
|
+
print("\nValidation Issues:")
|
|
375
|
+
for issue in preview.validation_result.issues:
|
|
376
|
+
print(f" - {issue.severity}: {issue.message}")
|
|
377
|
+
|
|
378
|
+
return CommandResult.success_result()
|
|
379
|
+
|
|
380
|
+
def _confirm_deployment(self, preview) -> bool:
|
|
381
|
+
"""Ask user to confirm deployment."""
|
|
382
|
+
if not preview.recommendations:
|
|
383
|
+
return False
|
|
384
|
+
|
|
385
|
+
if self.console:
|
|
386
|
+
self.console.print("\n" + "=" * 60)
|
|
387
|
+
self.console.print("Deploy these agents?", style="bold yellow")
|
|
388
|
+
self.console.print("=" * 60)
|
|
389
|
+
response = (
|
|
390
|
+
self.console.input("\n[bold]Proceed? (y/n/s for select):[/bold] ")
|
|
391
|
+
.strip()
|
|
392
|
+
.lower()
|
|
393
|
+
)
|
|
394
|
+
else:
|
|
395
|
+
print("\n" + "=" * 60)
|
|
396
|
+
print("Deploy these agents?")
|
|
397
|
+
print("=" * 60)
|
|
398
|
+
response = input("\nProceed? (y/n/s for select): ").strip().lower()
|
|
399
|
+
|
|
400
|
+
if response in ["y", "yes"]:
|
|
401
|
+
return True
|
|
402
|
+
if response in ["s", "select"]:
|
|
403
|
+
# TODO: Implement interactive selection
|
|
404
|
+
if self.console:
|
|
405
|
+
self.console.print(
|
|
406
|
+
"\nā ļø Interactive selection not yet implemented",
|
|
407
|
+
style="yellow",
|
|
408
|
+
)
|
|
409
|
+
else:
|
|
410
|
+
print("\nInteractive selection not yet implemented")
|
|
411
|
+
return False
|
|
412
|
+
return False
|
|
413
|
+
|
|
414
|
+
def _display_result(self, result: ConfigurationResult) -> CommandResult:
|
|
415
|
+
"""Display configuration result."""
|
|
416
|
+
if not self.console:
|
|
417
|
+
return self._display_result_plain(result)
|
|
418
|
+
|
|
419
|
+
# Display summary
|
|
420
|
+
if result.status == OperationResult.SUCCESS:
|
|
421
|
+
panel = Panel(
|
|
422
|
+
f"ā
Auto-configuration completed successfully!\n\n"
|
|
423
|
+
f"Deployed {len(result.deployed_agents)} agent(s)",
|
|
424
|
+
title="Success",
|
|
425
|
+
border_style="green",
|
|
426
|
+
)
|
|
427
|
+
self.console.print(panel)
|
|
428
|
+
|
|
429
|
+
# Show deployed agents
|
|
430
|
+
if result.deployed_agents:
|
|
431
|
+
self.console.print("\nš¦ Deployed Agents:", style="bold green")
|
|
432
|
+
for agent_id in result.deployed_agents:
|
|
433
|
+
self.console.print(f" ā {agent_id}")
|
|
434
|
+
|
|
435
|
+
return CommandResult.success_result()
|
|
436
|
+
|
|
437
|
+
if result.status == OperationResult.WARNING:
|
|
438
|
+
panel = Panel(
|
|
439
|
+
f"ā ļø Auto-configuration partially completed\n\n"
|
|
440
|
+
f"Deployed: {len(result.deployed_agents)}\n"
|
|
441
|
+
f"Failed: {len(result.failed_agents)}",
|
|
442
|
+
title="Partial Success",
|
|
443
|
+
border_style="yellow",
|
|
444
|
+
)
|
|
445
|
+
self.console.print(panel)
|
|
446
|
+
|
|
447
|
+
if result.failed_agents:
|
|
448
|
+
self.console.print("\nā Failed Agents:", style="bold red")
|
|
449
|
+
for agent_id in result.failed_agents:
|
|
450
|
+
error = result.errors.get(agent_id, "Unknown error")
|
|
451
|
+
self.console.print(f" ā {agent_id}: {error}")
|
|
452
|
+
|
|
453
|
+
return CommandResult.error_result("Partial configuration", exit_code=1)
|
|
454
|
+
|
|
455
|
+
panel = Panel(
|
|
456
|
+
f"ā Auto-configuration failed\n\n{result.errors.get('general', 'Unknown error')}",
|
|
457
|
+
title="Error",
|
|
458
|
+
border_style="red",
|
|
459
|
+
)
|
|
460
|
+
self.console.print(panel)
|
|
461
|
+
|
|
462
|
+
return CommandResult.error_result("Configuration failed", exit_code=1)
|
|
463
|
+
|
|
464
|
+
def _display_result_plain(self, result: ConfigurationResult) -> CommandResult:
|
|
465
|
+
"""Display result in plain text (fallback)."""
|
|
466
|
+
if result.status == OperationResult.SUCCESS:
|
|
467
|
+
print("\nā
Auto-configuration completed successfully!")
|
|
468
|
+
print(f"Deployed {len(result.deployed_agents)} agent(s)")
|
|
469
|
+
|
|
470
|
+
if result.deployed_agents:
|
|
471
|
+
print("\nDeployed Agents:")
|
|
472
|
+
for agent_id in result.deployed_agents:
|
|
473
|
+
print(f" - {agent_id}")
|
|
474
|
+
|
|
475
|
+
return CommandResult.success_result()
|
|
476
|
+
|
|
477
|
+
if result.status == OperationResult.WARNING:
|
|
478
|
+
print("\nā ļø Auto-configuration partially completed")
|
|
479
|
+
print(f"Deployed: {len(result.deployed_agents)}")
|
|
480
|
+
print(f"Failed: {len(result.failed_agents)}")
|
|
481
|
+
|
|
482
|
+
if result.failed_agents:
|
|
483
|
+
print("\nFailed Agents:")
|
|
484
|
+
for agent_id in result.failed_agents:
|
|
485
|
+
error = result.errors.get(agent_id, "Unknown error")
|
|
486
|
+
print(f" - {agent_id}: {error}")
|
|
487
|
+
|
|
488
|
+
return CommandResult.error_result("Partial configuration", exit_code=1)
|
|
489
|
+
|
|
490
|
+
print("\nā Auto-configuration failed")
|
|
491
|
+
print(result.errors.get("general", "Unknown error"))
|
|
492
|
+
|
|
493
|
+
return CommandResult.error_result("Configuration failed", exit_code=1)
|
|
494
|
+
|
|
495
|
+
def _output_preview_json(self, preview) -> CommandResult:
|
|
496
|
+
"""Output preview as JSON."""
|
|
497
|
+
output = {
|
|
498
|
+
"detected_toolchain": {
|
|
499
|
+
"components": (
|
|
500
|
+
[
|
|
501
|
+
{
|
|
502
|
+
"type": (
|
|
503
|
+
c.type.value
|
|
504
|
+
if hasattr(c.type, "value")
|
|
505
|
+
else str(c.type)
|
|
506
|
+
),
|
|
507
|
+
"version": c.version,
|
|
508
|
+
"confidence": c.confidence,
|
|
509
|
+
}
|
|
510
|
+
for c in preview.detected_toolchain.components
|
|
511
|
+
]
|
|
512
|
+
if preview.detected_toolchain
|
|
513
|
+
else []
|
|
514
|
+
)
|
|
515
|
+
},
|
|
516
|
+
"recommendations": [
|
|
517
|
+
{
|
|
518
|
+
"agent_id": r.agent_id,
|
|
519
|
+
"confidence": r.confidence,
|
|
520
|
+
"reasoning": r.reasoning,
|
|
521
|
+
}
|
|
522
|
+
for r in preview.recommendations
|
|
523
|
+
],
|
|
524
|
+
"validation": {
|
|
525
|
+
"is_valid": (
|
|
526
|
+
preview.validation_result.is_valid
|
|
527
|
+
if preview.validation_result
|
|
528
|
+
else True
|
|
529
|
+
),
|
|
530
|
+
"issues": (
|
|
531
|
+
[
|
|
532
|
+
{
|
|
533
|
+
"severity": (
|
|
534
|
+
i.severity.value
|
|
535
|
+
if hasattr(i.severity, "value")
|
|
536
|
+
else str(i.severity)
|
|
537
|
+
),
|
|
538
|
+
"message": i.message,
|
|
539
|
+
}
|
|
540
|
+
for i in preview.validation_result.issues
|
|
541
|
+
]
|
|
542
|
+
if preview.validation_result
|
|
543
|
+
else []
|
|
544
|
+
),
|
|
545
|
+
},
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
print(json.dumps(output, indent=2))
|
|
549
|
+
return CommandResult.success_result(data=output)
|
|
550
|
+
|
|
551
|
+
def _output_result_json(self, result: ConfigurationResult) -> CommandResult:
|
|
552
|
+
"""Output result as JSON."""
|
|
553
|
+
output = {
|
|
554
|
+
"status": (
|
|
555
|
+
result.status.value
|
|
556
|
+
if hasattr(result.status, "value")
|
|
557
|
+
else str(result.status)
|
|
558
|
+
),
|
|
559
|
+
"deployed_agents": result.deployed_agents,
|
|
560
|
+
"failed_agents": result.failed_agents,
|
|
561
|
+
"errors": result.errors,
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
print(json.dumps(output, indent=2))
|
|
565
|
+
|
|
566
|
+
if result.status == OperationResult.SUCCESS:
|
|
567
|
+
return CommandResult.success_result(data=output)
|
|
568
|
+
return CommandResult.error_result(
|
|
569
|
+
"Configuration failed or partial", exit_code=1, data=output
|
|
570
|
+
)
|