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
@@ -17,24 +17,26 @@ from abc import ABC
17
17
  from enum import Enum
18
18
  from typing import Any, Callable, Dict, List, Optional, Set, Type, TypeVar, Union
19
19
 
20
- from .logger import get_logger
21
20
  from claude_mpm.services.core.interfaces import IServiceContainer
22
21
 
22
+ from .logger import get_logger
23
+
23
24
  logger = get_logger(__name__)
24
25
 
25
- T = TypeVar('T')
26
+ T = TypeVar("T")
26
27
 
27
28
 
28
29
  class ServiceLifetime(Enum):
29
30
  """Service lifetime options."""
31
+
30
32
  SINGLETON = "singleton" # One instance per container
31
33
  TRANSIENT = "transient" # New instance per request
32
- SCOPED = "scoped" # One instance per scope
34
+ SCOPED = "scoped" # One instance per scope
33
35
 
34
36
 
35
37
  class ServiceRegistration:
36
38
  """Represents a service registration in the container."""
37
-
39
+
38
40
  def __init__(
39
41
  self,
40
42
  service_type: Type,
@@ -42,11 +44,11 @@ class ServiceRegistration:
42
44
  factory: Optional[Callable] = None,
43
45
  instance: Optional[Any] = None,
44
46
  lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
45
- dependencies: Optional[Dict[str, Type]] = None
47
+ dependencies: Optional[Dict[str, Type]] = None,
46
48
  ):
47
49
  """
48
50
  Initialize service registration.
49
-
51
+
50
52
  Args:
51
53
  service_type: The interface/base type being registered
52
54
  implementation: The concrete implementation class
@@ -62,15 +64,15 @@ class ServiceRegistration:
62
64
  self.lifetime = lifetime
63
65
  self.dependencies = dependencies or {}
64
66
  self._lock = threading.Lock()
65
-
66
- def create_instance(self, container: 'DIContainer') -> Any:
67
+
68
+ def create_instance(self, container: "DIContainer") -> Any:
67
69
  """Create an instance of the service."""
68
70
  if self.instance is not None:
69
71
  return self.instance
70
-
72
+
71
73
  if self.factory:
72
74
  return self.factory(container)
73
-
75
+
74
76
  # Get constructor parameters
75
77
  if inspect.isclass(self.implementation):
76
78
  return container.create_instance(self.implementation, self.dependencies)
@@ -81,65 +83,69 @@ class ServiceRegistration:
81
83
 
82
84
  class CircularDependencyError(Exception):
83
85
  """Raised when circular dependencies are detected."""
86
+
84
87
  pass
85
88
 
86
89
 
87
90
  class ServiceNotFoundError(Exception):
88
91
  """Raised when a requested service is not registered."""
92
+
89
93
  pass
90
94
 
91
95
 
92
96
  class ServiceScope:
93
97
  """
94
98
  Represents a service scope for scoped lifetime services.
95
-
99
+
96
100
  Scoped services live for the duration of the scope and are shared
97
101
  within that scope.
98
102
  """
99
-
100
- def __init__(self, container: 'DIContainer'):
103
+
104
+ def __init__(self, container: "DIContainer"):
101
105
  """Initialize service scope."""
102
106
  self._container = container
103
107
  self._scoped_instances: Dict[Type, Any] = {}
104
108
  self._disposed = False
105
109
  self._lock = threading.Lock()
106
-
110
+
107
111
  def get_scoped_instance(self, service_type: Type) -> Optional[Any]:
108
112
  """Get scoped instance if exists."""
109
113
  with self._lock:
110
114
  return self._scoped_instances.get(service_type)
111
-
115
+
112
116
  def set_scoped_instance(self, service_type: Type, instance: Any) -> None:
113
117
  """Store scoped instance."""
114
118
  with self._lock:
115
119
  if not self._disposed:
116
120
  self._scoped_instances[service_type] = instance
117
-
121
+
118
122
  def dispose(self) -> None:
119
123
  """
120
124
  Dispose of the scope and all scoped instances.
121
-
125
+
122
126
  Calls dispose() on instances that implement IDisposable.
