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
@@ -10,14 +10,12 @@ to create focused, maintainable modules.
10
10
  """
11
11
 
12
12
  import asyncio
13
- import logging
14
- import os
15
13
  import threading
16
14
  import time
17
15
  from collections import deque
18
16
  from datetime import datetime
19
17
  from pathlib import Path
20
- from typing import Any, Dict, List, Optional, Set
18
+ from typing import Any, Dict, Set
21
19
 
22
20
  try:
23
21
  import aiohttp
@@ -32,16 +30,15 @@ except ImportError:
32
30
  web = None
33
31
 
34
32
  # Import VersionService for dynamic version retrieval
33
+ import contextlib
34
+
35
35
  from claude_mpm.services.version_service import VersionService
36
36
 
37
37
  from ....core.constants import (
38
- NetworkConfig,
39
- PerformanceConfig,
40
38
  SystemLimits,
41
39
  TimeoutConfig,
42
40
  )
43
- from ....core.interfaces import SocketIOServiceInterface
44
- from ....core.logging_config import get_logger, log_operation, log_performance_context
41
+ from ....core.logging_config import get_logger
45
42
  from ....core.unified_paths import get_project_root, get_scripts_dir
46
43
  from ...exceptions import SocketIOServerError as MPMConnectionError
47
44
 
@@ -87,7 +84,7 @@ class SocketIOServerCore:
87
84
 
88
85
  # Static files path
89
86
  self.static_path = None
90
-
87
+
91
88
  # Heartbeat task
92
89
  self.heartbeat_task = None
93
90
  self.heartbeat_interval = 60 # seconds
@@ -145,7 +142,7 @@ class SocketIOServerCore:
145
142
  # condition window where other threads might try to access it.
146
143
  self.loop = asyncio.new_event_loop()
147
144
  asyncio.set_event_loop(self.loop)
148
-
145
+
149
146
  self.logger.debug("Event loop created and set for background thread")
150
147
 
151
148
  # Run the server
@@ -167,7 +164,7 @@ class SocketIOServerCore:
167
164
  logger=False, # Disable Socket.IO's own logging
168
165
  engineio_logger=False,
169
166
  ping_interval=25, # Send ping every 25 seconds
170
- ping_timeout=60, # Wait 60 seconds for pong response
167
+ ping_timeout=60, # Wait 60 seconds for pong response
171
168
  max_http_buffer_size=1e8, # 100MB max buffer
172
169
  )
173
170
 
@@ -215,10 +212,8 @@ class SocketIOServerCore:
215
212
  # Cancel heartbeat task
216
213
  if self.heartbeat_task and not self.heartbeat_task.done():
217
214
  self.heartbeat_task.cancel()
218
- try:
215
+ with contextlib.suppress(asyncio.CancelledError):
219
216
  await self.heartbeat_task
220
- except asyncio.CancelledError:
221
- pass
222
217
  self.logger.info("Stopped system heartbeat task")
223
218
 
224
219
  if self.site:
@@ -240,43 +235,48 @@ class SocketIOServerCore:
240
235
  # Add debug logging for deployment context
241
236
  try:
242
237
  from ....core.unified_paths import PathContext
238
+
243
239
  deployment_context = PathContext.detect_deployment_context()
244
- self.logger.debug(f"Setting up static files in {deployment_context.value} mode")
240
+ self.logger.debug(
241
+ f"Setting up static files in {deployment_context.value} mode"
242
+ )
245
243
  except Exception as e:
246
244
  self.logger.debug(f"Could not detect deployment context: {e}")
247
-
245
+
248
246
  self.dashboard_path = self._find_static_path()
249
247
 
250
248
  if self.dashboard_path and self.dashboard_path.exists():
251
249
  self.logger.info(f"✅ Dashboard found at: {self.dashboard_path}")
252
-
250
+
253
251
  # Serve index.html at root
254
252
  async def index_handler(request):
255
253
  index_file = self.dashboard_path / "index.html"
256
254
  if index_file.exists():
257
255
  self.logger.debug(f"Serving dashboard index from: {index_file}")
258
256
  return web.FileResponse(index_file)
259
- else:
260
- self.logger.warning(f"Dashboard index.html not found at: {index_file}")
261
- return web.Response(text="Dashboard not available", status=404)
257
+ self.logger.warning(
258
+ f"Dashboard index.html not found at: {index_file}"
259
+ )
260
+ return web.Response(text="Dashboard not available", status=404)
262
261
 
263
262
  self.app.router.add_get("/", index_handler)
264
-
263
+
265
264
  # Serve version.json from dashboard directory
266
265
  async def version_handler(request):
267
266
  version_file = self.dashboard_path / "version.json"
268
267
  if version_file.exists():
269
268
  self.logger.debug(f"Serving version.json from: {version_file}")
270
269
  return web.FileResponse(version_file)
271
- else:
272
- # Return default version info if file doesn't exist
273
- return web.json_response({
270
+ # Return default version info if file doesn't exist
271
+ return web.json_response(
272
+ {
274
273
  "version": "1.0.0",
275
274
  "build": 1,
276
275
  "formatted_build": "0001",
277
- "full_version": "v1.0.0-0001"
278
- })
279
-
276
+ "full_version": "v1.0.0-0001",
277
+ }
278
+ )
279
+
280
280
  self.app.router.add_get("/version.json", version_handler)
281
281
 
282
282
  # Serve static assets (CSS, JS) from the dashboard static directory
@@ -287,12 +287,17 @@ class SocketIOServerCore:
287
287
  self.app.router.add_static(
288
288
  "/static/", dashboard_static_path, name="dashboard_static"
289
289
  )
290
- self.logger.info(f"✅ Static assets available at: {dashboard_static_path}")
290
+ self.logger.info(
291
+ f"✅ Static assets available at: {dashboard_static_path}"
292
+ )
291
293
  else:
292
- self.logger.warning(f"⚠️ Static assets directory not found at: {dashboard_static_path}")
294
+ self.logger.warning(
295
+ f"⚠️ Static assets directory not found at: {dashboard_static_path}"
296
+ )
293
297
 
294
298
  else:
295
299
  self.logger.warning("⚠️ No dashboard found, serving fallback response")
300
+
296
301
  # Fallback handler
297
302
  async def fallback_handler(request):
298
303
  return web.Response(
@@ -301,18 +306,20 @@ class SocketIOServerCore:
301
306
  )
302
307
 
303
308
  self.app.router.add_get("/", fallback_handler)
304
-
309
+
305
310
  except Exception as e:
306
311
  self.logger.error(f"❌ Error setting up static files: {e}")
307
312
  import traceback
313
+
308
314
  self.logger.debug(f"Static file setup traceback: {traceback.format_exc()}")
309
-
315
+
310
316
  # Ensure we always have a basic handler
311
317
  async def error_handler(request):
312
318
  return web.Response(
313
319
  text="Socket.IO server running - Static files unavailable",
314
320
  status=200,
315
321
  )
322
+
316
323
  self.app.router.add_get("/", error_handler)
317
324
 
318
325
  def _find_static_path(self):
@@ -324,16 +331,17 @@ class SocketIOServerCore:
324
331
  # Get deployment-context-aware paths
325
332
  try:
326
333
  from ....core.unified_paths import get_path_manager
334
+
327
335
  path_manager = get_path_manager()
328
-
336
+
329
337
  # Use package root for installed packages (including pipx)
330
338
  package_root = path_manager.package_root
331
339
  self.logger.debug(f"Package root: {package_root}")
332
-
340
+
333
341
  # Use project root for development
334
342
  project_root = get_project_root()
335
343
  self.logger.debug(f"Project root: {project_root}")
336
-
344
+
337
345
  except Exception as e:
338
346
  self.logger.debug(f"Could not get path manager: {e}")
339
347
  package_root = None
@@ -345,7 +353,6 @@ class SocketIOServerCore:
345
353
  package_root / "dashboard" / "templates" if package_root else None,
346
354
  package_root / "services" / "socketio" / "static" if package_root else None,
347
355
  package_root / "static" if package_root else None,
348
-
349
356
  # Project-based paths (for development)
350
357
  project_root / "src" / "claude_mpm" / "dashboard" / "templates",
351
358
  project_root / "dashboard" / "templates",
@@ -353,15 +360,12 @@ class SocketIOServerCore:
353
360
  project_root / "src" / "claude_mpm" / "services" / "socketio" / "static",
354
361
  project_root / "static",
355
362
  project_root / "src" / "static",
356
-
357
363
  # Package installation locations (fallback)
358
364
  Path(__file__).parent.parent / "static",
359
365
  Path(__file__).parent / "static",
360
-
361
366
  # Scripts directory (for standalone installations)
362
367
  get_scripts_dir() / "static",
363
368
  get_scripts_dir() / "socketio" / "static",
364
-
365
369
  # Current working directory
366
370
  Path.cwd() / "static",
367
371
  Path.cwd() / "socketio" / "static",
@@ -369,7 +373,9 @@ class SocketIOServerCore:
369
373
 
370
374
  # Filter out None values
371
375
  possible_paths = [p for p in possible_paths if p is not None]
372
- self.logger.debug(f"Searching {len(possible_paths)} possible static file locations")
376
+ self.logger.debug(
377
+ f"Searching {len(possible_paths)} possible static file locations"
378
+ )
373
379
 
374
380
  for path in possible_paths:
375
381
  self.logger.debug(f"Checking for static files at: {path}")
@@ -379,14 +385,15 @@ class SocketIOServerCore:
379
385
  if (path / "index.html").exists():
380
386
  self.logger.info(f"✅ Found static files at: {path}")
381
387
  return path
382
- else:
383
- self.logger.debug(f"Directory exists but no index.html: {path}")
388
+ self.logger.debug(f"Directory exists but no index.html: {path}")
384
389
  else:
385
390
  self.logger.debug(f"Path does not exist: {path}")
386
391
  except Exception as e:
387
392
  self.logger.debug(f"Error checking path {path}: {e}")
388
393
 
389
- self.logger.warning("⚠️ Static files not found - dashboard will not be available")
394
+ self.logger.warning(
395
+ "⚠️ Static files not found - dashboard will not be available"
396
+ )
390
397
  self.logger.debug(f"Searched paths: {[str(p) for p in possible_paths]}")
391
398
  return None
392
399
 
@@ -409,10 +416,10 @@ class SocketIOServerCore:
409
416
  True if server is active
410
417
  """
