claude-mpm 3.9.9__py3-none-any.whl → 4.0.3__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.
Files changed (411) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +155 -0
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +90 -49
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +21 -18
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +143 -762
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1150
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +217 -0
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +36 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +571 -0
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +40 -23
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
  298. claude_mpm/services/mcp_gateway/main.py +307 -127
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
  303. claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +20 -534
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +9 -0
  358. claude_mpm/storage/state_storage.py +552 -0
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/config/memory_guardian_config.py +0 -325
  385. claude_mpm/core/config_paths.py +0 -150
  386. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  387. claude_mpm/deployment_paths.py +0 -261
  388. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  389. claude_mpm/models/state_models.py +0 -433
  390. claude_mpm/services/agent/__init__.py +0 -24
  391. claude_mpm/services/agent/deployment.py +0 -2548
  392. claude_mpm/services/agent/management.py +0 -598
  393. claude_mpm/services/agent/registry.py +0 -813
  394. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  395. claude_mpm/services/communication/socketio.py +0 -1935
  396. claude_mpm/services/communication/websocket.py +0 -479
  397. claude_mpm/services/framework_claude_md_generator.py +0 -624
  398. claude_mpm/services/health_monitor.py +0 -893
  399. claude_mpm/services/infrastructure/memory_guardian.py +0 -770
  400. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
  401. claude_mpm/services/optimized_hook_service.py +0 -542
  402. claude_mpm/services/project_analyzer.py +0 -864
  403. claude_mpm/services/project_registry.py +0 -608
  404. claude_mpm/services/standalone_socketio_server.py +0 -1300
  405. claude_mpm/services/ticket_manager_di.py +0 -318
  406. claude_mpm/services/ticketing_service_original.py +0 -510
  407. claude_mpm/utils/paths.py +0 -395
  408. claude_mpm/utils/platform_memory.py +0 -524
  409. claude_mpm-3.9.9.dist-info/RECORD +0 -293
  410. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  411. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -5,53 +5,51 @@ WHY: This module manages Claude Code native agents, including listing, deploying
5
5
  and cleaning agent deployments.
6
6
  """
7
7
 
8
- from pathlib import Path
9
8
  import json
9
+ from typing import Any, Dict, Optional
10
+
10
11
  import yaml
11
- from typing import Dict, Any, Optional
12
12
 
13
- from ...core.logger import get_logger
13
+ from ...agents.frontmatter_validator import FrontmatterValidator
14
14
  from ...constants import AgentCommands
15
- from ..utils import get_agent_versions_display
16
15
  from ...core.agent_registry import AgentRegistryAdapter
17
- from ...agents.frontmatter_validator import FrontmatterValidator
18
16
  from ...core.config import Config
17
+ from ...core.logger import get_logger
18
+ from ..utils import get_agent_versions_display
19
19
 
20
20
 
21
21
  def manage_agents(args):
22
22
  """
23
23
  Manage Claude Code native agents.
24
-
24
+
25
25
  WHY: Claude Code agents need to be deployed and managed. This command provides
26
26
  a unified interface for all agent-related operations.
27
-
27
+
28
28
  DESIGN DECISION: When no subcommand is provided, we show the current agent
29
29
  versions as a quick status check. This matches the behavior users see at startup.
30
-
30
+
31
31
  Args:
32
32
  args: Parsed command line arguments with agents_command attribute
33
33
  """
34
34
  logger = get_logger("cli")
35
-
35
+
36
36
  try:
37
- from ...services import AgentDeploymentService
38
37
  import os
39
38
  from pathlib import Path
40
-
39
+
40
+ from ...services import AgentDeploymentService
41
+
41
42
  # Determine the user's working directory from environment
42
43
  # This ensures agents are deployed to the correct directory
43
44
  user_working_dir = None
44
- if 'CLAUDE_MPM_USER_PWD' in os.environ:
45
- user_working_dir = Path(os.environ['CLAUDE_MPM_USER_PWD'])
46
-
45
+ if "CLAUDE_MPM_USER_PWD" in os.environ:
46
+ user_working_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
47
+
47
48
  # For system agents, don't pass working_directory so they deploy to ~/.claude/agents/
48
49
  # The service will determine the correct path based on the agent source
49
50
  deployment_service = AgentDeploymentService()
50
-
51
+
51
52
  if not args.agents_command:
52
- # No subcommand - show agent versions
53
- # WHY: This provides a quick way for users to check deployed agent versions
54
- # without needing to specify additional subcommands
55
53
  agent_versions = get_agent_versions_display()
56
54
  if agent_versions:
57
55
  print(agent_versions)
@@ -59,37 +57,37 @@ def manage_agents(args):
59
57
  print("No deployed agents found")
60
58
  print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
61
59
  return
62
-
60
+
63
61
  if args.agents_command == AgentCommands.LIST.value:
64
62
  _list_agents(args, deployment_service)
65
-
63
+
66
64
  elif args.agents_command == AgentCommands.DEPLOY.value:
67
65
  _deploy_agents(args, deployment_service, force=False)
68
-
66
+
69
67
  elif args.agents_command == AgentCommands.FORCE_DEPLOY.value:
70
68
  _deploy_agents(args, deployment_service, force=True)
71
-
69
+
72
70
  elif args.agents_command == AgentCommands.CLEAN.value:
73
71
  _clean_agents(args, deployment_service)
74
-
72
+
75
73
  elif args.agents_command == AgentCommands.VIEW.value:
76
74
  _view_agent(args)
77
-
75
+
78
76
  elif args.agents_command == AgentCommands.FIX.value:
79
77
  _fix_agents(args)
80
-
81
- elif args.agents_command == 'deps-check':
78
+
79
+ elif args.agents_command == "deps-check":
82
80
  _check_agent_dependencies(args)
83
-
84
- elif args.agents_command == 'deps-install':
81
+
82
+ elif args.agents_command == "deps-install":
85
83
  _install_agent_dependencies(args)
86
-
87
- elif args.agents_command == 'deps-list':
84
+
85
+ elif args.agents_command == "deps-list":
88
86
  _list_agent_dependencies(args)
89
-
90
- elif args.agents_command == 'deps-fix':
87
+
88
+ elif args.agents_command == "deps-fix":
91
89
  _fix_agent_dependencies(args)
92
-
90
+
93
91
  except ImportError:
94
92
  logger.error("Agent deployment service not available")
95
93
  print("Error: Agent deployment service not available")
@@ -101,15 +99,15 @@ def manage_agents(args):
101
99
  def _list_agents(args, deployment_service):
102
100
  """
