claude-mpm 4.1.1__py3-none-any.whl → 4.1.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 (389) 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/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  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 +280 -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 +22 -29
  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 +500 -680
  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 -17
  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 +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -6,6 +6,7 @@ The central event bus that manages event flow from producers to consumers.
6
6
  """
7
7
 
8
8
  import asyncio
9
+ import contextlib
9
10
  import re
10
11
  import time
11
12
  import uuid
@@ -22,6 +23,7 @@ from .interfaces import ConsumerPriority, IEventBus, IEventConsumer
22
23
 
23
24
  class EventPriority(Enum):
24
25
  """Priority levels for events."""
26
+
25
27
  CRITICAL = 1
26
28
  HIGH = 2
27
29
  NORMAL = 3
@@ -31,6 +33,7 @@ class EventPriority(Enum):
31
33
  @dataclass
32
34
  class EventMetadata:
33
35
  """Metadata associated with an event."""
36
+
34
37
  retry_count: int = 0
35
38
  max_retries: int = 3
36
39
  published_at: Optional[datetime] = None
@@ -44,19 +47,20 @@ class EventMetadata:
44
47
  class Event:
45
48
  """
46
49
  Standard event format for the event bus.
47
-
50
+
48
51
  All events flowing through the system use this format.
49
52
  """
50
- id: str # Unique event ID
51
- topic: str # Event topic (e.g., "hook.response")
52
- type: str # Event type (e.g., "AssistantResponse")
53
- timestamp: datetime # When event was created
54
- source: str # Who created the event
55
- data: Dict[str, Any] # Event payload
53
+
54
+ id: str # Unique event ID
55
+ topic: str # Event topic (e.g., "hook.response")
56
+ type: str # Event type (e.g., "AssistantResponse")
57
+ timestamp: datetime # When event was created
58
+ source: str # Who created the event
59
+ data: Dict[str, Any] # Event payload
56
60
  metadata: Optional[EventMetadata] = None # Event metadata
57
- correlation_id: Optional[str] = None # For tracking related events
61
+ correlation_id: Optional[str] = None # For tracking related events
58
62
  priority: EventPriority = EventPriority.NORMAL
59
-
63
+
60
64
  def __post_init__(self):
61
65
  if self.metadata is None:
62
66
  self.metadata = EventMetadata()
@@ -64,35 +68,35 @@ class Event:
64
68
  self.id = str(uuid.uuid4())
65
69
  if isinstance(self.timestamp, str):
66
70
  self.timestamp = datetime.fromisoformat(self.timestamp)
67
-
71
+
68
72
  def matches_topic(self, pattern: str) -> bool:
69
73
  """
70
74
  Check if event matches a topic pattern.
71
-
75
+
72
76
  Supports wildcards:
73
77
  - * matches any single segment
74
78
  - ** matches any number of segments
75
-
79
+
76
80
  Examples:
77
81
  - "hook.*" matches "hook.response" but not "hook.tool.usage"
78
82
  - "hook.**" matches both "hook.response" and "hook.tool.usage"
79
83
  """
80
- if pattern == "**" or pattern == "*":
84
+ if pattern in {"**", "*"}:
81
85
  return True
82
-
86
+
83
87
  # Convert wildcard pattern to regex
84
88
  regex_pattern = pattern.replace(".", r"\.")
85
89
  regex_pattern = regex_pattern.replace("**", ".*")
86
90
  regex_pattern = regex_pattern.replace("*", "[^.]+")
87
91
  regex_pattern = f"^{regex_pattern}$"
88
-
92
+
89
93
  return bool(re.match(regex_pattern, self.topic))
90
94
 
91
95
 
92
96
  class EventBus(IEventBus):
93
97
  """
94
98
  Central event bus implementation.
95
-
99
+
96
100
  Features:
97
101
  - Async event processing
98
102
  - Topic-based routing
@@ -101,7 +105,7 @@ class EventBus(IEventBus):
101
105
  - Metrics tracking
102
106
  - Optional persistence
103
107
  """
104
-
108
+
105
109
  def __init__(
106
110
  self,
107
111
  max_queue_size: int = 10000,
@@ -112,7 +116,7 @@ class EventBus(IEventBus):
112
116
  ):
113
117
  """
114
118
  Initialize the event bus.
115
-
119
+
116
120
  Args:
117
121
  max_queue_size: Maximum events in queue
118
122
  process_interval: How often to process events (seconds)
@@ -121,29 +125,28 @@ class EventBus(IEventBus):
121
125
  enable_persistence: Persist events to disk
