claude-mpm 4.24.0__py3-none-any.whl → 5.0.9__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/BASE_PM.md +12 -0
- claude_mpm/agents/OUTPUT_STYLE.md +3 -48
- claude_mpm/agents/PM_INSTRUCTIONS.md +721 -911
- claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
- claude_mpm/agents/WORKFLOW.md +4 -4
- claude_mpm/agents/__init__.py +6 -0
- claude_mpm/agents/agent_loader.py +1 -4
- claude_mpm/agents/base_agent.json +6 -3
- claude_mpm/agents/base_agent_loader.py +10 -35
- claude_mpm/agents/frontmatter_validator.py +1 -1
- claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +370 -3
- claude_mpm/agents/templates/context-management-examples.md +544 -0
- claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +48 -0
- claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
- claude_mpm/agents/templates/research-gate-examples.md +669 -0
- claude_mpm/agents/templates/structured-questions-examples.md +615 -0
- claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
- claude_mpm/agents/templates/ticketing-examples.md +277 -0
- claude_mpm/cli/__init__.py +38 -2
- claude_mpm/cli/commands/__init__.py +2 -0
- claude_mpm/cli/commands/agent_source.py +774 -0
- claude_mpm/cli/commands/agent_state_manager.py +188 -30
- claude_mpm/cli/commands/agents.py +959 -36
- claude_mpm/cli/commands/agents_cleanup.py +210 -0
- claude_mpm/cli/commands/agents_discover.py +338 -0
- claude_mpm/cli/commands/aggregate.py +1 -1
- claude_mpm/cli/commands/analyze.py +3 -3
- claude_mpm/cli/commands/auto_configure.py +2 -6
- claude_mpm/cli/commands/config.py +7 -4
- claude_mpm/cli/commands/configure.py +769 -45
- claude_mpm/cli/commands/configure_agent_display.py +4 -4
- claude_mpm/cli/commands/configure_navigation.py +63 -46
- claude_mpm/cli/commands/debug.py +12 -12
- claude_mpm/cli/commands/doctor.py +10 -2
- claude_mpm/cli/commands/hook_errors.py +277 -0
- claude_mpm/cli/commands/local_deploy.py +1 -4
- claude_mpm/cli/commands/mcp_install_commands.py +1 -1
- claude_mpm/cli/commands/mpm_init/core.py +49 -1
- claude_mpm/cli/commands/mpm_init/git_activity.py +10 -10
- claude_mpm/cli/commands/mpm_init/prompts.py +6 -6
- claude_mpm/cli/commands/postmortem.py +401 -0
- claude_mpm/cli/commands/run.py +123 -165
- claude_mpm/cli/commands/skill_source.py +694 -0
- claude_mpm/cli/commands/skills.py +757 -20
- claude_mpm/cli/executor.py +78 -3
- claude_mpm/cli/interactive/agent_wizard.py +955 -45
- claude_mpm/cli/parsers/agent_source_parser.py +171 -0
- claude_mpm/cli/parsers/agents_parser.py +256 -4
- claude_mpm/cli/parsers/base_parser.py +53 -0
- claude_mpm/cli/parsers/config_parser.py +96 -43
- claude_mpm/cli/parsers/skill_source_parser.py +169 -0
- claude_mpm/cli/parsers/skills_parser.py +145 -0
- claude_mpm/cli/parsers/source_parser.py +138 -0
- claude_mpm/cli/startup.py +538 -106
- claude_mpm/cli/startup_display.py +480 -0
- claude_mpm/cli/utils.py +1 -1
- claude_mpm/cli_module/commands.py +1 -1
- claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
- claude_mpm/commands/mpm-agents-detect.md +9 -0
- claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
- claude_mpm/commands/mpm-agents-recommend.md +9 -0
- claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
- claude_mpm/commands/mpm-doctor.md +9 -0
- claude_mpm/commands/mpm-help.md +14 -2
- claude_mpm/commands/mpm-init.md +27 -2
- claude_mpm/commands/mpm-monitor.md +9 -0
- claude_mpm/commands/mpm-postmortem.md +123 -0
- claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
- claude_mpm/commands/mpm-status.md +9 -0
- claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
- claude_mpm/commands/mpm-ticket-view.md +552 -0
- claude_mpm/commands/mpm-version.md +9 -0
- claude_mpm/commands/mpm.md +10 -0
- claude_mpm/config/agent_presets.py +488 -0
- claude_mpm/config/agent_sources.py +325 -0
- claude_mpm/config/skill_presets.py +392 -0
- claude_mpm/config/skill_sources.py +590 -0
- claude_mpm/constants.py +13 -0
- claude_mpm/core/claude_runner.py +5 -34
- claude_mpm/core/config.py +16 -0
- claude_mpm/core/constants.py +1 -1
- claude_mpm/core/framework/__init__.py +3 -16
- claude_mpm/core/framework/loaders/file_loader.py +54 -101
- claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
- claude_mpm/core/hook_error_memory.py +381 -0
- claude_mpm/core/hook_manager.py +41 -2
- claude_mpm/core/interactive_session.py +91 -10
- claude_mpm/core/logger.py +3 -1
- claude_mpm/core/oneshot_session.py +71 -8
- claude_mpm/core/protocols/__init__.py +23 -0
- claude_mpm/core/protocols/runner_protocol.py +103 -0
- claude_mpm/core/protocols/session_protocol.py +131 -0
- claude_mpm/core/shared/singleton_manager.py +11 -4
- claude_mpm/core/system_context.py +38 -0
- claude_mpm/dashboard/static/css/activity.css +69 -69
- claude_mpm/dashboard/static/css/connection-status.css +10 -10
- claude_mpm/dashboard/static/css/dashboard.css +15 -15
- claude_mpm/dashboard/static/js/components/activity-tree.js +178 -178
- claude_mpm/dashboard/static/js/components/agent-hierarchy.js +101 -101
- claude_mpm/dashboard/static/js/components/agent-inference.js +31 -31
- claude_mpm/dashboard/static/js/components/build-tracker.js +59 -59
- claude_mpm/dashboard/static/js/components/code-simple.js +107 -107
- claude_mpm/dashboard/static/js/components/connection-debug.js +101 -101
- claude_mpm/dashboard/static/js/components/diff-viewer.js +113 -113
- claude_mpm/dashboard/static/js/components/event-viewer.js +12 -12
- claude_mpm/dashboard/static/js/components/file-change-tracker.js +57 -57
- claude_mpm/dashboard/static/js/components/file-change-viewer.js +74 -74
- claude_mpm/dashboard/static/js/components/file-tool-tracker.js +6 -6
- claude_mpm/dashboard/static/js/components/file-viewer.js +42 -42
- claude_mpm/dashboard/static/js/components/module-viewer.js +27 -27
- claude_mpm/dashboard/static/js/components/session-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/socket-manager.js +1 -1
- claude_mpm/dashboard/static/js/components/ui-state-manager.js +14 -14
- claude_mpm/dashboard/static/js/components/unified-data-viewer.js +110 -110
- claude_mpm/dashboard/static/js/components/working-directory.js +8 -8
- claude_mpm/dashboard/static/js/connection-manager.js +76 -76
- claude_mpm/dashboard/static/js/dashboard.js +76 -58
- claude_mpm/dashboard/static/js/extension-error-handler.js +22 -22
- claude_mpm/dashboard/static/js/socket-client.js +138 -121
- claude_mpm/dashboard/templates/code_simple.html +23 -23
- claude_mpm/dashboard/templates/index.html +18 -18
- claude_mpm/experimental/cli_enhancements.py +1 -5
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +3 -1
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
- claude_mpm/hooks/failure_learning/__init__.py +2 -8
- claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
- claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
- claude_mpm/hooks/kuzu_response_hook.py +1 -5
- claude_mpm/models/git_repository.py +198 -0
- claude_mpm/scripts/claude-hook-handler.sh +3 -3
- claude_mpm/scripts/start_activity_logging.py +3 -1
- claude_mpm/services/agents/agent_builder.py +45 -9
- claude_mpm/services/agents/agent_preset_service.py +238 -0
- claude_mpm/services/agents/agent_selection_service.py +484 -0
- claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
- claude_mpm/services/agents/cache_git_manager.py +621 -0
- claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
- claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
- claude_mpm/services/agents/deployment/agent_format_converter.py +1 -1
- claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
- claude_mpm/services/agents/deployment/agent_metrics_collector.py +3 -3
- claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
- claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
- claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
- claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -3
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
- claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +2 -2
- claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
- claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
- claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
- claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
- claude_mpm/services/agents/git_source_manager.py +629 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +9 -12
- claude_mpm/services/agents/local_template_manager.py +50 -10
- claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
- claude_mpm/services/agents/sources/__init__.py +13 -0
- claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
- claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
- claude_mpm/services/agents/startup_sync.py +239 -0
- claude_mpm/services/agents/toolchain_detector.py +474 -0
- claude_mpm/services/analysis/__init__.py +25 -0
- claude_mpm/services/analysis/postmortem_reporter.py +474 -0
- claude_mpm/services/analysis/postmortem_service.py +765 -0
- claude_mpm/services/cli/session_pause_manager.py +1 -1
- claude_mpm/services/command_deployment_service.py +200 -6
- claude_mpm/services/core/base.py +7 -2
- claude_mpm/services/core/interfaces/__init__.py +1 -3
- claude_mpm/services/core/interfaces/health.py +1 -4
- claude_mpm/services/core/models/__init__.py +2 -11
- claude_mpm/services/diagnostics/checks/__init__.py +4 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +0 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
- claude_mpm/services/diagnostics/checks/instructions_check.py +1 -2
- claude_mpm/services/diagnostics/checks/mcp_check.py +0 -1
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
- claude_mpm/services/diagnostics/checks/monitor_check.py +0 -1
- claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
- claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +40 -10
- claude_mpm/services/event_bus/direct_relay.py +3 -3
- claude_mpm/services/events/consumers/logging.py +1 -2
- claude_mpm/services/git/__init__.py +21 -0
- claude_mpm/services/git/git_operations_service.py +494 -0
- claude_mpm/services/github/__init__.py +21 -0
- claude_mpm/services/github/github_cli_service.py +397 -0
- claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
- claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
- claude_mpm/services/instructions/__init__.py +9 -0
- claude_mpm/services/instructions/instruction_cache_service.py +374 -0
- claude_mpm/services/local_ops/__init__.py +3 -13
- claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
- claude_mpm/services/local_ops/health_manager.py +1 -4
- claude_mpm/services/local_ops/resource_monitor.py +1 -1
- claude_mpm/services/mcp_config_manager.py +75 -145
- claude_mpm/services/mcp_gateway/config/configuration.py +1 -1
- claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
- claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
- claude_mpm/services/mcp_gateway/server/stdio_server.py +0 -2
- claude_mpm/services/mcp_gateway/tools/kuzu_memory_service.py +6 -2
- claude_mpm/services/mcp_service_verifier.py +6 -3
- claude_mpm/services/model/model_router.py +1 -2
- claude_mpm/services/monitor/daemon.py +29 -9
- claude_mpm/services/monitor/daemon_manager.py +96 -19
- claude_mpm/services/monitor/server.py +2 -2
- claude_mpm/services/port_manager.py +1 -1
- claude_mpm/services/pr/__init__.py +14 -0
- claude_mpm/services/pr/pr_template_service.py +329 -0
- claude_mpm/services/project/documentation_manager.py +2 -1
- claude_mpm/services/project/toolchain_analyzer.py +3 -1
- claude_mpm/services/runner_configuration_service.py +16 -3
- claude_mpm/services/session_management_service.py +16 -4
- claude_mpm/services/skills/__init__.py +18 -0
- claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
- claude_mpm/services/skills/skill_discovery_service.py +568 -0
- claude_mpm/services/skills_config.py +547 -0
- claude_mpm/services/skills_deployer.py +955 -0
- claude_mpm/services/socketio/handlers/connection.py +1 -1
- claude_mpm/services/socketio/handlers/git.py +1 -1
- claude_mpm/services/socketio/server/core.py +1 -4
- claude_mpm/services/socketio/server/main.py +1 -3
- claude_mpm/services/system_instructions_service.py +1 -3
- claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +0 -3
- claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +0 -1
- claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
- claude_mpm/services/unified/unified_deployment.py +1 -5
- claude_mpm/services/version_control/conflict_resolution.py +6 -4
- claude_mpm/services/visualization/__init__.py +1 -5
- claude_mpm/services/visualization/mermaid_generator.py +2 -3
- claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +2 -2
- claude_mpm/skills/skills_registry.py +0 -1
- claude_mpm/templates/questions/__init__.py +38 -0
- claude_mpm/templates/questions/base.py +193 -0
- claude_mpm/templates/questions/pr_strategy.py +311 -0
- claude_mpm/templates/questions/project_init.py +385 -0
- claude_mpm/templates/questions/ticket_mgmt.py +394 -0
- claude_mpm/tools/__main__.py +8 -8
- claude_mpm/utils/agent_dependency_loader.py +77 -10
- claude_mpm/utils/agent_filters.py +288 -0
- claude_mpm/utils/dependency_cache.py +3 -1
- claude_mpm/utils/gitignore.py +241 -0
- claude_mpm/utils/migration.py +372 -0
- claude_mpm/utils/progress.py +387 -0
- claude_mpm/utils/robust_installer.py +2 -4
- claude_mpm/utils/structured_questions.py +619 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/METADATA +396 -43
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/RECORD +268 -422
- claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -17
- claude_mpm/agents/templates/.claude-mpm/memories/engineer_memories.md +0 -3
- claude_mpm/agents/templates/agent-manager.json +0 -273
- claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
- claude_mpm/agents/templates/api_qa.json +0 -183
- claude_mpm/agents/templates/clerk-ops.json +0 -235
- claude_mpm/agents/templates/code_analyzer.json +0 -101
- claude_mpm/agents/templates/content-agent.json +0 -358
- claude_mpm/agents/templates/dart_engineer.json +0 -307
- claude_mpm/agents/templates/data_engineer.json +0 -225
- claude_mpm/agents/templates/documentation.json +0 -238
- claude_mpm/agents/templates/engineer.json +0 -210
- claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
- claude_mpm/agents/templates/golang_engineer.json +0 -270
- claude_mpm/agents/templates/imagemagick.json +0 -264
- claude_mpm/agents/templates/java_engineer.json +0 -346
- claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
- claude_mpm/agents/templates/local_ops_agent.json +0 -1840
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250826_014258_728.md +0 -39
- claude_mpm/agents/templates/logs/prompts/agent_engineer_20250901_010124_142.md +0 -400
- claude_mpm/agents/templates/memory_manager.json +0 -158
- claude_mpm/agents/templates/nextjs_engineer.json +0 -285
- claude_mpm/agents/templates/ops.json +0 -185
- claude_mpm/agents/templates/php-engineer.json +0 -287
- claude_mpm/agents/templates/product_owner.json +0 -338
- claude_mpm/agents/templates/project_organizer.json +0 -144
- claude_mpm/agents/templates/prompt-engineer.json +0 -737
- claude_mpm/agents/templates/python_engineer.json +0 -387
- claude_mpm/agents/templates/qa.json +0 -243
- claude_mpm/agents/templates/react_engineer.json +0 -239
- claude_mpm/agents/templates/refactoring_engineer.json +0 -276
- claude_mpm/agents/templates/research.json +0 -188
- claude_mpm/agents/templates/ruby-engineer.json +0 -280
- claude_mpm/agents/templates/rust_engineer.json +0 -275
- claude_mpm/agents/templates/security.json +0 -202
- claude_mpm/agents/templates/svelte-engineer.json +0 -225
- claude_mpm/agents/templates/tauri_engineer.json +0 -274
- claude_mpm/agents/templates/ticketing.json +0 -178
- claude_mpm/agents/templates/typescript_engineer.json +0 -285
- claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
- claude_mpm/agents/templates/version_control.json +0 -159
- claude_mpm/agents/templates/web_qa.json +0 -400
- claude_mpm/agents/templates/web_ui.json +0 -189
- claude_mpm/commands/mpm-tickets.md +0 -151
- claude_mpm/dashboard/.claude-mpm/socketio-instances.json +0 -1
- claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
- claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
- claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
- claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
- claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
- claude_mpm/dashboard/static/archive/activity_dashboard_test.html +0 -61
- claude_mpm/dashboard/static/archive/test_activity_connection.html +0 -179
- claude_mpm/dashboard/static/archive/test_claude_tree_tab.html +0 -68
- claude_mpm/dashboard/static/archive/test_dashboard.html +0 -409
- claude_mpm/dashboard/static/archive/test_dashboard_fixed.html +0 -519
- claude_mpm/dashboard/static/archive/test_dashboard_verification.html +0 -181
- claude_mpm/dashboard/static/archive/test_file_data.html +0 -315
- claude_mpm/dashboard/static/archive/test_file_tree_empty_state.html +0 -243
- claude_mpm/dashboard/static/archive/test_file_tree_fix.html +0 -234
- claude_mpm/dashboard/static/archive/test_file_tree_rename.html +0 -117
- claude_mpm/dashboard/static/archive/test_file_tree_tab.html +0 -115
- claude_mpm/dashboard/static/archive/test_file_viewer.html +0 -224
- claude_mpm/dashboard/static/archive/test_final_activity.html +0 -220
- claude_mpm/dashboard/static/archive/test_tab_fix.html +0 -139
- claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
- claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
- claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
- claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
- claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
- claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
- claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
- claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
- claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
- claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
- claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
- claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
- claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
- claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/built/connection-manager.js +0 -536
- claude_mpm/dashboard/static/built/dashboard.js +0 -2
- claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
- claude_mpm/dashboard/static/built/react/events.js +0 -30
- claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
- claude_mpm/dashboard/static/built/shared/logger.js +0 -385
- claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
- claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/built/socket-client.js +0 -2
- claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
- claude_mpm/dashboard/static/dist/assets/events.DjpNxWNo.css +0 -1
- claude_mpm/dashboard/static/dist/components/activity-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/agent-inference.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-tree.js +0 -2
- claude_mpm/dashboard/static/dist/components/code-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-processor.js +0 -2
- claude_mpm/dashboard/static/dist/components/event-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/export-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +0 -2
- claude_mpm/dashboard/static/dist/components/file-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-library-loader.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/hud-visualizer.js +0 -2
- claude_mpm/dashboard/static/dist/components/module-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/session-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/socket-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/ui-state-manager.js +0 -2
- claude_mpm/dashboard/static/dist/components/unified-data-viewer.js +0 -2
- claude_mpm/dashboard/static/dist/components/working-directory.js +0 -2
- claude_mpm/dashboard/static/dist/dashboard.js +0 -2
- claude_mpm/dashboard/static/dist/react/events.js +0 -30
- claude_mpm/dashboard/static/dist/socket-client.js +0 -2
- claude_mpm/dashboard/static/events.html +0 -607
- claude_mpm/dashboard/static/index.html +0 -635
- claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
- claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
- claude_mpm/dashboard/static/js/shared/logger.js +0 -385
- claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
- claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
- claude_mpm/dashboard/static/legacy/activity.html +0 -736
- claude_mpm/dashboard/static/legacy/agents.html +0 -786
- claude_mpm/dashboard/static/legacy/files.html +0 -747
- claude_mpm/dashboard/static/legacy/tools.html +0 -831
- claude_mpm/dashboard/static/monitors.html +0 -431
- claude_mpm/dashboard/static/production/events.html +0 -659
- claude_mpm/dashboard/static/production/main.html +0 -698
- claude_mpm/dashboard/static/production/monitors.html +0 -483
- claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
- claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
- claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
- claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
- claude_mpm/dashboard/static/test-archive/test_debug.html +0 -25
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
- /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
- /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
- /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
- /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/WHEEL +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/entry_points.txt +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-4.24.0.dist-info → claude_mpm-5.0.9.dist-info}/top_level.txt +0 -0
|
@@ -15,12 +15,15 @@ import json
|
|
|
15
15
|
from pathlib import Path
|
|
16
16
|
from typing import Dict, List, Optional
|
|
17
17
|
|
|
18
|
+
import questionary
|
|
19
|
+
from questionary import Style
|
|
18
20
|
from rich.console import Console
|
|
19
21
|
from rich.prompt import Confirm, Prompt
|
|
20
22
|
from rich.text import Text
|
|
21
23
|
|
|
22
24
|
from ...core.config import Config
|
|
23
25
|
from ...services.version_service import VersionService
|
|
26
|
+
from ...utils.agent_filters import apply_all_filters, get_deployed_agent_ids
|
|
24
27
|
from ...utils.console import console as default_console
|
|
25
28
|
from ..shared import BaseCommand, CommandResult
|
|
26
29
|
from .agent_state_manager import SimpleAgentManager
|
|
@@ -41,6 +44,21 @@ from .configure_validators import (
|
|
|
41
44
|
class ConfigureCommand(BaseCommand):
|
|
42
45
|
"""Interactive configuration management command."""
|
|
43
46
|
|
|
47
|
+
# Questionary style optimized for dark terminals (WCAG AAA compliant)
|
|
48
|
+
QUESTIONARY_STYLE = Style(
|
|
49
|
+
[
|
|
50
|
+
("selected", "fg:#e0e0e0 bold"), # Light gray - excellent readability
|
|
51
|
+
("pointer", "fg:#ffd700 bold"), # Gold/yellow - highly visible pointer
|
|
52
|
+
("highlighted", "fg:#e0e0e0"), # Light gray - clear hover state
|
|
53
|
+
("question", "fg:#e0e0e0 bold"), # Light gray bold - prominent questions
|
|
54
|
+
("checkbox", "fg:#00ff00"), # Green - for checked boxes
|
|
55
|
+
(
|
|
56
|
+
"checkbox-selected",
|
|
57
|
+
"fg:#00ff00 bold",
|
|
58
|
+
), # Green bold - for checked selected boxes
|
|
59
|
+
]
|
|
60
|
+
)
|
|
61
|
+
|
|
44
62
|
def __init__(self):
|
|
45
63
|
super().__init__("configure")
|
|
46
64
|
self.console = default_console
|
|
@@ -284,61 +302,118 @@ class ConfigureCommand(BaseCommand):
|
|
|
284
302
|
return self.navigation.show_main_menu()
|
|
285
303
|
|
|
286
304
|
def _manage_agents(self) -> None:
|
|
287
|
-
"""
|
|
305
|
+
"""Enhanced agent management with remote agent discovery and installation."""
|
|
288
306
|
while True:
|
|
289
307
|
self.console.clear()
|
|
290
|
-
self.
|
|
308
|
+
self.navigation.display_header()
|
|
309
|
+
self.console.print("\n[bold blue]═══ Agent Management ═══[/bold blue]\n")
|
|
310
|
+
|
|
311
|
+
# Step 1: Show configured sources
|
|
312
|
+
self.console.print("[bold white]═══ Agent Sources ═══[/bold white]\n")
|
|
313
|
+
|
|
314
|
+
sources = self._get_configured_sources()
|
|
315
|
+
if sources:
|
|
316
|
+
from rich.table import Table
|
|
317
|
+
|
|
318
|
+
sources_table = Table(show_header=True, header_style="bold white")
|
|
319
|
+
sources_table.add_column(
|
|
320
|
+
"Source",
|
|
321
|
+
style="bright_yellow",
|
|
322
|
+
width=40,
|
|
323
|
+
no_wrap=True,
|
|
324
|
+
overflow="ellipsis",
|
|
325
|
+
)
|
|
326
|
+
sources_table.add_column(
|
|
327
|
+
"Status", style="green", width=15, no_wrap=True
|
|
328
|
+
)
|
|
329
|
+
sources_table.add_column(
|
|
330
|
+
"Agents", style="yellow", width=10, no_wrap=True
|
|
331
|
+
)
|
|
291
332
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
333
|
+
for source in sources:
|
|
334
|
+
status = "✓ Active" if source.get("enabled", True) else "Disabled"
|
|
335
|
+
agent_count = source.get("agent_count", "?")
|
|
336
|
+
sources_table.add_row(
|
|
337
|
+
source["identifier"], status, str(agent_count)
|
|
338
|
+
)
|
|
295
339
|
|
|
296
|
-
|
|
297
|
-
|
|
340
|
+
self.console.print(sources_table)
|
|
341
|
+
else:
|
|
342
|
+
self.console.print("[yellow]No agent sources configured[/yellow]")
|
|
343
|
+
self.console.print(
|
|
344
|
+
"[dim]Default source 'bobmatnyc/claude-mpm-agents' will be used[/dim]\n"
|
|
345
|
+
)
|
|
298
346
|
|
|
299
|
-
#
|
|
300
|
-
|
|
301
|
-
text_t.append("[t]", style="bold blue")
|
|
302
|
-
text_t.append(" Toggle agents (enable/disable multiple)")
|
|
303
|
-
self.console.print(text_t)
|
|
347
|
+
# Step 2: Discover and display available agents
|
|
348
|
+
self.console.print("\n[bold white]═══ Available Agents ═══[/bold white]\n")
|
|
304
349
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
350
|
+
try:
|
|
351
|
+
# Discover agents (includes both local and remote)
|
|
352
|
+
agents = self.agent_manager.discover_agents(include_remote=True)
|
|
353
|
+
|
|
354
|
+
# Set deployment status on each agent for display
|
|
355
|
+
deployed_ids = get_deployed_agent_ids()
|
|
356
|
+
for agent in agents:
|
|
357
|
+
# Extract leaf name for comparison
|
|
358
|
+
agent_leaf_name = agent.name.split("/")[-1]
|
|
359
|
+
agent.is_deployed = agent_leaf_name in deployed_ids
|
|
309
360
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
text_v.append(" View agent details")
|
|
313
|
-
self.console.print(text_v)
|
|
361
|
+
# Filter BASE_AGENT from display (1M-502 Phase 1)
|
|
362
|
+
agents = self._filter_agent_configs(agents, filter_deployed=False)
|
|
314
363
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
364
|
+
if not agents:
|
|
365
|
+
self.console.print("[yellow]No agents found[/yellow]")
|
|
366
|
+
self.console.print(
|
|
367
|
+
"[dim]Configure sources with 'claude-mpm agent-source add'[/dim]\n"
|
|
368
|
+
)
|
|
369
|
+
else:
|
|
370
|
+
# Display agents in a table (already filtered at line 339)
|
|
371
|
+
self._display_agents_with_source_info(agents)
|
|
319
372
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
self.console.print(text_b)
|
|
373
|
+
except Exception as e:
|
|
374
|
+
self.console.print(f"[red]Error discovering agents: {e}[/red]")
|
|
375
|
+
self.logger.error(f"Agent discovery failed: {e}", exc_info=True)
|
|
324
376
|
|
|
377
|
+
# Step 3: Menu options with arrow-key navigation
|
|
325
378
|
self.console.print()
|
|
379
|
+
try:
|
|
380
|
+
choice = questionary.select(
|
|
381
|
+
"Agent Management:",
|
|
382
|
+
choices=[
|
|
383
|
+
"Manage sources (add/remove repositories)",
|
|
384
|
+
"Select Agents",
|
|
385
|
+
"Install preset (predefined sets)",
|
|
386
|
+
"Remove agents",
|
|
387
|
+
"View agent details",
|
|
388
|
+
"Toggle agents (legacy enable/disable)",
|
|
389
|
+
questionary.Separator(),
|
|
390
|
+
"← Back to main menu",
|
|
391
|
+
],
|
|
392
|
+
style=self.QUESTIONARY_STYLE,
|
|
393
|
+
).ask()
|
|
394
|
+
|
|
395
|
+
if choice is None or choice == "← Back to main menu":
|
|
396
|
+
break
|
|
326
397
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
398
|
+
agents_var = agents if "agents" in locals() else []
|
|
399
|
+
|
|
400
|
+
# Map selection to action
|
|
401
|
+
if choice == "Manage sources (add/remove repositories)":
|
|
402
|
+
self._manage_sources()
|
|
403
|
+
elif choice == "Select Agents":
|
|
404
|
+
self._deploy_agents_individual(agents_var)
|
|
405
|
+
elif choice == "Install preset (predefined sets)":
|
|
406
|
+
self._deploy_agents_preset()
|
|
407
|
+
elif choice == "Remove agents":
|
|
408
|
+
self._remove_agents(agents_var)
|
|
409
|
+
elif choice == "View agent details":
|
|
410
|
+
self._view_agent_details_enhanced(agents_var)
|
|
411
|
+
elif choice == "Toggle agents (legacy enable/disable)":
|
|
412
|
+
self._toggle_agents_interactive(agents_var)
|
|
413
|
+
|
|
414
|
+
except KeyboardInterrupt:
|
|
415
|
+
self.console.print("\n[yellow]Operation cancelled[/yellow]")
|
|
330
416
|
break
|
|
331
|
-
if choice == "t":
|
|
332
|
-
self._toggle_agents_interactive(agents)
|
|
333
|
-
elif choice == "c":
|
|
334
|
-
self._customize_agent_template(agents)
|
|
335
|
-
elif choice == "v":
|
|
336
|
-
self._view_agent_details(agents)
|
|
337
|
-
elif choice == "r":
|
|
338
|
-
self._reset_agent_defaults(agents)
|
|
339
|
-
else:
|
|
340
|
-
self.console.print("[red]Invalid choice.[/red]")
|
|
341
|
-
Prompt.ask("Press Enter to continue")
|
|
342
417
|
|
|
343
418
|
def _display_agents_table(self, agents: List[AgentConfig]) -> None:
|
|
344
419
|
"""Display a table of available agents."""
|
|
@@ -511,6 +586,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
511
586
|
|
|
512
587
|
# Get list of enabled agents
|
|
513
588
|
agents = self.agent_manager.discover_agents()
|
|
589
|
+
# Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
|
|
590
|
+
agents = self._filter_agent_configs(agents, filter_deployed=False)
|
|
514
591
|
enabled_agents = [
|
|
515
592
|
a.name
|
|
516
593
|
for a in agents
|
|
@@ -554,9 +631,9 @@ class ConfigureCommand(BaseCommand):
|
|
|
554
631
|
else:
|
|
555
632
|
from rich.table import Table
|
|
556
633
|
|
|
557
|
-
table = Table(show_header=True, header_style="bold
|
|
558
|
-
table.add_column("Agent", style="
|
|
559
|
-
table.add_column("Skills", style="green")
|
|
634
|
+
table = Table(show_header=True, header_style="bold white")
|
|
635
|
+
table.add_column("Agent", style="white", no_wrap=True)
|
|
636
|
+
table.add_column("Skills", style="green", no_wrap=True)
|
|
560
637
|
|
|
561
638
|
for agent_id, skills in mappings.items():
|
|
562
639
|
skills_str = (
|
|
@@ -577,6 +654,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
577
654
|
|
|
578
655
|
# Get enabled agents
|
|
579
656
|
agents = self.agent_manager.discover_agents()
|
|
657
|
+
# Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
|
|
658
|
+
agents = self._filter_agent_configs(agents, filter_deployed=False)
|
|
580
659
|
enabled_agents = [
|
|
581
660
|
a.name
|
|
582
661
|
for a in agents
|
|
@@ -708,6 +787,8 @@ class ConfigureCommand(BaseCommand):
|
|
|
708
787
|
def _list_agents_non_interactive(self) -> CommandResult:
|
|
709
788
|
"""List agents in non-interactive mode."""
|
|
710
789
|
agents = self.agent_manager.discover_agents()
|
|
790
|
+
# Filter BASE_AGENT from all agent lists (1M-502 Phase 1)
|
|
791
|
+
agents = self._filter_agent_configs(agents, filter_deployed=False)
|
|
711
792
|
|
|
712
793
|
data = []
|
|
713
794
|
for agent in agents:
|
|
@@ -809,6 +890,649 @@ class ConfigureCommand(BaseCommand):
|
|
|
809
890
|
except Exception as e:
|
|
810
891
|
return CommandResult.error_result(f"Startup configuration failed: {e}")
|
|
811
892
|
|
|
893
|
+
# ========================================================================
|
|
894
|
+
# Enhanced Agent Management Methods (Remote Agent Discovery Integration)
|
|
895
|
+
# ========================================================================
|
|
896
|
+
|
|
897
|
+
def _get_configured_sources(self) -> List[Dict]:
|
|
898
|
+
"""Get list of configured agent sources with agent counts."""
|
|
899
|
+
try:
|
|
900
|
+
from claude_mpm.config.agent_sources import AgentSourceConfiguration
|
|
901
|
+
|
|
902
|
+
config = AgentSourceConfiguration.load()
|
|
903
|
+
|
|
904
|
+
# Convert repositories to source dictionaries
|
|
905
|
+
sources = []
|
|
906
|
+
for repo in config.repositories:
|
|
907
|
+
# Extract identifier from repository
|
|
908
|
+
identifier = repo.identifier
|
|
909
|
+
|
|
910
|
+
# Count agents in cache
|
|
911
|
+
cache_dir = (
|
|
912
|
+
Path.home() / ".claude-mpm" / "cache" / "remote-agents" / identifier
|
|
913
|
+
)
|
|
914
|
+
agent_count = 0
|
|
915
|
+
if cache_dir.exists():
|
|
916
|
+
agents_dir = cache_dir / "agents"
|
|
917
|
+
if agents_dir.exists():
|
|
918
|
+
agent_count = len(list(agents_dir.rglob("*.md")))
|
|
919
|
+
|
|
920
|
+
sources.append(
|
|
921
|
+
{
|
|
922
|
+
"identifier": identifier,
|
|
923
|
+
"url": repo.url,
|
|
924
|
+
"enabled": repo.enabled,
|
|
925
|
+
"priority": repo.priority,
|
|
926
|
+
"agent_count": agent_count,
|
|
927
|
+
}
|
|
928
|
+
)
|
|
929
|
+
|
|
930
|
+
return sources
|
|
931
|
+
except Exception as e:
|
|
932
|
+
self.logger.warning(f"Failed to get configured sources: {e}")
|
|
933
|
+
return []
|
|
934
|
+
|
|
935
|
+
def _filter_agent_configs(
|
|
936
|
+
self, agents: List[AgentConfig], filter_deployed: bool = False
|
|
937
|
+
) -> List[AgentConfig]:
|
|
938
|
+
"""Filter AgentConfig objects using agent_filters utilities.
|
|
939
|
+
|
|
940
|
+
Converts AgentConfig objects to dictionaries for filtering,
|
|
941
|
+
then back to AgentConfig. Always filters BASE_AGENT.
|
|
942
|
+
Optionally filters deployed agents.
|
|
943
|
+
|
|
944
|
+
Args:
|
|
945
|
+
agents: List of AgentConfig objects
|
|
946
|
+
filter_deployed: Whether to filter out deployed agents (default: False)
|
|
947
|
+
|
|
948
|
+
Returns:
|
|
949
|
+
Filtered list of AgentConfig objects
|
|
950
|
+
"""
|
|
951
|
+
# Convert AgentConfig to dict format for filtering
|
|
952
|
+
agent_dicts = []
|
|
953
|
+
for agent in agents:
|
|
954
|
+
agent_dicts.append(
|
|
955
|
+
{
|
|
956
|
+
"agent_id": agent.name,
|
|
957
|
+
"name": agent.name,
|
|
958
|
+
"description": agent.description,
|
|
959
|
+
"deployed": getattr(agent, "is_deployed", False),
|
|
960
|
+
}
|
|
961
|
+
)
|
|
962
|
+
|
|
963
|
+
# Apply filters (always filter BASE_AGENT)
|
|
964
|
+
filtered_dicts = apply_all_filters(
|
|
965
|
+
agent_dicts, filter_base=True, filter_deployed=filter_deployed
|
|
966
|
+
)
|
|
967
|
+
|
|
968
|
+
# Convert back to AgentConfig objects
|
|
969
|
+
filtered_names = {d["agent_id"] for d in filtered_dicts}
|
|
970
|
+
return [a for a in agents if a.name in filtered_names]
|
|
971
|
+
|
|
972
|
+
def _display_agents_with_source_info(self, agents: List[AgentConfig]) -> None:
|
|
973
|
+
"""Display agents table with source information and installation status."""
|
|
974
|
+
from rich.table import Table
|
|
975
|
+
|
|
976
|
+
agents_table = Table(show_header=True, header_style="bold white")
|
|
977
|
+
agents_table.add_column("#", style="dim", width=4, no_wrap=True)
|
|
978
|
+
agents_table.add_column(
|
|
979
|
+
"Agent ID", style="white", width=35, no_wrap=True, overflow="ellipsis"
|
|
980
|
+
)
|
|
981
|
+
agents_table.add_column(
|
|
982
|
+
"Name", style="white", width=25, no_wrap=True, overflow="ellipsis"
|
|
983
|
+
)
|
|
984
|
+
agents_table.add_column("Source", style="bright_yellow", width=20, no_wrap=True)
|
|
985
|
+
agents_table.add_column("Status", style="white", width=12, no_wrap=True)
|
|
986
|
+
|
|
987
|
+
for idx, agent in enumerate(agents, 1):
|
|
988
|
+
# Determine source with repo name
|
|
989
|
+
source_type = getattr(agent, "source_type", "local")
|
|
990
|
+
|
|
991
|
+
if source_type == "remote":
|
|
992
|
+
# Get repo name from agent metadata
|
|
993
|
+
source_dict = getattr(agent, "source_dict", {})
|
|
994
|
+
repo_url = source_dict.get("source", "")
|
|
995
|
+
|
|
996
|
+
# Extract repo name from URL
|
|
997
|
+
if (
|
|
998
|
+
"bobmatnyc/claude-mpm" in repo_url
|
|
999
|
+
or "claude-mpm" in repo_url.lower()
|
|
1000
|
+
):
|
|
1001
|
+
source_label = "MPM Agents"
|
|
1002
|
+
elif "/" in repo_url:
|
|
1003
|
+
# Extract last part of org/repo
|
|
1004
|
+
parts = repo_url.rstrip("/").split("/")
|
|
1005
|
+
if len(parts) >= 2:
|
|
1006
|
+
source_label = f"{parts[-2]}/{parts[-1]}"
|
|
1007
|
+
else:
|
|
1008
|
+
source_label = "Community"
|
|
1009
|
+
else:
|
|
1010
|
+
source_label = "Community"
|
|
1011
|
+
else:
|
|
1012
|
+
source_label = "Local"
|
|
1013
|
+
|
|
1014
|
+
# Determine installation status (removed symbols for cleaner look)
|
|
1015
|
+
is_installed = getattr(agent, "is_deployed", False)
|
|
1016
|
+
if is_installed:
|
|
1017
|
+
status = "[green]Installed[/green]"
|
|
1018
|
+
else:
|
|
1019
|
+
status = "Available"
|
|
1020
|
+
|
|
1021
|
+
# Get display name (for remote agents, use display_name instead of agent_id)
|
|
1022
|
+
display_name = getattr(agent, "display_name", agent.name)
|
|
1023
|
+
# Let overflow="ellipsis" handle truncation automatically
|
|
1024
|
+
|
|
1025
|
+
agents_table.add_row(
|
|
1026
|
+
str(idx), agent.name, display_name, source_label, status
|
|
1027
|
+
)
|
|
1028
|
+
|
|
1029
|
+
self.console.print(agents_table)
|
|
1030
|
+
self.console.print(f"\n[dim]Total: {len(agents)} agents available[/dim]")
|
|
1031
|
+
|
|
1032
|
+
def _manage_sources(self) -> None:
|
|
1033
|
+
"""Interactive source management."""
|
|
1034
|
+
self.console.print("\n[bold white]═══ Manage Agent Sources ═══[/bold white]\n")
|
|
1035
|
+
self.console.print(
|
|
1036
|
+
"[dim]Use 'claude-mpm agent-source' command to add/remove sources[/dim]"
|
|
1037
|
+
)
|
|
1038
|
+
self.console.print("\nExamples:")
|
|
1039
|
+
self.console.print(" claude-mpm agent-source add <git-url>")
|
|
1040
|
+
self.console.print(" claude-mpm agent-source remove <identifier>")
|
|
1041
|
+
self.console.print(" claude-mpm agent-source list")
|
|
1042
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1043
|
+
|
|
1044
|
+
def _deploy_agents_individual(self, agents: List[AgentConfig]) -> None:
|
|
1045
|
+
"""Manage agent installation state (unified install/remove interface)."""
|
|
1046
|
+
if not agents:
|
|
1047
|
+
self.console.print("[yellow]No agents available[/yellow]")
|
|
1048
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1049
|
+
return
|
|
1050
|
+
|
|
1051
|
+
# Get ALL agents (filter BASE_AGENT but keep deployed agents visible)
|
|
1052
|
+
from claude_mpm.utils.agent_filters import (
|
|
1053
|
+
filter_base_agents,
|
|
1054
|
+
get_deployed_agent_ids,
|
|
1055
|
+
)
|
|
1056
|
+
|
|
1057
|
+
# Filter BASE_AGENT but keep deployed agents visible
|
|
1058
|
+
all_agents = filter_base_agents(
|
|
1059
|
+
[
|
|
1060
|
+
{
|
|
1061
|
+
"agent_id": a.name,
|
|
1062
|
+
"name": a.name,
|
|
1063
|
+
"description": a.description,
|
|
1064
|
+
"deployed": getattr(a, "is_deployed", False),
|
|
1065
|
+
}
|
|
1066
|
+
for a in agents
|
|
1067
|
+
]
|
|
1068
|
+
)
|
|
1069
|
+
|
|
1070
|
+
# Get deployed agent IDs
|
|
1071
|
+
deployed_ids = get_deployed_agent_ids()
|
|
1072
|
+
|
|
1073
|
+
if not all_agents:
|
|
1074
|
+
self.console.print("[yellow]No agents available[/yellow]")
|
|
1075
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1076
|
+
return
|
|
1077
|
+
|
|
1078
|
+
# Loop to allow adjusting selection
|
|
1079
|
+
while True:
|
|
1080
|
+
# Build checkbox choices with pre-selection
|
|
1081
|
+
agent_choices = []
|
|
1082
|
+
agent_map = {} # For lookup after selection
|
|
1083
|
+
|
|
1084
|
+
for agent in agents:
|
|
1085
|
+
if agent.name in {a["agent_id"] for a in all_agents}:
|
|
1086
|
+
display_name = getattr(agent, "display_name", agent.name)
|
|
1087
|
+
|
|
1088
|
+
# Pre-check if deployed
|
|
1089
|
+
# Extract leaf name from full path for comparison with deployed_ids
|
|
1090
|
+
agent_leaf_name = agent.name.split("/")[-1]
|
|
1091
|
+
is_deployed = agent_leaf_name in deployed_ids
|
|
1092
|
+
|
|
1093
|
+
# Simple format: "agent/path - Display Name"
|
|
1094
|
+
# Checkbox state (checked/unchecked) indicates installed status
|
|
1095
|
+
choice_text = f"{agent.name}"
|
|
1096
|
+
if display_name and display_name != agent.name:
|
|
1097
|
+
choice_text += f" - {display_name}"
|
|
1098
|
+
|
|
1099
|
+
# Create choice with checked=True for deployed agents
|
|
1100
|
+
# Note: questionary's default param is for single-select only
|
|
1101
|
+
# For multi-select, must use checked=True on Choice objects
|
|
1102
|
+
choice = questionary.Choice(
|
|
1103
|
+
title=choice_text, value=agent.name, checked=is_deployed
|
|
1104
|
+
)
|
|
1105
|
+
|
|
1106
|
+
agent_choices.append(choice)
|
|
1107
|
+
agent_map[agent.name] = agent
|
|
1108
|
+
|
|
1109
|
+
# Multi-select with pre-selection
|
|
1110
|
+
self.console.print("\n[bold cyan]Manage Agent Installation[/bold cyan]")
|
|
1111
|
+
self.console.print("[dim]✓ Checked = Installed (uncheck to remove)[/dim]")
|
|
1112
|
+
self.console.print("[dim]○ Unchecked = Available (check to install)[/dim]")
|
|
1113
|
+
self.console.print(
|
|
1114
|
+
"[dim]Use arrow keys to navigate, space to toggle, "
|
|
1115
|
+
"Enter to apply changes[/dim]\n"
|
|
1116
|
+
)
|
|
1117
|
+
|
|
1118
|
+
# Pre-selection via checked=True on Choice objects
|
|
1119
|
+
# (questionary's default param is for single-select only)
|
|
1120
|
+
selected_agent_ids = questionary.checkbox(
|
|
1121
|
+
"Agents:", choices=agent_choices, style=self.QUESTIONARY_STYLE
|
|
1122
|
+
).ask()
|
|
1123
|
+
|
|
1124
|
+
# Handle Esc
|
|
1125
|
+
if selected_agent_ids is None:
|
|
1126
|
+
self.console.print("[yellow]No changes made[/yellow]")
|
|
1127
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1128
|
+
return
|
|
1129
|
+
|
|
1130
|
+
# Convert to sets for comparison
|
|
1131
|
+
selected_set = set(selected_agent_ids)
|
|
1132
|
+
deployed_set = deployed_ids
|
|
1133
|
+
|
|
1134
|
+
# Determine actions
|
|
1135
|
+
to_deploy = selected_set - deployed_set # Selected but not deployed
|
|
1136
|
+
to_remove = deployed_set - selected_set # Deployed but not selected
|
|
1137
|
+
|
|
1138
|
+
if not to_deploy and not to_remove:
|
|
1139
|
+
self.console.print("[yellow]No changes made[/yellow]")
|
|
1140
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1141
|
+
return
|
|
1142
|
+
|
|
1143
|
+
# Show what will happen
|
|
1144
|
+
self.console.print("\n[bold]Changes to apply:[/bold]")
|
|
1145
|
+
if to_deploy:
|
|
1146
|
+
self.console.print(f"[green]Install {len(to_deploy)} agent(s)[/green]")
|
|
1147
|
+
for agent_id in to_deploy:
|
|
1148
|
+
self.console.print(f" + {agent_id}")
|
|
1149
|
+
if to_remove:
|
|
1150
|
+
self.console.print(f"[red]Remove {len(to_remove)} agent(s)[/red]")
|
|
1151
|
+
for agent_id in to_remove:
|
|
1152
|
+
self.console.print(f" - {agent_id}")
|
|
1153
|
+
|
|
1154
|
+
# Ask user to confirm, adjust, or cancel
|
|
1155
|
+
action = questionary.select(
|
|
1156
|
+
"\nWhat would you like to do?",
|
|
1157
|
+
choices=[
|
|
1158
|
+
questionary.Choice("Apply these changes", value="apply"),
|
|
1159
|
+
questionary.Choice("Adjust selection", value="adjust"),
|
|
1160
|
+
questionary.Choice("Cancel", value="cancel"),
|
|
1161
|
+
],
|
|
1162
|
+
default="apply",
|
|
1163
|
+
style=self.QUESTIONARY_STYLE,
|
|
1164
|
+
).ask()
|
|
1165
|
+
|
|
1166
|
+
if action == "cancel":
|
|
1167
|
+
self.console.print("[yellow]Changes cancelled[/yellow]")
|
|
1168
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1169
|
+
return
|
|
1170
|
+
if action == "adjust":
|
|
1171
|
+
# Loop back to agent selection
|
|
1172
|
+
continue
|
|
1173
|
+
|
|
1174
|
+
# Execute changes
|
|
1175
|
+
deploy_success = 0
|
|
1176
|
+
deploy_fail = 0
|
|
1177
|
+
remove_success = 0
|
|
1178
|
+
remove_fail = 0
|
|
1179
|
+
|
|
1180
|
+
# Install new agents
|
|
1181
|
+
for agent_id in to_deploy:
|
|
1182
|
+
agent = agent_map.get(agent_id)
|
|
1183
|
+
if agent and self._deploy_single_agent(agent, show_feedback=False):
|
|
1184
|
+
deploy_success += 1
|
|
1185
|
+
self.console.print(f"[green]✓ Installed: {agent_id}[/green]")
|
|
1186
|
+
else:
|
|
1187
|
+
deploy_fail += 1
|
|
1188
|
+
self.console.print(f"[red]✗ Failed to install: {agent_id}[/red]")
|
|
1189
|
+
|
|
1190
|
+
# Remove agents
|
|
1191
|
+
for agent_id in to_remove:
|
|
1192
|
+
try:
|
|
1193
|
+
import json
|
|
1194
|
+
from pathlib import Path
|
|
1195
|
+
|
|
1196
|
+
# Remove from project, legacy, and user locations
|
|
1197
|
+
project_path = (
|
|
1198
|
+
Path.cwd() / ".claude-mpm" / "agents" / f"{agent_id}.md"
|
|
1199
|
+
)
|
|
1200
|
+
legacy_path = Path.cwd() / ".claude" / "agents" / f"{agent_id}.md"
|
|
1201
|
+
user_path = Path.home() / ".claude" / "agents" / f"{agent_id}.md"
|
|
1202
|
+
|
|
1203
|
+
removed = False
|
|
1204
|
+
for path in [project_path, legacy_path, user_path]:
|
|
1205
|
+
if path.exists():
|
|
1206
|
+
path.unlink()
|
|
1207
|
+
removed = True
|
|
1208
|
+
|
|
1209
|
+
# Also remove from virtual deployment state
|
|
1210
|
+
deployment_state_paths = [
|
|
1211
|
+
Path.cwd() / ".claude" / "agents" / ".mpm_deployment_state",
|
|
1212
|
+
Path.home() / ".claude" / "agents" / ".mpm_deployment_state",
|
|
1213
|
+
]
|
|
1214
|
+
|
|
1215
|
+
for state_path in deployment_state_paths:
|
|
1216
|
+
if state_path.exists():
|
|
1217
|
+
try:
|
|
1218
|
+
with state_path.open() as f:
|
|
1219
|
+
state = json.load(f)
|
|
1220
|
+
|
|
1221
|
+
# Remove agent from deployment state
|
|
1222
|
+
agents = state.get("last_check_results", {}).get(
|
|
1223
|
+
"agents", {}
|
|
1224
|
+
)
|
|
1225
|
+
if agent_id in agents:
|
|
1226
|
+
del agents[agent_id]
|
|
1227
|
+
removed = True
|
|
1228
|
+
|
|
1229
|
+
# Save updated state
|
|
1230
|
+
with state_path.open("w") as f:
|
|
1231
|
+
json.dump(state, f, indent=2)
|
|
1232
|
+
except (json.JSONDecodeError, KeyError) as e:
|
|
1233
|
+
# Log but don't fail - physical removal still counts
|
|
1234
|
+
self.logger.debug(
|
|
1235
|
+
f"Failed to update deployment state at {state_path}: {e}"
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
if removed:
|
|
1239
|
+
remove_success += 1
|
|
1240
|
+
self.console.print(f"[green]✓ Removed: {agent_id}[/green]")
|
|
1241
|
+
else:
|
|
1242
|
+
remove_fail += 1
|
|
1243
|
+
self.console.print(f"[yellow]⚠ Not found: {agent_id}[/yellow]")
|
|
1244
|
+
except Exception as e:
|
|
1245
|
+
remove_fail += 1
|
|
1246
|
+
self.console.print(f"[red]✗ Failed to remove {agent_id}: {e}[/red]")
|
|
1247
|
+
|
|
1248
|
+
# Show summary
|
|
1249
|
+
self.console.print()
|
|
1250
|
+
if deploy_success > 0:
|
|
1251
|
+
self.console.print(
|
|
1252
|
+
f"[green]✓ Installed {deploy_success} agent(s)[/green]"
|
|
1253
|
+
)
|
|
1254
|
+
if deploy_fail > 0:
|
|
1255
|
+
self.console.print(
|
|
1256
|
+
f"[red]✗ Failed to install {deploy_fail} agent(s)[/red]"
|
|
1257
|
+
)
|
|
1258
|
+
if remove_success > 0:
|
|
1259
|
+
self.console.print(
|
|
1260
|
+
f"[green]✓ Removed {remove_success} agent(s)[/green]"
|
|
1261
|
+
)
|
|
1262
|
+
if remove_fail > 0:
|
|
1263
|
+
self.console.print(
|
|
1264
|
+
f"[red]✗ Failed to remove {remove_fail} agent(s)[/red]"
|
|
1265
|
+
)
|
|
1266
|
+
|
|
1267
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1268
|
+
# Exit the loop after successful execution
|
|
1269
|
+
break
|
|
1270
|
+
|
|
1271
|
+
def _deploy_agents_preset(self) -> None:
|
|
1272
|
+
"""Install agents using preset configuration."""
|
|
1273
|
+
try:
|
|
1274
|
+
from claude_mpm.services.agents.agent_preset_service import (
|
|
1275
|
+
AgentPresetService,
|
|
1276
|
+
)
|
|
1277
|
+
from claude_mpm.services.agents.git_source_manager import GitSourceManager
|
|
1278
|
+
|
|
1279
|
+
source_manager = GitSourceManager()
|
|
1280
|
+
preset_service = AgentPresetService(source_manager)
|
|
1281
|
+
|
|
1282
|
+
presets = preset_service.list_presets()
|
|
1283
|
+
|
|
1284
|
+
if not presets:
|
|
1285
|
+
self.console.print("[yellow]No presets available[/yellow]")
|
|
1286
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1287
|
+
return
|
|
1288
|
+
|
|
1289
|
+
self.console.print("\n[bold white]═══ Available Presets ═══[/bold white]\n")
|
|
1290
|
+
for idx, preset in enumerate(presets, 1):
|
|
1291
|
+
self.console.print(f" {idx}. [white]{preset['name']}[/white]")
|
|
1292
|
+
self.console.print(f" {preset['description']}")
|
|
1293
|
+
self.console.print(f" [dim]Agents: {len(preset['agents'])}[/dim]\n")
|
|
1294
|
+
|
|
1295
|
+
selection = Prompt.ask("\nEnter preset number (or 'c' to cancel)")
|
|
1296
|
+
if selection.lower() == "c":
|
|
1297
|
+
return
|
|
1298
|
+
|
|
1299
|
+
idx = int(selection) - 1
|
|
1300
|
+
if 0 <= idx < len(presets):
|
|
1301
|
+
preset_name = presets[idx]["name"]
|
|
1302
|
+
|
|
1303
|
+
# Resolve and deploy preset
|
|
1304
|
+
resolution = preset_service.resolve_agents(preset_name)
|
|
1305
|
+
|
|
1306
|
+
if resolution.get("missing_agents"):
|
|
1307
|
+
self.console.print(
|
|
1308
|
+
f"[red]Missing agents: {len(resolution['missing_agents'])}[/red]"
|
|
1309
|
+
)
|
|
1310
|
+
for agent_id in resolution["missing_agents"]:
|
|
1311
|
+
self.console.print(f" • {agent_id}")
|
|
1312
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1313
|
+
return
|
|
1314
|
+
|
|
1315
|
+
# Confirm installation
|
|
1316
|
+
self.console.print(
|
|
1317
|
+
f"\n[bold]Preset '{preset_name}' includes {len(resolution['agents'])} agents[/bold]"
|
|
1318
|
+
)
|
|
1319
|
+
if Confirm.ask("Install all agents?", default=True):
|
|
1320
|
+
installed = 0
|
|
1321
|
+
for agent in resolution["agents"]:
|
|
1322
|
+
# Convert dict to AgentConfig-like object for installation
|
|
1323
|
+
agent_config = AgentConfig(
|
|
1324
|
+
name=agent.get("agent_id", "unknown"),
|
|
1325
|
+
description=agent.get("metadata", {}).get(
|
|
1326
|
+
"description", ""
|
|
1327
|
+
),
|
|
1328
|
+
dependencies=[],
|
|
1329
|
+
)
|
|
1330
|
+
agent_config.source_dict = agent
|
|
1331
|
+
agent_config.full_agent_id = agent.get("agent_id", "unknown")
|
|
1332
|
+
|
|
1333
|
+
if self._deploy_single_agent(agent_config, show_feedback=False):
|
|
1334
|
+
installed += 1
|
|
1335
|
+
|
|
1336
|
+
self.console.print(
|
|
1337
|
+
f"\n[green]✓ Installed {installed}/{len(resolution['agents'])} agents[/green]"
|
|
1338
|
+
)
|
|
1339
|
+
|
|
1340
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1341
|
+
else:
|
|
1342
|
+
self.console.print("[red]Invalid selection[/red]")
|
|
1343
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1344
|
+
|
|
1345
|
+
except Exception as e:
|
|
1346
|
+
self.console.print(f"[red]Error installing preset: {e}[/red]")
|
|
1347
|
+
self.logger.error(f"Preset installation failed: {e}", exc_info=True)
|
|
1348
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1349
|
+
|
|
1350
|
+
def _deploy_single_agent(
|
|
1351
|
+
self, agent: AgentConfig, show_feedback: bool = True
|
|
1352
|
+
) -> bool:
|
|
1353
|
+
"""Install a single agent to the appropriate location."""
|
|
1354
|
+
try:
|
|
1355
|
+
# Check if this is a remote agent with source_dict
|
|
1356
|
+
source_dict = getattr(agent, "source_dict", None)
|
|
1357
|
+
full_agent_id = getattr(agent, "full_agent_id", agent.name)
|
|
1358
|
+
|
|
1359
|
+
if source_dict:
|
|
1360
|
+
# Deploy remote agent using its source file
|
|
1361
|
+
source_file = Path(source_dict.get("source_file", ""))
|
|
1362
|
+
if not source_file.exists():
|
|
1363
|
+
if show_feedback:
|
|
1364
|
+
self.console.print(
|
|
1365
|
+
f"[red]✗ Source file not found: {source_file}[/red]"
|
|
1366
|
+
)
|
|
1367
|
+
return False
|
|
1368
|
+
|
|
1369
|
+
# Determine target file name (use leaf name from hierarchical ID)
|
|
1370
|
+
if "/" in full_agent_id:
|
|
1371
|
+
target_name = full_agent_id.split("/")[-1] + ".md"
|
|
1372
|
+
else:
|
|
1373
|
+
target_name = full_agent_id + ".md"
|
|
1374
|
+
|
|
1375
|
+
# Deploy to user-level agents directory
|
|
1376
|
+
target_dir = Path.home() / ".claude" / "agents"
|
|
1377
|
+
target_dir.mkdir(parents=True, exist_ok=True)
|
|
1378
|
+
target_file = target_dir / target_name
|
|
1379
|
+
|
|
1380
|
+
if show_feedback:
|
|
1381
|
+
self.console.print(
|
|
1382
|
+
f"\n[white]Installing {full_agent_id}...[/white]"
|
|
1383
|
+
)
|
|
1384
|
+
|
|
1385
|
+
# Copy the agent file
|
|
1386
|
+
import shutil
|
|
1387
|
+
|
|
1388
|
+
shutil.copy2(source_file, target_file)
|
|
1389
|
+
|
|
1390
|
+
if show_feedback:
|
|
1391
|
+
self.console.print(
|
|
1392
|
+
f"[green]✓ Successfully installed {full_agent_id} to {target_file}[/green]"
|
|
1393
|
+
)
|
|
1394
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1395
|
+
|
|
1396
|
+
return True
|
|
1397
|
+
# Legacy local template installation (not implemented here)
|
|
1398
|
+
if show_feedback:
|
|
1399
|
+
self.console.print(
|
|
1400
|
+
"[yellow]Local template installation not yet implemented[/yellow]"
|
|
1401
|
+
)
|
|
1402
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1403
|
+
return False
|
|
1404
|
+
|
|
1405
|
+
except Exception as e:
|
|
1406
|
+
if show_feedback:
|
|
1407
|
+
self.console.print(f"[red]Error installing agent: {e}[/red]")
|
|
1408
|
+
self.logger.error(f"Agent installation failed: {e}", exc_info=True)
|
|
1409
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1410
|
+
return False
|
|
1411
|
+
|
|
1412
|
+
def _remove_agents(self, agents: List[AgentConfig]) -> None:
|
|
1413
|
+
"""Remove installed agents."""
|
|
1414
|
+
# Filter to installed agents only
|
|
1415
|
+
installed = [a for a in agents if getattr(a, "is_deployed", False)]
|
|
1416
|
+
|
|
1417
|
+
if not installed:
|
|
1418
|
+
self.console.print("[yellow]No agents are currently installed[/yellow]")
|
|
1419
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1420
|
+
return
|
|
1421
|
+
|
|
1422
|
+
self.console.print(f"\n[bold]Installed agents ({len(installed)}):[/bold]")
|
|
1423
|
+
for idx, agent in enumerate(installed, 1):
|
|
1424
|
+
display_name = getattr(agent, "display_name", agent.name)
|
|
1425
|
+
self.console.print(f" {idx}. {agent.name} - {display_name}")
|
|
1426
|
+
|
|
1427
|
+
selection = Prompt.ask("\nEnter agent number to remove (or 'c' to cancel)")
|
|
1428
|
+
if selection.lower() == "c":
|
|
1429
|
+
return
|
|
1430
|
+
|
|
1431
|
+
try:
|
|
1432
|
+
idx = int(selection) - 1
|
|
1433
|
+
if 0 <= idx < len(installed):
|
|
1434
|
+
agent = installed[idx]
|
|
1435
|
+
full_agent_id = getattr(agent, "full_agent_id", agent.name)
|
|
1436
|
+
|
|
1437
|
+
# Determine possible file names (hierarchical and leaf)
|
|
1438
|
+
file_names = [f"{full_agent_id}.md"]
|
|
1439
|
+
if "/" in full_agent_id:
|
|
1440
|
+
leaf_name = full_agent_id.split("/")[-1]
|
|
1441
|
+
file_names.append(f"{leaf_name}.md")
|
|
1442
|
+
|
|
1443
|
+
# Remove from both project and user directories
|
|
1444
|
+
removed = False
|
|
1445
|
+
project_agent_dir = Path.cwd() / ".claude-mpm" / "agents"
|
|
1446
|
+
user_agent_dir = Path.home() / ".claude" / "agents"
|
|
1447
|
+
|
|
1448
|
+
for file_name in file_names:
|
|
1449
|
+
project_file = project_agent_dir / file_name
|
|
1450
|
+
user_file = user_agent_dir / file_name
|
|
1451
|
+
|
|
1452
|
+
if project_file.exists():
|
|
1453
|
+
project_file.unlink()
|
|
1454
|
+
removed = True
|
|
1455
|
+
self.console.print(f"[green]✓ Removed {project_file}[/green]")
|
|
1456
|
+
|
|
1457
|
+
if user_file.exists():
|
|
1458
|
+
user_file.unlink()
|
|
1459
|
+
removed = True
|
|
1460
|
+
self.console.print(f"[green]✓ Removed {user_file}[/green]")
|
|
1461
|
+
|
|
1462
|
+
if removed:
|
|
1463
|
+
self.console.print(
|
|
1464
|
+
f"[green]✓ Successfully removed {full_agent_id}[/green]"
|
|
1465
|
+
)
|
|
1466
|
+
else:
|
|
1467
|
+
self.console.print("[yellow]Agent files not found[/yellow]")
|
|
1468
|
+
|
|
1469
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1470
|
+
else:
|
|
1471
|
+
self.console.print("[red]Invalid selection[/red]")
|
|
1472
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1473
|
+
|
|
1474
|
+
except (ValueError, IndexError):
|
|
1475
|
+
self.console.print("[red]Invalid selection[/red]")
|
|
1476
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1477
|
+
|
|
1478
|
+
def _view_agent_details_enhanced(self, agents: List[AgentConfig]) -> None:
|
|
1479
|
+
"""View detailed agent information with enhanced remote agent details."""
|
|
1480
|
+
if not agents:
|
|
1481
|
+
self.console.print("[yellow]No agents available[/yellow]")
|
|
1482
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1483
|
+
return
|
|
1484
|
+
|
|
1485
|
+
self.console.print(f"\n[bold]Available agents ({len(agents)}):[/bold]")
|
|
1486
|
+
for idx, agent in enumerate(agents, 1):
|
|
1487
|
+
display_name = getattr(agent, "display_name", agent.name)
|
|
1488
|
+
self.console.print(f" {idx}. {agent.name} - {display_name}")
|
|
1489
|
+
|
|
1490
|
+
selection = Prompt.ask("\nEnter agent number to view (or 'c' to cancel)")
|
|
1491
|
+
if selection.lower() == "c":
|
|
1492
|
+
return
|
|
1493
|
+
|
|
1494
|
+
try:
|
|
1495
|
+
idx = int(selection) - 1
|
|
1496
|
+
if 0 <= idx < len(agents):
|
|
1497
|
+
agent = agents[idx]
|
|
1498
|
+
|
|
1499
|
+
self.console.clear()
|
|
1500
|
+
self.console.print("\n[bold white]═══ Agent Details ═══[/bold white]\n")
|
|
1501
|
+
|
|
1502
|
+
# Basic info
|
|
1503
|
+
self.console.print(f"[bold]ID:[/bold] {agent.name}")
|
|
1504
|
+
display_name = getattr(agent, "display_name", "N/A")
|
|
1505
|
+
self.console.print(f"[bold]Name:[/bold] {display_name}")
|
|
1506
|
+
self.console.print(f"[bold]Description:[/bold] {agent.description}")
|
|
1507
|
+
|
|
1508
|
+
# Source info
|
|
1509
|
+
source_type = getattr(agent, "source_type", "local")
|
|
1510
|
+
self.console.print(f"[bold]Source Type:[/bold] {source_type}")
|
|
1511
|
+
|
|
1512
|
+
if source_type == "remote":
|
|
1513
|
+
source_dict = getattr(agent, "source_dict", {})
|
|
1514
|
+
category = source_dict.get("category", "N/A")
|
|
1515
|
+
source = source_dict.get("source", "N/A")
|
|
1516
|
+
version = source_dict.get("version", "N/A")
|
|
1517
|
+
|
|
1518
|
+
self.console.print(f"[bold]Category:[/bold] {category}")
|
|
1519
|
+
self.console.print(f"[bold]Source:[/bold] {source}")
|
|
1520
|
+
self.console.print(f"[bold]Version:[/bold] {version[:16]}...")
|
|
1521
|
+
|
|
1522
|
+
# Installation status
|
|
1523
|
+
is_installed = getattr(agent, "is_deployed", False)
|
|
1524
|
+
status = "Installed" if is_installed else "Available"
|
|
1525
|
+
self.console.print(f"[bold]Status:[/bold] {status}")
|
|
1526
|
+
|
|
1527
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1528
|
+
else:
|
|
1529
|
+
self.console.print("[red]Invalid selection[/red]")
|
|
1530
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1531
|
+
|
|
1532
|
+
except (ValueError, IndexError):
|
|
1533
|
+
self.console.print("[red]Invalid selection[/red]")
|
|
1534
|
+
Prompt.ask("\nPress Enter to continue")
|
|
1535
|
+
|
|
812
1536
|
|
|
813
1537
|
def manage_configure(args) -> int:
|
|
814
1538
|
"""Main entry point for configuration management command.
|