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
@@ -0,0 +1,304 @@
1
+ from pathlib import Path
2
+
3
+ """Session management service for orchestrating Claude sessions.
4
+
5
+ This service handles:
6
+ 1. Interactive session orchestration
7
+ 2. Oneshot session orchestration
8
+ 3. Session lifecycle management
9
+ 4. Session logging and cleanup
10
+
11
+ Extracted from ClaudeRunner to follow Single Responsibility Principle.
12
+ """
13
+
14
+ import time
15
+ import uuid
16
+ from typing import Any, Dict, List, Optional
17
+
18
+ from claude_mpm.core.base_service import BaseService
19
+ from claude_mpm.services.core.interfaces import SessionManagementInterface
20
+
21
+
22
+ class SessionManagementService(BaseService, SessionManagementInterface):
23
+ """Service for managing Claude session orchestration."""
24
+
25
+ def __init__(self, runner=None):
26
+ """Initialize the session management service.
27
+
28
+ Args:
29
+ runner: ClaudeRunner instance for delegation
30
+ """
31
+ super().__init__(name="session_management_service")
32
+ self.runner = runner
33
+ self.active_sessions = {} # Track active sessions
34
+
35
+ async def _initialize(self) -> None:
36
+ """Initialize the service. No special initialization needed."""
37
+ pass
38
+
39
+ async def _cleanup(self) -> None:
40
+ """Cleanup service resources. No cleanup needed."""
41
+ pass
42
+
43
+ def run_interactive_session(self, initial_context: Optional[str] = None) -> bool:
44
+ """Run Claude in interactive mode using session delegation.
45
+
46
+ WHY: This method delegates to InteractiveSession class for better
47
+ maintainability and reduced complexity. The session class handles all
48
+ the details while this method provides the orchestration interface.
49
+
50
+ Args:
51
+ initial_context: Optional initial context to pass to Claude
52
+
53
+ Returns:
54
+ bool: True if session completed successfully, False otherwise
55
+ """
56
+ try:
57
+ from claude_mpm.core.interactive_session import InteractiveSession
58
+
59
+ # Create session handler
60
+ session = InteractiveSession(self.runner)
61
+
62
+ # Step 1: Initialize session
63
+ success, error = session.initialize_interactive_session()
64
+ if not success:
65
+ self.logger.error(f"Failed to initialize interactive session: {error}")
66
+ return False
67
+
68
+ # Step 2: Set up environment
69
+ success, environment = session.setup_interactive_environment()
70
+ if not success:
71
+ self.logger.error("Failed to setup interactive environment")
72
+ return False
73
+
74
+ # Step 3: Handle interactive input/output
75
+ # This is where the actual Claude process runs
76
+ session.handle_interactive_input(environment)
77
+
78
+ return True
79
+
80
+ except Exception as e:
81
+ self.logger.error(f"Interactive session failed: {e}")
82
+ return False
83
+ finally:
84
+ # Step 4: Clean up session
85
+ if "session" in locals():
86
+ session.cleanup_interactive_session()
87
+
88
+ def run_oneshot_session(self, prompt: str, context: Optional[str] = None) -> bool:
89
+ """Run Claude with a single prompt using session delegation.
90
+
91
+ WHY: This method delegates to OneshotSession class for better
92
+ maintainability and reduced complexity. The session class handles
93
+ all the details while this method provides the orchestration interface.
94
+
95
+ Args:
96
+ prompt: The command or prompt to execute
97
+ context: Optional context to prepend to the prompt
98
+
99
+ Returns:
100
+ bool: True if successful, False otherwise
101
+ """
102
+ try:
103
+ from claude_mpm.core.oneshot_session import OneshotSession
104
+
105
+ # Create session handler
106
+ session = OneshotSession(self.runner)
107
+
108
+ # Step 1: Initialize session
109
+ success, error = session.initialize_session(prompt)
110
+ if not success:
111
+ return False
112
+
113
+ # Special case: MPM commands return early
114
+ if (
115
+ error is None
116
+ and self.runner.command_handler_service
117
+ and self.runner.command_handler_service.is_mpm_command(prompt)
118
+ ):
119
+ return success
120
+
121
+ # Step 2: Deploy agents
122
+ if not session.deploy_agents():
123
+ self.logger.warning("Agent deployment had issues, continuing...")
124
+
125
+ # Step 3: Set up infrastructure
126
+ infrastructure = session.setup_infrastructure()
127
+
128
+ # Step 4: Execute command
129
+ success, response = session.execute_command(prompt, context, infrastructure)
130
+
131
+ return success
132
+
133
+ except Exception as e:
134
+ self.logger.error(f"Oneshot session failed: {e}")
135
+ return False
136
+ finally:
137
+ # Step 5: Clean up session
138
+ if "session" in locals():
139
+ session.cleanup_session()
140
+
141
+ def create_session_log_file(self) -> Optional[Path]:
142
+ """Create a session log file for the current session.
143
+
144
+ Returns:
145
+ Path to the created log file, or None if creation failed
146
+ """
147
+ try:
148
+ import uuid
149
+ from datetime import datetime
150
+
151
+ from claude_mpm.config.paths import paths
152
+
153
+ # Create session logs directory if it doesn't exist
154
+ session_logs_dir = paths.project_root / ".claude-mpm" / "logs" / "sessions"
155
+ session_logs_dir.mkdir(parents=True, exist_ok=True)
156
+
157
+ # Generate unique session log filename
158
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
159
+ session_id = str(uuid.uuid4())[:8]
160
+ log_filename = f"session_{timestamp}_{session_id}.jsonl"
161
+ log_file = session_logs_dir / log_filename
162
+
163
+ # Create empty log file
164
+ log_file.touch()
165
+
166
+ self.logger.debug(f"Created session log file: {log_file}")
167
+ return log_file
168
+
169
+ except Exception as e:
170
+ self.logger.warning(f"Failed to create session log file: {e}")
171
+ return None
172
+
173
+ def log_session_event(self, log_file: Path, event_data: dict):
174
+ """Log an event to the session log file.
175
+
176
+ Args:
177
+ log_file: Path to the session log file
178
+ event_data: Event data to log
179
+ """
180
+ if not log_file or not log_file.exists():
181
+ return
182
+
183
+ try:
184
+ import json
185
+ from datetime import datetime
186
+
187
+ # Add timestamp to event data
188
+ event_data["timestamp"] = datetime.now().isoformat()
189
+
190
+ # Append to log file as JSONL
191
+ with open(log_file, "a") as f:
192
+ f.write(json.dumps(event_data) + "\n")
193
+
194
+ except Exception as e:
195
+ self.logger.warning(f"Failed to log session event: {e}")
196
+
197
+ def get_service_status(self) -> dict:
198
+ """Get current session management service status.
199
+
200
+ Returns:
201
+ dict: Session management service status information
202
+ """
203
+ return {
204
+ "service_available": True,
205
+ "runner_available": self.runner is not None,
206
+ "interactive_session_available": True,
207
+ "oneshot_session_available": True,
208
+ "active_sessions": len(self.active_sessions),
209
+ }
210
+
211
+ # Implementation of abstract methods from SessionManagementInterface
212
+
213
+ def start_session(self, session_config: Dict[str, Any]) -> str:
214
+ """Start a new session.
215
+
216
+ Args:
217
+ session_config: Configuration for the session
218
+
219
+ Returns:
220
+ Session ID
221
+ """
222
+ session_id = str(uuid.uuid4())
223
+ session_info = {
224
+ "id": session_id,
225
+ "config": session_config,
226
+ "start_time": time.time(),
227
+ "status": "active",
228
+ "type": session_config.get("type", "interactive"),
229
+ }
230
+
231
+ self.active_sessions[session_id] = session_info
232
+ self.logger.info(f"Started session {session_id}")
233
+
234
+ return session_id
235
+
236
+ def end_session(self, session_id: str) -> bool:
237
+ """End an active session.
238
+
239
+ Args:
240
+ session_id: ID of session to end
241
+
242
+ Returns:
243
+ True if session ended successfully
244
+ """
245
+ if session_id in self.active_sessions:
246
+ session_info = self.active_sessions[session_id]
247
+ session_info["status"] = "ended"
248
+ session_info["end_time"] = time.time()
249
+
250
+ # Remove from active sessions
251
+ del self.active_sessions[session_id]
252
+
253
+ self.logger.info(f"Ended session {session_id}")
254
+ return True
255
+ else:
256
+ self.logger.warning(f"Session {session_id} not found")
257
+ return False
258
+
259
+ def get_session_status(self, session_id: str) -> Dict[str, Any]:
260
+ """Get status of a session.
261
+
262
+ Args:
263
+ session_id: ID of session
264
+
265
+ Returns:
266
+ Dictionary with session status information
267
+ """
268
+ if session_id in self.active_sessions:
269
+ return self.active_sessions[session_id].copy()
270
+ else:
271
+ return {
272
+ "id": session_id,
273
+ "status": "not_found",
274
+ "error": "Session not found",
275
+ }
276
+
277
+ def list_active_sessions(self) -> List[str]:
278
+ """List all active session IDs.
279
+
280
+ Returns:
281
+ List of active session IDs
282
+ """
283
+ return list(self.active_sessions.keys())
284
+
285
+ async def cleanup_sessions(self) -> int:
286
+ """Clean up inactive or expired sessions.
287
+
288
+ Returns:
289
+ Number of sessions cleaned up
290
+ """
291
+ current_time = time.time()
292
+ expired_sessions = []
293
+
294
+ # Find sessions older than 24 hours
295
+ for session_id, session_info in self.active_sessions.items():
296
+ if current_time - session_info["start_time"] > 86400: # 24 hours
297
+ expired_sessions.append(session_id)
298
+
299
+ # Clean up expired sessions
300
+ for session_id in expired_sessions:
301
+ self.end_session(session_id)
302
+
303
+ self.logger.info(f"Cleaned up {len(expired_sessions)} expired sessions")
304
+ return len(expired_sessions)
@@ -7,11 +7,11 @@ with separated event handlers for improved maintainability.
7
7
  from .handlers import (
8
8
  BaseEventHandler,
9
9
  ConnectionEventHandler,
10
- ProjectEventHandler,
11
- MemoryEventHandler,
10
+ EventHandlerRegistry,
12
11
  FileEventHandler,
13
12
  GitEventHandler,
14
- EventHandlerRegistry,
13
+ MemoryEventHandler,
14
+ ProjectEventHandler,
15
15
  )
