claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__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 (434) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +2 -2
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +330 -86
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +363 -220
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +124 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/built/components/agent-inference.js +2 -0
  113. claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
  114. claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
  115. claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
  116. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
  117. claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
  118. claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
  119. claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
  120. claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
  121. claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
  122. claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
  123. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
  124. claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
  125. claude_mpm/dashboard/static/built/dashboard.js +2 -0
  126. claude_mpm/dashboard/static/built/socket-client.js +2 -0
  127. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  128. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  129. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  130. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  131. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  132. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  133. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  134. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  135. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  136. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  137. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  138. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  139. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  140. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  141. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  142. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  143. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  144. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  145. claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
  146. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  147. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
  148. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  149. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  150. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  151. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  152. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  153. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  154. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  155. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  156. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  157. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  158. claude_mpm/dashboard/static/js/socket-client.js +133 -53
  159. claude_mpm/dashboard/templates/index.html +40 -50
  160. claude_mpm/experimental/cli_enhancements.py +60 -58
  161. claude_mpm/generators/__init__.py +1 -1
  162. claude_mpm/generators/agent_profile_generator.py +75 -65
  163. claude_mpm/hooks/__init__.py +1 -1
  164. claude_mpm/hooks/base_hook.py +33 -28
  165. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  166. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  167. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  168. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  169. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  170. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  171. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  172. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  173. claude_mpm/hooks/memory_integration_hook.py +140 -100
  174. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  175. claude_mpm/hooks/validation_hooks.py +57 -49
  176. claude_mpm/init.py +145 -121
  177. claude_mpm/models/__init__.py +9 -9
  178. claude_mpm/models/agent_definition.py +33 -23
  179. claude_mpm/models/agent_session.py +228 -200
  180. claude_mpm/scripts/__init__.py +1 -1
  181. claude_mpm/scripts/socketio_daemon.py +192 -75
  182. claude_mpm/scripts/socketio_server_manager.py +328 -0
  183. claude_mpm/scripts/start_activity_logging.py +25 -22
  184. claude_mpm/services/__init__.py +68 -43
  185. claude_mpm/services/agent_capabilities_service.py +271 -0
  186. claude_mpm/services/agents/__init__.py +23 -32
  187. claude_mpm/services/agents/deployment/__init__.py +3 -3
  188. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  189. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  190. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  191. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  192. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  193. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  194. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  195. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  196. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  197. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  198. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  199. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  200. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  201. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  202. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  203. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  204. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  205. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  206. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  207. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  208. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  209. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  210. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  211. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  212. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  213. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  214. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  215. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  216. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  217. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  218. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  219. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  220. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  221. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  222. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  223. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  224. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  225. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  226. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  227. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  228. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  229. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  230. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  231. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  232. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  233. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  234. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  235. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  236. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  237. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  238. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  239. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  240. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  241. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  242. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  243. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  244. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  245. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  246. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  247. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  248. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  249. claude_mpm/services/agents/loading/__init__.py +2 -2
  250. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  251. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  252. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  253. claude_mpm/services/agents/management/__init__.py +2 -2
  254. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  255. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  256. claude_mpm/services/agents/memory/__init__.py +9 -6
  257. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  258. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  259. claude_mpm/services/agents/memory/analyzer.py +430 -0
  260. claude_mpm/services/agents/memory/content_manager.py +376 -0
  261. claude_mpm/services/agents/memory/template_generator.py +468 -0
  262. claude_mpm/services/agents/registry/__init__.py +7 -10
  263. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  264. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  265. claude_mpm/services/async_session_logger.py +187 -153
  266. claude_mpm/services/claude_session_logger.py +87 -72
  267. claude_mpm/services/command_handler_service.py +217 -0
  268. claude_mpm/services/communication/__init__.py +3 -2
  269. claude_mpm/services/core/__init__.py +50 -97
  270. claude_mpm/services/core/base.py +60 -53
  271. claude_mpm/services/core/interfaces/__init__.py +188 -0
  272. claude_mpm/services/core/interfaces/agent.py +351 -0
  273. claude_mpm/services/core/interfaces/communication.py +343 -0
  274. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  275. claude_mpm/services/core/interfaces/service.py +434 -0
  276. claude_mpm/services/core/interfaces.py +19 -944
  277. claude_mpm/services/event_aggregator.py +208 -170
  278. claude_mpm/services/exceptions.py +387 -308
  279. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  280. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  281. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  282. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  283. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  284. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  285. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  286. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  287. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  288. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  289. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  290. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  291. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  292. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  293. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  294. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  295. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  296. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  297. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  298. claude_mpm/services/hook_service.py +106 -114
  299. claude_mpm/services/infrastructure/__init__.py +7 -5
  300. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  301. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  302. claude_mpm/services/infrastructure/logging.py +83 -76
  303. claude_mpm/services/infrastructure/monitoring.py +547 -404
  304. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  305. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  306. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  307. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  308. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  309. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  310. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  311. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  312. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  313. claude_mpm/services/mcp_gateway/main.py +287 -137
  314. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  315. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  316. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  317. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  318. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  319. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  320. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  321. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  322. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  323. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  324. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  325. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  326. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  327. claude_mpm/services/memory/__init__.py +2 -2
  328. claude_mpm/services/memory/builder.py +451 -362
  329. claude_mpm/services/memory/cache/__init__.py +2 -2
  330. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  331. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  332. claude_mpm/services/memory/indexed_memory.py +195 -193
  333. claude_mpm/services/memory/optimizer.py +267 -234
  334. claude_mpm/services/memory/router.py +571 -263
  335. claude_mpm/services/memory_hook_service.py +237 -0
  336. claude_mpm/services/port_manager.py +575 -0
  337. claude_mpm/services/project/__init__.py +3 -3
  338. claude_mpm/services/project/analyzer.py +451 -305
  339. claude_mpm/services/project/registry.py +262 -240
  340. claude_mpm/services/recovery_manager.py +287 -231
  341. claude_mpm/services/response_tracker.py +87 -67
  342. claude_mpm/services/runner_configuration_service.py +587 -0
  343. claude_mpm/services/session_management_service.py +304 -0
  344. claude_mpm/services/socketio/__init__.py +4 -4
  345. claude_mpm/services/socketio/client_proxy.py +174 -0
  346. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  347. claude_mpm/services/socketio/handlers/base.py +44 -30
  348. claude_mpm/services/socketio/handlers/connection.py +166 -64
  349. claude_mpm/services/socketio/handlers/file.py +123 -108
  350. claude_mpm/services/socketio/handlers/git.py +607 -373
  351. claude_mpm/services/socketio/handlers/hook.py +185 -0
  352. claude_mpm/services/socketio/handlers/memory.py +4 -4
  353. claude_mpm/services/socketio/handlers/project.py +4 -4
  354. claude_mpm/services/socketio/handlers/registry.py +53 -38
  355. claude_mpm/services/socketio/server/__init__.py +18 -0
  356. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  357. claude_mpm/services/socketio/server/core.py +399 -0
  358. claude_mpm/services/socketio/server/main.py +323 -0
  359. claude_mpm/services/socketio_client_manager.py +160 -133
  360. claude_mpm/services/socketio_server.py +36 -1885
  361. claude_mpm/services/subprocess_launcher_service.py +316 -0
  362. claude_mpm/services/system_instructions_service.py +258 -0
  363. claude_mpm/services/ticket_manager.py +19 -533
  364. claude_mpm/services/utility_service.py +285 -0
  365. claude_mpm/services/version_control/__init__.py +18 -21
  366. claude_mpm/services/version_control/branch_strategy.py +20 -10
  367. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  368. claude_mpm/services/version_control/git_operations.py +52 -21
  369. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  370. claude_mpm/services/version_control/version_parser.py +145 -125
  371. claude_mpm/services/version_service.py +270 -0
  372. claude_mpm/storage/__init__.py +2 -2
  373. claude_mpm/storage/state_storage.py +177 -181
  374. claude_mpm/ticket_wrapper.py +2 -2
  375. claude_mpm/utils/__init__.py +2 -2
  376. claude_mpm/utils/agent_dependency_loader.py +453 -243
  377. claude_mpm/utils/config_manager.py +157 -118
  378. claude_mpm/utils/console.py +1 -1
  379. claude_mpm/utils/dependency_cache.py +102 -107
  380. claude_mpm/utils/dependency_manager.py +52 -47
  381. claude_mpm/utils/dependency_strategies.py +131 -96
  382. claude_mpm/utils/environment_context.py +110 -102
  383. claude_mpm/utils/error_handler.py +75 -55
  384. claude_mpm/utils/file_utils.py +80 -67
  385. claude_mpm/utils/framework_detection.py +12 -11
  386. claude_mpm/utils/import_migration_example.py +12 -60
  387. claude_mpm/utils/imports.py +48 -45
  388. claude_mpm/utils/path_operations.py +100 -93
  389. claude_mpm/utils/robust_installer.py +172 -164
  390. claude_mpm/utils/session_logging.py +30 -23
  391. claude_mpm/utils/subprocess_utils.py +99 -61
  392. claude_mpm/validation/__init__.py +1 -1
  393. claude_mpm/validation/agent_validator.py +151 -111
  394. claude_mpm/validation/frontmatter_validator.py +92 -71
  395. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
  396. claude_mpm-4.0.4.dist-info/RECORD +417 -0
  397. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
  398. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
  399. claude_mpm/cli/commands/run_guarded.py +0 -511
  400. claude_mpm/config/memory_guardian_config.py +0 -325
  401. claude_mpm/config/memory_guardian_yaml.py +0 -335
  402. claude_mpm/core/config_paths.py +0 -150
  403. claude_mpm/core/memory_aware_runner.py +0 -353
  404. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  405. claude_mpm/deployment_paths.py +0 -261
  406. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  407. claude_mpm/models/state_models.py +0 -433
  408. claude_mpm/services/agent/__init__.py +0 -24
  409. claude_mpm/services/agent/deployment.py +0 -2548
  410. claude_mpm/services/agent/management.py +0 -598
  411. claude_mpm/services/agent/registry.py +0 -813
  412. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  413. claude_mpm/services/communication/socketio.py +0 -1935
  414. claude_mpm/services/communication/websocket.py +0 -479
  415. claude_mpm/services/framework_claude_md_generator.py +0 -624
  416. claude_mpm/services/health_monitor.py +0 -893
  417. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  418. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  419. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  420. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  421. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  422. claude_mpm/services/infrastructure/state_manager.py +0 -774
  423. claude_mpm/services/mcp_gateway/manager.py +0 -334
  424. claude_mpm/services/optimized_hook_service.py +0 -542
  425. claude_mpm/services/project_analyzer.py +0 -864
  426. claude_mpm/services/project_registry.py +0 -608
  427. claude_mpm/services/standalone_socketio_server.py +0 -1300
  428. claude_mpm/services/ticket_manager_di.py +0 -318
  429. claude_mpm/services/ticketing_service_original.py +0 -510
  430. claude_mpm/utils/paths.py +0 -395
  431. claude_mpm/utils/platform_memory.py +0 -524
  432. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  433. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
  434. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/top_level.txt +0 -0
