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
@@ -12,147 +12,160 @@ WHY this is needed:
12
12
  """
13
13
 
14
14
  import functools
15
- import json
16
15
  import os
17
16
  import threading
18
17
  import time
19
- from typing import Dict, Any, List, Optional
20
18
  from datetime import datetime
19
+ from typing import Any, Dict, List, Optional
21
20
 
22
- from ..core.logger import get_logger
23
21
  from ..core.hook_manager import get_hook_manager
22
+ from ..core.logger import get_logger
24
23
 
25
24
 
26
25
  class PMHookInterceptor:
27
26
  """Interceptor for PM operations that ensures hook events are triggered.
28
-
27
+
29
28
  WHY this design:
30
29
  - Acts as a transparent proxy for tool operations
31
30
  - Automatically triggers pre/post hook events
32
31
  - Maintains session consistency with regular Claude Code operations
33
32
  - Provides real-time event streaming for PM operations
34
33
  """
35
-
34
+
36
35
  def __init__(self):
37
36
  self.logger = get_logger("pm_hook_interceptor")
38
37
  self.hook_manager = get_hook_manager()
39
38
  self._in_intercept = threading.local() # Prevent recursion
40
-
39
+
41
40
  def intercept_todowrite(self, original_function):
42
41
  """Decorator to intercept TodoWrite calls and trigger hooks.
43
-
42
+
44
43
  Args:
45
44
  original_function: The original TodoWrite function
46
-
45
+
47
46
  Returns:
48
47
  Wrapped function that triggers hooks
49
48
  """
49
+
50
50
  @functools.wraps(original_function)
51
51
  def wrapper(*args, **kwargs):
52
52
  # Prevent recursive interception
53
- if getattr(self._in_intercept, 'active', False):
53
+ if getattr(self._in_intercept, "active", False):
54
54
  return original_function(*args, **kwargs)
55
-
55
+
56
56
  self._in_intercept.active = True
57
-
57
+
58
58
  try:
59
59
  # Extract todos from arguments
60
60
  todos = self._extract_todos_from_args(args, kwargs)
61
-
61
+
62
62
  # Trigger pre-tool hook
63
- self.hook_manager.trigger_pre_tool_hook("TodoWrite", {
64
- "todos": todos,
65
- "source": "PM",
66
- "intercepted": True
67
- })
68
-
63
+ self.hook_manager.trigger_pre_tool_hook(
64
+ "TodoWrite", {"todos": todos, "source": "PM", "intercepted": True}
65
+ )
66
+
69
67
  # Call the original function
70
68
  result = original_function(*args, **kwargs)
71
-
69
+
72
70
  # Trigger post-tool hook
73
- self.hook_manager.trigger_post_tool_hook("TodoWrite", 0, {
74
- "todos_count": len(todos) if todos else 0,
75
- "source": "PM",
76
- "success": True
77
- })
78
-
79
- self.logger.debug(f"Successfully intercepted TodoWrite with {len(todos) if todos else 0} todos")
80
-
71
+ self.hook_manager.trigger_post_tool_hook(
72
+ "TodoWrite",
73
+ 0,
74
+ {
75
+ "todos_count": len(todos) if todos else 0,
76
+ "source": "PM",
77
+ "success": True,
78
+ },
79
+ )
80
+
81
+ self.logger.debug(
82
+ f"Successfully intercepted TodoWrite with {len(todos) if todos else 0} todos"
83
+ )
84
+
81
85
  return result
82
-
86
+
83
87
  except Exception as e:
84
88
  # Trigger post-tool hook with error
85
- self.hook_manager.trigger_post_tool_hook("TodoWrite", 1, {
86
- "error": str(e),
87
- "source": "PM",
88
- "success": False
89
- })
90
-
89
+ self.hook_manager.trigger_post_tool_hook(
90
+ "TodoWrite", 1, {"error": str(e), "source": "PM", "success": False}
91
+ )
92
+
91
93
  self.logger.error(f"Error in TodoWrite interception: {e}")
92
94
  raise
93
95
  finally:
94
96
  self._in_intercept.active = False
95
-
97
+
96
98
  return wrapper
97
-
99
+
98
100
  def _extract_todos_from_args(self, args, kwargs) -> List[Dict[str, Any]]:
99
101
  """Extract todos from function arguments.
100
-
102
+
101
103
  Args:
102
104
  args: Positional arguments
103
105
  kwargs: Keyword arguments
104
-
106
+
105
107
  Returns:
106
108
  List of todo dictionaries
