claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +50 -2
  21. claude_mpm/cli/__init__.py +51 -46
  22. claude_mpm/cli/__main__.py +1 -1
  23. claude_mpm/cli/commands/__init__.py +10 -12
  24. claude_mpm/cli/commands/agent_manager.py +186 -181
  25. claude_mpm/cli/commands/agents.py +271 -268
  26. claude_mpm/cli/commands/aggregate.py +30 -29
  27. claude_mpm/cli/commands/cleanup.py +50 -44
  28. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  29. claude_mpm/cli/commands/config.py +162 -127
  30. claude_mpm/cli/commands/doctor.py +52 -62
  31. claude_mpm/cli/commands/info.py +37 -25
  32. claude_mpm/cli/commands/mcp.py +3 -7
  33. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  34. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  35. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  36. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  37. claude_mpm/cli/commands/memory.py +192 -141
  38. claude_mpm/cli/commands/monitor.py +117 -88
  39. claude_mpm/cli/commands/run.py +120 -84
  40. claude_mpm/cli/commands/run_config_checker.py +4 -5
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +204 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +20 -23
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +581 -280
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -15
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +93 -38
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  117. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  118. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  119. claude_mpm/hooks/memory_integration_hook.py +5 -5
  120. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  121. claude_mpm/hooks/validation_hooks.py +4 -4
  122. claude_mpm/init.py +4 -9
  123. claude_mpm/models/__init__.py +2 -2
  124. claude_mpm/models/agent_session.py +11 -14
  125. claude_mpm/scripts/mcp_server.py +20 -11
  126. claude_mpm/scripts/mcp_wrapper.py +5 -5
  127. claude_mpm/scripts/mpm_doctor.py +321 -0
  128. claude_mpm/scripts/socketio_daemon.py +28 -25
  129. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  130. claude_mpm/scripts/socketio_server_manager.py +116 -95
  131. claude_mpm/services/__init__.py +49 -49
  132. claude_mpm/services/agent_capabilities_service.py +12 -18
  133. claude_mpm/services/agents/__init__.py +22 -22
  134. claude_mpm/services/agents/agent_builder.py +140 -119
  135. claude_mpm/services/agents/deployment/__init__.py +3 -3
  136. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  137. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  138. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  139. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  140. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  141. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  142. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  143. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  144. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  145. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  146. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  147. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  148. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  149. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  150. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  151. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  152. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  153. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  154. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  155. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  156. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  157. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  158. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  159. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  161. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  162. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  163. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  164. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  167. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  168. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  169. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  170. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  172. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  173. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  175. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  176. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  177. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  178. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  179. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  180. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  181. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  182. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  183. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  184. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  186. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  187. claude_mpm/services/agents/loading/__init__.py +1 -1
  188. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  189. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  190. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  191. claude_mpm/services/agents/management/__init__.py +1 -1
  192. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  193. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  194. claude_mpm/services/agents/memory/__init__.py +4 -4
  195. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  196. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  197. claude_mpm/services/agents/memory/content_manager.py +44 -38
  198. claude_mpm/services/agents/memory/template_generator.py +4 -6
  199. claude_mpm/services/agents/registry/__init__.py +10 -6
  200. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  201. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  202. claude_mpm/services/async_session_logger.py +1 -2
  203. claude_mpm/services/claude_session_logger.py +1 -2
  204. claude_mpm/services/command_deployment_service.py +173 -0
  205. claude_mpm/services/command_handler_service.py +20 -22
  206. claude_mpm/services/core/__init__.py +25 -25
  207. claude_mpm/services/core/base.py +0 -5
  208. claude_mpm/services/core/interfaces/__init__.py +32 -32
  209. claude_mpm/services/core/interfaces/agent.py +0 -21
  210. claude_mpm/services/core/interfaces/communication.py +0 -27
  211. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  212. claude_mpm/services/core/interfaces/service.py +0 -29
  213. claude_mpm/services/diagnostics/__init__.py +1 -1
  214. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  215. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  216. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  217. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  218. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  219. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  220. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  221. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  222. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  223. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  224. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  225. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  226. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  227. claude_mpm/services/diagnostics/models.py +21 -19
  228. claude_mpm/services/event_aggregator.py +10 -17
  229. claude_mpm/services/event_bus/__init__.py +1 -1
  230. claude_mpm/services/event_bus/config.py +54 -35
  231. claude_mpm/services/event_bus/event_bus.py +76 -71
  232. claude_mpm/services/event_bus/relay.py +74 -64
  233. claude_mpm/services/events/__init__.py +11 -11
  234. claude_mpm/services/events/consumers/__init__.py +3 -3
  235. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  236. claude_mpm/services/events/consumers/logging.py +39 -37
  237. claude_mpm/services/events/consumers/metrics.py +56 -57
  238. claude_mpm/services/events/consumers/socketio.py +82 -81
  239. claude_mpm/services/events/core.py +110 -99
  240. claude_mpm/services/events/interfaces.py +56 -72
  241. claude_mpm/services/events/producers/__init__.py +1 -1
  242. claude_mpm/services/events/producers/hook.py +38 -38
  243. claude_mpm/services/events/producers/system.py +46 -44
  244. claude_mpm/services/exceptions.py +81 -80
  245. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  246. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  247. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  248. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  249. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  250. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  251. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  252. claude_mpm/services/hook_service.py +6 -9
  253. claude_mpm/services/infrastructure/__init__.py +1 -1
  254. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  255. claude_mpm/services/infrastructure/monitoring.py +21 -23
  256. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  257. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  258. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  259. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  260. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  261. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  262. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  263. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  264. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  265. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  266. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  267. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  268. claude_mpm/services/mcp_gateway/main.py +2 -1
  269. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  270. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  271. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  273. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  274. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  275. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  276. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  277. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  278. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  279. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  280. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  281. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  282. claude_mpm/services/memory/__init__.py +3 -3
  283. claude_mpm/services/memory/builder.py +3 -6
  284. claude_mpm/services/memory/cache/__init__.py +1 -1
  285. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  286. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  287. claude_mpm/services/memory/indexed_memory.py +5 -7
  288. claude_mpm/services/memory/optimizer.py +7 -10
  289. claude_mpm/services/memory/router.py +8 -9
  290. claude_mpm/services/memory_hook_service.py +48 -34
  291. claude_mpm/services/monitor_build_service.py +77 -73
  292. claude_mpm/services/port_manager.py +130 -108
  293. claude_mpm/services/project/analyzer.py +12 -10
  294. claude_mpm/services/project/registry.py +11 -11
  295. claude_mpm/services/recovery_manager.py +10 -19
  296. claude_mpm/services/response_tracker.py +0 -1
  297. claude_mpm/services/runner_configuration_service.py +19 -20
  298. claude_mpm/services/session_management_service.py +7 -11
  299. claude_mpm/services/shared/__init__.py +1 -1
  300. claude_mpm/services/shared/async_service_base.py +58 -50
  301. claude_mpm/services/shared/config_service_base.py +73 -67
  302. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  303. claude_mpm/services/shared/manager_base.py +94 -82
  304. claude_mpm/services/shared/service_factory.py +96 -98
  305. claude_mpm/services/socketio/__init__.py +3 -3
  306. claude_mpm/services/socketio/client_proxy.py +5 -5
  307. claude_mpm/services/socketio/event_normalizer.py +199 -181
  308. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  309. claude_mpm/services/socketio/handlers/base.py +5 -4
  310. claude_mpm/services/socketio/handlers/connection.py +163 -136
  311. claude_mpm/services/socketio/handlers/file.py +13 -14
  312. claude_mpm/services/socketio/handlers/git.py +12 -7
  313. claude_mpm/services/socketio/handlers/hook.py +49 -44
  314. claude_mpm/services/socketio/handlers/memory.py +0 -1
  315. claude_mpm/services/socketio/handlers/project.py +0 -1
  316. claude_mpm/services/socketio/handlers/registry.py +37 -19
  317. claude_mpm/services/socketio/migration_utils.py +98 -84
  318. claude_mpm/services/socketio/server/__init__.py +1 -1
  319. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  320. claude_mpm/services/socketio/server/core.py +65 -54
  321. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  322. claude_mpm/services/socketio/server/main.py +64 -38
  323. claude_mpm/services/socketio_client_manager.py +10 -12
  324. claude_mpm/services/subprocess_launcher_service.py +4 -7
  325. claude_mpm/services/system_instructions_service.py +13 -14
  326. claude_mpm/services/ticket_manager.py +2 -2
  327. claude_mpm/services/utility_service.py +5 -13
  328. claude_mpm/services/version_control/__init__.py +16 -16
  329. claude_mpm/services/version_control/branch_strategy.py +5 -8
  330. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  331. claude_mpm/services/version_control/git_operations.py +5 -7
  332. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  333. claude_mpm/services/version_control/version_parser.py +13 -18
  334. claude_mpm/services/version_service.py +10 -11
  335. claude_mpm/storage/__init__.py +1 -1
  336. claude_mpm/storage/state_storage.py +22 -28
  337. claude_mpm/utils/__init__.py +6 -6
  338. claude_mpm/utils/agent_dependency_loader.py +47 -33
  339. claude_mpm/utils/config_manager.py +11 -14
  340. claude_mpm/utils/dependency_cache.py +1 -1
  341. claude_mpm/utils/dependency_manager.py +13 -17
  342. claude_mpm/utils/dependency_strategies.py +8 -10
  343. claude_mpm/utils/environment_context.py +3 -9
  344. claude_mpm/utils/error_handler.py +3 -13
  345. claude_mpm/utils/file_utils.py +1 -1
  346. claude_mpm/utils/path_operations.py +8 -12
  347. claude_mpm/utils/robust_installer.py +110 -33
  348. claude_mpm/utils/subprocess_utils.py +5 -6
  349. claude_mpm/validation/agent_validator.py +3 -6
  350. claude_mpm/validation/frontmatter_validator.py +1 -1
  351. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  352. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  353. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  354. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  355. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  356. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  357. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -13,9 +13,9 @@ from .agent_versioning import AgentVersionManager