103
101
  List available or deployed agents.
104
-
102
+
105
103
  WHY: Users need to see what agents are available in the system and what's
106
104
  currently deployed. This helps them understand the agent ecosystem.
107
-
105
+
108
106
  Args:
109
107
  args: Command arguments with 'system', 'deployed', and 'by_tier' flags
110
108
  deployment_service: Agent deployment service instance
111
109
  """
112
- if hasattr(args, 'by_tier') and args.by_tier:
110
+ if hasattr(args, "by_tier") and args.by_tier:
113
111
  # List agents grouped by tier
114
112
  _list_agents_by_tier()
115
113
  elif args.system:
@@ -122,14 +120,14 @@ def _list_agents(args, deployment_service):
122
120
  else:
123
121
  for agent in agents:
124
122
  print(f"📄 {agent['file']}")
125
- if 'name' in agent:
123
+ if "name" in agent:
126
124
  print(f" Name: {agent['name']}")
127
- if 'description' in agent:
125
+ if "description" in agent:
128
126
  print(f" Description: {agent['description']}")
129
- if 'version' in agent:
127
+ if "version" in agent:
130
128
  print(f" Version: {agent['version']}")
131
129
  print()
132
-
130
+
133
131
  elif args.deployed:
134
132
  # List deployed agents
135
133
  print("Deployed Agents:")
@@ -140,28 +138,30 @@ def _list_agents(args, deployment_service):
140
138
  else:
141
139
  for agent in verification["agents_found"]:
142
140
  print(f"📄 {agent['file']}")
143
- if 'name' in agent:
141
+ if "name" in agent:
144
142
  print(f" Name: {agent['name']}")
145
143
  print(f" Path: {agent['path']}")
146
144
  print()
147
-
145
+
148
146
  if verification["warnings"]:
149
147
  print("\nWarnings:")
150
148
  for warning in verification["warnings"]:
151
149
  print(f" ⚠️ {warning}")
152
-
150
+
153
151
  else:
154
152
  # Default: show usage
155
- print("Use --system to list system agents, --deployed to list deployed agents, or --by-tier to group by precedence")
153
+ print(
154
+ "Use --system to list system agents, --deployed to list deployed agents, or --by-tier to group by precedence"
155
+ )
156
156
 
157
157
 
158
158
  def _deploy_agents(args, deployment_service, force=False):
159
159
  """
160
160
  Deploy both system and project agents.
161
-
161
+
162
162
  WHY: Agents need to be deployed to the working directory for Claude Code to use them.
163
163
  This function handles both regular and forced deployment, including project-specific agents.
164
-
164
+
165
165
  Args:
166
166
  args: Command arguments with optional 'target' path
167
167
  deployment_service: Agent deployment service instance