123
127
  """
124
128
  with self._lock:
125
129
  if self._disposed:
126
130
  return
127
-
131
+
128
132
  for service_type, instance in self._scoped_instances.items():
129
133
  # Call dispose if available
130
- if hasattr(instance, 'dispose'):
134
+ if hasattr(instance, "dispose"):
131
135
  try:
132
136
  instance.dispose()
133
137
  except Exception as e:
134
- logger.error(f"Error disposing scoped service {service_type}: {e}")
135
-
138
+ logger.error(
139
+ f"Error disposing scoped service {service_type}: {e}"
140
+ )
141
+
136
142
  self._scoped_instances.clear()
137
143
  self._disposed = True
138
-
144
+
139
145
  def __enter__(self):
140
146
  """Context manager entry."""
141
147
  return self
142
-
148
+
143
149
  def __exit__(self, exc_type, exc_val, exc_tb):
144
150
  """Context manager exit - dispose scope."""
145
151
  self.dispose()
@@ -148,10 +154,10 @@ class ServiceScope:
148
154
  class DIContainer(IServiceContainer):
149
155
  """
150
156
  Enhanced Dependency Injection Container.
151
-
157
+
152
158
  Implements IServiceContainer interface to provide a complete
153
159
  dependency injection solution.
154
-
160
+
155
161
  Provides:
156
162
  - Service registration with multiple lifetime options
157
163
  - Automatic constructor injection
@@ -163,7 +169,7 @@ class DIContainer(IServiceContainer):
163
169
  - Named registrations
164
170
  - Configuration injection
165
171
  """
166
-
172
+
167
173
  def __init__(self):
168
174
  """Initialize the DI container."""
169
175
  self._registrations: Dict[Type, ServiceRegistration] = {}
@@ -176,47 +182,42 @@ class DIContainer(IServiceContainer):
176
182
  self._lock = threading.RLock()
177
183
  self._resolving: Set[Type] = set()
178
184
  self._current_scope: Optional[ServiceScope] = None
179
-
185
+
180
186
  def register(
181
- self,
182
- service_type: type,
183
- implementation: type,
184
- singleton: bool = True
187
+ self, service_type: type, implementation: type, singleton: bool = True
185
188
  ) -> None:
186
189
  """
187
190
  Register a service implementation (IServiceContainer interface method).
188
-
191
+
189
192
  Args:
190
193
  service_type: The interface/base type to register
191
194
  implementation: The concrete implementation class
192
195
  singleton: Whether to use singleton lifetime (default True)
193
-
196
+
194
197
  Examples:
195
198
  # Register interface with implementation
196
199
  container.register(ILogger, ConsoleLogger)
197
-
200
+
198
201
  # Register as transient (new instance each time)
199
202
  container.register(IService, ServiceImpl, singleton=False)
200
203
  """
201
204
  lifetime = ServiceLifetime.SINGLETON if singleton else ServiceLifetime.TRANSIENT
202
205
  self._register_internal(
203
- service_type=service_type,
204
- implementation=implementation,
205
- lifetime=lifetime
206
+ service_type=service_type, implementation=implementation, lifetime=lifetime
206
207
  )
207
-
208
+
208
209
  def _register_internal(
209
210
  self,
210
211
  service_type: Type[T],
211
212
  implementation: Optional[Union[Type[T], Callable[..., T]]] = None,
212
213
  lifetime: ServiceLifetime = ServiceLifetime.SINGLETON,
213
- factory: Optional[Callable[['DIContainer'], T]] = None,
214
+ factory: Optional[Callable[["DIContainer"], T]] = None,
214
215
  instance: Optional[T] = None,
215
- dependencies: Optional[Dict[str, Type]] = None
216
+ dependencies: Optional[Dict[str, Type]] = None,
216
217
  ) -> None:
217
218
  """
218
219
  Internal registration method with full flexibility.
219
-
220
+
220
221
  Args:
221
222
  service_type: The interface/base type to register
222
223
  implementation: The concrete implementation (class or factory)
@@ -232,22 +233,22 @@ class DIContainer(IServiceContainer):
232
233
  factory=factory,
233
234
  instance=instance,
234
235
  lifetime=lifetime,
235
- dependencies=dependencies
236
+ dependencies=dependencies,
236
237
  )
237
238
  self._registrations[service_type] = registration
238
-
239
+
239
240
  # If instance provided, store as singleton
240
241
  if instance is not None:
241
242
  self._singletons[service_type] = instance
