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
@@ -4,32 +4,32 @@ Common error handling patterns for CLI commands.
4
4
 
5
5
  import traceback
6
6
  from functools import wraps
7
- from typing import Any, Callable
7
+ from typing import Any, Callable, Optional
8
8
 
9
9
  from ...core.logger import get_logger
10
10
 
11
11
 
12
12
  class CLIErrorHandler:
13
13
  """Centralized error handling for CLI commands."""
14
-
14
+
15
15
  def __init__(self, command_name: str):
16
16
  """
17
17
  Initialize error handler.
18
-
18
+
19
19
  Args:
20
20
  command_name: Name of the command for logging context
21
21
  """
22
22
  self.command_name = command_name
23
23
  self.logger = get_logger(f"cli.{command_name}")
24
-
25
- def handle_error(self, error: Exception, context: str = None) -> int:
24
+
25
+ def handle_error(self, error: Exception, context: Optional[str] = None) -> int:
26
26
  """
27
27
  Handle an error with appropriate logging and user feedback.
28
-
28
+
29
29
  Args:
30
30
  error: The exception that occurred
31
31
  context: Additional context about when the error occurred
32
-
32
+
33
33
  Returns:
34
34
  Appropriate exit code
35
35
  """
@@ -37,60 +37,59 @@ class CLIErrorHandler:
37
37
  error_msg = str(error)
38
38
  if context:
39
39
  error_msg = f"{context}: {error_msg}"
40
-
40
+
41
41
  # Determine error type and appropriate response
42
42
  if isinstance(error, KeyboardInterrupt):
43
43
  self.logger.info("Operation cancelled by user")
44
44
  print("\nOperation cancelled by user.")
45
45
  return 130 # Standard exit code for SIGINT
46
-
47
- elif isinstance(error, FileNotFoundError):
46
+
47
+ if isinstance(error, FileNotFoundError):
48
48
  self.logger.error(f"File not found: {error}")
49
49
  print(f"Error: File not found - {error}")
50
50
  return 2
51
-
52
- elif isinstance(error, PermissionError):
51
+
52
+ if isinstance(error, PermissionError):
53
53
  self.logger.error(f"Permission denied: {error}")
54
54
  print(f"Error: Permission denied - {error}")
55
55
  return 13
56
-
57
- elif isinstance(error, ValueError):
56
+
57
+ if isinstance(error, ValueError):
58
58
  self.logger.error(f"Invalid value: {error}")
59
59
  print(f"Error: Invalid value - {error}")
60
60
  return 22
61
-
62
- else:
63
- # Generic error handling
64
- self.logger.error(f"Command failed: {error}", exc_info=True)
65
- print(f"Error: {error_msg}")
66
-
67
- # Show traceback in debug mode
68
- if self.logger.isEnabledFor(10): # DEBUG level
69
- traceback.print_exc()
70
-
71
- return 1
72
-
61
+
62
+ # Generic error handling
63
+ self.logger.error(f"Command failed: {error}", exc_info=True)
64
+ print(f"Error: {error_msg}")
65
+
66
+ # Show traceback in debug mode
67
+ if self.logger.isEnabledFor(10): # DEBUG level
68
+ traceback.print_exc()
69
+
70
+ return 1
71
+
73
72
  def handle_validation_error(self, message: str) -> int:
74
73
  """
75
74
  Handle validation errors.
76
-
75
+
77
76
  Args:
78
77
  message: Validation error message
79
-
78
+
80
79
  Returns:
81
80
  Exit code for validation errors
82
81
  """
83
82
  self.logger.error(f"Validation error: {message}")
84
83
  print(f"Error: {message}")
85
84
  return 22 # Invalid argument exit code
86
-
85
+
87
86
  def handle_config_error(self, error: Exception) -> int:
88
87
  """
89
88
  Handle configuration-related errors.
90
-
89
+
91
90
  Args:
92
91
  error: Configuration error
93
-
92
+
94
93
  Returns:
95
94
  Exit code for configuration errors
96
95
  """
@@ -103,46 +102,49 @@ class CLIErrorHandler:
103
102
  def handle_cli_errors(command_name: str):
104
103
  """
105
104
  Decorator to add standard error handling to CLI command functions.
106
-
105
+
107
106
  Args:
108
107
  command_name: Name of the command for error context
109
-
108
+
110
109
  Returns:
111
110
  Decorated function with error handling
112
111
  """
112
+
113
113
  def decorator(func: Callable) -> Callable:
114
114
  @wraps(func)
115
115
  def wrapper(*args, **kwargs) -> int:
116
116
  error_handler = CLIErrorHandler(command_name)