@@ -1,137 +1,147 @@
1
+ from pathlib import Path
2
+
1
3
  """
2
4
  Agent profile generator using template system.
3
5
 
4
6
  Inspired by awesome-claude-code's template generation approach.
5
7
  """
6
8
 
7
- import yaml
8
- from pathlib import Path
9
- from datetime import datetime
10
- from typing import Dict, Any, Optional
11
9
  import re
10
+ from datetime import datetime
11
+ from typing import Any, Dict, Optional
12
+
13
+ import yaml
12
14
 
13
15
 
14
16
  class AgentProfileGenerator:
15
17
  """Generates agent profiles from templates."""
16
-
18
+
17
19
  def __init__(self, template_path: Optional[Path] = None):
18
20
  """Initialize the generator with a template path."""
19
- self.template_path = template_path or Path(__file__).parent.parent / "agents" / "agent-template.yaml"
21
+ self.template_path = (
22
+ template_path
23
+ or Path(__file__).parent.parent / "agents" / "agent-template.yaml"
24
+ )
20
25
  self.template = self._load_template()
21
-
26
+
22
27
  def _load_template(self) -> Dict[str, Any]:
23
28
  """Load the agent profile template."""
24
29
  if not self.template_path.exists():
25
30
  raise FileNotFoundError(f"Template not found: {self.template_path}")