@@ -169,97 +169,109 @@ def _deploy_agents(args, deployment_service, force=False):
169
169
  """
170
170
  # Load configuration to get exclusion settings
171
171
  config = Config()
172
-
172
+
173
173
  # Check if user wants to override exclusions
174
- if hasattr(args, 'include_all') and args.include_all:
174
+ if hasattr(args, "include_all") and args.include_all:
175
175
  # Clear exclusion list if --include-all flag is set
176
- config.set('agent_deployment.excluded_agents', [])
176
+ config.set("agent_deployment.excluded_agents", [])
177
177
  print("✅ Including all agents (exclusion configuration overridden)\n")
178
178
  else:
179
- excluded_agents = config.get('agent_deployment.excluded_agents', [])
180
-
179
+ excluded_agents = config.get("agent_deployment.excluded_agents", [])
180
+
181
181
  # Display exclusion information if agents are being excluded
182
182
  if excluded_agents:
183
183
  logger = get_logger("cli")
184
184
  logger.info(f"Configured agent exclusions: {excluded_agents}")
185
- print(f"\n⚠️ Excluding agents from deployment: {', '.join(excluded_agents)}")
186
-
185
+ print(
186
+ f"\n⚠️ Excluding agents from deployment: {', '.join(excluded_agents)}"
187
+ )
188
+
187
189
  # Warn if commonly used agents are being excluded
188
- common_agents = {'engineer', 'qa', 'security', 'documentation'}
190
+ common_agents = {"engineer", "qa", "security", "documentation"}
189
191
  excluded_common = set(a.lower() for a in excluded_agents) & common_agents
190
192
  if excluded_common:
191
- print(f"⚠️ Warning: Common agents are being excluded: {', '.join(excluded_common)}")
192
- print(" This may affect normal operations. Use 'claude-mpm agents deploy --include-all' to override.\n")
193
-
193
+ print(
194
+ f"⚠️ Warning: Common agents are being excluded: {', '.join(excluded_common)}"
195
+ )
196
+ print(
197
+ " This may affect normal operations. Use 'claude-mpm agents deploy --include-all' to override.\n"
198
+ )
199
+
194
200
  # Deploy system agents first
195
201
  if force:
196
202
  print("Force deploying all system agents...")
197
203
  else:
198
204
  print("Deploying system agents...")
199
-
200
- # Pass configuration to deployment service
201
- # Don't pass args.target for system agents - let the service determine the correct path
202
- # based on whether it's system, user, or project agents
205
+
203
206
  results = deployment_service.deploy_agents(None, force_rebuild=force, config=config)
204
-
207
+
205
208
  # Also deploy project agents if they exist
206
- from pathlib import Path
207
209
  import os
208
-
210
+ from pathlib import Path
211
+
209
212
  # Use the user's working directory if available
210
- if 'CLAUDE_MPM_USER_PWD' in os.environ:
211
- project_dir = Path(os.environ['CLAUDE_MPM_USER_PWD'])
213
+ if "CLAUDE_MPM_USER_PWD" in os.environ:
214
+ project_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
212
215
  else:
213
216
  project_dir = Path.cwd()
214
-
215
- project_agents_dir = project_dir / '.claude-mpm' / 'agents'
217
+
218
+ project_agents_dir = project_dir / ".claude-mpm" / "agents"
216
219
  if project_agents_dir.exists():
217
- json_files = list(project_agents_dir.glob('*.json'))
220
+ json_files = list(project_agents_dir.glob("*.json"))
218
221
  if json_files:
219
222
  print(f"\nDeploying {len(json_files)} project agents...")
220
- from claude_mpm.services.agents.deployment.agent_deployment import AgentDeploymentService
223
+ from claude_mpm.services.agents.deployment.agent_deployment import (
224
+ AgentDeploymentService,
225
+ )
226
+
221
227
  project_service = AgentDeploymentService(
222
228
  templates_dir=project_agents_dir,
223
- base_agent_path=project_agents_dir / 'base_agent.json' if (project_agents_dir / 'base_agent.json').exists() else None,
224
- working_directory=project_dir # Pass the project directory
229
+ base_agent_path=(
230
+ project_agents_dir / "base_agent.json"
231
+ if (project_agents_dir / "base_agent.json").exists()
232
+ else None
233
+ ),
234
+ working_directory=project_dir, # Pass the project directory
225
235
  )
226
236
  # Pass the same configuration to project agent deployment
227
237
  # For project agents, let the service determine they should stay in project directory
228
238
  project_results = project_service.deploy_agents(
229
239
  target_dir=None, # Let service detect it's a project deployment
230
240
  force_rebuild=force,
231
- deployment_mode='project',
232
- config=config
241
+ deployment_mode="project",
242
+ config=config,
233
243
  )
234
-
244
+
235
245
  # Merge project results into main results
236
- if project_results.get('deployed'):
237
- results['deployed'].extend(project_results['deployed'])
246
+ if project_results.get("deployed"):
247
+ results["deployed"].extend(project_results["deployed"])
238
248
  print(f"✓ Deployed {len(project_results['deployed'])} project agents")
239
- if project_results.get('updated'):
240
- results['updated'].extend(project_results['updated'])
249
+ if project_results.get("updated"):
250
+ results["updated"].extend(project_results["updated"])
241
251
  print(f"✓ Updated {len(project_results['updated'])} project agents")
242
- if project_results.get('errors'):
243
- results['errors'].extend(project_results['errors'])
244
-
252
+ if project_results.get("errors"):
253
+ results["errors"].extend(project_results["errors"])
254
+
245
255
  if results["deployed"]:
246
- print(f"\n✓ Successfully deployed {len(results['deployed'])} agents to {results['target_dir']}")
256
+ print(
257
+ f"\n✓ Successfully deployed {len(results['deployed'])} agents to {results['target_dir']}"
258
+ )
247
259
  for agent in results["deployed"]:
248
260
  print(f" - {agent['name']}")
249
-
261
+
250
262
  if force and results.get("updated", []):
251
263
  print(f"\n✓ Updated {len(results['updated'])} agents")
252
264
  for agent in results["updated"]:
253
265
  print(f" - {agent['name']}")
254
-
266
+
255
267
  if force and results.get("skipped", []):
256
268
  print(f"\n✓ Skipped {len(results['skipped'])} up-to-date agents")
257
-
269
+
258
270
  if results["errors"]:
259
271
  print("\n❌ Errors during deployment:")
260
272
  for error in results["errors"]:
261
273
  print(f" - {error}")
262
-
274
+
263
275
  if force:
264
276
  # Set environment for force deploy
265
277
  env_vars = deployment_service.set_claude_environment(
@@ -273,24 +285,24 @@ def _deploy_agents(args, deployment_service, force=False):
273
285
  def _clean_agents(args, deployment_service):
274
286
  """
275
287
  Clean deployed system agents.
276
-
288
+
277
289
  WHY: Users may want to remove deployed agents to start fresh or clean up
278
290
  their working directory.
279
-
291
+
280
292
  Args:
281
293
  args: Command arguments with optional 'target' path
282
294
  deployment_service: Agent deployment service instance
283
295
  """
284
296
  print("Cleaning deployed system agents...")
285
297
  results = deployment_service.clean_deployment(args.target)
286
-
298
+
287
299
  if results["removed"]:
288
300
  print(f"\n✓ Removed {len(results['removed'])} agents")
289
301
  for path in results["removed"]:
290
302
  print(f" - {Path(path).name}")
291
303
  else:
292
304
  print("No system agents found to remove")
293
-
305
+
294
306
  if results["errors"]:
295
307
  print("\n❌ Errors during cleanup:")
296
308
  for error in results["errors"]:
@@ -300,7 +312,7 @@ def _clean_agents(args, deployment_service):
300
312
  def _list_agents_by_tier():
301
313
  """