16
16
 
17
17
  __all__ = [
@@ -22,4 +22,4 @@ __all__ = [
22
22
  "FileEventHandler",
23
23
  "GitEventHandler",
24
24
  "EventHandlerRegistry",
25
- ]
25
+ ]
@@ -0,0 +1,174 @@
1
+ """
2
+ SocketIO Client Proxy for claude-mpm.
3
+
4
+ WHY: This module contains the SocketIOClientProxy class that was extracted from
5
+ the monolithic socketio_server.py file. In exec mode, a persistent Socket.IO
6
+ server runs in a separate process, and this proxy provides a Socket.IO-like
7
+ interface without starting another server.
8
+
9
+ DESIGN DECISION: Separated client proxy logic from server logic for better
10
+ organization and to reduce the complexity of the main server file.
11
+ """
12
+
13
+ import asyncio
14
+ import threading
15
+ import time
16
+ from datetime import datetime
17
+ from typing import Any, Dict, List, Optional, Set
18
+
19
+ try:
20
+ import socketio
21
+
22
+ SOCKETIO_AVAILABLE = True
23
+ except ImportError:
24
+ SOCKETIO_AVAILABLE = False
25
+ socketio = None
26
+
27
+ from ...core.logging_config import get_logger
28
+
29
+
30
+ class SocketIOClientProxy:
31
+ """Proxy that connects to an existing Socket.IO server as a client.
32
+
33
+ WHY: In exec mode, a persistent Socket.IO server runs in a separate process.
34
+ The hook handler in the Claude process needs a Socket.IO-like interface
35
+ but shouldn't start another server. This proxy provides that interface
36
+ while the actual events are handled by the persistent server.
37
+ """
38
+
39
+ def __init__(self, host: str = "localhost", port: int = 8765):
40
+ self.host = host
41
+ self.port = port
42
+ self.logger = get_logger(__name__ + ".SocketIOClientProxy")
43
+ self.running = True # Always "running" for compatibility
44
+ self._sio_client = None
45
+ self._client_thread = None
46
+ self._client_loop = None
47
+
48
+ def start_sync(self):
49
+ """Start the Socket.IO client connection to the persistent server."""
50
+ self.logger.debug(
51
+ f"SocketIOClientProxy: Connecting to server on {self.host}:{self.port}"
52
+ )
53
+ if SOCKETIO_AVAILABLE:
54
+ self._start_client()
55
+
56
+ def stop_sync(self):
57
+ """Stop the Socket.IO client connection."""
58
+ self.logger.debug(f"SocketIOClientProxy: Disconnecting from server")
59
+ if self._sio_client:
60
+ self._sio_client.disconnect()
61
+
62
+ def _start_client(self):
63
+ """Start Socket.IO client in a background thread."""
64
+
65
+ def run_client():
66
+ self._client_loop = asyncio.new_event_loop()
67
+ asyncio.set_event_loop(self._client_loop)
68
+ try:
69
+ self._client_loop.run_until_complete(self._connect_and_run())
70
+ except Exception as e:
71
+ self.logger.error(f"SocketIOClientProxy client thread error: {e}")
72
+ finally:
73
+ self._client_loop.close()
74
+
75
+ self._client_thread = threading.Thread(target=run_client, daemon=True)
76
+ self._client_thread.start()
77
+ # Give it a moment to connect
78
+ time.sleep(0.2)
79
+
80
+ async def _connect_and_run(self):
81
+ """Connect to the persistent Socket.IO server and keep connection alive."""
82
+ try:
83
+ self._sio_client = socketio.AsyncClient()
84
+
85
+ @self._sio_client.event
86
+ async def connect():
87
+ self.logger.info(
88
+ f"SocketIOClientProxy: Connected to server at http://{self.host}:{self.port}"
89
+ )
90
+
91
+ @self._sio_client.event
92
+ async def disconnect():
93
+ self.logger.info(f"SocketIOClientProxy: Disconnected from server")
94
+
95
+ # Connect to the server
96
+ await self._sio_client.connect(f"http://127.0.0.1:{self.port}")
97
+
98
+ # Keep the connection alive until stopped
99
+ while self.running:
100
+ await asyncio.sleep(1)
101
+
102
+ except Exception as e:
103
+ self.logger.error(f"SocketIOClientProxy: Connection error: {e}")
104
+ self._sio_client = None
105
+
106
+ def broadcast_event(self, event_type: str, data: Dict[str, Any]):
107
+ """Send event to the persistent Socket.IO server."""
108
+ if not SOCKETIO_AVAILABLE:
109
+ return
110
+
111
+ # Ensure client is started
112
+ if not self._client_thread or not self._client_thread.is_alive():
113
+ self.logger.debug(f"SocketIOClientProxy: Starting client for {event_type}")
114
+ self._start_client()
115
+
116
+ if self._sio_client and self._sio_client.connected:
117
+ try:
118
+ event = {
119
+ "type": event_type,
120
+ "timestamp": datetime.now().isoformat(),
121
+ "data": data,
122
+ }
123
+
124
+ # Send event safely using run_coroutine_threadsafe
125
+ if (
126
+ hasattr(self, "_client_loop")
127
+ and self._client_loop
128
+ and not self._client_loop.is_closed()
129
+ ):
130
+ try:
131
+ future = asyncio.run_coroutine_threadsafe(
132
+ self._sio_client.emit("claude_event", event),
133
+ self._client_loop,
134
+ )
135
+ # Don't wait for the result to avoid blocking
136
+ self.logger.debug(
137
+ f"SocketIOClientProxy: Scheduled emit for {event_type}"
138
+ )
139
+ except Exception as e:
140
+ self.logger.error(
141
+ f"SocketIOClientProxy: Failed to schedule emit for {event_type}: {e}"
142
+ )
143
+ else:
144
+ self.logger.warning(
145
+ f"SocketIOClientProxy: Client event loop not available for {event_type}"
146
+ )
147
+
148
+ self.logger.debug(f"SocketIOClientProxy: Sent event {event_type}")
149
+ except Exception as e:
150
+ self.logger.error(
151
+ f"SocketIOClientProxy: Failed to send event {event_type}: {e}"
152
+ )
153
+ else:
154
+ self.logger.warning(
155
+ f"SocketIOClientProxy: Client not ready for {event_type}"
156
+ )
157
+
158
+ # Compatibility methods for WebSocketServer interface
159
+ def session_started(self, session_id: str, launch_method: str, working_dir: str):
160
+ self.logger.debug(f"SocketIOClientProxy: Session started {session_id}")
161
+
162
+ def session_ended(self):
163
+ self.logger.debug(f"SocketIOClientProxy: Session ended")
164
+
165
+ def claude_status_changed(
166
+ self, status: str, pid: Optional[int] = None, message: str = ""
167
+ ):
168
+ self.logger.debug(f"SocketIOClientProxy: Claude status {status}")
169
+
170
+ def agent_delegated(self, agent: str, task: str, status: str = "started"):
171
+ self.logger.debug(f"SocketIOClientProxy: Agent {agent} delegated")
172
+
173
+ def todo_updated(self, todos: List[Dict[str, Any]]):
174
+ self.logger.debug(f"SocketIOClientProxy: Todo updated ({len(todos)} todos)")
@@ -8,10 +8,10 @@ and maintainability.
8
8
 