26
-
27
- with open(self.template_path, 'r') as f:
31
+
32
+ with open(self.template_path, "r") as f:
28
33
  return yaml.safe_load(f)
29
-
34
+
30
35
  def generate_profile(self, config: Dict[str, Any]) -> str:
31
36
  """Generate an agent profile from configuration."""
32
37
  # Set default values
33
- config.setdefault('VERSION', '1.0.0')
34
- config.setdefault('CREATED_DATE', datetime.now().strftime('%Y-%m-%d'))
35
- config.setdefault('AUTHOR', 'claude-mpm')
36
-
38
+ config.setdefault("VERSION", "1.0.0")
39
+ config.setdefault("CREATED_DATE", datetime.now().strftime("%Y-%m-%d"))
40
+ config.setdefault("AUTHOR", "claude-mpm")
41
+
37
42
  # Convert template to string
38
43
  template_str = yaml.dump(self.template, default_flow_style=False)
39
-
44
+
40
45
  # Replace placeholders
41
46
  result = self._replace_placeholders(template_str, config)
42
-
47
+
43
48
  # Clean up any remaining placeholders
44
- result = re.sub(r'\{\{[^}]+\}\}', '', result)
45
-
49
+ result = re.sub(r"\{\{[^}]+\}\}", "", result)
50
+
46
51
  return result