302
314
  List agents grouped by precedence tier.
303
-
315
+
304
316
  WHY: Users need to understand which agents are active across different tiers
305
317
  and which version takes precedence when multiple versions exist.
306
318
  """
@@ -309,71 +321,75 @@ def _list_agents_by_tier():
309
321
  if not adapter.registry:
310
322
  print("❌ Could not initialize agent registry")
311
323
  return
312
-
324
+
313
325
  # Get all agents and group by tier
314
326
  all_agents = adapter.registry.list_agents()
315
-
327
+
316
328
  # Group agents by tier and name
317
- tiers = {'project': {}, 'user': {}, 'system': {}}
329
+ tiers = {"project": {}, "user": {}, "system": {}}
318
330
  agent_names = set()
319
-
331
+
320
332
  for agent_id, metadata in all_agents.items():
321
- tier = metadata.get('tier', 'system')
333
+ tier = metadata.get("tier", "system")
322
334
  if tier in tiers:
323
335
  tiers[tier][agent_id] = metadata
324
336
  agent_names.add(agent_id)
325
-
337
+
326
338
  # Display header
327
339
  print("\n" + "=" * 80)
328
340
  print(" " * 25 + "AGENT HIERARCHY BY TIER")
329
341
  print("=" * 80)
330
342
  print("\nPrecedence: PROJECT > USER > SYSTEM")
331
343
  print("(Agents in higher tiers override those in lower tiers)\n")
332
-
344
+
333
345
  # Display each tier
334
- tier_order = [('PROJECT', 'project'), ('USER', 'user'), ('SYSTEM', 'system')]
335
-
346
+ tier_order = [("PROJECT", "project"), ("USER", "user"), ("SYSTEM", "system")]
347
+
336
348
  for tier_display, tier_key in tier_order:
337
349
  agents = tiers[tier_key]
338
350
  print(f"\n{'─' * 35} {tier_display} TIER {'─' * 35}")
339
-
351
+
340
352
  if not agents:
341
353
  print(f" No agents at {tier_key} level")
342
354
  else:
343
355
  # Check paths to determine actual locations
344
- if tier_key == 'project':
356
+ if tier_key == "project":
345
357
  print(f" Location: .claude-mpm/agents/ (in current project)")
346
- elif tier_key == 'user':
358
+ elif tier_key == "user":
347
359
  print(f" Location: ~/.claude-mpm/agents/")
348
360
  else:
349
361
  print(f" Location: Built-in framework agents")
350
-
362
+
351
363
  print(f"\n Found {len(agents)} agent(s):\n")
352
-
364
+
353
365
  for agent_id, metadata in sorted(agents.items()):
354
366
  # Check if this agent is overridden by higher tiers
355
367
  is_active = True
356
368
  overridden_by = []
357
-
369
+
358
370
  for check_tier_display, check_tier_key in tier_order:
359
371
  if check_tier_key == tier_key:
360
372
  break
361
373
  if agent_id in tiers[check_tier_key]:
362
374
  is_active = False
363
375
  overridden_by.append(check_tier_display)
364
-
376
+
365
377
  # Display agent info
366
- status = "✓ ACTIVE" if is_active else f"⊗ OVERRIDDEN by {', '.join(overridden_by)}"
378
+ status = (
379
+ "✓ ACTIVE"
380
+ if is_active
381
+ else f"⊗ OVERRIDDEN by {', '.join(overridden_by)}"
382
+ )
367
383
  print(f" 📄 {agent_id:<20} [{status}]")
368
-
384
+
369
385
  # Show metadata
370
- if 'description' in metadata:
386
+ if "description" in metadata:
371
387
  print(f" Description: {metadata['description']}")
372
- if 'path' in metadata:
373
- path = Path(metadata['path'])
388
+ if "path" in metadata:
389
+ path = Path(metadata["path"])
374
390
  print(f" File: {path.name}")
375
391
  print()
376
-
392
+
377
393
  # Summary
378
394
  print("\n" + "=" * 80)
379
395
  print("SUMMARY:")
@@ -382,7 +398,7 @@ def _list_agents_by_tier():
382
398
  print(f" User agents: {len(tiers['user'])}")
383
399
  print(f" System agents: {len(tiers['system'])}")
384
400
  print("=" * 80 + "\n")
385
-
401
+
386
402
  except Exception as e:
387
403
  print(f"❌ Error listing agents by tier: {e}")
388
404
 
@@ -390,24 +406,24 @@ def _list_agents_by_tier():
390
406
  def _view_agent(args):
391
407
  """
392
408
  View detailed information about a specific agent.
393
-
409
+
394
410
  WHY: Users need to inspect agent configurations, frontmatter, and instructions
395
411
  to understand what an agent does and how it's configured.
396
-
412
+
397
413
  Args:
398
414
  args: Command arguments with 'agent_name' attribute