242
-
243
+
243
244
  def register_instance(self, service_type: type, instance: Any) -> None:
244
245
  """
245
246
  Register a service instance (IServiceContainer interface method).
246
-
247
+
247
248
  Args:
248
249
  service_type: The interface/base type to register
249
250
  instance: Pre-created instance to register as singleton
250
-
251
+
251
252
  Examples:
252
253
  # Register a pre-created instance
253
254
  config = Config()
@@ -256,24 +257,24 @@ class DIContainer(IServiceContainer):
256
257
  self._register_internal(
257
258
  service_type=service_type,
258
259
  instance=instance,
259
- lifetime=ServiceLifetime.SINGLETON
260
+ lifetime=ServiceLifetime.SINGLETON,
260
261
  )
261
-
262
+
262
263
  def resolve_all(self, service_type: type) -> List[Any]:
263
264
  """
264
265
  Resolve all implementations of a service type (IServiceContainer interface method).
265
-
266
+
266
267
  Args:
267
268
  service_type: The type to resolve
268
-
269
+
269
270
  Returns:
270
271
  List of all registered implementations for the service type
271
-
272
+
272
273
  Examples:
273
274
  # Register multiple implementations
274
275
  container.register(IPlugin, PluginA)
275
276
  container.register(IPlugin, PluginB)
276
-
277
+
277
278
  # Get all implementations
278
279
  plugins = container.resolve_all(IPlugin)
279
280
  """
@@ -283,32 +284,32 @@ class DIContainer(IServiceContainer):
283
284
  if service_type in self._registrations:
284
285
  return [self._resolve_internal(service_type)]
285
286
  return []
286
-
287
+
287
288
  def register_singleton(
288
289
  self,
289
290
  interface: Type[T],
290
291
  implementation: Optional[Union[Type[T], T]] = None,
291
292
  instance: Optional[T] = None,
292
293
  name: Optional[str] = None,
293
- dispose_handler: Optional[Callable[[T], None]] = None
294
+ dispose_handler: Optional[Callable[[T], None]] = None,
294
295
  ) -> None:
295
296
  """
296
297
  Register a singleton service.
297
-
298
+
298
299
  Args:
299
300
  interface: The interface/base type to register
300
301
  implementation: The concrete implementation class
301
302
  instance: Pre-created instance (alternative to implementation)
302
303
  name: Optional name for named registration
303
304
  dispose_handler: Optional handler called when disposing service
304
-
305
+
305
306
  Examples:
306
307
  # Register with implementation class
307
308
  container.register_singleton(ILogger, ConsoleLogger)
308
-
309
+
309
310
  # Register with instance
310
311
  container.register_singleton(IConfig, instance=Config())
311
-
312
+
312
313
  # Register with disposal handler
313
314
  container.register_singleton(
314
315
  IDatabase,
@@ -323,15 +324,15 @@ class DIContainer(IServiceContainer):
323
324
  service_type=interface,
324
325
  implementation=implementation,
325
326
  instance=instance,
326
- lifetime=ServiceLifetime.SINGLETON
327
+ lifetime=ServiceLifetime.SINGLETON,
327
328
  )
328
329
  self._named_registrations[name] = registration
329
-
330
+
330
331
  # Also store the instance if provided
331
332
  if instance is not None:
332
333
  # Store with a composite key for retrieval
333
334
  named_key = (interface, name)
334
- if not hasattr(self, '_named_singletons'):
335
+ if not hasattr(self, "_named_singletons"):
335
336
  self._named_singletons = {}
336
337
  self._named_singletons[named_key] = instance
337
338
  else:
@@ -342,82 +343,86 @@ class DIContainer(IServiceContainer):
342
343
  # It's an instance passed as implementation (backward compatibility)
343
344
  self._register_internal(interface, instance=implementation)
344
345
  else:
345
- self._register_internal(interface, implementation, lifetime=ServiceLifetime.SINGLETON)
346
-
346
+ self._register_internal(
347
+ interface, implementation, lifetime=ServiceLifetime.SINGLETON
348
+ )
349
+
347
350
  # Handle disposal handler
348
351
  if dispose_handler:
349
352
  if name:
350
353
  # Store with composite key for named services