47
-
52
+
48
53
  def _replace_placeholders(self, template: str, values: Dict[str, Any]) -> str:
49
54
  """Replace template placeholders with actual values."""
50
55
  for key, value in values.items():
51
56
  placeholder = f"{{{{{key}}}}}"
52
57
  if isinstance(value, list):
53
58
  # Format lists nicely
54
- formatted_list = '\n'.join(f" - \"{item}\"" for item in value)
59
+ formatted_list = "\n".join(f' - "{item}"' for item in value)
55
60
  template = template.replace(placeholder, formatted_list)
56
61
  else:
57
62
  template = template.replace(placeholder, str(value))
58
-
63
+
59
64
  return template
60
-
65
+
61
66
  def generate_agent_documentation(self, agent_config: Dict[str, Any]) -> str:
62
67
  """Generate markdown documentation for an agent."""
63
68
  doc_lines = []
64
-
69
+
65
70
  # Header
66
71
  doc_lines.append(f"# {agent_config.get('name', 'Agent')} Documentation")
67
72
  doc_lines.append("")
68
-
73
+
69
74
  # Description
70
- if 'description' in agent_config:
75
+ if "description" in agent_config:
71
76
  doc_lines.append("## Description")
72
- doc_lines.append(agent_config['description'])
77
+ doc_lines.append(agent_config["description"])
73
78
  doc_lines.append("")
74
-
79
+
75
80
  # Capabilities
76
- if 'capabilities' in agent_config:
81
+ if "capabilities" in agent_config:
77
82
  doc_lines.append("## Capabilities")
78
- for capability in agent_config['capabilities']:
83
+ for capability in agent_config["capabilities"]:
79
84
  doc_lines.append(f"- {capability}")
80
85
  doc_lines.append("")
81
-
86
+
82
87
  # Tools
83
- if 'tools' in agent_config:
88
+ if "tools" in agent_config:
84
89
  doc_lines.append("## Required Tools")
85
- for tool in agent_config['tools']:
90
+ for tool in agent_config["tools"]:
86
91
  if isinstance(tool, dict):