399
415
  """
400
- if not hasattr(args, 'agent_name') or not args.agent_name:
416
+ if not hasattr(args, "agent_name") or not args.agent_name:
401
417
  print("❌ Please specify an agent name to view")
402
418
  print("Usage: claude-mpm agents view <agent_name>")
403
419
  return
404
-
420
+
405
421
  try:
406
422
  adapter = AgentRegistryAdapter()
407
423
  if not adapter.registry:
408
424
  print("❌ Could not initialize agent registry")
409
425
  return
410
-
426
+
411
427
  # Get the agent
412
428
  agent = adapter.registry.get_agent(args.agent_name)
413
429
  if not agent:
@@ -417,21 +433,21 @@ def _view_agent(args):
417
433
  for agent_id in sorted(all_agents.keys()):
418
434
  print(f" - {agent_id}")
419
435
  return
420
-
436
+
421
437
  # Read the agent file
422
438
  agent_path = Path(agent.path)
423
439
  if not agent_path.exists():
424
440
  print(f"❌ Agent file not found: {agent_path}")
425
441
  return
426
-
427
- with open(agent_path, 'r') as f:
442
+
443
+ with open(agent_path, "r") as f:
428
444
  content = f.read()
429
-
445
+
430
446
  # Display agent information
431
447
  print("\n" + "=" * 80)
432
448
  print(f" AGENT: {agent.name}")
433
449
  print("=" * 80)
434
-
450
+
435
451
  # Basic info
436
452
  print(f"\n📋 BASIC INFORMATION:")
437
453
  print(f" Name: {agent.name}")
@@ -442,18 +458,18 @@ def _view_agent(args):
442
458
  print(f" Description: {agent.description}")
443
459
  if agent.specializations:
444
460
  print(f" Specializations: {', '.join(agent.specializations)}")
445
-
461
+
446
462
  # Extract and display frontmatter
447
463
  if content.startswith("---"):
448
464
  try:
449
465
  end_marker = content.find("\n---\n", 4)
450
466
  if end_marker == -1:
451
467
  end_marker = content.find("\n---\r\n", 4)
452
-
468
+
453
469
  if end_marker != -1:
454
470
  frontmatter_str = content[4:end_marker]
455
471
  frontmatter = yaml.safe_load(frontmatter_str)
456
-
472
+
457
473
  print(f"\n📝 FRONTMATTER:")
458
474
  for key, value in frontmatter.items():
459
475
  if isinstance(value, list):
@@ -464,37 +480,41 @@ def _view_agent(args):
464
480
  print(f" {k}: {v}")
465
481
  else:
466
482
  print(f" {key}: {value}")
467
-
483
+
468
484
  # Extract instructions preview
469
485
  instructions_start = end_marker + 5
470
486
  instructions = content[instructions_start:].strip()
471
-
487
+
472
488
  if instructions:
473
489
  print(f"\n📖 INSTRUCTIONS PREVIEW (first 500 chars):")
474
490
  print(" " + "-" * 76)
475
491
  preview = instructions[:500]
476
492
  if len(instructions) > 500:
477
- preview += "...\n\n [Truncated - {:.1f}KB total]".format(len(instructions) / 1024)
478
-
479
- for line in preview.split('\n'):
493
+ preview += "...\n\n [Truncated - {:.1f}KB total]".format(
494
+ len(instructions) / 1024
495
+ )
496
+
497
+ for line in preview.split("\n"):
480
498
  print(f" {line}")
481
499
  print(" " + "-" * 76)
482
500
  except Exception as e:
483
501
  print(f"\n⚠️ Could not parse frontmatter: {e}")
484
502
  else:
485
503
  print(f"\n⚠️ No frontmatter found in agent file")
486
-
504
+
487
505
  # File stats
488
506
  import os
507
+
489
508
  stat = os.stat(agent_path)
490
509
  from datetime import datetime
510
+
491
511
  modified = datetime.fromtimestamp(stat.st_mtime).strftime("%Y-%m-%d %H:%M:%S")
492
512
  print(f"\n📊 FILE STATS:")
493
513
  print(f" Size: {stat.st_size:,} bytes")
494
514
  print(f" Last modified: {modified}")
495
-
515
+
496
516
  print("\n" + "=" * 80 + "\n")
497
-
517
+
498
518
  except Exception as e:
499
519
  print(f"❌ Error viewing agent: {e}")
500
520
 
@@ -502,31 +522,33 @@ def _view_agent(args):
502
522
  def _fix_agents(args):
503
523
  """
504
524
  Fix agent frontmatter issues using FrontmatterValidator.
505
-
525
+
506
526
  WHY: Agent files may have formatting issues in their frontmatter that prevent
507
527
  proper loading. This command automatically fixes common issues.
508
-
528
+
509
529
  Args:
510
530
  args: Command arguments with 'agent_name', 'dry_run', and 'all' flags