107
109
  """
108
110
  # Look for todos in kwargs first
109
- if 'todos' in kwargs:
110
- return kwargs['todos']
111
-
111
+ if "todos" in kwargs:
112
+ return kwargs["todos"]
113
+
112
114
  # Look for todos in positional args
113
115
  for arg in args:
114
116
  if isinstance(arg, list) and arg and isinstance(arg[0], dict):
115
117
  # Check if this looks like a todos list
116
- if 'content' in arg[0] or 'id' in arg[0]:
118
+ if "content" in arg[0] or "id" in arg[0]:
117
119
  return arg
118
-
120
+
119
121
  return []
120
-
122
+
121
123
  def trigger_manual_todowrite_hooks(self, todos: List[Dict[str, Any]]):
122
124
  """Manually trigger TodoWrite hooks for given todos.
123
-
125
+
124
126
  This method can be called directly when TodoWrite operations
125
127
  are detected outside of function interception.
126
-
128
+
127
129
  Args:
128
130
  todos: List of todo dictionaries
129
131
  """
130
132
  try:
131
133
  # Trigger pre-tool hook
132
- success1 = self.hook_manager.trigger_pre_tool_hook("TodoWrite", {
133
- "todos": todos,
134
- "source": "PM_Manual",
135
- "timestamp": datetime.utcnow().isoformat()
136
- })
137
-
134
+ success1 = self.hook_manager.trigger_pre_tool_hook(
135
+ "TodoWrite",
136
+ {
137
+ "todos": todos,
138
+ "source": "PM_Manual",
139
+ "timestamp": datetime.utcnow().isoformat(),
140
+ },
141
+ )
142
+
138
143
  # Small delay to ensure proper event ordering
139
144
  time.sleep(0.1)
140
-
145
+
141
146
  # Trigger post-tool hook
142
- success2 = self.hook_manager.trigger_post_tool_hook("TodoWrite", 0, {
143
- "todos_count": len(todos),
144
- "source": "PM_Manual",
145
- "success": True,
146
- "timestamp": datetime.utcnow().isoformat()
147
- })
148
-
147
+ success2 = self.hook_manager.trigger_post_tool_hook(
148
+ "TodoWrite",
149
+ 0,
150
+ {
151
+ "todos_count": len(todos),
152
+ "source": "PM_Manual",
153
+ "success": True,
154
+ "timestamp": datetime.utcnow().isoformat(),
155
+ },
156
+ )
157
+
149
158
  if success1 and success2:
150
- self.logger.info(f"Manually triggered TodoWrite hooks for {len(todos)} todos")
159
+ self.logger.info(
160
+ f"Manually triggered TodoWrite hooks for {len(todos)} todos"
161
+ )
151
162
  else:
152
- self.logger.warning(f"Hook triggering partially failed: pre={success1}, post={success2}")
153
-
163
+ self.logger.warning(
164
+ f"Hook triggering partially failed: pre={success1}, post={success2}"
165
+ )
166
+
154
167
  return success1 and success2
155
-
168
+
156
169
  except Exception as e:
157
170
  self.logger.error(f"Error manually triggering TodoWrite hooks: {e}")
158
171
  return False
@@ -172,10 +185,10 @@ def get_pm_hook_interceptor() -> PMHookInterceptor:
172
185
 
173
186
  def trigger_pm_todowrite_hooks(todos: List[Dict[str, Any]]) -> bool:
174
187
  """Convenience function to trigger PM TodoWrite hooks.
175
-
188
+
176
189
  Args:
177
190
  todos: List of todo dictionaries
178
-
191
+
179
192
  Returns:
180
193
  bool: True if hooks were triggered successfully
181
194
  """
@@ -185,21 +198,21 @@ def trigger_pm_todowrite_hooks(todos: List[Dict[str, Any]]) -> bool:
185
198
 
186
199
  def simulate_pm_todowrite_operation(todos: List[Dict[str, Any]]):
187
200
  """Simulate a PM TodoWrite operation with proper hook triggering.
188
-
201
+
189
202
  This function is useful for testing and for cases where we want to
190
203
  simulate a TodoWrite operation from the PM agent.
191
-
204
+
192
205
  Args:
193
206
  todos: List of todo dictionaries