87
- doc_lines.append(f"- **{tool['name']}**: {tool.get('description', '')}")
92
+ doc_lines.append(
93
+ f"- **{tool['name']}**: {tool.get('description', '')}"
94
+ )
88
95
  else:
89
96
  doc_lines.append(f"- {tool}")
90
97
  doc_lines.append("")
91
-
98
+
92
99
  # Examples
93
- if 'examples' in agent_config:
100
+ if "examples" in agent_config:
94
101
  doc_lines.append("## Usage Examples")
95
- for i, example in enumerate(agent_config['examples'], 1):
96
- doc_lines.append(f"### Example {i}: {example.get('scenario', 'Scenario')}")
102
+ for i, example in enumerate(agent_config["examples"], 1):
103
+ doc_lines.append(
104
+ f"### Example {i}: {example.get('scenario', 'Scenario')}"
105
+ )
97
106
  doc_lines.append("```")
98
107
  doc_lines.append(f"Input: {example.get('input', '')}")
99
108
  doc_lines.append("```")
100
109
  doc_lines.append("Expected Output:")
101
110
  doc_lines.append("```")
102
- doc_lines.append(example.get('expected_output', ''))
111
+ doc_lines.append(example.get("expected_output", ""))
103
112
  doc_lines.append("```")
104
113
  doc_lines.append("")
105
-
114
+
106
115
  # Best Practices
107
- if 'best_practices' in agent_config:
116
+ if "best_practices" in agent_config:
108
117
  doc_lines.append("## Best Practices")
109
- for practice in agent_config['best_practices']:
118
+ for practice in agent_config["best_practices"]:
110
119
  doc_lines.append(f"- {practice}")
111
120
  doc_lines.append("")
112
-
113
- return '\n'.join(doc_lines)
114
-
115
- def create_agent_from_template(self, agent_name: str, role: str,
116
- category: str = "analysis") -> Dict[str, Any]:
121
+
122
+ return "\n".join(doc_lines)
123
+
124
+ def create_agent_from_template(
125
+ self, agent_name: str, role: str, category: str = "analysis"
126
+ ) -> Dict[str, Any]:
117
127
  """Create a new agent configuration from template."""
118
128
  return {
119
- 'AGENT_NAME': agent_name,
120
- 'AGENT_ID': agent_name.lower().replace(' ', '_'),
121
- 'ROLE': role,
122
- 'CATEGORY': category,
123
- 'DESCRIPTION': f"Agent profile for {agent_name}",
124
- 'AGENT_DESCRIPTION': f"Specialized {role} agent",
125
- 'SPECIALIZATION': role.lower(),
126
- 'CAPABILITIES_LIST': "- Analyze code structure\n- Identify patterns\n- Generate reports",
127
- 'CONSTRAINTS_LIST': "- Read-only operations\n- Respect file permissions",
128
- 'TOOL_NAME': 'code_analysis',
129
- 'TOOL_DESCRIPTION': 'Analyzes code structure and patterns',
130
- 'EXAMPLE_SCENARIO': 'Analyzing a Python project',
131
- 'EXAMPLE_INPUT': 'Analyze the architecture of this codebase',
132
- 'EXAMPLE_OUTPUT': 'Detailed analysis report with recommendations',
133
- 'BEST_PRACTICE_1': 'Always validate input parameters',
134
- 'BEST_PRACTICE_2': 'Provide clear, actionable insights',
135
- 'BEST_PRACTICE_3': 'Include examples in reports',
136
- 'ADDITIONAL_INSTRUCTIONS': 'Be thorough but concise in your analysis.'
137
- }
129
+ "AGENT_NAME": agent_name,
130
+ "AGENT_ID": agent_name.lower().replace(" ", "_"),
131
+ "ROLE": role,
132
+ "CATEGORY": category,
133
+ "DESCRIPTION": f"Agent profile for {agent_name}",
134
+ "AGENT_DESCRIPTION": f"Specialized {role} agent",
135
+ "SPECIALIZATION": role.lower(),
136
+ "CAPABILITIES_LIST": "- Analyze code structure\n- Identify patterns\n- Generate reports",
137
+ "CONSTRAINTS_LIST": "- Read-only operations\n- Respect file permissions",
138
+ "TOOL_NAME": "code_analysis",
139
+ "TOOL_DESCRIPTION": "Analyzes code structure and patterns",
140
+ "EXAMPLE_SCENARIO": "Analyzing a Python project",
141
+ "EXAMPLE_INPUT": "Analyze the architecture of this codebase",
142
+ "EXAMPLE_OUTPUT": "Detailed analysis report with recommendations",
143
+ "BEST_PRACTICE_1": "Always validate input parameters",
144
+ "BEST_PRACTICE_2": "Provide clear, actionable insights",
145
+ "BEST_PRACTICE_3": "Include examples in reports",
146
+ "ADDITIONAL_INSTRUCTIONS": "Be thorough but concise in your analysis.",
147
+ }
@@ -2,4 +2,4 @@
2
2
 