351
- if not hasattr(self, '_named_disposal_handlers'):
354
+ if not hasattr(self, "_named_disposal_handlers"):
352
355
  self._named_disposal_handlers = {}
353
356
  self._named_disposal_handlers[(interface, name)] = dispose_handler
354
357
  else:
355
358
  self._disposal_handlers[interface] = dispose_handler
356
-
359
+
357
360
  # Track initialization order for proper disposal
358
361
  key = (interface, name) if name else interface
359
362
  if key not in self._initialization_order:
360
363
  self._initialization_order.append(key)
361
-
364
+
362
365
  def register_scoped(
363
366
  self,
364
367
  interface: Type[T],
365
368
  implementation: Optional[Type[T]] = None,
366
- name: Optional[str] = None
369
+ name: Optional[str] = None,
367
370
  ) -> None:
368
371
  """
369
372
  Register a scoped service.
370
-
373
+
371
374
  Scoped services are created once per scope and shared within that scope.
372
-
375
+
373
376
  Args:
374
377
  interface: The interface/base type to register
375
378
  implementation: The concrete implementation
376
379
  name: Optional name for named registration
377
-
380
+
378
381
  Examples:
379
382
  # Register scoped service
380
383
  container.register_scoped(IRequestContext, RequestContext)
381
-
384
+
382
385
  # Use in scope
383
386
  with container.create_scope() as scope:
384
387
  context = container.get(IRequestContext) # Created
385
388
  context2 = container.get(IRequestContext) # Same instance
386
389
  """
387
- self._register_internal(interface, implementation, lifetime=ServiceLifetime.SCOPED)
390
+ self._register_internal(
391
+ interface, implementation, lifetime=ServiceLifetime.SCOPED
392
+ )
388
393
  if name:
389
394
  self._named_registrations[name] = self._registrations[interface]
390
-
395
+
391
396
  def register_transient(
392
- self,
393
- service_type: Type[T],
394
- implementation: Optional[Type[T]] = None
397
+ self, service_type: Type[T], implementation: Optional[Type[T]] = None
395
398
  ) -> None:
396
399
  """
397
400
  Register a transient service.
398
-
401
+
399
402
  Convenience method for registering transient services.
400
403
  """
401
- self._register_internal(service_type, implementation, lifetime=ServiceLifetime.TRANSIENT)
402
-
404
+ self._register_internal(
405
+ service_type, implementation, lifetime=ServiceLifetime.TRANSIENT
406
+ )
407
+
403
408
  def register_factory(
404
409
  self,
405
410
  interface: Type[T],
406
- factory: Callable[['DIContainer'], T],
411
+ factory: Callable[["DIContainer"], T],
407
412
  lifetime: ServiceLifetime = ServiceLifetime.TRANSIENT,
408
- name: Optional[str] = None
413
+ name: Optional[str] = None,
409
414
  ) -> None:
410
415
  """
411
416
  Register a service with a factory function.
412
-
417
+
413
418
  The factory receives the container as parameter for resolving dependencies.
414
-
419
+
415
420
  Args:
416
421
  interface: The interface/base type to register
417
422
  factory: Factory function that creates instances
418
423
  lifetime: Service lifetime (default: TRANSIENT for factories)
419
424
  name: Optional name for named registration
420
-
425
+
421
426
  Examples:
422
427
  # Register with factory
423
428
  container.register_factory(
@@ -430,29 +435,29 @@ class DIContainer(IServiceContainer):
430
435
  self._factories[interface] = factory
431
436
  if name:
432
437
  self._named_registrations[name] = self._registrations[interface]
433
-
438
+
434
439
  def get(self, interface: Type[T], name: Optional[str] = None) -> T:
435
440
  """
436
441
  Get service instance with dependency resolution.
437
-
442
+
438
443
  This is the primary method for retrieving services from the container.
439
444
  It handles all lifetime management and dependency resolution.
440
-
445
+
441
446
  Args:
442
447
  interface: The type to resolve
443
448
  name: Optional name for named registration lookup
444
-
449
+
445
450
  Returns:
446
451
  Instance of the requested service
447
-
452
+
448
453
  Raises:
449
454
  ServiceNotFoundError: If service is not registered
450
455
  CircularDependencyError: If circular dependencies detected
451
-
456
+
452
457
  Examples:
453
458
  # Get by interface