13
13
  __all__ = [
14
14
  "AgentDeploymentService",
15
15
  "AgentLifecycleManager",
16
- "LifecycleState",
17
- "LifecycleOperation",
18
16
  "AgentLifecycleRecord",
19
- "LifecycleOperationResult",
20
17
  "AgentVersionManager",
18
+ "LifecycleOperation",
19
+ "LifecycleOperationResult",
20
+ "LifecycleState",
21
21
  ]
@@ -38,18 +38,18 @@ class AgentConfigProvider:
38
38
 
39
39
  # Agent-specific tools
40
40
  agent_tools = {
41
- "engineer": base_tools + ["Bash", "WebSearch", "WebFetch"],
42
- "qa": base_tools + ["Bash", "WebSearch"],
43
- "documentation": base_tools + ["WebSearch", "WebFetch"],
44
- "research": base_tools + ["WebSearch", "WebFetch", "Bash"],
45
- "security": base_tools + ["Bash", "WebSearch", "Grep"],
46
- "ops": base_tools + ["Bash", "WebSearch"],
47
- "data_engineer": base_tools + ["Bash", "WebSearch"],
48
- "version_control": base_tools + ["Bash"],
41
+ "engineer": [*base_tools, "Bash", "WebSearch", "WebFetch"],
42
+ "qa": [*base_tools, "Bash", "WebSearch"],
43
+ "documentation": [*base_tools, "WebSearch", "WebFetch"],
44
+ "research": [*base_tools, "WebSearch", "WebFetch", "Bash"],
45
+ "security": [*base_tools, "Bash", "WebSearch", "Grep"],
46
+ "ops": [*base_tools, "Bash", "WebSearch"],
47
+ "data_engineer": [*base_tools, "Bash", "WebSearch"],
48
+ "version_control": [*base_tools, "Bash"],
49
49
  }