411
418
  return self.running
412
-
419
+
413
420
  async def _heartbeat_loop(self):
414
421
  """Send periodic heartbeat events to connected clients.
415
-
422
+
416
423
  WHY: This provides a way to verify the event flow is working and
417
424
  track server health and active sessions without relying on hook events.
418
425
  """
@@ -420,23 +427,27 @@ class SocketIOServerCore:
420
427
  try:
421
428
  # Wait for the interval
422
429
  await asyncio.sleep(self.heartbeat_interval)
423
-
430
+
424
431
  if not self.sio:
425
432
  continue
426
-
433
+
427
434
  # Calculate uptime
428
435
  uptime_seconds = 0
429
436
  if self.stats.get("start_time"):
430
- uptime_seconds = int((datetime.now() - self.stats["start_time"]).total_seconds())
431
-
437
+ uptime_seconds = int(
438
+ (datetime.now() - self.stats["start_time"]).total_seconds()
439
+ )
440
+
432
441
  # Get active sessions from main server if available
433
442
  active_sessions = []
434
- if self.main_server and hasattr(self.main_server, 'get_active_sessions'):
443
+ if self.main_server and hasattr(
444
+ self.main_server, "get_active_sessions"
445
+ ):
435
446
  try:
436
447
  active_sessions = self.main_server.get_active_sessions()