9
9
  from .base import BaseEventHandler
10
10
  from .connection import ConnectionEventHandler
11
- from .project import ProjectEventHandler
12
- from .memory import MemoryEventHandler
13
11
  from .file import FileEventHandler
14
12
  from .git import GitEventHandler
13
+ from .memory import MemoryEventHandler
14
+ from .project import ProjectEventHandler
15
15
  from .registry import EventHandlerRegistry
16
16
 
17
17
  __all__ = [
@@ -22,4 +22,4 @@ __all__ = [
22
22
  "FileEventHandler",
23
23
  "GitEventHandler",
24
24
  "EventHandlerRegistry",
25
- ]
25
+ ]
@@ -6,52 +6,55 @@ classes inherit from this to ensure consistent behavior.
6
6
  """
7
7
 
8
8
  import logging
9
- from typing import Any, Dict, Optional, List, TYPE_CHECKING
10
9
  from datetime import datetime
11
10
  from logging import Logger
11
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional
12
12
 
13
13
  from ....core.logger import get_logger
14
- from ....core.typing_utils import EventName, EventData, SocketId
14
+ from ....core.typing_utils import EventData, EventName, SocketId
15
15
 
16
16
  if TYPE_CHECKING:
17
- from ..server import SocketIOServer
18
17
  import socketio
19
18
 
19
+ from ..server import SocketIOServer
20
+
20
21
 
21
22
  class BaseEventHandler:
22
23
  """Base class for Socket.IO event handlers.