50
50
 
51
51
  # Return specific tools or default set
52
- return agent_tools.get(agent_name, base_tools + ["Bash", "WebSearch"])
52
+ return agent_tools.get(agent_name, [*base_tools, "Bash", "WebSearch"])
53
53
 
54
54
  @staticmethod
55
55
  def get_agent_specific_config(agent_name: str) -> Dict[str, Any]:
@@ -8,7 +8,6 @@ maintainability and testability.
8
8
  """
9
9
 
10
10
  import json
11
- import logging
12
11
  from pathlib import Path
13
12
  from typing import Any, Dict, List, Optional, Tuple
14
13
 
@@ -114,26 +113,26 @@ class AgentConfigurationManager:
114
113
  # Agent-specific tools based on name patterns
115
114
  agent_tools = {
116
115
  # Security agents
117
- "security": base_tools + ["SecurityScan", "VulnerabilityCheck"],
118
- "sec": base_tools + ["SecurityScan", "VulnerabilityCheck"],
116
+ "security": [*base_tools, "SecurityScan", "VulnerabilityCheck"],
117
+ "sec": [*base_tools, "SecurityScan", "VulnerabilityCheck"],
119
118
  # QA and testing agents
120
- "qa": base_tools + ["TestRunner", "CodeAnalysis"],
121
- "test": base_tools + ["TestRunner", "CodeAnalysis"],
122
- "testing": base_tools + ["TestRunner", "CodeAnalysis"],
119
+ "qa": [*base_tools, "TestRunner", "CodeAnalysis"],
120
+ "test": [*base_tools, "TestRunner", "CodeAnalysis"],
121
+ "testing": [*base_tools, "TestRunner", "CodeAnalysis"],
123
122
  # Documentation agents
124
- "doc": base_tools + ["DocumentGenerator", "MarkdownProcessor"],
125
- "docs": base_tools + ["DocumentGenerator", "MarkdownProcessor"],
126
- "documentation": base_tools + ["DocumentGenerator", "MarkdownProcessor"],
123
+ "doc": [*base_tools, "DocumentGenerator", "MarkdownProcessor"],
124
+ "docs": [*base_tools, "DocumentGenerator", "MarkdownProcessor"],
125
+ "documentation": [*base_tools, "DocumentGenerator", "MarkdownProcessor"],
127
126
  # Data processing agents
128
- "data": base_tools + ["DataProcessor", "CSVHandler"],
129
- "analytics": base_tools + ["DataProcessor", "CSVHandler"],
127
+ "data": [*base_tools, "DataProcessor", "CSVHandler"],
128
+ "analytics": [*base_tools, "DataProcessor", "CSVHandler"],
130
129
  # Operations agents
131
- "ops": base_tools + ["SystemMonitor", "LogAnalyzer"],
132
- "operations": base_tools + ["SystemMonitor", "LogAnalyzer"],
133
- "monitor": base_tools + ["SystemMonitor", "LogAnalyzer"],
130
+ "ops": [*base_tools, "SystemMonitor", "LogAnalyzer"],
131
+ "operations": [*base_tools, "SystemMonitor", "LogAnalyzer"],
132
+ "monitor": [*base_tools, "SystemMonitor", "LogAnalyzer"],
134
133
  # Research agents
135
- "research": base_tools + ["WebSearch", "DataCollector"],
136
- "analysis": base_tools + ["WebSearch", "DataCollector"],
134
+ "research": [*base_tools, "WebSearch", "DataCollector"],
135
+ "analysis": [*base_tools, "WebSearch", "DataCollector"],
137
136
  }
138
137
 
139
138
  # Check agent name for tool assignment
@@ -150,7 +149,7 @@ class AgentConfigurationManager:
150
149
  return agent_tools[spec_lower]
151
150
 
152
151
  # Return default tools with web search and bash
153
- return base_tools + ["Bash", "WebSearch"]
152
+ return [*base_tools, "Bash", "WebSearch"]
154
153
 
155
154
  def get_agent_specific_config(self, agent_name: str) -> Dict[str, Any]:
156
155
  """
