claude-mpm 4.25.10__py3-none-any.whl → 5.1.8__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.

Files changed (507) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/BASE_PM.md +12 -0
  3. claude_mpm/agents/PM_INSTRUCTIONS.md +1055 -2230
  4. claude_mpm/agents/PM_INSTRUCTIONS_TEACH.md +1322 -0
  5. claude_mpm/agents/WORKFLOW.md +4 -4
  6. claude_mpm/agents/__init__.py +6 -0
  7. claude_mpm/agents/agent_loader.py +1 -4
  8. claude_mpm/agents/base_agent_loader.py +10 -35
  9. claude_mpm/agents/templates/{circuit_breakers.md → circuit-breakers.md} +576 -66
  10. claude_mpm/agents/templates/context-management-examples.md +544 -0
  11. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  12. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  13. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  14. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  15. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  16. claude_mpm/cli/__init__.py +28 -3
  17. claude_mpm/cli/commands/__init__.py +2 -0
  18. claude_mpm/cli/commands/agent_source.py +774 -0
  19. claude_mpm/cli/commands/agent_state_manager.py +188 -30
  20. claude_mpm/cli/commands/agents.py +959 -36
  21. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  22. claude_mpm/cli/commands/agents_discover.py +338 -0
  23. claude_mpm/cli/commands/auto_configure.py +537 -239
  24. claude_mpm/cli/commands/config.py +7 -4
  25. claude_mpm/cli/commands/configure.py +924 -45
  26. claude_mpm/cli/commands/configure_navigation.py +63 -46
  27. claude_mpm/cli/commands/doctor.py +10 -2
  28. claude_mpm/cli/commands/local_deploy.py +1 -4
  29. claude_mpm/cli/commands/postmortem.py +401 -0
  30. claude_mpm/cli/commands/run.py +1 -39
  31. claude_mpm/cli/commands/skill_source.py +694 -0
  32. claude_mpm/cli/commands/skills.py +322 -19
  33. claude_mpm/cli/executor.py +22 -3
  34. claude_mpm/cli/interactive/agent_wizard.py +1028 -43
  35. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  36. claude_mpm/cli/parsers/agents_parser.py +256 -4
  37. claude_mpm/cli/parsers/auto_configure_parser.py +13 -0
  38. claude_mpm/cli/parsers/base_parser.py +25 -0
  39. claude_mpm/cli/parsers/config_parser.py +96 -43
  40. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  41. claude_mpm/cli/parsers/skills_parser.py +7 -0
  42. claude_mpm/cli/parsers/source_parser.py +138 -0
  43. claude_mpm/cli/startup.py +456 -103
  44. claude_mpm/cli/startup_display.py +4 -4
  45. claude_mpm/commands/{mpm-auto-configure.md → mpm-agents-auto-configure.md} +9 -0
  46. claude_mpm/commands/mpm-agents-detect.md +9 -0
  47. claude_mpm/commands/{mpm-agents.md → mpm-agents-list.md} +9 -0
  48. claude_mpm/commands/mpm-agents-recommend.md +9 -0
  49. claude_mpm/commands/{mpm-config.md → mpm-config-view.md} +9 -0
  50. claude_mpm/commands/mpm-doctor.md +9 -0
  51. claude_mpm/commands/mpm-help.md +14 -2
  52. claude_mpm/commands/mpm-init.md +9 -0
  53. claude_mpm/commands/mpm-monitor.md +9 -0
  54. claude_mpm/commands/mpm-postmortem.md +123 -0
  55. claude_mpm/commands/{mpm-resume.md → mpm-session-resume.md} +9 -0
  56. claude_mpm/commands/mpm-status.md +9 -0
  57. claude_mpm/commands/{mpm-organize.md → mpm-ticket-organize.md} +9 -0
  58. claude_mpm/commands/mpm-ticket-view.md +552 -0
  59. claude_mpm/commands/mpm-version.md +9 -0
  60. claude_mpm/commands/mpm.md +10 -0
  61. claude_mpm/config/agent_presets.py +488 -0
  62. claude_mpm/config/agent_sources.py +325 -0
  63. claude_mpm/config/skill_presets.py +392 -0
  64. claude_mpm/config/skill_sources.py +590 -0
  65. claude_mpm/constants.py +1 -0
  66. claude_mpm/core/claude_runner.py +5 -34
  67. claude_mpm/core/config.py +16 -0
  68. claude_mpm/core/framework/__init__.py +3 -16
  69. claude_mpm/core/framework/loaders/file_loader.py +54 -101
  70. claude_mpm/core/framework/loaders/instruction_loader.py +25 -5
  71. claude_mpm/core/interactive_session.py +83 -7
  72. claude_mpm/core/oneshot_session.py +71 -8
  73. claude_mpm/core/protocols/__init__.py +23 -0
  74. claude_mpm/core/protocols/runner_protocol.py +103 -0
  75. claude_mpm/core/protocols/session_protocol.py +131 -0
  76. claude_mpm/core/shared/singleton_manager.py +11 -4
  77. claude_mpm/core/system_context.py +38 -0
  78. claude_mpm/core/unified_config.py +22 -0
  79. claude_mpm/experimental/cli_enhancements.py +1 -5
  80. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-313.pyc +0 -0
  81. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-313.pyc +0 -0
  82. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-313.pyc +0 -0
  83. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-313.pyc +0 -0
  84. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-313.pyc +0 -0
  85. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-313.pyc +0 -0
  86. claude_mpm/hooks/claude_hooks/memory_integration.py +12 -1
  87. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-313.pyc +0 -0
  88. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-313.pyc +0 -0
  89. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-313.pyc +0 -0
  90. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-313.pyc +0 -0
  91. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-313.pyc +0 -0
  92. claude_mpm/hooks/failure_learning/__init__.py +2 -8
  93. claude_mpm/hooks/failure_learning/failure_detection_hook.py +1 -6
  94. claude_mpm/hooks/failure_learning/fix_detection_hook.py +1 -6
  95. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +1 -6
  96. claude_mpm/hooks/kuzu_response_hook.py +1 -5
  97. claude_mpm/models/git_repository.py +198 -0
  98. claude_mpm/services/agents/agent_builder.py +45 -9
  99. claude_mpm/services/agents/agent_preset_service.py +238 -0
  100. claude_mpm/services/agents/agent_selection_service.py +484 -0
  101. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  102. claude_mpm/services/agents/cache_git_manager.py +621 -0
  103. claude_mpm/services/agents/deployment/agent_deployment.py +126 -2
  104. claude_mpm/services/agents/deployment/agent_discovery_service.py +105 -73
  105. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +1 -5
  106. claude_mpm/services/agents/deployment/agent_restore_handler.py +1 -4
  107. claude_mpm/services/agents/deployment/agent_template_builder.py +236 -15
  108. claude_mpm/services/agents/deployment/agents_directory_resolver.py +101 -15
  109. claude_mpm/services/agents/deployment/async_agent_deployment.py +2 -1
  110. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +115 -15
  111. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +1 -4
  112. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +363 -0
  113. claude_mpm/services/agents/deployment/single_agent_deployer.py +2 -2
  114. claude_mpm/services/agents/deployment/system_instructions_deployer.py +168 -46
  115. claude_mpm/services/agents/deployment/validation/deployment_validator.py +2 -2
  116. claude_mpm/services/agents/git_source_manager.py +629 -0
  117. claude_mpm/services/agents/loading/framework_agent_loader.py +1 -4
  118. claude_mpm/services/agents/local_template_manager.py +47 -9
  119. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  120. claude_mpm/services/agents/sources/__init__.py +13 -0
  121. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  122. claude_mpm/services/agents/sources/git_source_sync_service.py +1087 -0
  123. claude_mpm/services/agents/startup_sync.py +239 -0
  124. claude_mpm/services/agents/toolchain_detector.py +474 -0
  125. claude_mpm/services/analysis/__init__.py +25 -0
  126. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  127. claude_mpm/services/analysis/postmortem_service.py +765 -0
  128. claude_mpm/services/command_deployment_service.py +200 -6
  129. claude_mpm/services/core/base.py +7 -2
  130. claude_mpm/services/core/interfaces/__init__.py +1 -3
  131. claude_mpm/services/core/interfaces/health.py +1 -4
  132. claude_mpm/services/core/models/__init__.py +2 -11
  133. claude_mpm/services/diagnostics/checks/__init__.py +4 -0
  134. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  135. claude_mpm/services/diagnostics/checks/mcp_services_check.py +7 -15
  136. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  137. claude_mpm/services/diagnostics/diagnostic_runner.py +9 -0
  138. claude_mpm/services/diagnostics/doctor_reporter.py +34 -6
  139. claude_mpm/services/git/__init__.py +21 -0
  140. claude_mpm/services/git/git_operations_service.py +494 -0
  141. claude_mpm/services/github/__init__.py +21 -0
  142. claude_mpm/services/github/github_cli_service.py +397 -0
  143. claude_mpm/services/infrastructure/monitoring/__init__.py +1 -5
  144. claude_mpm/services/infrastructure/monitoring/aggregator.py +1 -6
  145. claude_mpm/services/instructions/__init__.py +9 -0
  146. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  147. claude_mpm/services/local_ops/__init__.py +3 -13
  148. claude_mpm/services/local_ops/health_checks/__init__.py +1 -3
  149. claude_mpm/services/local_ops/health_manager.py +1 -4
  150. claude_mpm/services/mcp_config_manager.py +75 -145
  151. claude_mpm/services/mcp_gateway/core/process_pool.py +22 -16
  152. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +1 -6
  153. claude_mpm/services/mcp_service_verifier.py +6 -3
  154. claude_mpm/services/monitor/daemon.py +28 -8
  155. claude_mpm/services/monitor/daemon_manager.py +96 -19
  156. claude_mpm/services/pr/__init__.py +14 -0
  157. claude_mpm/services/pr/pr_template_service.py +329 -0
  158. claude_mpm/services/project/project_organizer.py +4 -0
  159. claude_mpm/services/runner_configuration_service.py +16 -3
  160. claude_mpm/services/session_management_service.py +16 -4
  161. claude_mpm/services/skills/__init__.py +18 -0
  162. claude_mpm/services/skills/git_skill_source_manager.py +1169 -0
  163. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  164. claude_mpm/services/socketio/server/core.py +1 -4
  165. claude_mpm/services/socketio/server/main.py +1 -3
  166. claude_mpm/services/unified/deployment_strategies/vercel.py +1 -5
  167. claude_mpm/services/unified/unified_deployment.py +1 -5
  168. claude_mpm/services/visualization/__init__.py +1 -5
  169. claude_mpm/templates/questions/__init__.py +2 -7
  170. claude_mpm/templates/questions/pr_strategy.py +1 -4
  171. claude_mpm/templates/questions/project_init.py +1 -4
  172. claude_mpm/templates/questions/ticket_mgmt.py +1 -4
  173. claude_mpm/utils/agent_dependency_loader.py +77 -10
  174. claude_mpm/utils/agent_filters.py +288 -0
  175. claude_mpm/utils/gitignore.py +3 -0
  176. claude_mpm/utils/migration.py +372 -0
  177. claude_mpm/utils/progress.py +387 -0
  178. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/METADATA +356 -112
  179. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/RECORD +188 -439
  180. claude_mpm/agents/templates/agent-manager.json +0 -273
  181. claude_mpm/agents/templates/agentic-coder-optimizer.json +0 -248
  182. claude_mpm/agents/templates/api_qa.json +0 -183
  183. claude_mpm/agents/templates/clerk-ops.json +0 -235
  184. claude_mpm/agents/templates/code_analyzer.json +0 -101
  185. claude_mpm/agents/templates/content-agent.json +0 -358
  186. claude_mpm/agents/templates/dart_engineer.json +0 -307
  187. claude_mpm/agents/templates/data_engineer.json +0 -225
  188. claude_mpm/agents/templates/documentation.json +0 -238
  189. claude_mpm/agents/templates/engineer.json +0 -210
  190. claude_mpm/agents/templates/gcp_ops_agent.json +0 -253
  191. claude_mpm/agents/templates/golang_engineer.json +0 -270
  192. claude_mpm/agents/templates/imagemagick.json +0 -264
  193. claude_mpm/agents/templates/java_engineer.json +0 -346
  194. claude_mpm/agents/templates/javascript_engineer_agent.json +0 -380
  195. claude_mpm/agents/templates/local_ops_agent.json +0 -1840
  196. claude_mpm/agents/templates/memory_manager.json +0 -158
  197. claude_mpm/agents/templates/nextjs_engineer.json +0 -285
  198. claude_mpm/agents/templates/ops.json +0 -185
  199. claude_mpm/agents/templates/php-engineer.json +0 -287
  200. claude_mpm/agents/templates/product_owner.json +0 -338
  201. claude_mpm/agents/templates/project_organizer.json +0 -144
  202. claude_mpm/agents/templates/prompt-engineer.json +0 -737
  203. claude_mpm/agents/templates/python_engineer.json +0 -387
  204. claude_mpm/agents/templates/qa.json +0 -243
  205. claude_mpm/agents/templates/react_engineer.json +0 -239
  206. claude_mpm/agents/templates/refactoring_engineer.json +0 -276
  207. claude_mpm/agents/templates/research.json +0 -258
  208. claude_mpm/agents/templates/ruby-engineer.json +0 -280
  209. claude_mpm/agents/templates/rust_engineer.json +0 -275
  210. claude_mpm/agents/templates/security.json +0 -202
  211. claude_mpm/agents/templates/svelte-engineer.json +0 -225
  212. claude_mpm/agents/templates/tauri_engineer.json +0 -274
  213. claude_mpm/agents/templates/ticketing.json +0 -181
  214. claude_mpm/agents/templates/typescript_engineer.json +0 -285
  215. claude_mpm/agents/templates/vercel_ops_agent.json +0 -412
  216. claude_mpm/agents/templates/version_control.json +0 -159
  217. claude_mpm/agents/templates/web_qa.json +0 -400
  218. claude_mpm/agents/templates/web_ui.json +0 -189
  219. claude_mpm/cli/README.md +0 -253
  220. claude_mpm/cli/commands/mcp_install_commands.py.backup +0 -284
  221. claude_mpm/cli/commands/mpm_init/README.md +0 -365
  222. claude_mpm/cli_module/refactoring_guide.md +0 -253
  223. claude_mpm/commands/mpm-tickets.md +0 -151
  224. claude_mpm/config/agent_capabilities.yaml +0 -658
  225. claude_mpm/config/async_logging_config.yaml +0 -145
  226. claude_mpm/core/.claude-mpm/logs/hooks_20250730.log +0 -34
  227. claude_mpm/d2/.gitignore +0 -22
  228. claude_mpm/d2/ARCHITECTURE_COMPARISON.md +0 -273
  229. claude_mpm/d2/FLASK_INTEGRATION.md +0 -156
  230. claude_mpm/d2/IMPLEMENTATION_SUMMARY.md +0 -452
  231. claude_mpm/d2/QUICKSTART.md +0 -186
  232. claude_mpm/d2/README.md +0 -232
  233. claude_mpm/d2/STORE_FIX_SUMMARY.md +0 -167
  234. claude_mpm/d2/SVELTE5_STORES_GUIDE.md +0 -180
  235. claude_mpm/d2/TESTING.md +0 -288
  236. claude_mpm/d2/index.html +0 -118
  237. claude_mpm/d2/package.json +0 -19
  238. claude_mpm/d2/src/App.svelte +0 -110
  239. claude_mpm/d2/src/components/Header.svelte +0 -153
  240. claude_mpm/d2/src/components/MainContent.svelte +0 -74
  241. claude_mpm/d2/src/components/Sidebar.svelte +0 -85
  242. claude_mpm/d2/src/components/tabs/EventsTab.svelte +0 -326
  243. claude_mpm/d2/src/lib/socketio.js +0 -144
  244. claude_mpm/d2/src/main.js +0 -7
  245. claude_mpm/d2/src/stores/events.js +0 -114
  246. claude_mpm/d2/src/stores/socket.js +0 -108
  247. claude_mpm/d2/src/stores/theme.js +0 -65
  248. claude_mpm/d2/svelte.config.js +0 -12
  249. claude_mpm/d2/vite.config.js +0 -15
  250. claude_mpm/dashboard/.claude-mpm/memories/README.md +0 -36
  251. claude_mpm/dashboard/BUILD_NUMBER +0 -1
  252. claude_mpm/dashboard/README.md +0 -121
  253. claude_mpm/dashboard/VERSION +0 -1
  254. claude_mpm/dashboard/react/components/DataInspector/DataInspector.module.css +0 -188
  255. claude_mpm/dashboard/react/components/DataInspector/DataInspector.tsx +0 -273
  256. claude_mpm/dashboard/react/components/ErrorBoundary.tsx +0 -75
  257. claude_mpm/dashboard/react/components/EventViewer/EventViewer.module.css +0 -156
  258. claude_mpm/dashboard/react/components/EventViewer/EventViewer.tsx +0 -141
  259. claude_mpm/dashboard/react/components/shared/ConnectionStatus.module.css +0 -38
  260. claude_mpm/dashboard/react/components/shared/ConnectionStatus.tsx +0 -36
  261. claude_mpm/dashboard/react/components/shared/FilterBar.module.css +0 -92
  262. claude_mpm/dashboard/react/components/shared/FilterBar.tsx +0 -89
  263. claude_mpm/dashboard/react/contexts/DashboardContext.tsx +0 -215
  264. claude_mpm/dashboard/react/entries/events.tsx +0 -165
  265. claude_mpm/dashboard/react/hooks/useEvents.ts +0 -191
  266. claude_mpm/dashboard/react/hooks/useSocket.ts +0 -225
  267. claude_mpm/dashboard/static/archive/activity_dashboard_fixed.html +0 -248
  268. claude_mpm/dashboard/static/built/REFACTORING_SUMMARY.md +0 -170
  269. claude_mpm/dashboard/static/built/assets/events.DjpNxWNo.css +0 -1
  270. claude_mpm/dashboard/static/built/components/activity-tree.js +0 -2
  271. claude_mpm/dashboard/static/built/components/activity-tree.js.map +0 -1
  272. claude_mpm/dashboard/static/built/components/agent-hierarchy.js +0 -777
  273. claude_mpm/dashboard/static/built/components/agent-inference.js +0 -2
  274. claude_mpm/dashboard/static/built/components/agent-inference.js.map +0 -1
  275. claude_mpm/dashboard/static/built/components/build-tracker.js +0 -333
  276. claude_mpm/dashboard/static/built/components/code-simple.js +0 -857
  277. claude_mpm/dashboard/static/built/components/code-tree/tree-breadcrumb.js +0 -353
  278. claude_mpm/dashboard/static/built/components/code-tree/tree-constants.js +0 -235
  279. claude_mpm/dashboard/static/built/components/code-tree/tree-search.js +0 -409
  280. claude_mpm/dashboard/static/built/components/code-tree/tree-utils.js +0 -435
  281. claude_mpm/dashboard/static/built/components/code-tree.js +0 -2
  282. claude_mpm/dashboard/static/built/components/code-tree.js.map +0 -1
  283. claude_mpm/dashboard/static/built/components/code-viewer.js +0 -2
  284. claude_mpm/dashboard/static/built/components/code-viewer.js.map +0 -1
  285. claude_mpm/dashboard/static/built/components/connection-debug.js +0 -654
  286. claude_mpm/dashboard/static/built/components/diff-viewer.js +0 -891
  287. claude_mpm/dashboard/static/built/components/event-processor.js +0 -2
  288. claude_mpm/dashboard/static/built/components/event-processor.js.map +0 -1
  289. claude_mpm/dashboard/static/built/components/event-viewer.js +0 -2
  290. claude_mpm/dashboard/static/built/components/event-viewer.js.map +0 -1
  291. claude_mpm/dashboard/static/built/components/export-manager.js +0 -2
  292. claude_mpm/dashboard/static/built/components/export-manager.js.map +0 -1
  293. claude_mpm/dashboard/static/built/components/file-change-tracker.js +0 -443
  294. claude_mpm/dashboard/static/built/components/file-change-viewer.js +0 -690
  295. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +0 -2
  296. claude_mpm/dashboard/static/built/components/file-tool-tracker.js.map +0 -1
  297. claude_mpm/dashboard/static/built/components/file-viewer.js +0 -2
  298. claude_mpm/dashboard/static/built/components/file-viewer.js.map +0 -1
  299. claude_mpm/dashboard/static/built/components/hud-library-loader.js +0 -2
  300. claude_mpm/dashboard/static/built/components/hud-library-loader.js.map +0 -1
  301. claude_mpm/dashboard/static/built/components/hud-manager.js +0 -2
  302. claude_mpm/dashboard/static/built/components/hud-manager.js.map +0 -1
  303. claude_mpm/dashboard/static/built/components/hud-visualizer.js +0 -2
  304. claude_mpm/dashboard/static/built/components/hud-visualizer.js.map +0 -1
  305. claude_mpm/dashboard/static/built/components/module-viewer.js +0 -2
  306. claude_mpm/dashboard/static/built/components/module-viewer.js.map +0 -1
  307. claude_mpm/dashboard/static/built/components/nav-bar.js +0 -145
  308. claude_mpm/dashboard/static/built/components/page-structure.js +0 -429
  309. claude_mpm/dashboard/static/built/components/session-manager.js +0 -2
  310. claude_mpm/dashboard/static/built/components/session-manager.js.map +0 -1
  311. claude_mpm/dashboard/static/built/components/socket-manager.js +0 -2
  312. claude_mpm/dashboard/static/built/components/socket-manager.js.map +0 -1
  313. claude_mpm/dashboard/static/built/components/ui-state-manager.js +0 -2
  314. claude_mpm/dashboard/static/built/components/ui-state-manager.js.map +0 -1
  315. claude_mpm/dashboard/static/built/components/unified-data-viewer.js +0 -2
  316. claude_mpm/dashboard/static/built/components/unified-data-viewer.js.map +0 -1
  317. claude_mpm/dashboard/static/built/components/working-directory.js +0 -2
  318. claude_mpm/dashboard/static/built/components/working-directory.js.map +0 -1
  319. claude_mpm/dashboard/static/built/connection-manager.js +0 -536
  320. claude_mpm/dashboard/static/built/dashboard.js +0 -2
  321. claude_mpm/dashboard/static/built/dashboard.js.map +0 -1
  322. claude_mpm/dashboard/static/built/extension-error-handler.js +0 -164
  323. claude_mpm/dashboard/static/built/react/events.js +0 -30
  324. claude_mpm/dashboard/static/built/react/events.js.map +0 -1
  325. claude_mpm/dashboard/static/built/shared/dom-helpers.js +0 -396
  326. claude_mpm/dashboard/static/built/shared/event-bus.js +0 -330
  327. claude_mpm/dashboard/static/built/shared/event-filter-service.js +0 -540
  328. claude_mpm/dashboard/static/built/shared/logger.js +0 -385
  329. claude_mpm/dashboard/static/built/shared/page-structure.js +0 -249
  330. claude_mpm/dashboard/static/built/shared/tooltip-service.js +0 -253
  331. claude_mpm/dashboard/static/built/socket-client.js +0 -2
  332. claude_mpm/dashboard/static/built/socket-client.js.map +0 -1
  333. claude_mpm/dashboard/static/built/tab-isolation-fix.js +0 -185
  334. claude_mpm/dashboard/static/events.html +0 -607
  335. claude_mpm/dashboard/static/index.html +0 -635
  336. claude_mpm/dashboard/static/js/REFACTORING_SUMMARY.md +0 -170
  337. claude_mpm/dashboard/static/js/shared/dom-helpers.js +0 -396
  338. claude_mpm/dashboard/static/js/shared/event-bus.js +0 -330
  339. claude_mpm/dashboard/static/js/shared/logger.js +0 -385
  340. claude_mpm/dashboard/static/js/shared/tooltip-service.js +0 -253
  341. claude_mpm/dashboard/static/js/stores/dashboard-store.js +0 -562
  342. claude_mpm/dashboard/static/legacy/activity.html +0 -736
  343. claude_mpm/dashboard/static/legacy/agents.html +0 -786
  344. claude_mpm/dashboard/static/legacy/files.html +0 -747
  345. claude_mpm/dashboard/static/legacy/tools.html +0 -831
  346. claude_mpm/dashboard/static/monitors.html +0 -431
  347. claude_mpm/dashboard/static/navigation-test-results.md +0 -118
  348. claude_mpm/dashboard/static/production/events.html +0 -659
  349. claude_mpm/dashboard/static/production/main.html +0 -698
  350. claude_mpm/dashboard/static/production/monitors.html +0 -483
  351. claude_mpm/dashboard/static/test-archive/dashboard.html +0 -635
  352. claude_mpm/dashboard/static/test-archive/debug-events.html +0 -147
  353. claude_mpm/dashboard/static/test-archive/test-navigation.html +0 -256
  354. claude_mpm/dashboard/static/test-archive/test-react-exports.html +0 -180
  355. claude_mpm/dashboard/templates/.claude-mpm/memories/README.md +0 -36
  356. claude_mpm/dashboard/templates/.claude-mpm/memories/engineer_agent.md +0 -39
  357. claude_mpm/dashboard/templates/.claude-mpm/memories/version_control_agent.md +0 -38
  358. claude_mpm/hooks/README.md +0 -143
  359. claude_mpm/hooks/templates/README.md +0 -180
  360. claude_mpm/hooks/templates/settings.json.example +0 -147
  361. claude_mpm/schemas/agent_schema.json +0 -596
  362. claude_mpm/schemas/frontmatter_schema.json +0 -165
  363. claude_mpm/services/event_bus/README.md +0 -244
  364. claude_mpm/services/events/README.md +0 -303
  365. claude_mpm/services/framework_claude_md_generator/README.md +0 -119
  366. claude_mpm/services/mcp_gateway/README.md +0 -185
  367. claude_mpm/services/socketio/handlers/connection.py.backup +0 -217
  368. claude_mpm/services/socketio/handlers/hook.py.backup +0 -154
  369. claude_mpm/services/static/.gitkeep +0 -2
  370. claude_mpm/services/version_control/VERSION +0 -1
  371. claude_mpm/skills/bundled/.gitkeep +0 -2
  372. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +0 -79
  373. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +0 -178
  374. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +0 -577
  375. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +0 -467
  376. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +0 -537
  377. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +0 -730
  378. claude_mpm/skills/bundled/collaboration/git-worktrees.md +0 -317
  379. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +0 -112
  380. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +0 -146
  381. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +0 -412
  382. claude_mpm/skills/bundled/collaboration/stacked-prs.md +0 -251
  383. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +0 -81
  384. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +0 -362
  385. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +0 -312
  386. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +0 -152
  387. claude_mpm/skills/bundled/debugging/root-cause-tracing/find-polluter.sh +0 -63
  388. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +0 -668
  389. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +0 -587
  390. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +0 -438
  391. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +0 -391
  392. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +0 -119
  393. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +0 -148
  394. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +0 -483
  395. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +0 -452
  396. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +0 -449
  397. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +0 -411
  398. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +0 -14
  399. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +0 -58
  400. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +0 -68
  401. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +0 -69
  402. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +0 -131
  403. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +0 -325
  404. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +0 -490
  405. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +0 -425
  406. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +0 -499
  407. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +0 -611
  408. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +0 -596
  409. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +0 -260
  410. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +0 -315
  411. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +0 -436
  412. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +0 -433
  413. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +0 -452
  414. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +0 -404
  415. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +0 -420
  416. claude_mpm/skills/bundled/main/artifacts-builder/LICENSE.txt +0 -202
  417. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +0 -86
  418. claude_mpm/skills/bundled/main/artifacts-builder/scripts/bundle-artifact.sh +0 -54
  419. claude_mpm/skills/bundled/main/artifacts-builder/scripts/init-artifact.sh +0 -322
  420. claude_mpm/skills/bundled/main/artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
  421. claude_mpm/skills/bundled/main/internal-comms/LICENSE.txt +0 -202
  422. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +0 -43
  423. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +0 -47
  424. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +0 -65
  425. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +0 -30
  426. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +0 -16
  427. claude_mpm/skills/bundled/main/mcp-builder/LICENSE.txt +0 -202
  428. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +0 -160
  429. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +0 -412
  430. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +0 -602
  431. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +0 -915
  432. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +0 -916
  433. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +0 -752
  434. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +0 -1237
  435. claude_mpm/skills/bundled/main/mcp-builder/scripts/example_evaluation.xml +0 -22
  436. claude_mpm/skills/bundled/main/mcp-builder/scripts/requirements.txt +0 -2
  437. claude_mpm/skills/bundled/main/skill-creator/LICENSE.txt +0 -202
  438. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +0 -189
  439. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +0 -500
  440. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +0 -464
  441. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +0 -619
  442. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +0 -437
  443. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +0 -231
  444. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +0 -170
  445. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +0 -602
  446. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +0 -821
  447. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +0 -742
  448. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +0 -726
  449. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +0 -764
  450. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +0 -831
  451. claude_mpm/skills/bundled/react/flexlayout-react.md +0 -742
  452. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +0 -226
  453. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +0 -901
  454. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +0 -901
  455. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +0 -775
  456. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +0 -937
  457. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +0 -770
  458. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +0 -961
  459. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +0 -495
  460. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +0 -599
  461. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +0 -535
  462. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +0 -613
  463. claude_mpm/skills/bundled/tauri/tauri-event-system.md +0 -648
  464. claude_mpm/skills/bundled/tauri/tauri-file-system.md +0 -673
  465. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +0 -767
  466. claude_mpm/skills/bundled/tauri/tauri-performance.md +0 -669
  467. claude_mpm/skills/bundled/tauri/tauri-state-management.md +0 -573
  468. claude_mpm/skills/bundled/tauri/tauri-testing.md +0 -384
  469. claude_mpm/skills/bundled/tauri/tauri-window-management.md +0 -628
  470. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +0 -119
  471. claude_mpm/skills/bundled/testing/condition-based-waiting/example.ts +0 -158
  472. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +0 -253
  473. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +0 -145
  474. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +0 -543
  475. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +0 -741
  476. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +0 -470
  477. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +0 -458
  478. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +0 -639
  479. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +0 -458
  480. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +0 -411
  481. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +0 -317
  482. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +0 -270
  483. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +0 -436
  484. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +0 -140
  485. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +0 -572
  486. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +0 -411
  487. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +0 -569
  488. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +0 -695
  489. claude_mpm/skills/bundled/testing/webapp-testing/LICENSE.txt +0 -202
  490. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +0 -184
  491. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +0 -459
  492. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +0 -479
  493. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +0 -687
  494. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +0 -758
  495. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +0 -868
  496. claude_mpm/templates/questions/EXAMPLES.md +0 -501
  497. claude_mpm/tools/README_SOCKETIO_DEBUG.md +0 -224
  498. claude_mpm/tools/code_tree_analyzer/README.md +0 -64
  499. /claude_mpm/agents/templates/{git_file_tracking.md → git-file-tracking.md} +0 -0
  500. /claude_mpm/agents/templates/{pm_examples.md → pm-examples.md} +0 -0
  501. /claude_mpm/agents/templates/{pm_red_flags.md → pm-red-flags.md} +0 -0
  502. /claude_mpm/agents/templates/{response_format.md → response-format.md} +0 -0
  503. /claude_mpm/agents/templates/{validation_templates.md → validation-templates.md} +0 -0
  504. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/WHEEL +0 -0
  505. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/entry_points.txt +0 -0
  506. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/licenses/LICENSE +0 -0
  507. {claude_mpm-4.25.10.dist-info → claude_mpm-5.1.8.dist-info}/top_level.txt +0 -0