3
3
  from .base_hook import BaseHook, HookContext, HookResult, HookType
4
4
 
5
- __all__ = ["BaseHook", "HookContext", "HookResult", "HookType"]
5
+ __all__ = ["BaseHook", "HookContext", "HookResult", "HookType"]
@@ -1,18 +1,19 @@
1
1
  """Base hook class and types for claude-mpm hook system."""
2
2
 
3
+ import asyncio
4
+ import logging
3
5
  from abc import ABC, abstractmethod
4
6
  from dataclasses import dataclass
7
+ from datetime import datetime
5
8
  from enum import Enum
6
9
  from typing import Any, Dict, List, Optional, Union
7
- import asyncio
8
- import logging
9
- from datetime import datetime
10
10
 
11
11
  logger = logging.getLogger(__name__)
12
12
 
13
13
 
14
14
  class HookType(Enum):
15
15
  """Types of hooks available in the system."""
16
+
16
17
  SUBMIT = "submit" # Process user prompts
17
18
  PRE_DELEGATION = "pre_delegation" # Filter context before delegation
18
19
  POST_DELEGATION = "post_delegation" # Process results after delegation
@@ -23,22 +24,24 @@ class HookType(Enum):
23
24
  @dataclass
24
25
  class HookContext:
25
26
  """Context passed to hooks for processing."""
27
+
26
28
  hook_type: HookType
27
29
  data: Dict[str, Any]
28
30
  metadata: Dict[str, Any]
29
31
  timestamp: datetime
30
32
  session_id: Optional[str] = None
31
33
  user_id: Optional[str] = None
32
-
34
+
33
35
  def __post_init__(self):
34
36
  """Ensure timestamp is set."""
35
- if not hasattr(self, 'timestamp') or self.timestamp is None:
37
+ if not hasattr(self, "timestamp") or self.timestamp is None:
36
38
  self.timestamp = datetime.now()
37
39
 
38
40
 
39
41
  @dataclass
40
42
  class HookResult:
41
43
  """Result returned from hook execution."""
44
+
42
45
  success: bool
43
46
  data: Optional[Dict[str, Any]] = None
44
47
  error: Optional[str] = None
@@ -49,10 +52,10 @@ class HookResult:
49
52
 
50
53
  class BaseHook(ABC):
51
54
  """Base class for all hooks."""
52
-
55
+
53
56
  def __init__(self, name: str, priority: int = 50):
54
57
  """Initialize hook with name and priority.
55
-
58
+
56
59
  Args:
57
60
  name: Unique name for the hook
58
61
  priority: Execution priority (0-100, lower executes first)
@@ -61,40 +64,40 @@ class BaseHook(ABC):
61
64
  self.priority = max(0, min(100, priority)) # Clamp to 0-100
62
65
  self.enabled = True
63
66
  self._async = False
64
-
67
+
65
68
  @abstractmethod
66
69
  def execute(self, context: HookContext) -> HookResult:
67
70
  """Execute the hook with given context.
68
-
71
+
69
72
  Args:
70
73
  context: Hook context containing data and metadata
71
-
74
+
72
75
  Returns:
73
76
  HookResult with execution results