@@ -348,9 +347,9 @@ class AgentConfigurationManager:
348
347
  base_agent_data, base_agent_version = self.load_base_agent()
349
348
 
350
349
  return {
351
- "base_agent_path": str(self.base_agent_path)
352
- if self.base_agent_path
353
- else None,
350
+ "base_agent_path": (
351
+ str(self.base_agent_path) if self.base_agent_path else None
352
+ ),
354
353
  "base_agent_loaded": self._base_agent_cache is not None,
355
354
  "base_agent_version": base_agent_version,
356
355
  "base_agent_name": base_agent_data.get("name", "unknown"),
@@ -4,8 +4,6 @@ This module provides factory functionality for creating AgentDefinition objects
4
4
  from lifecycle manager parameters. Extracted to reduce complexity.
5
5
  """
6
6
 
7
- from typing import Any
8
-
9
7
  from claude_mpm.core.enums import AgentType, ModificationTier
10
8
  from claude_mpm.models.agent_definition import (
11
9
  AgentDefinition,
@@ -64,7 +62,7 @@ class AgentDefinitionFactory:
64
62
  )
65
63
 
66
64
  # Create minimal definition
67
- definition = AgentDefinition(
65
+ return AgentDefinition(
68
66
  name=agent_name,
69
67
  title=agent_name.replace("-", " ").title(),
70
68
  file_path="", # Will be set by AgentManager
@@ -80,5 +78,3 @@ class AgentDefinitionFactory:
80
78
  tools_commands="",
81
79
  raw_content=agent_content,
82
80
  )
83
-
84
- return definition
@@ -27,24 +27,16 @@ ROLLBACK PROCEDURES:
27
27
  - Version tracking allows targeted rollbacks
28
28
  """
29
29
 
30
- import logging
31
30
  import os
32
- import shutil
33
31
  import time
34
32
  from pathlib import Path
35
33
  from typing import Any, Dict, List, Optional, Tuple
36
34
 
37
35
  from claude_mpm.config.paths import paths
38
- from claude_mpm.constants import AgentMetadata, EnvironmentVars, Paths
36
+ from claude_mpm.constants import Paths
39
37
  from claude_mpm.core.config import Config
40
- from claude_mpm.core.constants import ResourceLimits, SystemLimits, TimeoutConfig
41
38
  from claude_mpm.core.exceptions import AgentDeploymentError
42
39
  from claude_mpm.core.interfaces import AgentDeploymentInterface
43
- from claude_mpm.core.logging_config import (
44
- get_logger,
45
- log_operation,
46
- log_performance_context,
47
- )
48
40
  from claude_mpm.services.shared import ConfigServiceBase
49
41
 
50
42
  from .agent_configuration_manager import AgentConfigurationManager
@@ -148,7 +140,7 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
148
140
  self.working_directory = self.get_config_value(
149
141
  "working_directory",
150
142
  default=working_directory or Path.cwd(),
151
- config_type=Path
143
+ config_type=Path,
152
144
  )
153
145
  self.logger.info(f"Working directory for deployment: {self.working_directory}")
154
146
 
@@ -157,18 +149,20 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
157
149
  self.templates_dir = self.get_config_value(
158
150
  "templates_dir",
159
151
  default=templates_dir or paths.agents_dir / "templates",
160
- config_type=Path
152
+ config_type=Path,
161
153
  )
162
154
 
163
155
  # Initialize discovery service (after templates_dir is set)
164
156
  self.discovery_service = AgentDiscoveryService(self.templates_dir)
165
-
157
+
166
158
  # Initialize multi-source deployment service for version comparison
167
159
  self.multi_source_service = MultiSourceAgentDeploymentService()
168
160
 
169
161
  # Find base agent file using configuration
170
162
  # Priority: param > config > search
171
- configured_base_agent = self.get_config_value("base_agent_path", config_type=Path)
163
+ configured_base_agent = self.get_config_value(
164
+ "base_agent_path", config_type=Path
165
+ )
172
166
  if base_agent_path:
173
167
  self.base_agent_path = Path(base_agent_path)
174
168
  elif configured_base_agent:
@@ -185,14 +179,14 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
185
179
 
186
180
  self.logger.info(f"Templates directory: {self.templates_dir}")
187
181
  self.logger.info(f"Base agent path: {self.base_agent_path}")
188
-
182
+
189
183
  def _find_base_agent_file(self) -> Path:
190
184
  """Find base agent file with priority-based search.
191
-
185
+
192
186
  Priority order:
193
187
  1. Environment variable override (CLAUDE_MPM_BASE_AGENT_PATH)
194
188
  2. Current working directory (for local development)
195
- 3. Known development locations
189
+ 3. Known development locations
196
190
  4. User override location (~/.claude/agents/)
197
191
  5. Framework agents directory (from paths)
198
192
  """
@@ -201,49 +195,68 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
201
195
  if env_path:
202
196
  env_base_agent = Path(env_path)
203
197
  if env_base_agent.exists():
204
- self.logger.info(f"Using environment variable base_agent: {env_base_agent}")
198
+ self.logger.info(
199
+ f"Using environment variable base_agent: {env_base_agent}"
200
+ )
205
201
  return env_base_agent
206
- else:
207
- self.logger.warning(f"CLAUDE_MPM_BASE_AGENT_PATH set but file doesn't exist: {env_base_agent}")
208
-
202
+ self.logger.warning(
203
+ f"CLAUDE_MPM_BASE_AGENT_PATH set but file doesn't exist: {env_base_agent}"
204
+ )
205
+
209
206
  # Priority 1: Check current working directory for local development
210
207
  cwd = Path.cwd()
211
208
  cwd_base_agent = cwd / "src" / "claude_mpm" / "agents" / "base_agent.json"
212
209
  if cwd_base_agent.exists():
213
- self.logger.info(f"Using local development base_agent from cwd: {cwd_base_agent}")
210
+ self.logger.info(
211
+ f"Using local development base_agent from cwd: {cwd_base_agent}"
212
+ )
214
213
  return cwd_base_agent
215
-
214
+
216
215
  # Priority 2: Check known development locations
217
216
  known_dev_paths = [
218
- Path("/Users/masa/Projects/claude-mpm/src/claude_mpm/agents/base_agent.json"),
219
- Path.home() / "Projects" / "claude-mpm" / "src" / "claude_mpm" / "agents" / "base_agent.json",
220
- Path.home() / "projects" / "claude-mpm" / "src" / "claude_mpm" / "agents" / "base_agent.json",
217
+ Path(
218
+ "/Users/masa/Projects/claude-mpm/src/claude_mpm/agents/base_agent.json"
219
+ ),
220
+ Path.home()
221
+ / "Projects"
222
+ / "claude-mpm"
223
+ / "src"
224
+ / "claude_mpm"
225
+ / "agents"
226
+ / "base_agent.json",
227
+ Path.home()
228
+ / "projects"
229
+ / "claude-mpm"
230
+ / "src"
231
+ / "claude_mpm"
232
+ / "agents"
233
+ / "base_agent.json",
221
234
  ]
222
-
235
+
223
236
  for dev_path in known_dev_paths:
224
237
  if dev_path.exists():
225
238
  self.logger.info(f"Using development base_agent: {dev_path}")
226
239
  return dev_path
227
-
240
+
228
241
  # Priority 3: Check user override location
229
242
  user_base_agent = Path.home() / ".claude" / "agents" / "base_agent.json"
230
243
  if user_base_agent.exists():
231
244
  self.logger.info(f"Using user override base_agent: {user_base_agent}")
232
245
  return user_base_agent
233
-
246
+
234
247
  # Priority 4: Use framework agents directory (fallback)
235
248
  framework_base_agent = paths.agents_dir / "base_agent.json"
236
249
  if framework_base_agent.exists():
237
250
  self.logger.info(f"Using framework base_agent: {framework_base_agent}")
238
251
  return framework_base_agent
239
-
252
+
240
253
  # If still not found, log all searched locations and raise error
241
254
  self.logger.error("Base agent file not found in any location:")
242
255
  self.logger.error(f" 1. CWD: {cwd_base_agent}")
243
256
  self.logger.error(f" 2. Dev paths: {known_dev_paths}")
244
257
  self.logger.error(f" 3. User: {user_base_agent}")
245
258
  self.logger.error(f" 4. Framework: {framework_base_agent}")
246
-
259
+
247
260
  # Final fallback to framework path even if it doesn't exist
248
261
  # (will fail later with better error message)
249
262
  return framework_base_agent
@@ -382,17 +395,19 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
382
395
 
383
396
  # Check if we should use multi-source deployment
384
397
  use_multi_source = self._should_use_multi_source_deployment(deployment_mode)
385
-
398
+
386
399
  if use_multi_source:
387
400
  # Use multi-source deployment to get highest version agents
388
- template_files, agent_sources, cleanup_results = self._get_multi_source_templates(
389
- excluded_agents, config, agents_dir, force_rebuild
401
+ template_files, agent_sources, cleanup_results = (
402
+ self._get_multi_source_templates(
403
+ excluded_agents, config, agents_dir, force_rebuild
404
+ )
390
405
  )
391
406
  results["total"] = len(template_files)
392
407
  results["multi_source"] = True
393
408
  results["agent_sources"] = agent_sources
394
409
  results["cleanup"] = cleanup_results
395
-
410
+
396
411
  # Log cleanup results if any agents were removed
397
412
  if cleanup_results.get("removed"):
398
413
  self.logger.info(
@@ -410,12 +425,20 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
410
425
 
411
426
  # Deploy each agent template
412
427
  for template_file in template_files:
413
- template_file_path = template_file if isinstance(template_file, Path) else Path(template_file)
428
+ template_file_path = (
429
+ template_file
430
+ if isinstance(template_file, Path)
431
+ else Path(template_file)
432
+ )
414
433
  agent_name = template_file_path.stem
415
-
434
+
416
435
  # Get source info for this agent (agent_sources now uses file stems as keys)
417
- source_info = agent_sources.get(agent_name, "unknown") if agent_sources else "single"
418
-
436
+ source_info = (
437
+ agent_sources.get(agent_name, "unknown")
438
+ if agent_sources
439
+ else "single"
440
+ )
441
+
419
442
  self._deploy_single_agent(
420
443
  template_file=template_file_path,
421
444
  agents_dir=agents_dir,
@@ -558,8 +581,7 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
558
581
  if not needs_update:
559
582
  self.logger.info(f"Agent {agent_name} is up to date")
560
583
  return True
561
- else:
562
- self.logger.info(f"Updating agent {agent_name}: {reason}")
584
+ self.logger.info(f"Updating agent {agent_name}: {reason}")
563
585
 
564
586
  # Load base agent data for building
565
587
  base_agent_data = {}
@@ -628,25 +650,23 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
628
650
  from .system_instructions_deployer import SystemInstructionsDeployer
629
651
 
630
652
  deployer = SystemInstructionsDeployer(self.logger, self.working_directory)
631
- deployer.deploy_system_instructions(
632
- target_dir, force_rebuild, results
633
- )
653
+ deployer.deploy_system_instructions(target_dir, force_rebuild, results)
634
654
 
635
655
  def deploy_system_instructions_explicit(
636
656
  self, target_dir: Optional[Path] = None, force_rebuild: bool = False
637
657
  ) -> Dict[str, Any]:
638
658
  """
639
659
  Explicitly deploy system instructions when requested by user.
640
-
660
+
641
661
  This method should ONLY be called when the user explicitly requests
642
662
  deployment of system instructions through agent-manager commands.
643
663
  It will deploy INSTRUCTIONS.md, MEMORY.md, and WORKFLOW.md to .claude/
644
664
  directory in the project.
645
-
665
+
646
666
  Args:
647
667
  target_dir: Target directory for deployment (ignored - always uses .claude/)
648
668
  force_rebuild: Force rebuild even if files exist
649
-
669
+
650
670
  Returns:
651
671
  Dict with deployment results
652
672
  """
@@ -656,35 +676,34 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
656
676
  "skipped": [],
657
677
  "errors": [],
658
678
  }
659
-
679
+
660
680
  try:
661
681
  # Always use project's .claude directory
662
682
  target_dir = self.working_directory / ".claude"
663
-
683
+
664
684
  # Ensure directory exists
665
685
  target_dir.mkdir(parents=True, exist_ok=True)
666
-
686
+
667
687
  # Deploy using the deployer (targeting .claude/)
668
688
  from .system_instructions_deployer import SystemInstructionsDeployer
689
+
669
690
  deployer = SystemInstructionsDeployer(self.logger, self.working_directory)
670
-
691
+
671
692
  # Deploy to .claude directory
672
- deployer.deploy_system_instructions(
673
- target_dir, force_rebuild, results
674
- )
675
-
693
+ deployer.deploy_system_instructions(target_dir, force_rebuild, results)
694
+
676
695
  self.logger.info(
677
696
  f"Explicitly deployed system instructions to {target_dir}: "
678
697
  f"deployed={len(results['deployed'])}, "
679
698
  f"updated={len(results['updated'])}, "
680
699
  f"skipped={len(results['skipped'])}"
681
700
  )
682
-
701
+
683
702
  except Exception as e:
684
703
  error_msg = f"Failed to deploy system instructions: {e}"
685
704
  self.logger.error(error_msg)
686
705
  results["errors"].append(error_msg)
687
-
706
+
688
707
  return results
689
708
 
690
709
  def _convert_yaml_to_md(self, target_dir: Path) -> Dict[str, Any]:
@@ -774,7 +793,6 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
774
793
  resolver = AgentsDirectoryResolver(self.working_directory)
775
794
  return resolver.determine_agents_directory(target_dir)
776
795
 
777
-
778
796
  def _initialize_deployment_results(
779
797
  self, agents_dir: Path, deployment_start_time: float
780
798
  ) -> Dict[str, Any]:
@@ -1053,74 +1071,77 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
1053
1071
 
1054
1072
  validator = AgentFrontmatterValidator(self.logger)
1055
1073
  return validator.validate_and_repair_existing_agents(agents_dir)
1056
-
1074
+
1057
1075
  def _determine_agent_source(self, template_path: Path) -> str:
1058
1076
  """Determine the source of an agent from its template path.
1059
-
1077
+
1060
1078
  WHY: When deploying single agents, we need to track their source
1061
1079
  for proper version management and debugging.
1062
-
1080
+
1063
1081
  Args:
1064
1082
  template_path: Path to the agent template
1065
-
1083
+
1066
1084
  Returns:
1067
1085
  Source string (system/project/user/unknown)
1068
1086
  """
1069
1087
  template_str = str(template_path.resolve())
1070
-
1088
+
1071
1089
  # Check if it's a system template
1072
- if "/claude_mpm/agents/templates/" in template_str or "/src/claude_mpm/agents/templates/" in template_str:
1090
+ if (
1091
+ "/claude_mpm/agents/templates/" in template_str
1092
+ or "/src/claude_mpm/agents/templates/" in template_str
1093
+ ):
1073
1094
  return "system"
1074
-
1095
+
1075
1096
  # Check if it's a project agent
1076
1097
  if "/.claude-mpm/agents/" in template_str:
1077
1098
  # Check if it's in the current working directory
1078
1099
  if str(self.working_directory) in template_str:
1079
1100
  return "project"
1080
1101
  # Check if it's in user home
1081
- elif str(Path.home()) in template_str:
1102
+ if str(Path.home()) in template_str:
1082
1103
  return "user"
1083
-
1104
+
1084
1105
  return "unknown"
1085
-
1106
+
1086
1107
  def _should_use_multi_source_deployment(self, deployment_mode: str) -> bool:
1087
1108
  """Determine if multi-source deployment should be used.
1088
-
1109
+
1089
1110
  WHY: Multi-source deployment ensures the highest version wins,
1090
1111
  but we may want to preserve backward compatibility in some modes.
1091
-
1112
+
1092
1113
  Args:
1093
1114
  deployment_mode: Current deployment mode
1094
-
1115
+
1095
1116
  Returns:
1096
1117
  True if multi-source deployment should be used
1097
1118
  """
1098
1119
  # Always use multi-source for update mode to get highest versions
1099
1120
  if deployment_mode == "update":
1100
1121
  return True
1101
-
1122
+
1102
1123
  # For project mode, also use multi-source to ensure highest version wins
1103
1124
  # This is the key change - project mode should also compare versions
1104
- if deployment_mode == "project":
1105
- return True
1106
-
1107
- return False
1108
-
1125
+ return deployment_mode == "project"
1126
+
1109
1127
  def _get_multi_source_templates(
1110
- self, excluded_agents: List[str], config: Config, agents_dir: Path,
1111
- force_rebuild: bool = False
1128
+ self,
1129
+ excluded_agents: List[str],
1130
+ config: Config,
1131
+ agents_dir: Path,
1132
+ force_rebuild: bool = False,
1112
1133
  ) -> Tuple[List[Path], Dict[str, str], Dict[str, Any]]:
1113
1134
  """Get agent templates from multiple sources with version comparison.
1114
-
1135
+
1115
1136
  WHY: This method uses the multi-source service to discover agents
1116
1137
  from all available sources and select the highest version of each.
1117
-
1138
+
1118
1139
  Args:
1119
1140
  excluded_agents: List of agents to exclude
1120
1141
  config: Configuration object
1121
1142
  agents_dir: Target deployment directory
1122
1143
  force_rebuild: Whether to force rebuild
1123
-
1144
+
1124
1145
  Returns:
1125
1146
  Tuple of (template_files, agent_sources, cleanup_results)
1126
1147
  """
@@ -1128,70 +1149,79 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
1128
1149
  system_templates_dir = self.templates_dir
1129
1150
  project_agents_dir = None
1130
1151
  user_agents_dir = None
1131
-
1152
+
1132
1153
  # Check for project agents
1133
1154
  if self.working_directory:
1134
1155
  potential_project_dir = self.working_directory / ".claude-mpm" / "agents"
1135
1156
  if potential_project_dir.exists():
1136
1157
  project_agents_dir = potential_project_dir
1137
1158
  self.logger.info(f"Found project agents at: {project_agents_dir}")
1138
-
1159
+
1139
1160
  # Check for user agents
1140
1161
  user_home = Path.home()
1141
1162
  potential_user_dir = user_home / ".claude-mpm" / "agents"
1142
1163
  if potential_user_dir.exists():
1143
1164
  user_agents_dir = potential_user_dir
1144
1165
  self.logger.info(f"Found user agents at: {user_agents_dir}")
1145
-
1166
+
1146
1167
  # Get agents with version comparison and cleanup
1147
- agents_to_deploy, agent_sources, cleanup_results = self.multi_source_service.get_agents_for_deployment(
1148
- system_templates_dir=system_templates_dir,
1149
- project_agents_dir=project_agents_dir,
1150
- user_agents_dir=user_agents_dir,
1151
- working_directory=self.working_directory,
1152
- excluded_agents=excluded_agents,
1153
- config=config,
1154
- cleanup_outdated=True # Enable cleanup by default
1168
+ agents_to_deploy, agent_sources, cleanup_results = (
1169
+ self.multi_source_service.get_agents_for_deployment(
1170
+ system_templates_dir=system_templates_dir,
1171
+ project_agents_dir=project_agents_dir,
1172
+ user_agents_dir=user_agents_dir,
1173
+ working_directory=self.working_directory,
1174
+ excluded_agents=excluded_agents,
1175
+ config=config,
1176
+ cleanup_outdated=True, # Enable cleanup by default
1177
+ )
1155
1178
  )
1156
-
1179
+
1157
1180
  # Compare with deployed versions if agents directory exists
1158
1181
  if agents_dir.exists():
1159
1182
  comparison_results = self.multi_source_service.compare_deployed_versions(
1160
1183
  deployed_agents_dir=agents_dir,
1161
1184
  agents_to_deploy=agents_to_deploy,
1162
- agent_sources=agent_sources
1185
+ agent_sources=agent_sources,
1163
1186
  )
1164
-
1187
+
1165
1188
  # Log version upgrades and source changes
1166
1189
  if comparison_results.get("version_upgrades"):
1167
- self.logger.info(f"Version upgrades available for {len(comparison_results['version_upgrades'])} agents")
1190
+ self.logger.info(
1191
+ f"Version upgrades available for {len(comparison_results['version_upgrades'])} agents"
1192
+ )
1168
1193
  if comparison_results.get("source_changes"):
1169
- self.logger.info(f"Source changes for {len(comparison_results['source_changes'])} agents")
1170
-
1194
+ self.logger.info(
1195
+ f"Source changes for {len(comparison_results['source_changes'])} agents"
1196
+ )
1197
+
1171
1198
  # Filter agents based on comparison results (unless force_rebuild is set)
1172
1199
  if not force_rebuild:
1173
1200
  # Only deploy agents that need updates or are new
1174
1201
  agents_needing_update = set(comparison_results.get("needs_update", []))
1175
-
1202
+
1176
1203
  # Extract agent names from new_agents list (which contains dicts)
1177
1204
  new_agent_names = [
1178
1205
  agent["name"] if isinstance(agent, dict) else agent
1179
1206
  for agent in comparison_results.get("new_agents", [])
1180
1207
  ]
1181
1208
  agents_needing_update.update(new_agent_names)
1182
-
1209
+
1183
1210
  # Filter agents_to_deploy to only include those needing updates
1184
1211
  filtered_agents = {
1185
- name: path for name, path in agents_to_deploy.items()
1212
+ name: path
1213
+ for name, path in agents_to_deploy.items()
1186
1214
  if name in agents_needing_update
1187
1215
  }
1188
1216
  agents_to_deploy = filtered_agents
1189
-
1190
- self.logger.info(f"Filtered to {len(agents_to_deploy)} agents needing deployment")
1191
-
1217
+
1218
+ self.logger.info(
1219
+ f"Filtered to {len(agents_to_deploy)} agents needing deployment"
1220
+ )
1221
+
1192
1222
  # Convert to list of Path objects
1193
1223
  template_files = list(agents_to_deploy.values())
1194
-
1224
+
1195
1225
  return template_files, agent_sources, cleanup_results
1196
1226
 
1197
1227
  # ================================================================================
@@ -1243,7 +1273,7 @@ class AgentDeploymentService(ConfigServiceBase, AgentDeploymentInterface):
1243
1273
  return len(errors) == 0, errors
1244
1274
 
1245
1275
  except Exception as e:
1246
- return False, [f"Validation error: {str(e)}"]
1276
+ return False, [f"Validation error: {e!s}"]
1247
1277
 
1248
1278
  def get_deployment_status(self) -> Dict[str, Any]:
1249
1279
  """Get current deployment status and metrics."""