23
-
24
+
24
25
  WHY: Provides common functionality and structure for all event handlers,
25
26
  ensuring consistent error handling, logging, and server access patterns.
26
27
  Each handler focuses on a specific domain while sharing common infrastructure.
27
28
  """
28
-
29
- def __init__(self, server: 'SocketIOServer') -> None:
29
+
30
+ def __init__(self, server: "SocketIOServer") -> None:
30
31
  """Initialize the base handler.
31
-
32
+
32
33
  Args:
33
34
  server: The SocketIOServer instance that owns this handler
34
35
  """
35
- self.server: 'SocketIOServer' = server
36
- self.sio: 'socketio.AsyncServer' = server.sio
36
+ self.server: "SocketIOServer" = server
37
+ self.sio: "socketio.AsyncServer" = server.sio
37
38
  self.logger: Logger = get_logger(self.__class__.__name__)
38
39
  self.clients: Dict[SocketId, Dict[str, Any]] = server.clients
39
40
  self.event_history: List[Dict[str, Any]] = server.event_history
40
-
41
+
41
42
  def register_events(self) -> None:
42
43
  """Register all events handled by this handler.
43
-
44
+
44
45
  WHY: This method must be implemented by each handler subclass
45
46
  to register its specific events with the Socket.IO server.
46
47
  """
47
48
  raise NotImplementedError("Subclasses must implement register_events()")
48
-
49
- async def emit_to_client(self, sid: SocketId, event: EventName, data: EventData) -> None:
49
+
50
+ async def emit_to_client(
51
+ self, sid: SocketId, event: EventName, data: EventData
52
+ ) -> None:
50
53
  """Emit an event to a specific client.