511
531
  """
512
532
  validator = FrontmatterValidator()
513
-
533
+
514
534
  try:
515
535
  adapter = AgentRegistryAdapter()
516
536
  if not adapter.registry:
517
537
  print("❌ Could not initialize agent registry")
518
538
  return
519
-
539
+
520
540
  # Determine which agents to fix
521
541
  agents_to_fix = []
522
-
523
- if hasattr(args, 'all') and args.all:
542
+
543
+ if hasattr(args, "all") and args.all:
524
544
  # Fix all agents
525
545
  all_agents = adapter.registry.list_agents()
526
546
  for agent_id, metadata in all_agents.items():
527
- agents_to_fix.append((agent_id, metadata['path']))
528
- print(f"\n🔧 Checking {len(agents_to_fix)} agent(s) for frontmatter issues...\n")
529
- elif hasattr(args, 'agent_name') and args.agent_name:
547
+ agents_to_fix.append((agent_id, metadata["path"]))
548
+ print(
549
+ f"\n🔧 Checking {len(agents_to_fix)} agent(s) for frontmatter issues...\n"
550
+ )
551
+ elif hasattr(args, "agent_name") and args.agent_name:
530
552
  # Fix specific agent
531
553
  agent = adapter.registry.get_agent(args.agent_name)
532
554
  if not agent:
@@ -538,26 +560,26 @@ def _fix_agents(args):
538
560
  print("❌ Please specify an agent name or use --all to fix all agents")
539
561
  print("Usage: claude-mpm agents fix [agent_name] [--dry-run] [--all]")
540
562
  return
541
-
542
- dry_run = hasattr(args, 'dry_run') and args.dry_run
563
+
564
+ dry_run = hasattr(args, "dry_run") and args.dry_run
543
565
  if dry_run:
544
566
  print("🔍 DRY RUN MODE - No changes will be made\n")
545
-
567
+
546
568
  # Process each agent
547
569
  total_issues = 0
548
570
  total_fixed = 0
549
-
571
+
550
572
  for agent_name, agent_path in agents_to_fix:
551
573
  path = Path(agent_path)
552
574
  if not path.exists():
553
575
  print(f"⚠️ Skipping {agent_name}: File not found at {path}")
554
576
  continue
555
-
577
+
556
578
  print(f"📄 {agent_name}:")
557
-
579
+
558
580
  # Validate and potentially fix
559
581
  result = validator.correct_file(path, dry_run=dry_run)
560
-
582
+
561
583
  if result.is_valid and not result.corrections:
562
584
  print(" ✓ No issues found")
563
585
  else:
@@ -566,13 +588,13 @@ def _fix_agents(args):
566
588
  for error in result.errors:
567
589
  print(f" - {error}")
568
590
  total_issues += len(result.errors)
569
-
591
+
570
592
  if result.warnings:
571
593
  print(" ⚠️ Warnings:")
572
594
  for warning in result.warnings:
573
595
  print(f" - {warning}")
574
596
  total_issues += len(result.warnings)
575
-
597
+
576
598
  if result.corrections:
577
599
  if dry_run:
578
600
  print(" 🔧 Would fix:")
@@ -581,23 +603,25 @@ def _fix_agents(args):
581
603
  total_fixed += len(result.corrections)
582
604
  for correction in result.corrections:
583
605
  print(f" - {correction}")
584
-
606
+
585
607
  print()
586
-
608
+
587
609
  # Summary
588
610
  print("=" * 80)
589
611
  print("SUMMARY:")
590
612
  print(f" Agents checked: {len(agents_to_fix)}")
591
613
  print(f" Total issues found: {total_issues}")
592
614
  if dry_run:
593
- print(f" Issues that would be fixed: {sum(1 for _, path in agents_to_fix if validator.validate_file(Path(path)).corrections)}")
615
+ print(
616
+ f" Issues that would be fixed: {sum(1 for _, path in agents_to_fix if validator.validate_file(Path(path)).corrections)}"
617
+ )
594
618
  print("\n💡 Run without --dry-run to apply fixes")
595
619
  else:
596
620
  print(f" Issues fixed: {total_fixed}")
597
621
  if total_fixed > 0:
598
622
  print("\n✓ Frontmatter issues have been fixed!")
599
623
  print("=" * 80 + "\n")
600
-
624
+
601
625
  except Exception as e:
602
626
  print(f"❌ Error fixing agents: {e}")
603
627
 
@@ -605,20 +629,20 @@ def _fix_agents(args):
605
629
  def _check_agent_dependencies(args):
606
630
  """
607
631
  Check dependencies for deployed agents.
608
-
632
+
609
633
  Args:
610
634
  args: Parsed command line arguments
611
635
  """
612
636
  from ...utils.agent_dependency_loader import AgentDependencyLoader
613
-
614
- verbose = getattr(args, 'verbose', False)
615
- specific_agent = getattr(args, 'agent', None)
616
-
637
+
638
+ verbose = getattr(args, "verbose", False)
639
+ specific_agent = getattr(args, "agent", None)
640
+
617
641
  loader = AgentDependencyLoader(auto_install=False)
618
-
642
+
619
643
  # Discover deployed agents
620
644
  loader.discover_deployed_agents()
621
-
645
+
622
646
  # Filter to specific agent if requested
623
647
  if specific_agent:
624
648
  if specific_agent not in loader.deployed_agents:
@@ -626,12 +650,14 @@ def _check_agent_dependencies(args):
626
650
  print(f" Available agents: {', '.join(loader.deployed_agents.keys())}")
627
651
  return
628
652
  # Keep only the specified agent
629
- loader.deployed_agents = {specific_agent: loader.deployed_agents[specific_agent]}
630
-
653
+ loader.deployed_agents = {
654
+ specific_agent: loader.deployed_agents[specific_agent]
655
+ }
656
+
631
657
  # Load dependencies and check
632
658
  loader.load_agent_dependencies()
633
659
  results = loader.analyze_dependencies()
634
-
660
+
635
661
  # Print report
636
662
  report = loader.format_report(results)
637
663
  print(report)
@@ -640,59 +666,64 @@ def _check_agent_dependencies(args):
640
666
  def _install_agent_dependencies(args):
641
667
  """
642
668
  Install missing dependencies for deployed agents.
643
-
669
+
644
670
  Args:
645
671
  args: Parsed command line arguments