194
207
  """
195
208
  interceptor = get_pm_hook_interceptor()
196
-
209
+
197
210
  # Log the operation
198
211
  logger = get_logger("pm_todowrite_simulation")
199
212
  logger.info(f"Simulating PM TodoWrite operation with {len(todos)} todos")
200
-
213
+
201
214
  # Trigger hooks
202
215
  interceptor.trigger_manual_todowrite_hooks(todos)
203
-
216
+
204
217
  # Log completion
205
- logger.info("PM TodoWrite simulation completed")
218
+ logger.info("PM TodoWrite simulation completed")
@@ -5,14 +5,12 @@ Provides centralized service registration and discovery, working with
5
5
  the DI container to manage application services.
6
6
  """
7
7
 
8
- import logging
9
- from pathlib import Path
10
- from typing import Any, Dict, List, Optional, Type, Union, TYPE_CHECKING
8
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union
11
9
 
12
- from .container import DIContainer, ServiceLifetime, get_container
13
10
  from .base_service import BaseService
14
- from .logger import get_logger
15
11
  from .config import Config
12
+ from .container import DIContainer, ServiceLifetime, get_container
13
+ from .logger import get_logger
16
14
 
17
15
  if TYPE_CHECKING:
18
16
  from claude_mpm.services.agents.deployment import AgentDeploymentService
@@ -23,91 +21,87 @@ logger = get_logger(__name__)
23
21
  class ServiceRegistry:
24
22
  """
25
23
  Central registry for all application services.
26
-
24
+
27
25
  Manages service registration, configuration, and lifecycle.
28
26
  """
29
-
27
+
30
28
  def __init__(self, container: Optional[DIContainer] = None):
31
29
  """
32
30
  Initialize service registry.
33
-
31
+
34
32
  Args:
35
33
  container: DI container to use (uses global if not provided)
36
34
  """
37
35
  self.container = container or get_container()
38
36
  self._services: Dict[str, Type[BaseService]] = {}
39
37
  self._initialized = False
40
-
38
+
41
39
  def register_core_services(self) -> None:
42
40
  """Register all core framework services."""
43
- from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
44
- from ..services.ticket_manager import TicketManager
41
+ from claude_mpm.services.memory.cache.shared_prompt_cache import (
42
+ SharedPromptCache,
43
+ )
44
+
45
45
  from ..services import AgentDeploymentService
46
- from .session_manager import SessionManager
47
46
  from .agent_session_manager import AgentSessionManager
48
-
47
+ from .session_manager import SessionManager
48
+
49
49
  # Register configuration as singleton with name
50
50
  config = Config()
51
51
  self.container.register_singleton(Config, instance=config, name="main_config")
52
-
52
+
53
53
  # Register core services with proper lifetime management
54
54
  self.register_service(
55
- "session_manager",
56
- SessionManager,
57
- lifetime=ServiceLifetime.SINGLETON
55
+ "session_manager", SessionManager, lifetime=ServiceLifetime.SINGLETON
58
56
  )
59
-
57
+
60
58
  self.register_service(
61
59
  "agent_session_manager",
62
60
  AgentSessionManager,
63
61
  lifetime=ServiceLifetime.SINGLETON,
64
- dependencies={
65
- 'session_dir': lambda c: c.get(Config).get('session_dir')
66
- }
62
+ dependencies={"session_dir": lambda c: c.get(Config).get("session_dir")},
67
63
  )
68
-
64
+
69
65
  # Register shared cache as singleton with factory
70
66
  self.container.register_factory(
71
67
  SharedPromptCache,
72
68
  lambda c: SharedPromptCache.get_instance(),
73
69
  lifetime=ServiceLifetime.SINGLETON,
74
- name="prompt_cache"
75
- )
76
-
77
- # Register ticket manager as scoped (per-request)
78
- self.container.register_scoped(
79
- TicketManager,
80
- TicketManager,
81
- name="ticket_manager"
70
+ name="prompt_cache",
82
71
  )
83
-
72
+
73
+ # Ticket manager removed - use claude-mpm tickets CLI commands instead
74
+
84
75
  # Register agent deployment service with factory for better initialization
85
76
  self.container.register_factory(
86
77
  AgentDeploymentService,
87
78
  lambda c: self._create_agent_deployment_service(c),
88
79
  lifetime=ServiceLifetime.TRANSIENT,
89
- name="agent_deployment"
80
+ name="agent_deployment",
90
81
  )
91
-
82
+
92
83
  logger.info("Core services registered with enhanced DI container")
93
-
94
- def _create_agent_deployment_service(self, container: DIContainer) -> 'AgentDeploymentService':
84
+
85
+ def _create_agent_deployment_service(
86
+ self, container: DIContainer
87
+ ) -> "AgentDeploymentService":
95
88
  """Factory method for creating agent deployment service."""
96
89
  import os
97
90
  from pathlib import Path