122
126
  """
123
127
  self.logger = get_logger("EventBus")
124
-
128
+
125
129
  # Configuration
126
130
  self.max_queue_size = max_queue_size
127
131
  self.process_interval = process_interval
128
132
  self.batch_timeout = batch_timeout
129
133
  self.enable_metrics = enable_metrics
130
134
  self.enable_persistence = enable_persistence
131
-
135
+
132
136
  # State
133
137
  self._running = False
134
138
  self._processing_task: Optional[asyncio.Task] = None
135
-
139
+
136
140
  # Event queue (priority-based)
137
141
  self._event_queues: Dict[EventPriority, Deque[Event]] = {
138
- priority: deque(maxlen=max_queue_size // 4)
139
- for priority in EventPriority
142
+ priority: deque(maxlen=max_queue_size // 4) for priority in EventPriority
140
143
  }
141
-
144
+
142
145
  # Consumers
143
146
  self._consumers: Dict[str, IEventConsumer] = {}
144
147
  self._consumer_topics: Dict[str, List[str]] = {}
145
148
  self._topic_consumers: Dict[str, Set[str]] = defaultdict(set)
146
-
149
+
147
150
  # Metrics
148
151
  self._metrics = {
149
152
  "events_published": 0,
@@ -155,98 +158,102 @@ class EventBus(IEventBus):
155
158
  "processing_time_ms": 0,
156
159
  "last_event_time": None,
157
160
  }
158
-
161
+
159
162
  # Dead letter queue for failed events
160
163
  self._dead_letter_queue: Deque[Event] = deque(maxlen=1000)
161
-
164
+
162
165
  async def start(self) -> None:
163
166
  """Start the event bus."""
164
167
  if self._running:
165
168
  self.logger.warning("Event bus already running")
166
169
  return
167
-
170
+
168
171
  self.logger.info("Starting event bus")
169
172
  self._running = True
170
-
173
+
171
174
  # Start processing task
172
175
  self._processing_task = asyncio.create_task(self._process_events())
173
-
176
+
174
177
  self.logger.info("Event bus started")
175
-
178
+
176
179
  async def stop(self) -> None:
177
180
  """Stop the event bus gracefully."""
178
181
  if not self._running:
179
182
  return
180
-
183
+
181
184
  self.logger.info("Stopping event bus")
182
185
  self._running = False
183
-
186
+
184
187
  # Wait for processing to complete
185
188
  if self._processing_task:
186
189
  self._processing_task.cancel()
187
- try:
190
+ with contextlib.suppress(asyncio.CancelledError):
188
191
  await self._processing_task
189
- except asyncio.CancelledError:
190
- pass
191
-
192
+
192
193
  # Process remaining events
193
194
  await self._flush_events()
194
-
195
+
195
196
  # Shutdown consumers
196
197
  for consumer in self._consumers.values():
197
198
  try:
198
199
  await consumer.shutdown()
199
200
  except Exception as e:
200
- self.logger.error(f"Error shutting down consumer {consumer.config.name}: {e}")
201
-
201
+ self.logger.error(
202
+ f"Error shutting down consumer {consumer.config.name}: {e}"
203
+ )
204
+
202
205
  self.logger.info("Event bus stopped")
203
-
206
+
204
207
  async def publish(self, event: Event) -> bool:
205
208
  """
206
209
  Publish an event to the bus.
207
-
210
+
208
211
  Events are queued based on priority and processed asynchronously.