646
672
  """
647
- from ...utils.agent_dependency_loader import AgentDependencyLoader
648
673
  import sys
649
-
650
- specific_agent = getattr(args, 'agent', None)
651
- dry_run = getattr(args, 'dry_run', False)
652
-
674
+
675
+ from ...utils.agent_dependency_loader import AgentDependencyLoader
676
+
677
+ specific_agent = getattr(args, "agent", None)
678
+ dry_run = getattr(args, "dry_run", False)
679
+
653
680
  loader = AgentDependencyLoader(auto_install=not dry_run)
654
-
681
+
655
682
  # Discover deployed agents
656
683
  loader.discover_deployed_agents()
657
-
684
+
658
685
  # Filter to specific agent if requested
659
686
  if specific_agent:
660
687
  if specific_agent not in loader.deployed_agents:
661
688
  print(f"❌ Agent '{specific_agent}' is not deployed")
662
689
  print(f" Available agents: {', '.join(loader.deployed_agents.keys())}")
663
690
  return
664
- loader.deployed_agents = {specific_agent: loader.deployed_agents[specific_agent]}
665
-
691
+ loader.deployed_agents = {
692
+ specific_agent: loader.deployed_agents[specific_agent]
693
+ }
694
+
666
695
  # Load dependencies
667
696
  loader.load_agent_dependencies()
668
697
  results = loader.analyze_dependencies()
669
-
670
- missing_deps = results['summary']['missing_python']
671
-
698
+
699
+ missing_deps = results["summary"]["missing_python"]
700
+
672
701
  if not missing_deps:
673
702
  print("✅ All Python dependencies are already installed")
674
703
  return
675
-
704
+
676
705
  print(f"Found {len(missing_deps)} missing dependencies:")
677
706
  for dep in missing_deps:
678
707
  print(f" - {dep}")
679
-
708
+
680
709
  if dry_run:
681
710
  print("\n--dry-run specified, not installing anything")
682
711
  print(f"Would install: pip install {' '.join(missing_deps)}")
683
712
  else:
684
713
  print(f"\nInstalling {len(missing_deps)} dependencies...")
685
714
  success, error = loader.install_missing_dependencies(missing_deps)
686
-
715
+
687
716
  if success:
688
717
  print("✅ Successfully installed all dependencies")
689
-
718
+
690
719
  # Re-check after installation
691
720
  loader.checked_packages.clear()
692
721
  results = loader.analyze_dependencies()
693
-
694
- if results['summary']['missing_python']:
695
- print(f"⚠️ {len(results['summary']['missing_python'])} dependencies still missing after installation")
722
+
723
+ if results["summary"]["missing_python"]:
724
+ print(
725
+ f"⚠️ {len(results['summary']['missing_python'])} dependencies still missing after installation"
726
+ )
696
727
  else:
697
728
  print("✅ All dependencies verified after installation")
698
729
  else:
@@ -702,74 +733,75 @@ def _install_agent_dependencies(args):
702
733
  def _list_agent_dependencies(args):
703
734
  """
704
735
  List all dependencies from deployed agents.
705
-
736
+
706
737
  Args:
707
738
  args: Parsed command line arguments
708
739
  """
709
- from ...utils.agent_dependency_loader import AgentDependencyLoader
710
740
  import json
711
-
712
- output_format = getattr(args, 'format', 'text')
713
-
741
+
742
+ from ...utils.agent_dependency_loader import AgentDependencyLoader
743
+
744
+ output_format = getattr(args, "format", "text")
745
+
714
746
  loader = AgentDependencyLoader(auto_install=False)
715
-
747
+
716
748
  # Discover and load
717
749
  loader.discover_deployed_agents()
718
750
  loader.load_agent_dependencies()
719
-
751
+
720
752
  # Collect all unique dependencies
721
753
  all_python_deps = set()
722
754
  all_system_deps = set()
723
-
755
+
724
756
  for agent_id, deps in loader.agent_dependencies.items():
725
- if 'python' in deps:
726
- all_python_deps.update(deps['python'])
727
- if 'system' in deps:
728
- all_system_deps.update(deps['system'])
729
-
757
+ if "python" in deps:
758
+ all_python_deps.update(deps["python"])
759
+ if "system" in deps:
760
+ all_system_deps.update(deps["system"])
761
+
730
762
  # Format output based on requested format
731
- if output_format == 'pip':
763
+ if output_format == "pip":
732
764
  # Output pip-installable format
733
765
  for dep in sorted(all_python_deps):
734
766
  print(dep)
735
-
736
- elif output_format == 'json':
767
+
768
+ elif output_format == "json":
737
769
  # Output JSON format
738
770
  output = {
739
- 'python': sorted(list(all_python_deps)),
740
- 'system': sorted(list(all_system_deps)),
741
- 'agents': {}
771
+ "python": sorted(list(all_python_deps)),
772
+ "system": sorted(list(all_system_deps)),
773
+ "agents": {},
742
774
  }
743
775
  for agent_id, deps in loader.agent_dependencies.items():
744
- output['agents'][agent_id] = deps
776
+ output["agents"][agent_id] = deps
745
777
  print(json.dumps(output, indent=2))
746
-
778
+
747
779
  else: # text format
748
780
  print("=" * 60)
749
781
  print("DEPENDENCIES FROM DEPLOYED AGENTS")
750
782
  print("=" * 60)
751
783
  print()
752
-
784
+
753
785
  if all_python_deps:
754
786
  print(f"Python Dependencies ({len(all_python_deps)}):")
755
787
  print("-" * 30)
756
788
  for dep in sorted(all_python_deps):
757
789
  print(f" {dep}")
758
790
  print()
759
-
791
+
760
792
  if all_system_deps:
761
793
  print(f"System Dependencies ({len(all_system_deps)}):")
762
794
  print("-" * 30)
763
795
  for dep in sorted(all_system_deps):
764
796
  print(f" {dep}")
765
797
  print()
766
-
798
+
767
799
  print("Per-Agent Dependencies:")
768
800
  print("-" * 30)
769
801
  for agent_id in sorted(loader.agent_dependencies.keys()):
770
802
  deps = loader.agent_dependencies[agent_id]
771
- python_count = len(deps.get('python', []))
772
- system_count = len(deps.get('system', []))
803
+ python_count = len(deps.get("python", []))
804
+ system_count = len(deps.get("system", []))
773
805
  if python_count or system_count:
774
806
  print(f" {agent_id}: {python_count} Python, {system_count} System")
775
807
 
@@ -777,47 +809,47 @@ def _list_agent_dependencies(args):
777
809
  def _fix_agent_dependencies(args):
778
810
  """