74
77
  """
75
78
  pass
76
-
79
+
77
80
  async def async_execute(self, context: HookContext) -> HookResult:
78
81
  """Async version of execute. Override for async hooks."""
79
82
  # Default implementation calls sync execute in executor
80
83
  loop = asyncio.get_event_loop()
81
84
  return await loop.run_in_executor(None, self.execute, context)
82
-
85
+
83
86
  def validate(self, context: HookContext) -> bool:
84
87
  """Validate if hook should run for given context.
85
-
88
+
86
89
  Args:
87
90
  context: Hook context to validate
88
-
91
+
89
92
  Returns:
90
93
  True if hook should execute, False otherwise
91
94
  """
92
95
  return self.enabled
93
-
96
+
94
97
  def __repr__(self):
95
98
  """String representation of hook."""
96
99
  return f"{self.__class__.__name__}(name='{self.name}', priority={self.priority}, enabled={self.enabled})"
97
-
100
+
98
101
  def __lt__(self, other):
99
102
  """Compare hooks by priority for sorting."""
100
103
  if not isinstance(other, BaseHook):
@@ -104,51 +107,53 @@ class BaseHook(ABC):
104
107
 
105
108
  class SubmitHook(BaseHook):
106
109
  """Base class for hooks that process user prompts."""
107
-
110
+
108
111
  def __init__(self, name: str, priority: int = 50):
109
112
  super().__init__(name, priority)
110
-
113
+
111
114
  def validate(self, context: HookContext) -> bool:
112
115
  """Validate submit hook context."""
113
116
  if not super().validate(context):
114
117
  return False
115
- return context.hook_type == HookType.SUBMIT and 'prompt' in context.data
118
+ return context.hook_type == HookType.SUBMIT and "prompt" in context.data
116
119
 
117
120
 
118
121
  class PreDelegationHook(BaseHook):
119
122
  """Base class for hooks that filter context before delegation."""
120
-
123
+
121
124
  def __init__(self, name: str, priority: int = 50):
122
125
  super().__init__(name, priority)
123
-
126
+
124
127
  def validate(self, context: HookContext) -> bool:
125
128
  """Validate pre-delegation hook context."""
126
129
  if not super().validate(context):
127
130
  return False
128
- return context.hook_type == HookType.PRE_DELEGATION and 'agent' in context.data
131
+ return context.hook_type == HookType.PRE_DELEGATION and "agent" in context.data
129
132
 
130
133
 
131
134
  class PostDelegationHook(BaseHook):
132
135
  """Base class for hooks that process results after delegation."""
133
-
136
+
134
137
  def __init__(self, name: str, priority: int = 50):
135
138
  super().__init__(name, priority)
136
-
139
+
137
140
  def validate(self, context: HookContext) -> bool:
138
141
  """Validate post-delegation hook context."""
139
142
  if not super().validate(context):
140
143
  return False
141
- return context.hook_type == HookType.POST_DELEGATION and 'result' in context.data
144
+ return (
145
+ context.hook_type == HookType.POST_DELEGATION and "result" in context.data
146
+ )
142
147
 
143
148
 
144
149
  class TicketExtractionHook(BaseHook):
145
150
  """Base class for hooks that extract and create tickets."""
146
-
151
+
147
152
  def __init__(self, name: str, priority: int = 50):
148
153
  super().__init__(name, priority)
149
-
154
+
150
155
  def validate(self, context: HookContext) -> bool:
151
156
  """Validate ticket extraction hook context."""
152
157
  if not super().validate(context):
153
158
  return False
154
- return context.hook_type == HookType.TICKET_EXTRACTION
159
+ return context.hook_type == HookType.TICKET_EXTRACTION
@@ -2,4 +2,4 @@
2
2
 
3
3
  from .hook_handler import ClaudeHookHandler
4
4
 
5
- __all__ = ['ClaudeHookHandler']
5
+ __all__ = ["ClaudeHookHandler"]
@@ -0,0 +1,120 @@
1
+ #!/usr/bin/env python3
2
+ """Socket.IO connection pool for Claude Code hook handler.
3
+
4
+ This module provides connection pooling for Socket.IO clients to reduce
5
+ connection overhead and implement circuit breaker patterns.
6
+ """
7
+
8
+ import time
9
+ from typing import Any, Dict, List, Optional
10
+
11
+ # Import constants for configuration
12
+ try:
13
+ from claude_mpm.core.constants import NetworkConfig
14
+ except ImportError:
15
+ # Fallback values if constants module not available
16
+ class NetworkConfig:
17
+ SOCKETIO_PORT_RANGE = (8080, 8099)
18
+ RECONNECTION_DELAY = 0.5
19
+ SOCKET_WAIT_TIMEOUT = 1.0
20
+
21
+
22
+ # Socket.IO import
23
+ try:
24
+ import socketio
25
+
26
+ SOCKETIO_AVAILABLE = True
27
+ except ImportError:
28
+ SOCKETIO_AVAILABLE = False
29
+ socketio = None
30
+
31
+
32
+ class SocketIOConnectionPool:
33
+ """Connection pool for Socket.IO clients to prevent connection leaks."""
34
+
35
+ def __init__(self, max_connections: int = 3):
36
+ self.max_connections = max_connections
37
+ self.connections: List[Dict[str, Any]] = []
38
+ self.last_cleanup = time.time()
39
+
40
+ def get_connection(self, port: int) -> Optional[Any]:
41
+ """Get or create a connection to the specified port."""
42
+ if time.time() - self.last_cleanup > 60:
43
+ self._cleanup_dead_connections()
44
+ self.last_cleanup = time.time()
45
+
46
+ for conn in self.connections:
47
+ if conn.get("port") == port and conn.get("client"):
48
+ client = conn["client"]
49
+ if self._is_connection_alive(client):
50
+ return client
51
+ else:
52
+ self.connections.remove(conn)
53
+
54
+ if len(self.connections) < self.max_connections:
55
+ client = self._create_connection(port)
56
+ if client:
57
+ self.connections.append(
58
+ {"port": port, "client": client, "created": time.time()}
59
+ )
60
+ return client
61
+
62
+ if self.connections:
63
+ oldest = min(self.connections, key=lambda x: x["created"])
64
+ self._close_connection(oldest["client"])
65
+ oldest["client"] = self._create_connection(port)
66
+ oldest["port"] = port
67
+ oldest["created"] = time.time()
68
+ return oldest["client"]
69
+
70
+ return None
71
+
72
+ def _create_connection(self, port: int) -> Optional[Any]:
73
+ """Create a new Socket.IO connection."""
74
+ if not SOCKETIO_AVAILABLE:
75
+ return None
76
+ try:
77
+ client = socketio.Client(
78
+ reconnection=False,
79
+ logger=False,
80
+ engineio_logger=False, # Disable auto-reconnect
81
+ )
82
+ client.connect(
83
+ f"http://localhost:{port}",
84
+ wait=True,
85
+ wait_timeout=NetworkConfig.SOCKET_WAIT_TIMEOUT,
86
+ )
87
+ if client.connected:
88
+ return client
89
+ except Exception:
90
+ pass
91
+ return None
92
+
93
+ def _is_connection_alive(self, client: Any) -> bool:
94
+ """Check if a connection is still alive."""
95
+ try:
96
+ return client and client.connected
97
+ except:
98
+ return False
99
+
100
+ def _close_connection(self, client: Any) -> None:
101
+ """Safely close a connection."""
102
+ try:
103
+ if client:
104
+ client.disconnect()
105
+ except:
106
+ pass
107
+
108
+ def _cleanup_dead_connections(self) -> None:
109
+ """Remove dead connections from the pool."""
110
+ self.connections = [
111
+ conn
112
+ for conn in self.connections
113
+ if self._is_connection_alive(conn.get("client"))
114
+ ]
115
+
116
+ def close_all(self) -> None:
117
+ """Close all connections in the pool."""
118
+ for conn in self.connections:
119
+ self._close_connection(conn.get("client"))
120
+ self.connections.clear()