454
459
  logger = container.get(ILogger)
455
-
460
+
456
461
  # Get named service
457
462
  primary_db = container.get(IDatabase, name="primary")
458
463
  """
@@ -461,14 +466,19 @@ class DIContainer(IServiceContainer):
461
466
  suggestions = self._get_similar_names(name)
462
467
  raise ServiceNotFoundError(
463
468
  f"Named service '{name}' is not registered. "
464
- f"Did you mean: {', '.join(suggestions)}?" if suggestions else ""
469
+ f"Did you mean: {', '.join(suggestions)}?"
470
+ if suggestions
471
+ else ""
465
472
  )
466
-
473
+
467
474
  # Check if we have a pre-stored instance for this named service
468
475
  named_key = (interface, name)
469
- if hasattr(self, '_named_singletons') and named_key in self._named_singletons:
476
+ if (
477
+ hasattr(self, "_named_singletons")
478
+ and named_key in self._named_singletons
479
+ ):
470
480
  return self._named_singletons[named_key]
471
-
481
+
472
482
  # Otherwise resolve from named registration
473
483
  registration = self._named_registrations[name]
474
484
  if registration.instance is not None:
@@ -476,41 +486,46 @@ class DIContainer(IServiceContainer):
476
486
  elif registration.factory:
477
487
  return registration.factory(self)
478
488
  else:
479
- return self.create_instance(registration.implementation, registration.dependencies)
480
-
489
+ return self.create_instance(
490
+ registration.implementation, registration.dependencies
491
+ )
492
+
481
493
  return self._resolve_internal(interface)
482
-
494
+
483
495
  def resolve(self, service_type: Type[T]) -> T:
484
496
  """
485
497
  Resolve a service from the container (legacy method).
486
-
498
+
487
499
  This method is maintained for backward compatibility.
488
500
  New code should use get() instead.
489
-
501
+
490
502
  Args:
491
503
  service_type: The type to resolve
492
-
504
+
493
505
  Returns:
494
506
  Instance of the requested service
495
-
507
+
496
508
  Raises:
497
509
  ServiceNotFoundError: If service is not registered
498
510
  CircularDependencyError: If circular dependencies detected
499
511
  """
500
512
  return self.get(service_type)
501
-
513
+
502
514
  def _resolve_internal(self, service_type: Type[T]) -> T:
503
515
  """
504
516
  Internal method to resolve a service.
505
-
517
+
506
518
  Handles the actual resolution logic with proper locking and lifecycle management.
507
519
  """
508
520
  with self._lock:
509
521
  # Check for circular dependencies
510
522
  if service_type in self._resolving:
511
- cycle = " -> ".join(str(t.__name__) for t in self._resolving) + f" -> {service_type.__name__}"
523
+ cycle = (
524
+ " -> ".join(str(t.__name__) for t in self._resolving)
525
+ + f" -> {service_type.__name__}"
526
+ )
512
527
  raise CircularDependencyError(f"Circular dependency detected: {cycle}")
513
-
528
+
514
529
  # Check if registered
515
530
  if service_type not in self._registrations:
516
531
  suggestions = self._get_similar_types(service_type)
@@ -518,98 +533,105 @@ class DIContainer(IServiceContainer):
518
533
  if suggestions:
519
534
  error_msg += f" Did you mean: {', '.join(suggestions)}?"
520
535
  raise ServiceNotFoundError(error_msg)
521
-
536
+
522
537
  registration = self._registrations[service_type]
523
-
538
+
524
539
  # Handle different lifetimes
525
540
  if registration.lifetime == ServiceLifetime.SINGLETON:
526
541
  # Return existing singleton if available
527
542
  if service_type in self._singletons:
528
543
  return self._singletons[service_type]
529
-
544
+
530
545
  elif registration.lifetime == ServiceLifetime.SCOPED:
531
546
  # Check current scope
532
547
  if self._current_scope:
533
548
  instance = self._current_scope.get_scoped_instance(service_type)
534
549
  if instance is not None:
535
550
  return instance
536
-
551
+
537
552
  # Mark as resolving
538
553
  self._resolving.add(service_type)
539
-
554
+
540
555
  try:
541
556
  # Create instance
542
557
  instance = registration.create_instance(self)
543
-
558
+
544
559
  # Store based on lifetime
545
560
  if registration.lifetime == ServiceLifetime.SINGLETON:
546
561
  self._singletons[service_type] = instance
547
562
  if service_type not in self._initialization_order:
548
563
  self._initialization_order.append(service_type)
549
-
564
+
550
565
  elif registration.lifetime == ServiceLifetime.SCOPED:
551
566
  if self._current_scope:
552
567
  self._current_scope.set_scoped_instance(service_type, instance)
553
-
568
+
554
569
  # Call initialization hook if available
555
- if hasattr(instance, 'initialize'):
570
+ if hasattr(instance, "initialize"):
556
571
  try:
557
572
  instance.initialize()
558
573
  except Exception as e:
559
- logger.error(f"Failed to initialize service {service_type.__name__}: {e}")
574
+ logger.error(
575
+ f"Failed to initialize service {service_type.__name__}: {e}"
576
+ )
560
577
  raise
561
-
578
+
562
579
  return instance
563
-
580
+
564
581
  finally:
565
582
  self._resolving.remove(service_type)
566
-
567
- def resolve_optional(self, service_type: Type[T], default: Optional[T] = None) -> Optional[T]:
583
+
584
+ def resolve_optional(
585
+ self, service_type: Type[T], default: Optional[T] = None
586
+ ) -> Optional[T]:
568
587
  """