779
811
  Fix missing agent dependencies with robust retry logic.
780
-
812
+
781
813
  WHY: Network issues and temporary package unavailability can cause
782
814
  dependency installation to fail. This command uses robust retry logic
783
815
  to maximize success rate.
784
-
816
+
785
817
  Args:
786
818
  args: Parsed command line arguments
787
819
  """
788
820
  from ...utils.agent_dependency_loader import AgentDependencyLoader
789
821
  from ...utils.robust_installer import RobustPackageInstaller
790
-
791
- max_retries = getattr(args, 'max_retries', 3)
792
-
822
+
823
+ max_retries = getattr(args, "max_retries", 3)
824
+
793
825
  print("=" * 70)
794
826
  print("FIXING AGENT DEPENDENCIES WITH RETRY LOGIC")
795
827
  print("=" * 70)
796
828
  print()
797
-
829
+
798
830
  loader = AgentDependencyLoader(auto_install=False)
799
-
831
+
800
832
  # Discover and analyze
801
833
  print("Discovering deployed agents...")
802
834
  loader.discover_deployed_agents()
803
-
835
+
804
836
  if not loader.deployed_agents:
805
837
  print("No deployed agents found")
806
838
  return
807
-
839
+
808
840
  print(f"Found {len(loader.deployed_agents)} deployed agents")
809
841
  print("Analyzing dependencies...")
810
-
842
+
811
843
  loader.load_agent_dependencies()
812
844
  results = loader.analyze_dependencies()
813
-
814
- missing_python = results['summary']['missing_python']
815
- missing_system = results['summary']['missing_system']
816
-
845
+
846
+ missing_python = results["summary"]["missing_python"]
847
+ missing_system = results["summary"]["missing_system"]
848
+
817
849
  if not missing_python and not missing_system:
818
850
  print("\n✅ All dependencies are already satisfied!")
819
851
  return
820
-
852
+
821
853
  # Show what's missing
822
854
  if missing_python:
823
855
  print(f"\n❌ Missing Python packages: {len(missing_python)}")
@@ -825,7 +857,7 @@ def _fix_agent_dependencies(args):
825
857
  print(f" - {pkg}")
826
858
  if len(missing_python) > 10:
827
859
  print(f" ... and {len(missing_python) - 10} more")
828
-
860
+
829
861
  if missing_system:
830
862
  print(f"\n❌ Missing system commands: {len(missing_system)}")
831
863
  for cmd in missing_system:
@@ -833,56 +865,56 @@ def _fix_agent_dependencies(args):
833
865
  print("\n⚠️ System dependencies must be installed manually:")
834
866
  print(f" macOS: brew install {' '.join(missing_system)}")
835
867
  print(f" Ubuntu: apt-get install {' '.join(missing_system)}")
836
-
868
+
837
869
  # Fix Python dependencies with robust installer
838
870
  if missing_python:
839
- print(f"\n🔧 Fixing Python dependencies with {max_retries} retries per package...")
840
-
871
+ print(
872
+ f"\n🔧 Fixing Python dependencies with {max_retries} retries per package..."
873
+ )
874
+
841
875
  # Check compatibility
842
876
  compatible, incompatible = loader.check_python_compatibility(missing_python)
843
-
877
+
844
878
  if incompatible:
845
879
  print(f"\n⚠️ Skipping {len(incompatible)} incompatible packages:")
846
880
  for pkg in incompatible[:5]:
847
881
  print(f" - {pkg}")
848
882
  if len(incompatible) > 5:
849
883
  print(f" ... and {len(incompatible) - 5} more")
850
-
884
+
851
885
  if compatible:
852
886
  installer = RobustPackageInstaller(
853
- max_retries=max_retries,
854
- retry_delay=2.0,
855
- timeout=300
887
+ max_retries=max_retries, retry_delay=2.0, timeout=300
856
888
  )
857
-
889
+
858
890
  print(f"\nInstalling {len(compatible)} compatible packages...")
859
891
  successful, failed, errors = installer.install_packages(compatible)
860
-
892
+
861
893
  print("\n" + "=" * 70)
862
894
  print("INSTALLATION RESULTS:")
863
895
  print("=" * 70)
864
-
896
+
865
897
  if successful:
866
898
  print(f"✅ Successfully installed: {len(successful)} packages")
867
-
899
+
868
900
  if failed:
869
901
  print(f"❌ Failed to install: {len(failed)} packages")
870
902
  for pkg in failed:
871
903
  print(f" - {pkg}: {errors.get(pkg, 'Unknown error')}")
872
-
904
+
873
905
  # Re-check
874
906
  print("\nVerifying installation...")
875
907
  loader.checked_packages.clear()
876
908
  final_results = loader.analyze_dependencies()
877
-
878
- final_missing = final_results['summary']['missing_python']
909
+
910
+ final_missing = final_results["summary"]["missing_python"]
879
911
  if not final_missing:
880
912
  print("✅ All Python dependencies are now satisfied!")
881
913
  else:
882
914
  print(f"⚠️ Still missing {len(final_missing)} packages")
883
915
  print("\nTry running again or install manually:")
884
916
  print(f" pip install {' '.join(final_missing[:3])}")
885
-
917
+
886
918
  print("\n" + "=" * 70)
887
919
  print("DONE")
888
- print("=" * 70)
920
+ print("=" * 70)