209
212
  """
210
213
  if not self._running:
211
214
  self.logger.warning("Cannot publish event - bus not running")
212
215
  return False
213
-
216
+
214
217
  # Check queue size
215
218
  total_size = sum(len(q) for q in self._event_queues.values())
216
219
  if total_size >= self.max_queue_size:
217
- self.logger.error(f"Event queue full ({total_size}/{self.max_queue_size}), dropping event")
220
+ self.logger.error(
221
+ f"Event queue full ({total_size}/{self.max_queue_size}), dropping event"
222
+ )
218
223
  self._metrics["events_dropped"] += 1
219
224
  return False
220
-
225
+
221
226
  # Add metadata
222
227
  if event.metadata:
223
228
  event.metadata.published_at = datetime.now()
224
-
229
+
225
230
  # Queue event
226
231
  self._event_queues[event.priority].append(event)
227
232
  self._metrics["events_published"] += 1
228
233
  self._metrics["queue_size"] = total_size + 1
229
-
230
- self.logger.debug(f"Published event: {event.topic}/{event.type} (priority={event.priority.name})")
234
+
235
+ self.logger.debug(
236
+ f"Published event: {event.topic}/{event.type} (priority={event.priority.name})"
237
+ )
231
238
  return True
232
-
239
+
233
240
  async def subscribe(self, consumer: IEventConsumer) -> bool:
234
241
  """Subscribe a consumer to the bus."""
235
242
  config = consumer.config
236
-
243
+
237
244
  if config.name in self._consumers:
238
245
  self.logger.warning(f"Consumer {config.name} already subscribed")
239
246
  return False
240
-
247
+
241
248
  try:
242
249
  # Initialize consumer
243
250
  if not await consumer.initialize():
244
251
  self.logger.error(f"Failed to initialize consumer {config.name}")
245
252
  return False
246
-
253
+
247
254
  # Register consumer
248
255
  self._consumers[config.name] = consumer
249
-
256
+
250
257
  # Register topics
251
258
  if config.topics:
252
259
  self._consumer_topics[config.name] = config.topics
@@ -256,53 +263,53 @@ class EventBus(IEventBus):
256
263
  # Consumer receives all events
257
264
  self._consumer_topics[config.name] = ["**"]
258
265
  self._topic_consumers["**"].add(config.name)
259
-
266
+
260
267
  self._metrics["consumers_active"] = len(self._consumers)
261
-
268
+
262
269
  self.logger.info(
263
270
  f"Subscribed consumer {config.name} to topics: "
264
271
  f"{self._consumer_topics[config.name]}"
265
272
  )
266
273
  return True
267
-
274
+
268
275
  except Exception as e:
269
276
  self.logger.error(f"Error subscribing consumer {config.name}: {e}")
270
277
  return False
271
-
278
+
272
279
  async def unsubscribe(self, consumer_name: str) -> bool:
273
280
  """Unsubscribe a consumer from the bus."""
274
281
  if consumer_name not in self._consumers:
275
282
  self.logger.warning(f"Consumer {consumer_name} not found")
276
283
  return False
277
-
284
+
278
285
  try:
279
286
  consumer = self._consumers[consumer_name]
280
-
287
+
281
288
  # Shutdown consumer
282
289
  await consumer.shutdown()
283
-
290
+
284
291
  # Remove from registries
285
292
  del self._consumers[consumer_name]
286
-
293
+
287
294
  # Remove topic subscriptions
288
295
  if consumer_name in self._consumer_topics:
289
296
  for topic in self._consumer_topics[consumer_name]:
290
297
  self._topic_consumers[topic].discard(consumer_name)
291
298
  del self._consumer_topics[consumer_name]
292
-
299
+
293
300
  self._metrics["consumers_active"] = len(self._consumers)
294
-
301
+
295
302
  self.logger.info(f"Unsubscribed consumer {consumer_name}")
296
303
  return True
297
-
304
+
298
305
  except Exception as e:
299
306
  self.logger.error(f"Error unsubscribing consumer {consumer_name}: {e}")
300
307
  return False
301
-
308
+
302
309
  def get_consumers(self) -> List[IEventConsumer]:
303
310
  """Get list of active consumers."""
304
311
  return list(self._consumers.values())
305
-
312
+
306
313
  def get_metrics(self) -> Dict[str, Any]:
307
314
  """Get event bus metrics."""
308
315
  return {
@@ -311,18 +318,18 @@ class EventBus(IEventBus):
311
318
  "consumers": {
312
319
  name: consumer.get_metrics()
313
320
  for name, consumer in self._consumers.items()
314
- }
321
+ },
315
322
  }
316
-
323
+
317
324
  @property
318
325
  def is_running(self) -> bool:
319
326
  """Check if event bus is running."""
320
327
  return self._running
321
-
328
+
322
329
  async def _process_events(self) -> None:
323
330
  """
324
331
  Main event processing loop.
325
-
332
+
326
333
  Continuously processes events from the queue and routes them
327
334
  to appropriate consumers.
328
335
  """
@@ -330,73 +337,77 @@ class EventBus(IEventBus):
330
337
  try:
331
338
  # Process events by priority
332
339
  events_processed = 0
333
-
340
+
334
341
  for priority in EventPriority:
335
342
  queue = self._event_queues[priority]
336
-
343
+
337
344
  # Process up to batch_size events
338
345
  batch = []
339
346
  while queue and len(batch) < 10:
340
347
  batch.append(queue.popleft())
341
-
348
+
342
349
  if batch:
343
350
  await self._route_events(batch)
344
351
  events_processed += len(batch)
345
-
352
+
346
353
  # Update metrics
347
354
  if events_processed > 0:
348
355
  self._metrics["events_processed"] += events_processed
349
356
  self._metrics["last_event_time"] = datetime.now()
350
- self._metrics["queue_size"] = sum(len(q) for q in self._event_queues.values())
351
-
357
+ self._metrics["queue_size"] = sum(
358
+ len(q) for q in self._event_queues.values()
359
+ )
360
+
352
361
  # Sleep if no events
353
362
  if events_processed == 0:
354
363
  await asyncio.sleep(self.process_interval)
355
-
364
+
356
365
  except Exception as e:
357
366
  self.logger.error(f"Error in event processing loop: {e}")
358
367
  await asyncio.sleep(1) # Back off on error
359
-
368
+
360
369
  async def _route_events(self, events: List[Event]) -> None:
361
370
  """