569
588
  Resolve a service if registered, otherwise return default.
570
-
589
+
571
590
  Useful for optional dependencies.
572
591
  """
573
592
  try:
574
593
  return self.resolve(service_type)
575
594
  except ServiceNotFoundError:
576
595
  return default
577
-
578
- def create_instance(self, cls: Type[T], explicit_deps: Optional[Dict[str, Type]] = None) -> T:
596
+
597
+ def create_instance(
598
+ self, cls: Type[T], explicit_deps: Optional[Dict[str, Type]] = None
599
+ ) -> T:
579
600
  """
580
601
  Create an instance of a class, resolving constructor dependencies.
581
-
602
+
582
603
  Args:
583
604
  cls: The class to instantiate
584
605
  explicit_deps: Explicit dependency mapping for constructor params
585
-
606
+
586
607
  Returns:
587
608
  New instance with resolved dependencies
588
609
  """
589
610
  # Get constructor signature
590
611
  sig = inspect.signature(cls.__init__)
591
612
  kwargs = {}
592
-
613
+
593
614
  for param_name, param in sig.parameters.items():
594
- if param_name == 'self':
615
+ if param_name == "self":
595
616
  continue
596
-
617
+
597
618
  # Check explicit dependencies first
598
619
  if explicit_deps and param_name in explicit_deps:
599
620
  dep_type = explicit_deps[param_name]
600
621
  kwargs[param_name] = self.resolve(dep_type)
601
622
  continue
602
-
623
+
603
624
  # Try to resolve by type annotation
604
625
  if param.annotation != param.empty:
605
626
  param_type = param.annotation
606
-
627
+
607
628
  # Handle string annotations (forward references)
608
629
  if isinstance(param_type, str):
609
630
  # Try to resolve forward reference
610
631
  try:
611
632
  # Get the module where the class is defined
612
633
  import sys
634
+
613
635
  frame = sys._getframe(1)
614
636
  module = frame.f_globals
615
637
  if param_type in module:
@@ -625,45 +647,52 @@ class DIContainer(IServiceContainer):
625
647
  if param.default != param.empty:
626
648
  kwargs[param_name] = param.default
627
649
  continue
628
-
650
+
629
651
  # Handle Optional types
630
- if hasattr(param_type, '__origin__') and param_type.__origin__ is Union:
652
+ if hasattr(param_type, "__origin__") and param_type.__origin__ is Union:
631
653
  # Get the non-None type from Optional
632
654
  args = param_type.__args__
633
- param_type = next((arg for arg in args if arg is not type(None)), None)
634
-
655
+ param_type = next(
656
+ (arg for arg in args if arg is not type(None)), None
657
+ )
658
+
635
659
  if param_type and param_type in self._registrations:
636
660
  # Check for circular dependency
637
661
  if param_type in self._resolving:
638
662
  # Circular dependency detected
639
- cycle = " -> ".join(str(t.__name__) for t in self._resolving) + f" -> {param_type.__name__}"
640
- raise CircularDependencyError(f"Circular dependency detected: {cycle}")
663
+ cycle = (
664
+ " -> ".join(str(t.__name__) for t in self._resolving)
665
+ + f" -> {param_type.__name__}"
666
+ )
667
+ raise CircularDependencyError(
668
+ f"Circular dependency detected: {cycle}"
669
+ )
641
670
  else:
642
671
  kwargs[param_name] = self.resolve(param_type)
643
672
  elif param.default != param.empty:
644
673
  # Use default value
645
674
  kwargs[param_name] = param.default
646
-
675
+
647
676
  return cls(**kwargs)
648
-
677
+
649
678
  def is_registered(self, service_type: Type) -> bool:
650
679
  """Check if a service type is registered."""
651
680
  return service_type in self._registrations
652
-
681
+
653
682
  def get_all_registrations(self) -> Dict[Type, ServiceRegistration]:
654
683
  """Get all service registrations."""
655
684
  with self._lock:
656
685
  return self._registrations.copy()
657
-
686
+
658
687
  def create_scope(self) -> ServiceScope:
659
688
  """