437
448
  except Exception as e:
438
449
  self.logger.debug(f"Could not get active sessions: {e}")
439
-
450
+
440
451
  # Prepare heartbeat data (using new schema)
441
452
  heartbeat_data = {
442
453
  "type": "system",
@@ -454,20 +465,20 @@ class SocketIOServerCore:
454
465
  },
455
466
  },
456
467
  }
457
-
468
+
458
469
  # Add to event history if main server is available
459
- if self.main_server and hasattr(self.main_server, 'event_history'):
470
+ if self.main_server and hasattr(self.main_server, "event_history"):
460
471
  self.main_server.event_history.append(heartbeat_data)
461
-
472
+
462
473
  # Emit heartbeat to all connected clients (already using new schema)
463
474
  await self.sio.emit("system_event", heartbeat_data)
464
-
475
+
465
476
  self.logger.info(
466
477
  f"System heartbeat sent - clients: {len(self.connected_clients)}, "
467
478
  f"uptime: {uptime_seconds}s, events: {self.stats.get('events_sent', 0)}, "
468
479
  f"sessions: {len(active_sessions)}"
469
480
  )
470
-
481
+
471
482
  except asyncio.CancelledError:
472
483
  # Task was cancelled, exit gracefully
473
484
  break
@@ -7,7 +7,6 @@ WHY this integration module:
7
7
  - Provides clean separation of concerns
8
8
  """
9
9
 
10
- import asyncio
11
10
  import logging
12
11
  from typing import Optional
13
12
 
@@ -19,17 +18,17 @@ logger = logging.getLogger(__name__)
19
18
 
20
19
  class EventBusIntegration:
21
20
  """Integrates EventBus relay with Socket.IO server.