51
-
54
+
52
55
  WHY: Centralizes client communication with consistent error handling
53
56
  and logging for debugging connection issues.
54
-
57
+
55
58
  Args:
56
59
  sid: Socket.IO session ID of the client
57
60
  event: Event name to emit
@@ -63,34 +66,40 @@ class BaseEventHandler:
63
66
  except Exception as e:
64
67
  self.logger.error(f"Failed to emit {event} to client {sid}: {e}")
65
68
  import traceback
69
+
66
70
  self.logger.error(f"Stack trace: {traceback.format_exc()}")
67
-
68
- async def broadcast_event(self, event: EventName, data: EventData, skip_sid: Optional[SocketId] = None) -> None:
71
+
72
+ async def broadcast_event(
73
+ self, event: EventName, data: EventData, skip_sid: Optional[SocketId] = None
74
+ ) -> None:
69
75
  """Broadcast an event to all connected clients.
70
-
76
+
71
77
  WHY: Provides consistent broadcasting with optional exclusion
72
78
  of the originating client.
73
-
79
+
74
80
  Args:
75
81
  event: Event name to broadcast
76
82
  data: Data to send with the event
77
83
  skip_sid: Optional session ID to skip
78
84
  """
79
85
  try:
86
+ self.logger.info(f"🔔 Broadcasting {event} (skip_sid={skip_sid})")
80
87
  if skip_sid:
81
88
  await self.sio.emit(event, data, skip_sid=skip_sid)
82
89
  else:
83
90
  await self.sio.emit(event, data)
84
- self.logger.debug(f"Broadcasted {event} to all clients")
91
+ self.logger.info(f"Broadcasted {event} to all clients")
85
92
  except Exception as e:
86
93
  self.logger.error(f"Failed to broadcast {event}: {e}")
87
-
94
+ import traceback
95
+ self.logger.error(f"Stack trace: {traceback.format_exc()}")
96
+
88
97
  def add_to_history(self, event_type: str, data: EventData) -> None:
89
98
  """Add an event to the server's event history.
90
-
99
+
91
100
  WHY: Maintains a history of events for new clients to receive
92
101
  when they connect, ensuring they have context.
93
-
102
+
94
103
  Args:
95
104
  event_type: Type of the event
96
105
  data: Event data
@@ -98,17 +107,21 @@ class BaseEventHandler:
98
107
  event = {
99
108
  "type": event_type,
100
109
  "timestamp": datetime.utcnow().isoformat() + "Z",
101
- "data": data
110
+ "data": data,
102
111
  }
103
112
  self.event_history.append(event)
104
- self.logger.debug(f"Added {event_type} to history (total: {len(self.event_history)})")
105
-
106
- def log_error(self, operation: str, error: Exception, context: Optional[Dict[str, Any]] = None) -> None:
113
+ self.logger.debug(
114
+ f"Added {event_type} to history (total: {len(self.event_history)})"
115
+ )
116
+
117
+ def log_error(
118
+ self, operation: str, error: Exception, context: Optional[Dict[str, Any]] = None
119
+ ) -> None:
107
120
  """Log an error with context.
108
-
121
+
109
122
  WHY: Provides consistent error logging with context information
110
123
  for debugging issues in production.
111
-
124
+
112
125
  Args:
113
126
  operation: Description of the operation that failed
114
127
  error: The exception that occurred
@@ -118,4 +131,5 @@ class BaseEventHandler:
118
131
  if context:
119
132
  self.logger.error(f"Context: {context}")
120
133
  import traceback
121
- self.logger.error(f"Stack trace: {traceback.format_exc()}")
134
+
135
+ self.logger.error(f"Stack trace: {traceback.format_exc()}")