117
-
117
+
118
118
  try:
119
119
  result = func(*args, **kwargs)
120
-
120
+
121
121
  # Handle different return types
122
122
  if isinstance(result, int):
123
123
  return result
124
- elif hasattr(result, 'exit_code'):
124
+ if hasattr(result, "exit_code"):
125
125
  return result.exit_code
126
- else:
127
- return 0 # Success
128
-
126
+ return 0 # Success
127
+
129
128
  except Exception as e:
130
129
  return error_handler.handle_error(e)
131
-
130
+
132
131
  return wrapper
132
+
133
133
  return decorator
134
134
 
135
135
 
136
- def safe_execute(func: Callable, *args, error_handler: CLIErrorHandler = None, **kwargs) -> Any:
136
+ def safe_execute(
137
+ func: Callable, *args, error_handler: CLIErrorHandler = None, **kwargs
138
+ ) -> Any:
137
139
  """
138
140
  Safely execute a function with error handling.
139
-
141
+
140
142
  Args:
141
143
  func: Function to execute
142
144
  *args: Function arguments
143
145
  error_handler: Optional error handler
144
146
  **kwargs: Function keyword arguments
145
-
147
+
146
148
  Returns:
147
149
  Function result or None if error occurred
148
150
  """
@@ -161,78 +163,80 @@ def safe_execute(func: Callable, *args, error_handler: CLIErrorHandler = None, *
161
163
  def validate_file_exists(file_path: str, error_handler: CLIErrorHandler = None) -> bool:
162
164
  """
163
165
  Validate that a file exists.
164
-
166
+
165
167
  Args:
166
168
  file_path: Path to validate
167
169
  error_handler: Optional error handler
168
-
170
+
169
171
  Returns:
170
172
  True if file exists, False otherwise
171
173
  """
172
174
  from pathlib import Path
173
-
175
+
174
176
  path = Path(file_path)
175
177
  if not path.exists():
176
178
  message = f"File does not exist: {file_path}"
177
179
  if error_handler:
178
180
  error_handler.handle_validation_error(message)
179
181
  return False
180
-
182
+
181
183
  if not path.is_file():
182
184
  message = f"Path is not a file: {file_path}"
183
185
  if error_handler:
184
186
  error_handler.handle_validation_error(message)
185
187
  return False
186
-
188
+
187
189
  return True
188
190
 
189
191
 
190
- def validate_directory_exists(dir_path: str, error_handler: CLIErrorHandler = None) -> bool:
192
+ def validate_directory_exists(
193
+ dir_path: str, error_handler: CLIErrorHandler = None
194
+ ) -> bool:
191
195
  """
192
196
  Validate that a directory exists.
193
-
197
+
194
198
  Args:
195
199
  dir_path: Directory path to validate
196
200
  error_handler: Optional error handler
197
-
201
+
198
202
  Returns:
199
203
  True if directory exists, False otherwise
200
204
  """
201
205
  from pathlib import Path
202
-
206
+
203
207
  path = Path(dir_path)
204
208
  if not path.exists():
205
209
  message = f"Directory does not exist: {dir_path}"
206
210
  if error_handler:
207
211
  error_handler.handle_validation_error(message)
208
212
  return False
209
-
213
+
210
214
  if not path.is_dir():
211
215
  message = f"Path is not a directory: {dir_path}"
212
216
  if error_handler:
213
217
  error_handler.handle_validation_error(message)
214
218
  return False
215
-
219
+
216
220
  return True
217
221
 
218
222
 
219
223
  def confirm_operation(message: str, force: bool = False) -> bool:
220
224
  """
221
225
  Ask user for confirmation unless force flag is set.
222
-
226
+
223
227
  Args:
224
228
  message: Confirmation message
225
229
  force: If True, skip confirmation
226
-
230
+
227
231
  Returns:
228
232
  True if operation should proceed
229
233
  """
230
234
  if force:
231
235
  return True
232
-
236
+
233
237
  try:
234
238
  response = input(f"{message} (y/N): ").strip().lower()
235
- return response in ('y', 'yes')
239
+ return response in ("y", "yes")
236
240
  except (EOFError, KeyboardInterrupt):
237
241
  print("\nOperation cancelled.")
238
242
  return False
@@ -3,70 +3,71 @@ Output formatting utilities for CLI commands.
3
3
  """
4
4
 
5
5
  import json
6
- from typing import Any, Dict, List, Union
6
+ from typing import Any, Dict, List, Optional, Union
7
7
 
8
8
  import yaml
9
9
 
10
10
 
11
11
  class OutputFormatter:
12
12
  """Handles formatting output in different formats."""
13
-
13
+
14
14
  @staticmethod
15
15
  def format_json(data: Any, indent: int = 2) -> str:
16
16
  """Format data as JSON."""
17
17
  return json.dumps(data, indent=indent, default=str)
18
-
18
+
19
19
  @staticmethod
20
20
  def format_yaml(data: Any) -> str:
21
21
  """Format data as YAML."""
22
22
  return yaml.dump(data, default_flow_style=False, sort_keys=False)
23
-
23
+
24
24
  @staticmethod
25
- def format_table(data: Union[List[Dict], Dict], headers: List[str] = None) -> str:
25
+ def format_table(
26
+ data: Union[List[Dict], Dict], headers: Optional[List[str]] = None
27
+ ) -> str:
26
28
  """Format data as a simple table."""
27
29
  if not data:
28
30
  return "No data to display"
29
-
31
+
30
32
  # Handle single dict
31
33
  if isinstance(data, dict):
32
34
  data = [data]
33
-
35
+
34
36
  # Auto-detect headers if not provided
35
37
  if headers is None and data:
36
38
  headers = list(data[0].keys())
37
-
39
+
38
40
  if not headers:
39
41
  return "No data to display"
40
-
42
+
41
43
  # Calculate column widths
42
44
  col_widths = {}
43
45
  for header in headers:
44
46
  col_widths[header] = len(header)
45
47
  for row in data:
46
- value = str(row.get(header, ''))
48
+ value = str(row.get(header, ""))
47
49
  col_widths[header] = max(col_widths[header], len(value))
48
-
50
+
49
51
  # Build table
50
52
  lines = []
51
-
53
+
52
54
  # Header row
53
55
  header_row = " | ".join(header.ljust(col_widths[header]) for header in headers)
54
56
  lines.append(header_row)
55
-
57
+
56
58
  # Separator row
57
59
  separator = " | ".join("-" * col_widths[header] for header in headers)
58
60
  lines.append(separator)
59
-
61
+
60
62
  # Data rows
61
63
  for row in data:
62
64
  data_row = " | ".join(
63
- str(row.get(header, '')).ljust(col_widths[header])
64
- for header in headers
65
+ str(row.get(header, "")).ljust(col_widths[header]) for header in headers
65
66
  )
66
67
  lines.append(data_row)
67
-
68
+
68
69
  return "\n".join(lines)
69
-
70
+
70
71
  @staticmethod
71
72
  def format_text(data: Any) -> str:
72
73
  """Format data as human-readable text."""
@@ -77,69 +78,69 @@ class OutputFormatter:
77
78
  lines.append(f"{key}:")
78
79
  # Indent nested content
79
80
  nested = OutputFormatter.format_text(value)
80
- for line in nested.split('\n'):
81
+ for line in nested.split("\n"):
81
82
  if line.strip():
82
83
  lines.append(f" {line}")
83
84
  else:
84
85
  lines.append(f"{key}: {value}")
85
86
  return "\n".join(lines)
86
-
87
- elif isinstance(data, list):
87
+
88
+ if isinstance(data, list):
88
89
  if not data:
89
90
  return "No items"
90
-
91
+
91
92
  lines = []
92
93
  for i, item in enumerate(data):
93
94
  if isinstance(item, dict):
94
95
  lines.append(f"Item {i + 1}:")
95
96
  nested = OutputFormatter.format_text(item)
96
- for line in nested.split('\n'):
97
+ for line in nested.split("\n"):
97
98
  if line.strip():
98
99
  lines.append(f" {line}")
99
100
  else:
100
101
  lines.append(f"- {item}")
101
102
  return "\n".join(lines)
102
-
103
- else:
104
- return str(data)
103
+
104
+ return str(data)
105
105
 
106
106
 
107
107
  def format_output(data: Any, format_type: str = "text", **kwargs) -> str:
108
108
  """
109
109
  Format data according to the specified format.
110
-
110
+
111
111
  Args:
112
112
  data: Data to format
113
113
  format_type: Output format ('json', 'yaml', 'table', 'text')
114
114
  **kwargs: Additional formatting options
115
-
115
+
116
116
  Returns:
117
117
  Formatted string
118
118
  """
119
119
  formatter = OutputFormatter()
120
-
120
+
121
121
  if format_type == "json":
122
122
  return formatter.format_json(data, **kwargs)
123
- elif format_type == "yaml":
123
+ if format_type == "yaml":
124
124
  return formatter.format_yaml(data)
125
- elif format_type == "table":
125
+ if format_type == "table":
126
126
  return formatter.format_table(data, **kwargs)
127
- elif format_type == "text":
128
- return formatter.format_text(data)
129
- else:
130
- # Fallback to text format
127
+ if format_type == "text":
131
128
  return formatter.format_text(data)
129
+ # Fallback to text format
130
+ return formatter.format_text(data)
132
131
 
133
132
 
134
- def format_success_message(message: str, data: Any = None, format_type: str = "text") -> str:
133
+ def format_success_message(
134
+ message: str, data: Any = None, format_type: str = "text"
135
+ ) -> str:
135
136
  """
136
137
  Format a success message with optional data.
137
-
138
+
138
139
  Args:
139
140
  message: Success message
140
141
  data: Optional data to include
141
142
  format_type: Output format
142
-
143
+
143
144
  Returns:
144
145
  Formatted success message
145
146
  """
@@ -148,24 +149,25 @@ def format_success_message(message: str, data: Any = None, format_type: str = "t
148
149
  if data is not None:
149
150
  result["data"] = data
150
151
  return format_output(result, format_type)
151
- else:
152
- # Text format
153
- lines = [f"✓ {message}"]
154
- if data is not None:
155
- lines.append("")
156
- lines.append(format_output(data, format_type))
157
- return "\n".join(lines)
152
+ # Text format
153
+ lines = [f"✓ {message}"]
154
+ if data is not None:
155
+ lines.append("")
156
+ lines.append(format_output(data, format_type))
157
+ return "\n".join(lines)
158
158
 
159
159
 
160
- def format_error_message(message: str, details: Any = None, format_type: str = "text") -> str:
160
+ def format_error_message(
161
+ message: str, details: Any = None, format_type: str = "text"
162
+ ) -> str:
161
163
  """
162
164
  Format an error message with optional details.
163
-
165
+
164
166
  Args:
165
167
  message: Error message
166
168
  details: Optional error details
167
169
  format_type: Output format
168
-
170
+
169
171
  Returns:
170
172
  Formatted error message
171
173
  """
@@ -174,28 +176,29 @@ def format_error_message(message: str, details: Any = None, format_type: str = "
174
176
  if details is not None:
175
177
  result["details"] = details
176
178
  return format_output(result, format_type)
177
- else:
178
- # Text format
179
- lines = [f"✗ {message}"]
180
- if details is not None:
181
- lines.append("")
182
- lines.append(format_output(details, format_type))
183
- return "\n".join(lines)
179
+ # Text format
180
+ lines = [f"✗ {message}"]
181
+ if details is not None:
182
+ lines.append("")
183
+ lines.append(format_output(details, format_type))
184
+ return "\n".join(lines)
184
185
 
185
186
 
186
- def format_list_output(items: List[Any],
187
- title: str = None,
188
- format_type: str = "text",
189
- headers: List[str] = None) -> str:
187
+ def format_list_output(
188
+ items: List[Any],
189
+ title: Optional[str] = None,
190
+ format_type: str = "text",
191
+ headers: Optional[List[str]] = None,
192
+ ) -> str:
190
193
  """
191
194
  Format a list of items for output.
192
-
195
+
193
196
  Args:
194
197
  items: List of items to format
195
198
  title: Optional title for the list
196
199
  format_type: Output format
197
200
  headers: Optional headers for table format
198
-
201
+
199
202
  Returns:
200
203
  Formatted list output
201
204
  """
@@ -203,29 +206,27 @@ def format_list_output(items: List[Any],
203
206
  empty_msg = f"No {title.lower() if title else 'items'} found"
204
207
  if format_type in ("json", "yaml"):
205
208
  return format_output({"items": [], "message": empty_msg}, format_type)
206
- else:
207
- return empty_msg
208
-
209
+ return empty_msg
210
+
209
211
  if format_type in ("json", "yaml"):
210
212
  result = {"items": items}
211
213
  if title:
212
214
  result["title"] = title
213
215
  return format_output(result, format_type)
214
-
215
- elif format_type == "table":
216
+
217
+ if format_type == "table":
216
218
  output = ""
217
219
  if title:
218
220
  output += f"{title}\n{'=' * len(title)}\n\n"
219
221
  output += format_output(items, "table", headers=headers)
220
222
  return output
221
-
222
- else:
223
- # Text format
224
- lines = []
225
- if title:
226
- lines.append(title)
227
- lines.append("=" * len(title))
228
- lines.append("")
229
-
230
- lines.append(format_output(items, "text"))
231
- return "\n".join(lines)
223
+
224
+ # Text format
225
+ lines = []
226
+ if title:
227
+ lines.append(title)
228
+ lines.append("=" * len(title))
229
+ lines.append("")
230
+
231
+ lines.append(format_output(items, "text"))
232
+ return "\n".join(lines)