22
-
21
+
23
22
  WHY integration class:
24
23
  - Encapsulates EventBus setup and teardown
25
24
  - Provides lifecycle management for relay
26
25
  - Handles configuration and error cases
27
26
  - Can be easily added to existing server
28
27
  """
29
-
28
+
30
29
  def __init__(self, server_instance=None):
31
30
  """Initialize EventBus integration.
32
-
31
+
33
32
  Args:
34
33
  server_instance: Optional Socket.IO server instance
35
34
  """
@@ -38,43 +37,78 @@ class EventBusIntegration:
38
37
  self.event_bus: Optional[EventBus] = None
39
38
  self.config = get_config()
40
39
  self.enabled = self.config.enabled and self.config.relay_enabled
41
-
40
+
42
41
  def setup(self, port: Optional[int] = None) -> bool:
43
42
  """Set up EventBus and relay.
44
-
43
+
45
44
  Args:
46
45
  port: Optional Socket.IO server port
47
-
46
+
48
47
  Returns:
49
48
  bool: True if setup successful
50
49
  """
50
+ from datetime import datetime
51
+
52
+ print(
53
+ f"[{datetime.now().isoformat()}] EventBusIntegration.setup() called",
54
+ flush=True,
55
+ )
56
+
51
57
  if not self.enabled:
52
58
  logger.info("EventBus integration disabled by configuration")
59
+ print(
60
+ f"[{datetime.now().isoformat()}] EventBus integration disabled by configuration",
61
+ flush=True,
62
+ )
53
63
  return False
54
-
64
+
55
65
  try:
56
66
  # Get EventBus instance
67
+ print(
68
+ f"[{datetime.now().isoformat()}] Getting EventBus instance...",
69
+ flush=True,
70
+ )
57
71
  self.event_bus = EventBus.get_instance()
58
-
72
+ print(
73
+ f"[{datetime.now().isoformat()}] EventBus instance obtained", flush=True
74
+ )
75
+
59
76
  # Apply configuration
60
77
  self.config.apply_to_eventbus(self.event_bus)
61
-
78
+
62
79
  # Create and configure relay
63
80
  relay_port = port or self.config.relay_port
81
+ print(
82
+ f"[{datetime.now().isoformat()}] Creating SocketIORelay on port {relay_port}...",
83
+ flush=True,
84
+ )
64
85
  self.relay = SocketIORelay(relay_port)
65
86
  self.config.apply_to_relay(self.relay)
66
-
87
+
67
88
  # Start the relay
89
+ print(f"[{datetime.now().isoformat()}] Starting relay...", flush=True)
68
90
  self.relay.start()
69
-
91
+ print(f"[{datetime.now().isoformat()}] Relay started", flush=True)
92
+
70
93
  logger.info(f"EventBus integration setup complete (port: {relay_port})")
94
+ print(
95
+ f"[{datetime.now().isoformat()}] EventBus integration setup complete",
96
+ flush=True,
97
+ )
71
98
  return True
72
-
99
+
73
100
  except Exception as e:
74
101
  logger.error(f"Failed to setup EventBus integration: {e}")
102
+ print(
103
+ f"[{datetime.now().isoformat()}] Failed to setup EventBus integration: {e}",
104
+ flush=True,
105
+ )
106
+ import traceback
107
+
108
+ traceback.print_exc()
75
109
  self.enabled = False
76
110
  return False
77
-
111
+
78
112
  def teardown(self) -> None:
79
113
  """Tear down EventBus integration."""
80
114
  if self.relay:
@@ -85,105 +119,110 @@ class EventBusIntegration:
85
119
  logger.error(f"Error stopping relay: {e}")
86
120
  finally:
87
121
  self.relay = None
88
-
122
+
89
123
  def is_active(self) -> bool:
90
124
  """Check if integration is active.
91
-
125
+
92
126
  Returns:
93
127
  bool: True if relay is active and connected
94
128
  """
95
- return (
96
- self.enabled and
97
- self.relay is not None and
98
- self.relay.enabled
99
- )
100
-
129
+ return self.enabled and self.relay is not None and self.relay.enabled
130
+
101
131
  def get_stats(self) -> dict:
102
132
  """Get integration statistics.
103
-
133
+
104
134
  Returns:
105
135
  dict: Combined stats from EventBus and relay