362
371
  Route events to appropriate consumers.
363
-
372
+
364
373
  Events are routed based on topic subscriptions.
365
374
  Consumers are called in priority order.
366
375
  """
367
376
  for event in events:
368
377
  # Find matching consumers
369
378
  matching_consumers = set()
370
-
379
+
371
380
  # Check exact topic matches
372
381
  if event.topic in self._topic_consumers:
373
382
  matching_consumers.update(self._topic_consumers[event.topic])
374
-
383
+
375
384
  # Check wildcard subscriptions
376
385
  for pattern, consumers in self._topic_consumers.items():
377
386
  if "*" in pattern and event.matches_topic(pattern):
378
387
  matching_consumers.update(consumers)
379
-
388
+
380
389
  # Check consumers with no specific topics (receive all)
381
390
  if "**" in self._topic_consumers:
382
391
  matching_consumers.update(self._topic_consumers["**"])
383
-
392
+
384
393
  # Sort consumers by priority
385
394
  consumers_by_priority = defaultdict(list)
386
395
  for consumer_name in matching_consumers:
387
396
  if consumer_name in self._consumers:
388
397
  consumer = self._consumers[consumer_name]
389
398
  consumers_by_priority[consumer.config.priority].append(consumer)
390
-
399
+
391
400
  # Process event with each consumer
392
401
  for priority in ConsumerPriority:
393
402
  for consumer in consumers_by_priority[priority]:
394
403
  await self._deliver_to_consumer(event, consumer)
395
-
396
- async def _deliver_to_consumer(self, event: Event, consumer: IEventConsumer) -> None:
404
+
405
+ async def _deliver_to_consumer(
406
+ self, event: Event, consumer: IEventConsumer
407
+ ) -> None:
397
408
  """
398
409
  Deliver an event to a specific consumer.
399
-
410
+
400
411
  Handles errors gracefully without affecting other consumers.
401
412
  """
402
413
  try:
@@ -404,16 +415,16 @@ class EventBus(IEventBus):
404
415
  if consumer.config.filter_func:
405
416
  if not consumer.config.filter_func(event):
406
417
  return
407
-
418
+
408
419
  # Apply transformation if configured
409
420
  if consumer.config.transform_func:
410
421
  event = consumer.config.transform_func(event)
411
-
422
+
412
423
  # Process event
413
424
  start_time = time.time()
414
425
  success = await consumer.consume(event)
415
426
  elapsed_ms = (time.time() - start_time) * 1000
416
-
427
+
417
428
  # Update metrics
418
429
  if success:
419
430
  event.metadata.consumers_processed.add(consumer.config.name)
@@ -426,12 +437,12 @@ class EventBus(IEventBus):
426
437
  self.logger.warning(
427
438
  f"Consumer {consumer.config.name} failed to process event {event.id}"
428
439
  )
429
-
440
+
430
441
  # Add to dead letter queue if all retries exhausted
431
442
  if event.metadata.retry_count >= event.metadata.max_retries:
432
443
  self._dead_letter_queue.append(event)
433
444
  self._metrics["events_failed"] += 1
434
-
445
+
435
446
  except Exception as e:
436
447
  self.logger.error(
437
448
  f"Error delivering event {event.id} to consumer "
@@ -439,7 +450,7 @@ class EventBus(IEventBus):
439
450
  )
440
451
  event.metadata.consumers_failed.add(consumer.config.name)
441
452
  event.metadata.error_messages.append(str(e))
442
-
453
+
443
454
  # Use custom error handler if provided
444
455
  if consumer.config.error_handler:
445
456
  try:
@@ -449,22 +460,22 @@ class EventBus(IEventBus):
449
460
  f"Error in custom error handler for {consumer.config.name}: "
450
461
  f"{handler_error}"
451
462
  )
452
-
463
+
453
464
  async def _flush_events(self) -> None:
454
465
  """Process all remaining events in the queue."""
455
466
  total_events = sum(len(q) for q in self._event_queues.values())
456
-
467
+
457
468
  if total_events > 0:
458
469
  self.logger.info(f"Flushing {total_events} remaining events")
459
-
470
+
460
471
  for priority in EventPriority:
461
472
  queue = self._event_queues[priority]
462
473
  while queue:
463
474
  batch = []
464
475
  for _ in range(min(10, len(queue))):
465
476
  batch.append(queue.popleft())
466
-
477
+
467
478
  if batch:
468
479
  await self._route_events(batch)
469
-
470
- self.logger.info("Event flush complete")
480
+
481
+ self.logger.info("Event flush complete")