660
689
  Create a new service scope.
661
-
690
+
662
691
  Scoped services will be created once per scope and shared within that scope.
663
-
692
+
664
693
  Returns:
665
694
  New ServiceScope instance
666
-
695
+
667
696
  Examples:
668
697
  # Use scope with context manager
669
698
  with container.create_scope() as scope:
@@ -671,7 +700,7 @@ class DIContainer(IServiceContainer):
671
700
  service1 = container.get(IScopedService)
672
701
  service2 = container.get(IScopedService)
673
702
  assert service1 is service2 # Same instance
674
-
703
+
675
704
  # Scope is disposed, scoped instances are cleaned up
676
705
  """
677
706
  scope = ServiceScope(self)
@@ -680,30 +709,30 @@ class DIContainer(IServiceContainer):
680
709
  # Set as current scope for resolution
681
710
  old_scope = self._current_scope
682
711
  self._current_scope = scope
683
-
712
+
684
713
  # Return a context manager that restores old scope
685
714
  class ScopeContext:
686
715
  def __init__(self, container, new_scope, old_scope):
687
716
  self.container = container
688
717
  self.new_scope = new_scope
689
718
  self.old_scope = old_scope
690
-
719
+
691
720
  def __enter__(self):
692
721
  return self.new_scope
693
-
722
+
694
723
  def __exit__(self, exc_type, exc_val, exc_tb):
695
724
  with self.container._lock:
696
725
  self.container._current_scope = self.old_scope
697
726
  if self.new_scope in self.container._scopes:
698
727
  self.container._scopes.remove(self.new_scope)
699
728
  self.new_scope.dispose()
700
-
729
+
701
730
  return ScopeContext(self, scope, old_scope)
702
-
703
- def create_child_container(self) -> 'DIContainer':
731
+
732
+ def create_child_container(self) -> "DIContainer":
704
733
  """
705
734
  Create a child container that inherits registrations.
706
-
735
+
707
736
  Useful for isolated scenarios where you want separate singleton instances.
708
737
  """
709
738
  child = DIContainer()
@@ -718,11 +747,11 @@ class DIContainer(IServiceContainer):
718
747
  # Copy disposal handlers
719
748
  child._disposal_handlers = self._disposal_handlers.copy()
720
749
  return child
721
-
750
+
722
751
  def dispose(self) -> None:
723
752
  """
724
753
  Dispose of the container and all managed services.
725
-
754
+
726
755
  Calls disposal handlers for singleton services in reverse initialization order.
727
756
  Also disposes any active scopes.