106
136
  """
107
- stats = {
108
- "enabled": self.enabled,
109
- "active": self.is_active()
110
- }
111
-
137
+ stats = {"enabled": self.enabled, "active": self.is_active()}
138
+
112
139
  if self.event_bus:
113
140
  stats["eventbus"] = self.event_bus.get_stats()
114
-
141
+
115
142
  if self.relay:
116
143
  stats["relay"] = self.relay.get_stats()
117
-
144
+
118
145
  return stats
119
146
 
120
147
 
121
- def integrate_with_server(server_instance, port: Optional[int] = None) -> EventBusIntegration:
148
+ def integrate_with_server(
149
+ server_instance, port: Optional[int] = None
150
+ ) -> EventBusIntegration:
122
151
  """Helper function to integrate EventBus with a Socket.IO server.
123
-
152
+
124
153
  Args:
125
154
  server_instance: Socket.IO server instance
126
155
  port: Optional server port
127
-
156
+
128
157
  Returns:
129
158
  EventBusIntegration: The integration instance
130
159
  """
131
160
  integration = EventBusIntegration(server_instance)
132
- integration.setup(port or getattr(server_instance, 'port', 8765))
161
+ integration.setup(port or getattr(server_instance, "port", 8765))
133
162
  return integration
134
163
 
135
164
 
136
165
  # Monkey-patch helper for existing server
137
166
  def patch_socketio_server(server_class):
138
167
  """Monkey-patch an existing Socket.IO server class to add EventBus.
139
-
168
+
140
169
  WHY monkey-patching:
141
170
  - Allows integration without modifying existing code
142
171
  - Can be applied selectively based on configuration
143
172
  - Easy to remove or disable
144
-
173
+
145
174
  Args:
146
175
  server_class: The server class to patch
147
176
  """
148
177
  original_init = server_class.__init__
149
- original_start = getattr(server_class, 'start_sync', None) or getattr(server_class, 'start', None)
150
- original_stop = getattr(server_class, 'stop_sync', None) or getattr(server_class, 'stop', None)
151
-
178
+ original_start = getattr(server_class, "start_sync", None) or getattr(
179
+ server_class, "start", None
180
+ )
181
+ original_stop = getattr(server_class, "stop_sync", None) or getattr(
182
+ server_class, "stop", None
183
+ )
184
+
152
185
  def patched_init(self, *args, **kwargs):
153
186
  """Patched __init__ that adds EventBus integration."""
154
187
  original_init(self, *args, **kwargs)
155
188
  self._eventbus_integration = EventBusIntegration(self)
156
-
189
+
157
190
  def patched_start(self, *args, **kwargs):
158
191
  """Patched start method that sets up EventBus."""
159
192
  # Call original start
160
- if original_start:
161
- result = original_start(self, *args, **kwargs)
162
- else:
163
- result = None
164
-
193
+ result = original_start(self, *args, **kwargs) if original_start else None
194
+
165
195
  # Setup EventBus integration
166
- if hasattr(self, '_eventbus_integration'):
167
- port = getattr(self, 'port', 8765)
196
+ if hasattr(self, "_eventbus_integration"):
197
+ port = getattr(self, "port", 8765)
168
198
  self._eventbus_integration.setup(port)
169
-
199
+
170
200
  return result
171
-
201
+
172
202
  def patched_stop(self, *args, **kwargs):
173
203
  """Patched stop method that tears down EventBus."""
174
204
  # Teardown EventBus first
175
- if hasattr(self, '_eventbus_integration'):
205
+ if hasattr(self, "_eventbus_integration"):
176
206
  self._eventbus_integration.teardown()
177
-
207
+
178
208
  # Call original stop
179
209
  if original_stop:
180
210
  return original_stop(self, *args, **kwargs)
181
-
211
+ return None
212
+
182
213
  # Apply patches
183
214
  server_class.__init__ = patched_init
184
215
  if original_start:
185
- setattr(server_class, 'start_sync' if hasattr(server_class, 'start_sync') else 'start', patched_start)
216
+ setattr(
217
+ server_class,
218
+ "start_sync" if hasattr(server_class, "start_sync") else "start",
219
+ patched_start,
220
+ )
186
221
  if original_stop:
187
- setattr(server_class, 'stop_sync' if hasattr(server_class, 'stop_sync') else 'stop', patched_stop)
188
-
189
- logger.info(f"Patched {server_class.__name__} with EventBus integration")
222
+ setattr(
223
+ server_class,
224
+ "stop_sync" if hasattr(server_class, "stop_sync") else "stop",
225
+ patched_stop,
226
+ )
227
+
228
+ logger.info(f"Patched {server_class.__name__} with EventBus integration")