@@ -12,15 +12,20 @@ DESIGN DECISIONS:
12
12
  """
13
13
 
14
14
  import json
15
+ import shutil
15
16
  from pathlib import Path
16
17
  from typing import Dict, List, Optional
17
18
 
19
+ import questionary
20
+ import questionary.constants # For checkbox symbol customization
21
+ from questionary import Style
18
22
  from rich.console import Console
19
23
  from rich.prompt import Confirm, Prompt
20
24
  from rich.text import Text
21
25
 
22
26
  from ...core.config import Config
23
27
  from ...services.version_service import VersionService
28
+ from ...utils.agent_filters import apply_all_filters, get_deployed_agent_ids
24
29
  from ...utils.console import console as default_console
25
30
  from ..shared import BaseCommand, CommandResult
26
31
  from .agent_state_manager import SimpleAgentManager
@@ -41,6 +46,21 @@ from .configure_validators import (
41
46
  class ConfigureCommand(BaseCommand):
42
47
  """Interactive configuration management command."""
43
48
 
49
+ # Questionary style optimized for dark terminals (WCAG AAA compliant)
50
+ QUESTIONARY_STYLE = Style(
51
+ [
52
+ ("selected", "fg:#e0e0e0 bold"), # Light gray - excellent readability
53
+ ("pointer", "fg:#ffd700 bold"), # Gold/yellow - highly visible pointer
54
+ ("highlighted", "fg:#e0e0e0"), # Light gray - clear hover state
55
+ ("question", "fg:#e0e0e0 bold"), # Light gray bold - prominent questions
56
+ ("checkbox", "fg:#00ff00"), # Green - for checked boxes
57
+ (
58
+ "checkbox-selected",
59
+ "fg:#00ff00 bold",
60
+ ), # Green bold - for checked selected boxes
61
+ ]
62
+ )
63
+
44
64
  def __init__(self):
45
65
  super().__init__("configure")
46
66
  self.console = default_console
@@ -284,61 +304,140 @@ class ConfigureCommand(BaseCommand):
284
304
  return self.navigation.show_main_menu()
285
305
 
286
306
  def _manage_agents(self) -> None:
287
- """Agent management interface."""
307
+ """Enhanced agent management with remote agent discovery and installation."""
288
308
  while True:
289
309
  self.console.clear()
290
- self._display_header()
310
+ self.navigation.display_header()
311
+ self.console.print("\n[bold blue]═══ Agent Management ═══[/bold blue]\n")
312
+
313
+ # Step 1: Show configured sources
314
+ self.console.print("[bold white]═══ Agent Sources ═══[/bold white]\n")
315
+
316
+ sources = self._get_configured_sources()
317
+ if sources:
318
+ from rich.table import Table
319
+
320
+ sources_table = Table(show_header=True, header_style="bold white")
321
+ sources_table.add_column(
322
+ "Source",
323
+ style="bright_yellow",
324
+ width=40,
325
+ no_wrap=True,
326
+ overflow="ellipsis",
327
+ )
328
+ sources_table.add_column(
329
+ "Status", style="green", width=15, no_wrap=True
330
+ )
331
+ sources_table.add_column(
332
+ "Agents", style="yellow", width=10, no_wrap=True
333
+ )
334
+
335
+ for source in sources:
336
+ status = "✓ Active" if source.get("enabled", True) else "Disabled"
337
+ agent_count = source.get("agent_count", "?")
338
+ sources_table.add_row(
339
+ source["identifier"], status, str(agent_count)
340
+ )
291
341
 
292
- # Display available agents
293
- agents = self.agent_manager.discover_agents()
294
- self._display_agents_table(agents)
342
+ self.console.print(sources_table)
343
+ else:
344
+ self.console.print("[yellow]No agent sources configured[/yellow]")
345
+ self.console.print(
346
+ "[dim]Default source 'bobmatnyc/claude-mpm-agents' will be used[/dim]\n"
347
+ )
295
348
 
296
- # Show agent menu
297
- self.console.print("\n[bold]Agent Management Options:[/bold]")
349
+ # Step 2: Discover and display available agents
350
+ self.console.print("\n[bold white]═══ Available Agents ═══[/bold white]\n")
298
351
 
299
- # Use Text objects to properly display shortcuts with styling
300
- text_t = Text(" ")
301
- text_t.append("[t]", style="bold blue")
302
- text_t.append(" Toggle agents (enable/disable multiple)")
303
- self.console.print(text_t)
352
+ try:
353
+ # Discover agents (includes both local and remote)
354
+ agents = self.agent_manager.discover_agents(include_remote=True)
304
355
 
305
- text_c = Text(" ")
306
- text_c.append("[c]", style="bold blue")
307
- text_c.append(" Customize agent template")
308
- self.console.print(text_c)
356
+ # Set deployment status on each agent for display
357
+ deployed_ids = get_deployed_agent_ids()
358
+ for agent in agents:
359
+ # Extract leaf name for comparison
360
+ agent_leaf_name = agent.name.split("/")[-1]
361
+ agent.is_deployed = agent_leaf_name in deployed_ids
309
362
 
310
- text_v = Text(" ")
311
- text_v.append("[v]", style="bold blue")
312
- text_v.append(" View agent details")
313
- self.console.print(text_v)
363
+ # Filter BASE_AGENT from display (1M-502 Phase 1)
364
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
314
365
 
315
- text_r = Text(" ")
316
- text_r.append("[r]", style="bold blue")
317
- text_r.append(" Reset agent to defaults")
318
- self.console.print(text_r)
366
+ if not agents:
367
+ self.console.print("[yellow]No agents found[/yellow]")
368
+ self.console.print(
369
+ "[dim]Configure sources with 'claude-mpm agent-source add'[/dim]\n"
370
+ )
371
+ else:
372
+ # Display agents in a table (already filtered at line 339)
373
+ self._display_agents_with_source_info(agents)
319
374
 
320
- text_b = Text(" ")
321
- text_b.append("[b]", style="bold blue")
322
- text_b.append(" Back to main menu")
323
- self.console.print(text_b)
375
+ except Exception as e:
376
+ self.console.print(f"[red]Error discovering agents: {e}[/red]")
377
+ self.logger.error(f"Agent discovery failed: {e}", exc_info=True)
324
378
 
379
+ # Step 3: Menu options with arrow-key navigation
325
380
  self.console.print()
381
+ self.logger.debug("About to show agent management menu")
382
+ try:
383
+ choice = questionary.select(
384
+ "Agent Management:",
385
+ choices=[
386
+ "Manage sources (add/remove repositories)",
387
+ "Select Agents",
388
+ "Install preset (predefined sets)",
389
+ "Remove agents",
390
+ "View agent details",
391
+ "Toggle agents (legacy enable/disable)",
392
+ questionary.Separator(),
393
+ "← Back to main menu",
394
+ ],
395
+ style=self.QUESTIONARY_STYLE,
396
+ ).ask()
397
+
398
+ if choice is None or choice == "← Back to main menu":
399
+ break
326
400
 
327
- choice = Prompt.ask("[bold blue]Select an option[/bold blue]", default="b")
328
-
329
- if choice == "b":
401
+ agents_var = agents if "agents" in locals() else []
402
+
403
+ # Map selection to action
404
+ if choice == "Manage sources (add/remove repositories)":
405
+ self._manage_sources()
406
+ elif choice == "Select Agents":
407
+ self.logger.debug("User selected 'Select Agents' from menu")
408
+ self._deploy_agents_individual(agents_var)
409
+ elif choice == "Install preset (predefined sets)":
410
+ self._deploy_agents_preset()
411
+ elif choice == "Remove agents":
412
+ self._remove_agents(agents_var)
413
+ elif choice == "View agent details":
414
+ self._view_agent_details_enhanced(agents_var)
415
+ elif choice == "Toggle agents (legacy enable/disable)":
416
+ self._toggle_agents_interactive(agents_var)
417
+
418
+ except KeyboardInterrupt:
419
+ self.console.print("\n[yellow]Operation cancelled[/yellow]")
420
+ break
421
+ except Exception as e:
422
+ # Handle questionary menu failure
423
+ import sys
424
+
425
+ self.logger.error(f"Agent management menu failed: {e}", exc_info=True)
426
+ self.console.print("[red]Error: Interactive menu failed[/red]")
427
+ self.console.print(f"[dim]Reason: {e}[/dim]")
428
+ if not sys.stdin.isatty():
429
+ self.console.print(
430
+ "[dim]Interactive terminal required for this operation[/dim]"
431
+ )
432
+ self.console.print("[dim]Use command-line options instead:[/dim]")
433
+ self.console.print(
434
+ "[dim] claude-mpm configure --list-agents[/dim]"
435
+ )
436
+ self.console.print(
437
+ "[dim] claude-mpm configure --enable-agent <id>[/dim]"
438
+ )
439
+ Prompt.ask("\nPress Enter to continue")
330
440
  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
441
 
343
442
  def _display_agents_table(self, agents: List[AgentConfig]) -> None:
344
443
  """Display a table of available agents."""
@@ -511,6 +610,8 @@ class ConfigureCommand(BaseCommand):
511
610
 
512
611
  # Get list of enabled agents
513
612
  agents = self.agent_manager.discover_agents()
613
+ # Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
614
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
514
615
  enabled_agents = [
515
616
  a.name
516
617
  for a in agents
@@ -554,9 +655,9 @@ class ConfigureCommand(BaseCommand):
554
655
  else:
555
656
  from rich.table import Table
556
657
 
557
- table = Table(show_header=True, header_style="bold cyan")
558
- table.add_column("Agent", style="yellow")
559
- table.add_column("Skills", style="green")
658
+ table = Table(show_header=True, header_style="bold white")
659
+ table.add_column("Agent", style="white", no_wrap=True)
660
+ table.add_column("Skills", style="green", no_wrap=True)
560
661
 
561
662
  for agent_id, skills in mappings.items():
562
663
  skills_str = (
@@ -577,6 +678,8 @@ class ConfigureCommand(BaseCommand):
577
678
 
578
679
  # Get enabled agents
579
680
  agents = self.agent_manager.discover_agents()
681
+ # Filter BASE_AGENT from all agent operations (1M-502 Phase 1)
682
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
580
683
  enabled_agents = [
581
684
  a.name
582
685
  for a in agents
@@ -708,6 +811,8 @@ class ConfigureCommand(BaseCommand):
708
811
  def _list_agents_non_interactive(self) -> CommandResult:
709
812
  """List agents in non-interactive mode."""
710
813
  agents = self.agent_manager.discover_agents()
814
+ # Filter BASE_AGENT from all agent lists (1M-502 Phase 1)
815
+ agents = self._filter_agent_configs(agents, filter_deployed=False)
711
816
 
712
817
  data = []
713
818
  for agent in agents:
@@ -809,6 +914,780 @@ class ConfigureCommand(BaseCommand):
809
914
  except Exception as e:
810
915
  return CommandResult.error_result(f"Startup configuration failed: {e}")
811
916
 
917
+ # ========================================================================
918
+ # Enhanced Agent Management Methods (Remote Agent Discovery Integration)
919
+ # ========================================================================
920
+
921
+ def _get_configured_sources(self) -> List[Dict]:
922
+ """Get list of configured agent sources with agent counts."""
923
+ try:
924
+ from claude_mpm.config.agent_sources import AgentSourceConfiguration
925
+
926
+ config = AgentSourceConfiguration.load()
927
+
928
+ # Convert repositories to source dictionaries
929
+ sources = []
930
+ for repo in config.repositories:
931
+ # Extract identifier from repository
932
+ identifier = repo.identifier
933
+
934
+ # Count agents in cache
935
+ cache_dir = (
936
+ Path.home() / ".claude-mpm" / "cache" / "remote-agents" / identifier
937
+ )
938
+ agent_count = 0
939
+ if cache_dir.exists():
940
+ agents_dir = cache_dir / "agents"
941
+ if agents_dir.exists():
942
+ agent_count = len(list(agents_dir.rglob("*.md")))
943
+
944
+ sources.append(
945
+ {
946
+ "identifier": identifier,
947
+ "url": repo.url,
948
+ "enabled": repo.enabled,
949
+ "priority": repo.priority,
950
+ "agent_count": agent_count,
951
+ }
952
+ )
953
+
954
+ return sources
955
+ except Exception as e:
956
+ self.logger.warning(f"Failed to get configured sources: {e}")
957
+ return []
958
+
959
+ def _filter_agent_configs(
960
+ self, agents: List[AgentConfig], filter_deployed: bool = False
961
+ ) -> List[AgentConfig]:
962
+ """Filter AgentConfig objects using agent_filters utilities.
963
+
964
+ Converts AgentConfig objects to dictionaries for filtering,
965
+ then back to AgentConfig. Always filters BASE_AGENT.
966
+ Optionally filters deployed agents.
967
+
968
+ Args:
969
+ agents: List of AgentConfig objects
970
+ filter_deployed: Whether to filter out deployed agents (default: False)
971
+
972
+ Returns:
973
+ Filtered list of AgentConfig objects
974
+ """
975
+ # Convert AgentConfig to dict format for filtering
976
+ agent_dicts = []
977
+ for agent in agents:
978
+ agent_dicts.append(
979
+ {
980
+ "agent_id": agent.name,
981
+ "name": agent.name,
982
+ "description": agent.description,
983
+ "deployed": getattr(agent, "is_deployed", False),
984
+ }
985
+ )
986
+
987
+ # Apply filters (always filter BASE_AGENT)
988
+ filtered_dicts = apply_all_filters(
989
+ agent_dicts, filter_base=True, filter_deployed=filter_deployed
990
+ )
991
+
992
+ # Convert back to AgentConfig objects
993
+ filtered_names = {d["agent_id"] for d in filtered_dicts}
994
+ return [a for a in agents if a.name in filtered_names]
995
+
996
+ @staticmethod
997
+ def _calculate_column_widths(
998
+ terminal_width: int, columns: Dict[str, int]
999
+ ) -> Dict[str, int]:
1000
+ """Calculate dynamic column widths based on terminal size.
1001
+
1002
+ Args:
1003
+ terminal_width: Current terminal width in characters
1004
+ columns: Dict mapping column names to minimum widths
1005
+
1006
+ Returns:
1007
+ Dict mapping column names to calculated widths
1008
+
1009
+ Design:
1010
+ - Ensures minimum widths are respected
1011
+ - Distributes extra space proportionally
1012
+ - Handles narrow terminals gracefully (minimum 80 chars)
1013
+ """
1014
+ # Ensure minimum terminal width
1015
+ min_terminal_width = 80
1016
+ terminal_width = max(terminal_width, min_terminal_width)
1017
+
1018
+ # Calculate total minimum width needed
1019
+ total_min_width = sum(columns.values())
1020
+
1021
+ # Account for table borders and padding (2 chars per column + 2 for edges)
1022
+ overhead = (len(columns) * 2) + 2
1023
+ available_width = terminal_width - overhead
1024
+
1025
+ # If we have extra space, distribute proportionally
1026
+ if available_width > total_min_width:
1027
+ extra_space = available_width - total_min_width
1028
+ total_weight = sum(columns.values())
1029
+
1030
+ result = {}
1031
+ for col_name, min_width in columns.items():
1032
+ # Distribute extra space based on minimum width proportion
1033
+ proportion = min_width / total_weight
1034
+ extra = int(extra_space * proportion)
1035
+ result[col_name] = min_width + extra
1036
+ return result
1037
+ # Terminal too narrow, use minimum widths
1038
+ return columns.copy()
1039
+
1040
+ def _display_agents_with_source_info(self, agents: List[AgentConfig]) -> None:
1041
+ """Display agents table with source information and installation status."""
1042
+ from rich.table import Table
1043
+
1044
+ # Get terminal width and calculate dynamic column widths
1045
+ terminal_width = shutil.get_terminal_size().columns
1046
+ min_widths = {
1047
+ "#": 4,
1048
+ "Agent ID": 30,
1049
+ "Name": 20,
1050
+ "Source": 15,
1051
+ "Status": 10,
1052
+ }
1053
+ widths = self._calculate_column_widths(terminal_width, min_widths)
1054
+
1055
+ agents_table = Table(show_header=True, header_style="bold white")
1056
+ agents_table.add_column("#", style="dim", width=widths["#"], no_wrap=True)
1057
+ agents_table.add_column(
1058
+ "Agent ID",
1059
+ style="white",
1060
+ width=widths["Agent ID"],
1061
+ no_wrap=True,
1062
+ overflow="ellipsis",
1063
+ )
1064
+ agents_table.add_column(
1065
+ "Name",
1066
+ style="white",
1067
+ width=widths["Name"],
1068
+ no_wrap=True,
1069
+ overflow="ellipsis",
1070
+ )
1071
+ agents_table.add_column(
1072
+ "Source",
1073
+ style="bright_yellow",
1074
+ width=widths["Source"],
1075
+ no_wrap=True,
1076
+ )
1077
+ agents_table.add_column(
1078
+ "Status", style="white", width=widths["Status"], no_wrap=True
1079
+ )
1080
+
1081
+ for idx, agent in enumerate(agents, 1):
1082
+ # Determine source with repo name
1083
+ source_type = getattr(agent, "source_type", "local")
1084
+
1085
+ if source_type == "remote":
1086
+ # Get repo name from agent metadata
1087
+ source_dict = getattr(agent, "source_dict", {})
1088
+ repo_url = source_dict.get("source", "")
1089
+
1090
+ # Extract repo name from URL
1091
+ if (
1092
+ "bobmatnyc/claude-mpm" in repo_url
1093
+ or "claude-mpm" in repo_url.lower()
1094
+ ):
1095
+ source_label = "MPM Agents"
1096
+ elif "/" in repo_url:
1097
+ # Extract last part of org/repo
1098
+ parts = repo_url.rstrip("/").split("/")
1099
+ if len(parts) >= 2:
1100
+ source_label = f"{parts[-2]}/{parts[-1]}"
1101
+ else:
1102
+ source_label = "Community"
1103
+ else:
1104
+ source_label = "Community"
1105
+ else:
1106
+ source_label = "Local"
1107
+
1108
+ # Determine installation status (removed symbols for cleaner look)
1109
+ is_installed = getattr(agent, "is_deployed", False)
1110
+ if is_installed:
1111
+ status = "[green]Installed[/green]"
1112
+ else:
1113
+ status = "Available"
1114
+
1115
+ # Get display name (for remote agents, use display_name instead of agent_id)
1116
+ display_name = getattr(agent, "display_name", agent.name)
1117
+ # Let overflow="ellipsis" handle truncation automatically
1118
+
1119
+ agents_table.add_row(
1120
+ str(idx), agent.name, display_name, source_label, status
1121
+ )
1122
+
1123
+ self.console.print(agents_table)
1124
+
1125
+ # Show installed vs available count
1126
+ installed_count = sum(1 for a in agents if getattr(a, "is_deployed", False))
1127
+ available_count = len(agents) - installed_count
1128
+ self.console.print(
1129
+ f"\n[green]✓ {installed_count} installed[/green] | "
1130
+ f"[dim]{available_count} available[/dim] | "
1131
+ f"[dim]Total: {len(agents)}[/dim]"
1132
+ )
1133
+
1134
+ def _manage_sources(self) -> None:
1135
+ """Interactive source management."""
1136
+ self.console.print("\n[bold white]═══ Manage Agent Sources ═══[/bold white]\n")
1137
+ self.console.print(
1138
+ "[dim]Use 'claude-mpm agent-source' command to add/remove sources[/dim]"
1139
+ )
1140
+ self.console.print("\nExamples:")
1141
+ self.console.print(" claude-mpm agent-source add <git-url>")
1142
+ self.console.print(" claude-mpm agent-source remove <identifier>")
1143
+ self.console.print(" claude-mpm agent-source list")
1144
+ Prompt.ask("\nPress Enter to continue")
1145
+
1146
+ def _deploy_agents_individual(self, agents: List[AgentConfig]) -> None:
1147
+ """Manage agent installation state (unified install/remove interface)."""
1148
+ if not agents:
1149
+ self.console.print("[yellow]No agents available[/yellow]")
1150
+ Prompt.ask("\nPress Enter to continue")
1151
+ return
1152
+
1153
+ # Get ALL agents (filter BASE_AGENT but keep deployed agents visible)
1154
+ from claude_mpm.utils.agent_filters import (
1155
+ filter_base_agents,
1156
+ get_deployed_agent_ids,
1157
+ )
1158
+
1159
+ # Filter BASE_AGENT but keep deployed agents visible
1160
+ all_agents = filter_base_agents(
1161
+ [
1162
+ {
1163
+ "agent_id": a.name,
1164
+ "name": a.name,
1165
+ "description": a.description,
1166
+ "deployed": getattr(a, "is_deployed", False),
1167
+ }
1168
+ for a in agents
1169
+ ]
1170
+ )
1171
+
1172
+ # Get deployed agent IDs (original state - for calculating final changes)
1173
+ deployed_ids = get_deployed_agent_ids()
1174
+
1175
+ if not all_agents:
1176
+ self.console.print("[yellow]No agents available[/yellow]")
1177
+ Prompt.ask("\nPress Enter to continue")
1178
+ return
1179
+
1180
+ # Track current selection state (starts with deployed, updated after each iteration)
1181
+ current_selection = set(deployed_ids)
1182
+
1183
+ # Loop to allow adjusting selection
1184
+ while True:
1185
+ # Build checkbox choices with pre-selection based on current_selection
1186
+ agent_choices = []
1187
+ agent_map = {} # For lookup after selection
1188
+
1189
+ for agent in agents:
1190
+ if agent.name in {a["agent_id"] for a in all_agents}:
1191
+ display_name = getattr(agent, "display_name", agent.name)
1192
+
1193
+ # Pre-check based on current_selection (not deployed_ids)
1194
+ # Extract leaf name from full path for comparison
1195
+ agent_leaf_name = agent.name.split("/")[-1]
1196
+ is_selected = agent_leaf_name in current_selection
1197
+
1198
+ # Simple format: "agent/path - Display Name"
1199
+ # Checkbox state (checked/unchecked) indicates installed status
1200
+ choice_text = f"{agent.name}"
1201
+ if display_name and display_name != agent.name:
1202
+ choice_text += f" - {display_name}"
1203
+
1204
+ # Create choice with checked based on current_selection
1205
+ choice = questionary.Choice(
1206
+ title=choice_text, value=agent.name, checked=is_selected
1207
+ )
1208
+
1209
+ agent_choices.append(choice)
1210
+ agent_map[agent.name] = agent
1211
+
1212
+ # Multi-select with pre-selection
1213
+ self.console.print("\n[bold cyan]Manage Agent Installation[/bold cyan]")
1214
+ self.console.print("[dim][✓] Checked = Installed (uncheck to remove)[/dim]")
1215
+ self.console.print(
1216
+ "[dim][ ] Unchecked = Available (check to install)[/dim]"
1217
+ )
1218
+ self.console.print(
1219
+ "[dim]Use arrow keys to navigate, space to toggle, "
1220
+ "Enter to apply changes[/dim]\n"
1221
+ )
1222
+
1223
+ # Monkey-patch questionary symbols for better visibility
1224
+ questionary.constants.INDICATOR_SELECTED = "[✓]"
1225
+ questionary.constants.INDICATOR_UNSELECTED = "[ ]"
1226
+
1227
+ # Pre-selection via checked=True on Choice objects
1228
+ self.logger.debug(
1229
+ "About to show checkbox selection with %d agents", len(agent_choices)
1230
+ )
1231
+
1232
+ try:
1233
+ selected_agent_ids = questionary.checkbox(
1234
+ "Agents:", choices=agent_choices, style=self.QUESTIONARY_STYLE
1235
+ ).ask()
1236
+ except Exception as e:
1237
+ # Handle questionary failure (non-TTY, broken pipe, keyboard interrupt, etc.)
1238
+ import sys
1239
+
1240
+ self.logger.error(f"Questionary checkbox failed: {e}", exc_info=True)
1241
+ self.console.print(
1242
+ "[red]Error: Could not display interactive menu[/red]"
1243
+ )
1244
+ self.console.print(f"[dim]Reason: {e}[/dim]")
1245
+ if not sys.stdin.isatty():
1246
+ self.console.print("[dim]Interactive terminal required. Use:[/dim]")
1247
+ self.console.print(
1248
+ "[dim] --list-agents to see available agents[/dim]"
1249
+ )
1250
+ self.console.print(
1251
+ "[dim] --enable-agent/--disable-agent for scripting[/dim]"
1252
+ )
1253
+ else:
1254
+ self.console.print(
1255
+ "[dim]This might be a terminal compatibility issue.[/dim]"
1256
+ )
1257
+ Prompt.ask("\nPress Enter to continue")
1258
+ return
1259
+
1260
+ # Handle Esc OR non-interactive terminal
1261
+ if selected_agent_ids is None:
1262
+ # Check if we're in a non-interactive environment
1263
+ import sys
1264
+
1265
+ if not sys.stdin.isatty():
1266
+ self.console.print(
1267
+ "[red]Error: Interactive terminal required for agent selection[/red]"
1268
+ )
1269
+ self.console.print(
1270
+ "[dim]Use --list-agents to see available agents[/dim]"
1271
+ )
1272
+ self.console.print(
1273
+ "[dim]Use --enable-agent/--disable-agent for non-interactive mode[/dim]"
1274
+ )
1275
+ else:
1276
+ self.console.print("[yellow]No changes made[/yellow]")
1277
+ Prompt.ask("\nPress Enter to continue")
1278
+ return
1279
+
1280
+ # Update current_selection based on user's choices
1281
+ current_selection = set(selected_agent_ids)
1282
+
1283
+ # Determine actions based on ORIGINAL deployed_ids
1284
+ to_deploy = (
1285
+ current_selection - deployed_ids
1286
+ ) # Selected but not originally deployed
1287
+ to_remove = (
1288
+ deployed_ids - current_selection
1289
+ ) # Originally deployed but not selected
1290
+
1291
+ if not to_deploy and not to_remove:
1292
+ self.console.print(
1293
+ "[yellow]No changes needed - all selected agents are already installed[/yellow]"
1294
+ )
1295
+ Prompt.ask("\nPress Enter to continue")
1296
+ return
1297
+
1298
+ # Show what will happen
1299
+ self.console.print("\n[bold]Changes to apply:[/bold]")
1300
+ if to_deploy:
1301
+ self.console.print(f"[green]Install {len(to_deploy)} agent(s)[/green]")
1302
+ for agent_id in to_deploy:
1303
+ self.console.print(f" + {agent_id}")
1304
+ if to_remove:
1305
+ self.console.print(f"[red]Remove {len(to_remove)} agent(s)[/red]")
1306
+ for agent_id in to_remove:
1307
+ self.console.print(f" - {agent_id}")
1308
+
1309
+ # Ask user to confirm, adjust, or cancel
1310
+ action = questionary.select(
1311
+ "\nWhat would you like to do?",
1312
+ choices=[
1313
+ questionary.Choice("Apply these changes", value="apply"),
1314
+ questionary.Choice("Adjust selection", value="adjust"),
1315
+ questionary.Choice("Cancel", value="cancel"),
1316
+ ],
1317
+ default="apply",
1318
+ style=self.QUESTIONARY_STYLE,
1319
+ ).ask()
1320
+
1321
+ if action == "cancel":
1322
+ self.console.print("[yellow]Changes cancelled[/yellow]")
1323
+ Prompt.ask("\nPress Enter to continue")
1324
+ return
1325
+ if action == "adjust":
1326
+ # current_selection is already updated, loop will use it
1327
+ continue
1328
+
1329
+ # Execute changes
1330
+ deploy_success = 0
1331
+ deploy_fail = 0
1332
+ remove_success = 0
1333
+ remove_fail = 0
1334
+
1335
+ # Install new agents
1336
+ for agent_id in to_deploy:
1337
+ agent = agent_map.get(agent_id)
1338
+ if agent and self._deploy_single_agent(agent, show_feedback=False):
1339
+ deploy_success += 1
1340
+ self.console.print(f"[green]✓ Installed: {agent_id}[/green]")
1341
+ else:
1342
+ deploy_fail += 1
1343
+ self.console.print(f"[red]✗ Failed to install: {agent_id}[/red]")
1344
+
1345
+ # Remove agents
1346
+ for agent_id in to_remove:
1347
+ try:
1348
+ import json
1349
+ from pathlib import Path
1350
+
1351
+ # Remove from project, legacy, and user locations
1352
+ project_path = (
1353
+ Path.cwd() / ".claude-mpm" / "agents" / f"{agent_id}.md"
1354
+ )
1355
+ legacy_path = Path.cwd() / ".claude" / "agents" / f"{agent_id}.md"
1356
+ user_path = Path.home() / ".claude" / "agents" / f"{agent_id}.md"
1357
+
1358
+ removed = False
1359
+ for path in [project_path, legacy_path, user_path]:
1360
+ if path.exists():
1361
+ path.unlink()
1362
+ removed = True
1363
+
1364
+ # Also remove from virtual deployment state
1365
+ deployment_state_paths = [
1366
+ Path.cwd() / ".claude" / "agents" / ".mpm_deployment_state",
1367
+ Path.home() / ".claude" / "agents" / ".mpm_deployment_state",
1368
+ ]
1369
+
1370
+ for state_path in deployment_state_paths:
1371
+ if state_path.exists():
1372
+ try:
1373
+ with state_path.open() as f:
1374
+ state = json.load(f)
1375
+
1376
+ # Remove agent from deployment state
1377
+ agents = state.get("last_check_results", {}).get(
1378
+ "agents", {}
1379
+ )
1380
+ if agent_id in agents:
1381
+ del agents[agent_id]
1382
+ removed = True
1383
+
1384
+ # Save updated state
1385
+ with state_path.open("w") as f:
1386
+ json.dump(state, f, indent=2)
1387
+ except (json.JSONDecodeError, KeyError) as e:
1388
+ # Log but don't fail - physical removal still counts
1389
+ self.logger.debug(
1390
+ f"Failed to update deployment state at {state_path}: {e}"
1391
+ )
1392
+
1393
+ if removed:
1394
+ remove_success += 1
1395
+ self.console.print(f"[green]✓ Removed: {agent_id}[/green]")
1396
+ else:
1397
+ remove_fail += 1
1398
+ self.console.print(f"[yellow]⚠ Not found: {agent_id}[/yellow]")
1399
+ except Exception as e:
1400
+ remove_fail += 1
1401
+ self.console.print(f"[red]✗ Failed to remove {agent_id}: {e}[/red]")
1402
+
1403
+ # Show summary
1404
+ self.console.print()
1405
+ if deploy_success > 0:
1406
+ self.console.print(
1407
+ f"[green]✓ Installed {deploy_success} agent(s)[/green]"
1408
+ )
1409
+ if deploy_fail > 0:
1410
+ self.console.print(
1411
+ f"[red]✗ Failed to install {deploy_fail} agent(s)[/red]"
1412
+ )
1413
+ if remove_success > 0:
1414
+ self.console.print(
1415
+ f"[green]✓ Removed {remove_success} agent(s)[/green]"
1416
+ )
1417
+ if remove_fail > 0:
1418
+ self.console.print(
1419
+ f"[red]✗ Failed to remove {remove_fail} agent(s)[/red]"
1420
+ )
1421
+
1422
+ Prompt.ask("\nPress Enter to continue")
1423
+ # Exit the loop after successful execution
1424
+ break
1425
+
1426
+ def _deploy_agents_preset(self) -> None:
1427
+ """Install agents using preset configuration."""
1428
+ try:
1429
+ from claude_mpm.services.agents.agent_preset_service import (
1430
+ AgentPresetService,
1431
+ )
1432
+ from claude_mpm.services.agents.git_source_manager import GitSourceManager
1433
+
1434
+ source_manager = GitSourceManager()
1435
+ preset_service = AgentPresetService(source_manager)
1436
+
1437
+ presets = preset_service.list_presets()
1438
+
1439
+ if not presets:
1440
+ self.console.print("[yellow]No presets available[/yellow]")
1441
+ Prompt.ask("\nPress Enter to continue")
1442
+ return
1443
+
1444
+ self.console.print("\n[bold white]═══ Available Presets ═══[/bold white]\n")
1445
+ for idx, preset in enumerate(presets, 1):
1446
+ self.console.print(f" {idx}. [white]{preset['name']}[/white]")
1447
+ self.console.print(f" {preset['description']}")
1448
+ self.console.print(f" [dim]Agents: {len(preset['agents'])}[/dim]\n")
1449
+
1450
+ selection = Prompt.ask("\nEnter preset number (or 'c' to cancel)")
1451
+ if selection.lower() == "c":
1452
+ return
1453
+
1454
+ idx = int(selection) - 1
1455
+ if 0 <= idx < len(presets):
1456
+ preset_name = presets[idx]["name"]
1457
+
1458
+ # Resolve and deploy preset
1459
+ resolution = preset_service.resolve_agents(preset_name)
1460
+
1461
+ if resolution.get("missing_agents"):
1462
+ self.console.print(
1463
+ f"[red]Missing agents: {len(resolution['missing_agents'])}[/red]"
1464
+ )
1465
+ for agent_id in resolution["missing_agents"]:
1466
+ self.console.print(f" • {agent_id}")
1467
+ Prompt.ask("\nPress Enter to continue")
1468
+ return
1469
+
1470
+ # Confirm installation
1471
+ self.console.print(
1472
+ f"\n[bold]Preset '{preset_name}' includes {len(resolution['agents'])} agents[/bold]"
1473
+ )
1474
+ if Confirm.ask("Install all agents?", default=True):
1475
+ installed = 0
1476
+ for agent in resolution["agents"]:
1477
+ # Convert dict to AgentConfig-like object for installation
1478
+ agent_config = AgentConfig(
1479
+ name=agent.get("agent_id", "unknown"),
1480
+ description=agent.get("metadata", {}).get(
1481
+ "description", ""
1482
+ ),
1483
+ dependencies=[],
1484
+ )
1485
+ agent_config.source_dict = agent
1486
+ agent_config.full_agent_id = agent.get("agent_id", "unknown")
1487
+
1488
+ if self._deploy_single_agent(agent_config, show_feedback=False):
1489
+ installed += 1
1490
+
1491
+ self.console.print(
1492
+ f"\n[green]✓ Installed {installed}/{len(resolution['agents'])} agents[/green]"
1493
+ )
1494
+
1495
+ Prompt.ask("\nPress Enter to continue")
1496
+ else:
1497
+ self.console.print("[red]Invalid selection[/red]")
1498
+ Prompt.ask("\nPress Enter to continue")
1499
+
1500
+ except Exception as e:
1501
+ self.console.print(f"[red]Error installing preset: {e}[/red]")
1502
+ self.logger.error(f"Preset installation failed: {e}", exc_info=True)
1503
+ Prompt.ask("\nPress Enter to continue")
1504
+
1505
+ def _deploy_single_agent(
1506
+ self, agent: AgentConfig, show_feedback: bool = True
1507
+ ) -> bool:
1508
+ """Install a single agent to the appropriate location."""
1509
+ try:
1510
+ # Check if this is a remote agent with source_dict
1511
+ source_dict = getattr(agent, "source_dict", None)
1512
+ full_agent_id = getattr(agent, "full_agent_id", agent.name)
1513
+
1514
+ if source_dict:
1515
+ # Deploy remote agent using its source file
1516
+ source_file = Path(source_dict.get("source_file", ""))
1517
+ if not source_file.exists():
1518
+ if show_feedback:
1519
+ self.console.print(
1520
+ f"[red]✗ Source file not found: {source_file}[/red]"
1521
+ )
1522
+ return False
1523
+
1524
+ # Determine target file name (use leaf name from hierarchical ID)
1525
+ if "/" in full_agent_id:
1526
+ target_name = full_agent_id.split("/")[-1] + ".md"
1527
+ else:
1528
+ target_name = full_agent_id + ".md"
1529
+
1530
+ # Deploy to user-level agents directory
1531
+ target_dir = Path.home() / ".claude" / "agents"
1532
+ target_dir.mkdir(parents=True, exist_ok=True)
1533
+ target_file = target_dir / target_name
1534
+
1535
+ if show_feedback:
1536
+ self.console.print(
1537
+ f"\n[white]Installing {full_agent_id}...[/white]"
1538
+ )
1539
+
1540
+ # Copy the agent file
1541
+ import shutil
1542
+
1543
+ shutil.copy2(source_file, target_file)
1544
+
1545
+ if show_feedback:
1546
+ self.console.print(
1547
+ f"[green]✓ Successfully installed {full_agent_id} to {target_file}[/green]"
1548
+ )
1549
+ Prompt.ask("\nPress Enter to continue")
1550
+
1551
+ return True
1552
+ # Legacy local template installation (not implemented here)
1553
+ if show_feedback:
1554
+ self.console.print(
1555
+ "[yellow]Local template installation not yet implemented[/yellow]"
1556
+ )
1557
+ Prompt.ask("\nPress Enter to continue")
1558
+ return False
1559
+
1560
+ except Exception as e:
1561
+ if show_feedback:
1562
+ self.console.print(f"[red]Error installing agent: {e}[/red]")
1563
+ self.logger.error(f"Agent installation failed: {e}", exc_info=True)
1564
+ Prompt.ask("\nPress Enter to continue")
1565
+ return False
1566
+
1567
+ def _remove_agents(self, agents: List[AgentConfig]) -> None:
1568
+ """Remove installed agents."""
1569
+ # Filter to installed agents only
1570
+ installed = [a for a in agents if getattr(a, "is_deployed", False)]
1571
+
1572
+ if not installed:
1573
+ self.console.print("[yellow]No agents are currently installed[/yellow]")
1574
+ Prompt.ask("\nPress Enter to continue")
1575
+ return
1576
+
1577
+ self.console.print(f"\n[bold]Installed agents ({len(installed)}):[/bold]")
1578
+ for idx, agent in enumerate(installed, 1):
1579
+ display_name = getattr(agent, "display_name", agent.name)
1580
+ self.console.print(f" {idx}. {agent.name} - {display_name}")
1581
+
1582
+ selection = Prompt.ask("\nEnter agent number to remove (or 'c' to cancel)")
1583
+ if selection.lower() == "c":
1584
+ return
1585
+
1586
+ try:
1587
+ idx = int(selection) - 1
1588
+ if 0 <= idx < len(installed):
1589
+ agent = installed[idx]
1590
+ full_agent_id = getattr(agent, "full_agent_id", agent.name)
1591
+
1592
+ # Determine possible file names (hierarchical and leaf)
1593
+ file_names = [f"{full_agent_id}.md"]
1594
+ if "/" in full_agent_id:
1595
+ leaf_name = full_agent_id.split("/")[-1]
1596
+ file_names.append(f"{leaf_name}.md")
1597
+
1598
+ # Remove from both project and user directories
1599
+ removed = False
1600
+ project_agent_dir = Path.cwd() / ".claude-mpm" / "agents"
1601
+ user_agent_dir = Path.home() / ".claude" / "agents"
1602
+
1603
+ for file_name in file_names:
1604
+ project_file = project_agent_dir / file_name
1605
+ user_file = user_agent_dir / file_name
1606
+
1607
+ if project_file.exists():
1608
+ project_file.unlink()
1609
+ removed = True
1610
+ self.console.print(f"[green]✓ Removed {project_file}[/green]")
1611
+
1612
+ if user_file.exists():
1613
+ user_file.unlink()
1614
+ removed = True
1615
+ self.console.print(f"[green]✓ Removed {user_file}[/green]")
1616
+
1617
+ if removed:
1618
+ self.console.print(
1619
+ f"[green]✓ Successfully removed {full_agent_id}[/green]"
1620
+ )
1621
+ else:
1622
+ self.console.print("[yellow]Agent files not found[/yellow]")
1623
+
1624
+ Prompt.ask("\nPress Enter to continue")
1625
+ else:
1626
+ self.console.print("[red]Invalid selection[/red]")
1627
+ Prompt.ask("\nPress Enter to continue")
1628
+
1629
+ except (ValueError, IndexError):
1630
+ self.console.print("[red]Invalid selection[/red]")
1631
+ Prompt.ask("\nPress Enter to continue")
1632
+
1633
+ def _view_agent_details_enhanced(self, agents: List[AgentConfig]) -> None:
1634
+ """View detailed agent information with enhanced remote agent details."""
1635
+ if not agents:
1636
+ self.console.print("[yellow]No agents available[/yellow]")
1637
+ Prompt.ask("\nPress Enter to continue")
1638
+ return
1639
+
1640
+ self.console.print(f"\n[bold]Available agents ({len(agents)}):[/bold]")
1641
+ for idx, agent in enumerate(agents, 1):
1642
+ display_name = getattr(agent, "display_name", agent.name)
1643
+ self.console.print(f" {idx}. {agent.name} - {display_name}")
1644
+
1645
+ selection = Prompt.ask("\nEnter agent number to view (or 'c' to cancel)")
1646
+ if selection.lower() == "c":
1647
+ return
1648
+
1649
+ try:
1650
+ idx = int(selection) - 1
1651
+ if 0 <= idx < len(agents):
1652
+ agent = agents[idx]
1653
+
1654
+ self.console.clear()
1655
+ self.console.print("\n[bold white]═══ Agent Details ═══[/bold white]\n")
1656
+
1657
+ # Basic info
1658
+ self.console.print(f"[bold]ID:[/bold] {agent.name}")
1659
+ display_name = getattr(agent, "display_name", "N/A")
1660
+ self.console.print(f"[bold]Name:[/bold] {display_name}")
1661
+ self.console.print(f"[bold]Description:[/bold] {agent.description}")
1662
+
1663
+ # Source info
1664
+ source_type = getattr(agent, "source_type", "local")
1665
+ self.console.print(f"[bold]Source Type:[/bold] {source_type}")
1666
+
1667
+ if source_type == "remote":
1668
+ source_dict = getattr(agent, "source_dict", {})
1669
+ category = source_dict.get("category", "N/A")
1670
+ source = source_dict.get("source", "N/A")
1671
+ version = source_dict.get("version", "N/A")
1672
+
1673
+ self.console.print(f"[bold]Category:[/bold] {category}")
1674
+ self.console.print(f"[bold]Source:[/bold] {source}")
1675
+ self.console.print(f"[bold]Version:[/bold] {version[:16]}...")
1676
+
1677
+ # Installation status
1678
+ is_installed = getattr(agent, "is_deployed", False)
1679
+ status = "Installed" if is_installed else "Available"
1680
+ self.console.print(f"[bold]Status:[/bold] {status}")
1681
+
1682
+ Prompt.ask("\nPress Enter to continue")
1683
+ else:
1684
+ self.console.print("[red]Invalid selection[/red]")
1685
+ Prompt.ask("\nPress Enter to continue")
1686
+
1687
+ except (ValueError, IndexError):
1688
+ self.console.print("[red]Invalid selection[/red]")
1689
+ Prompt.ask("\nPress Enter to continue")
1690
+
812
1691
 
813
1692
  def manage_configure(args) -> int:
814
1693
  """Main entry point for configuration management command.