728
757
  """
@@ -731,31 +760,35 @@ class DIContainer(IServiceContainer):
731
760
  for scope in reversed(self._scopes):
732
761
  scope.dispose()
733
762
  self._scopes.clear()
734
-
763
+
735
764
  # Dispose singletons in reverse initialization order
736
765
  for service_type in reversed(self._initialization_order):
737
766
  if service_type in self._singletons:
738
767
  instance = self._singletons[service_type]
739
-
768
+
740
769
  # Call disposal handler if registered
741
770
  if service_type in self._disposal_handlers:
742
771
  try:
743
772
  self._disposal_handlers[service_type](instance)
744
773
  except Exception as e:
745
- logger.error(f"Error in disposal handler for {service_type.__name__}: {e}")
746
-
774
+ logger.error(
775
+ f"Error in disposal handler for {service_type.__name__}: {e}"
776
+ )
777
+
747
778
  # Call dispose method if available
748
- elif hasattr(instance, 'dispose'):
779
+ elif hasattr(instance, "dispose"):
749
780
  try:
750
781
  instance.dispose()
751
782
  except Exception as e:
752
- logger.error(f"Error disposing service {service_type.__name__}: {e}")
753
-
783
+ logger.error(
784
+ f"Error disposing service {service_type.__name__}: {e}"
785
+ )
786
+
754
787
  # Clear everything
755
788
  self._singletons.clear()
756
789
  self._initialization_order.clear()
757
790
  self._current_scope = None
758
-
791
+
759
792
  def clear(self) -> None:
760
793
  """Clear all registrations and instances."""
761
794
  self.dispose()
@@ -765,28 +798,28 @@ class DIContainer(IServiceContainer):
765
798
  self._factories.clear()
766
799
  self._disposal_handlers.clear()
767
800
  self._resolving.clear()
768
-
801
+
769
802
  def _get_similar_types(self, service_type: Type) -> List[str]:
770
803
  """
771
804
  Get similar registered type names for better error messages.
772
-
805
+
773
806
  Uses simple string similarity to suggest possible alternatives.
774
807
  """
775
808
  if not self._registrations:
776
809
  return []
777
-
810
+
778
811
  type_name = service_type.__name__.lower()
779
812
  similar = []
780
-
813
+
781
814
  for registered_type in self._registrations.keys():
782
815
  registered_name = registered_type.__name__
783
816
  registered_lower = registered_name.lower()
784
-
817
+
785
818
  # Check for substring match
786
819
  if type_name in registered_lower or registered_lower in type_name:
787
820
  similar.append(registered_name)
788
821
  continue
789
-
822
+
790
823
  # Check for common prefix
791
824
  common_prefix_len = 0
792
825
  for i, (a, b) in enumerate(zip(type_name, registered_lower)):
@@ -794,30 +827,30 @@ class DIContainer(IServiceContainer):
794
827
  common_prefix_len = i + 1
795
828
  else:
796
829
  break
797
-
830
+
798
831
  if common_prefix_len >= min(3, len(type_name) // 2):
799
832
  similar.append(registered_name)
800
-
833
+
801
834
  return similar[:3] # Return top 3 suggestions
802
-
835
+
803
836
  def _get_similar_names(self, name: str) -> List[str]:
804
837
  """
805
838
  Get similar registered names for better error messages.
806
839
  """
807
840
  if not self._named_registrations:
808
841
  return []
809
-
842
+
810
843
  name_lower = name.lower()
811
844
  similar = []
812
-
845
+
813
846
  for registered_name in self._named_registrations.keys():
814
847
  registered_lower = registered_name.lower()
815
-
848
+
816
849
  # Check for substring match
817
850
  if name_lower in registered_lower or registered_lower in name_lower:
818
851
  similar.append(registered_name)
819
852
  continue
820
-
853
+
821
854
  # Check for common prefix
822
855
  common_prefix_len = 0
823
856
  for i, (a, b) in enumerate(zip(name_lower, registered_lower)):
@@ -825,10 +858,10 @@ class DIContainer(IServiceContainer):
825
858
  common_prefix_len = i + 1
826
859
  else:
827
860
  break
828
-
861
+
829
862
  if common_prefix_len >= min(3, len(name_lower) // 2):
830
863
  similar.append(registered_name)
831
-
864
+
832
865
  return similar[:3] # Return top 3 suggestions
833
866
 
834
867
 
@@ -840,7 +873,7 @@ _global_lock = threading.Lock()
840
873
  def get_container() -> DIContainer:
841
874
  """
842
875
  Get the global DI container instance.
843
-
876
+
844
877
  Creates one if it doesn't exist.
845
878
  """
846
879
  global _global_container
@@ -854,4 +887,4 @@ def set_container(container: DIContainer) -> None:
854
887
  """Set the global DI container instance."""
855
888
  global _global_container
856
889
  with _global_lock:
857
- _global_container = container
890
+ _global_container = container