98
-
91
+
99
92
  config = container.get(Config)
100
-
93
+
101
94
  # Get working directory from environment or config
102
- if 'CLAUDE_MPM_USER_PWD' in os.environ:
103
- working_dir = Path(os.environ['CLAUDE_MPM_USER_PWD'])
95
+ if "CLAUDE_MPM_USER_PWD" in os.environ:
96
+ working_dir = Path(os.environ["CLAUDE_MPM_USER_PWD"])
104
97
  else:
105
- working_dir = Path(config.get('project.dir', '.'))
106
-
98
+ working_dir = Path(config.get("project.dir", "."))
99
+
107
100
  # Lazy import to avoid circular dependencies
108
101
  from claude_mpm.services.agents.deployment import AgentDeploymentService
102
+
109
103
  return AgentDeploymentService(working_directory=working_dir)
110
-
104
+
111
105
  def register_service(
112
106
  self,
113
107
  name: str,
@@ -115,11 +109,11 @@ class ServiceRegistry:
115
109
  lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
116
110
  factory: Optional[Any] = None,
117
111
  dependencies: Optional[Dict[str, Any]] = None,
118
- config: Optional[Dict[str, Any]] = None
112
+ config: Optional[Dict[str, Any]] = None,
119
113
  ) -> None:
120
114
  """
121
115
  Register a service with the registry.
122
-
116
+
123
117
  Args:
124
118
  name: Service name for lookup
125
119
  service_class: Service class (must inherit from BaseService)
@@ -130,31 +124,28 @@ class ServiceRegistry:
130
124
  """
131
125
  # Store service metadata
132
126
  self._services[name] = service_class
133
-
127
+
134
128
  # Create factory wrapper if config provided
135
129
  if config and not factory:
136
130
  factory = lambda c: service_class(name=name, config=config, container=c)
137
131
  elif not factory:
138
132
  # Default factory with container injection
139
133
  factory = lambda c: service_class(name=name, container=c)
140
-
134
+
141
135
  # Register with DI container
142
136
  self.container.register(
143
- service_class,
144
- factory=factory,
145
- lifetime=lifetime,
146
- dependencies=dependencies
137
+ service_class, factory=factory, lifetime=lifetime, dependencies=dependencies
147
138
  )
148
-
139
+
149
140
  logger.debug(f"Registered service: {name} ({service_class.__name__})")
150
-
141
+
151
142
  def get_service(self, service_type: Union[str, Type[BaseService]]) -> BaseService:
152
143
  """
153
144
  Get a service instance.
154
-
145
+
155
146
  Args:
156
147
  service_type: Service name or class
157
-
148
+
158
149
  Returns:
159
150
  Service instance
160
151
  """
@@ -172,110 +163,121 @@ class ServiceRegistry:
172
163
  else:
173
164
  # Direct class resolution
174
165
  return self.container.get(service_type)
175
-
166
+
176
167
  def get_service_optional(
177
168
  self,
178
169
  service_type: Union[str, Type[BaseService]],
179
- default: Optional[BaseService] = None
170
+ default: Optional[BaseService] = None,
180
171
  ) -> Optional[BaseService]:
181
172
  """Get a service if available, otherwise return default."""
182
173
  try:
183
174
  return self.get_service(service_type)
184
175
  except (KeyError, Exception):
185
176
  return default
186
-
177
+
187
178
  def start_all_services(self) -> None:
188
179
  """Start all registered singleton services."""
189
180
  import asyncio
190
-
181
+
191
182
  async def _start_all():
192
183
  for name, service_class in self._services.items():
193
184
  try:
194
185
  # Only start singleton services
195
- registration = self.container.get_all_registrations().get(service_class)
196
- if registration and registration.lifetime == ServiceLifetime.SINGLETON:
186
+ registration = self.container.get_all_registrations().get(
187
+ service_class
188
+ )
189
+ if (
190
+ registration
191
+ and registration.lifetime == ServiceLifetime.SINGLETON
192
+ ):
197
193
  service = self.get_service(service_class)
198
- if hasattr(service, 'start'):
194
+ if hasattr(service, "start"):
199
195
  await service.start()
200
196
  logger.info(f"Started service: {name}")
201
197
  except Exception as e:
202
198
  logger.error(f"Failed to start service {name}: {e}")
203
-
199
+
204
200
  asyncio.run(_start_all())
205
201
  self._initialized = True
206
-
202
+
207
203
  def stop_all_services(self) -> None:
208
204
  """Stop all running singleton services."""
209
205
  import asyncio
210
-
206
+
211
207
  async def _stop_all():
212
208
  for name, service_class in reversed(list(self._services.items())):
213
209
  try:
214
210
  # Only stop singleton services
215
- registration = self.container.get_all_registrations().get(service_class)
216
- if registration and registration.lifetime == ServiceLifetime.SINGLETON:
211
+ registration = self.container.get_all_registrations().get(
212
+ service_class
213
+ )
214
+ if (
215
+ registration
216
+ and registration.lifetime == ServiceLifetime.SINGLETON
217
+ ):
217
218
  if service_class in self.container._singletons:
218
219
  service = self.container._singletons[service_class]
219
- if hasattr(service, 'stop') and service.running:
220
+ if hasattr(service, "stop") and service.running:
220
221
  await service.stop()
221
222
  logger.info(f"Stopped service: {name}")
222
223
  except Exception as e:
223
224
  logger.error(f"Failed to stop service {name}: {e}")
224
-
225
+
225
226
  asyncio.run(_stop_all())
226
-
227
+
227
228
  def get_service_health(self) -> Dict[str, Dict[str, Any]]:
228
229
  """Get health status of all services."""
229
230
  import asyncio
230
-
231
+
231
232
  async def _get_health():
232
233
  health_status = {}
233
-
234
+
234
235
  for name, service_class in self._services.items():
235
236
  try:
236
237
  if service_class in self.container._singletons:
237
238
  service = self.container._singletons[service_class]
238
- if hasattr(service, 'health_check'):
239
+ if hasattr(service, "health_check"):
239
240
  health = await service.health_check()
240
241
  health_status[name] = {
241
- 'status': health.status,
242
- 'message': health.message,
243
- 'metrics': health.metrics
242
+ "status": health.status,
243
+ "message": health.message,
244
+ "metrics": health.metrics,
244
245
  }
245
246
  except Exception as e:
246
- health_status[name] = {
247
- 'status': 'error',
248
- 'message': str(e)
249
- }
250
-
247
+ health_status[name] = {"status": "error", "message": str(e)}
248
+
251
249
  return health_status
252
-
250
+
253
251
  return asyncio.run(_get_health())
254
-
252
+
255
253
  def list_services(self) -> List[Dict[str, Any]]:
256
254
  """List all registered services with their metadata."""
257
255
  services = []
258
-
256
+
259
257
  for name, service_class in self._services.items():
260
258
  registration = self.container.get_all_registrations().get(service_class)
261
-
259
+
262
260
  service_info = {
263
- 'name': name,
264
- 'class': service_class.__name__,
265
- 'module': service_class.__module__,
266
- 'lifetime': registration.lifetime.value if registration else 'unknown',
267
- 'is_singleton': registration.lifetime == ServiceLifetime.SINGLETON if registration else False,
268
- 'is_running': False
261
+ "name": name,
262
+ "class": service_class.__name__,
263
+ "module": service_class.__module__,
264
+ "lifetime": registration.lifetime.value if registration else "unknown",
265
+ "is_singleton": (
266
+ registration.lifetime == ServiceLifetime.SINGLETON
267
+ if registration
268
+ else False
269
+ ),
270
+ "is_running": False,
269
271
  }
270
-
272
+
271
273
  # Check if singleton is running
272
274
  if service_class in self.container._singletons:
273
275
  service = self.container._singletons[service_class]
274
- if hasattr(service, 'running'):
275
- service_info['is_running'] = service.running
276
-
276
+ if hasattr(service, "running"):
277
+ service_info["is_running"] = service.running
278
+
277
279
  services.append(service_info)
278
-
280
+
279
281
  return services
280
282
 
281
283
 
@@ -295,23 +297,23 @@ def get_service_registry() -> ServiceRegistry:
295
297
  def initialize_services(config: Optional[Dict[str, Any]] = None) -> ServiceRegistry:
296
298
  """
297
299
  Initialize all application services.
298
-
300
+
299
301
  Args:
300
302
  config: Optional configuration overrides
301
-
303
+
302
304
  Returns:
303
305
  Initialized service registry
304
306
  """
305
307
  registry = get_service_registry()
306
-
308
+
307
309
  if config:
308
310
  # Apply configuration overrides
309
311
  config_service = registry.container.resolve(Config)
310
312
  for key, value in config.items():
311
313
  config_service.set(key, value)
312
-
314
+
313
315
  # Start all services
314
316
  if not registry._initialized:
315
317
  registry.start_all_services()
316
-
317
- return registry
318
+
319
+ return registry