claude-mpm 3.9.9__py3-none-any.whl → 4.0.3__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 (411) 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 +155 -0
  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 +1 -1
  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 +90 -49
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +21 -18
  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 +143 -762
  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 +203 -81
  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 +305 -197
  50. claude_mpm/cli/parser.py +24 -1150
  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 +104 -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 +217 -0
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +36 -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/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +571 -0
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +40 -23
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
  298. claude_mpm/services/mcp_gateway/main.py +307 -127
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
  303. claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +20 -534
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +9 -0
  358. claude_mpm/storage/state_storage.py +552 -0
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/config/memory_guardian_config.py +0 -325
  385. claude_mpm/core/config_paths.py +0 -150
  386. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  387. claude_mpm/deployment_paths.py +0 -261
  388. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  389. claude_mpm/models/state_models.py +0 -433
  390. claude_mpm/services/agent/__init__.py +0 -24
  391. claude_mpm/services/agent/deployment.py +0 -2548
  392. claude_mpm/services/agent/management.py +0 -598
  393. claude_mpm/services/agent/registry.py +0 -813
  394. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  395. claude_mpm/services/communication/socketio.py +0 -1935
  396. claude_mpm/services/communication/websocket.py +0 -479
  397. claude_mpm/services/framework_claude_md_generator.py +0 -624
  398. claude_mpm/services/health_monitor.py +0 -893
  399. claude_mpm/services/infrastructure/memory_guardian.py +0 -770
  400. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
  401. claude_mpm/services/optimized_hook_service.py +0 -542
  402. claude_mpm/services/project_analyzer.py +0 -864
  403. claude_mpm/services/project_registry.py +0 -608
  404. claude_mpm/services/standalone_socketio_server.py +0 -1300
  405. claude_mpm/services/ticket_manager_di.py +0 -318
  406. claude_mpm/services/ticketing_service_original.py +0 -510
  407. claude_mpm/utils/paths.py +0 -395
  408. claude_mpm/utils/platform_memory.py +0 -524
  409. claude_mpm-3.9.9.dist-info/RECORD +0 -293
  410. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  411. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -7,11 +7,12 @@ Tool adapters and implementations for the MCP Gateway service.
7
7
 
8
8
  from .base_adapter import (
9
9
  BaseToolAdapter,
10
- EchoToolAdapter,
11
10
  CalculatorToolAdapter,
11
+ EchoToolAdapter,
12
12
  SystemInfoToolAdapter,
13
13
  )
14
14
  from .document_summarizer import DocumentSummarizerTool
15
+ from .unified_ticket_tool import UnifiedTicketTool
15
16
 
16
17
  __all__ = [
17
18
  "BaseToolAdapter",
@@ -19,4 +20,5 @@ __all__ = [
19
20
  "CalculatorToolAdapter",
20
21
  "SystemInfoToolAdapter",
21
22
  "DocumentSummarizerTool",
22
- ]
23
+ "UnifiedTicketTool",
24
+ ]
@@ -7,47 +7,46 @@ Base class for MCP tool adapters and example implementations.
7
7
  Part of ISS-0035: MCP Server Implementation - Core Server and Tool Registry
8
8
  """
9
9
 
10
- from abc import ABC
11
- from typing import Any, Dict, Optional
12
- import json
13
10
  import traceback
11
+ from abc import ABC
14
12
  from datetime import datetime
13
+ from typing import Any, Dict, Optional
15
14
 
15
+ from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
16
16
  from claude_mpm.services.mcp_gateway.core.interfaces import (
17
17
  IMCPToolAdapter,
18
18
  MCPToolDefinition,
19
19
  MCPToolInvocation,
20
20
  MCPToolResult,
21
21
  )
22
- from claude_mpm.services.mcp_gateway.core.base import BaseMCPService
23
22
 
24
23
 
25
24
  class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
26
25
  """
27
26
  Base class for MCP tool adapters.
28
-
27
+
29
28
  WHY: This base class provides common functionality for all tool adapters,
30
29
  including parameter validation, error handling, and metrics tracking.
31
30
  Concrete tool implementations should extend this class.
32
-
31
+
33
32
  DESIGN DECISIONS:
34
33
  - Provide default parameter validation using JSON Schema
35
34
  - Include standard error handling and logging
36
35
  - Track execution metrics for monitoring
37
36
  - Support both sync and async tool implementations
38
37
  """
39
-
38
+
40
39
  def __init__(self, tool_definition: MCPToolDefinition):
41
40
  """
42
41
  Initialize the base tool adapter.
43
-
42
+
44
43
  Args:
45
44
  tool_definition: Tool definition with schema and metadata
46
45
  """
47
46
  super().__init__(f"Tool-{tool_definition.name}")
48
47
  self._definition = tool_definition
49
48
  self._initialized = False
50
-
49
+
51
50
  # Metrics
52
51
  self._metrics = {
53
52
  "invocations": 0,
@@ -56,28 +55,28 @@ class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
56
55
  "total_execution_time": 0.0,
57
56
  "average_execution_time": 0.0,
58
57
  "last_invocation": None,
59
- "last_error": None
58
+ "last_error": None,
60
59
  }
61
-
60
+
62
61
  def get_definition(self) -> MCPToolDefinition:
63
62
  """
64
63
  Get the tool definition.
65
-
64
+
66
65
  Returns:
67
66
  Tool definition with schema and metadata
68
67
  """
69
68
  return self._definition
70
-
69
+
71
70
  def validate_parameters(self, parameters: Dict[str, Any]) -> bool:
72
71
  """
73
72
  Validate tool parameters against schema.
74
-
73
+
75
74
  Default implementation performs basic JSON Schema validation.
76
75
  Override for custom validation logic.
77
-
76
+
78
77
  Args:
79
78
  parameters: Parameters to validate
80
-
79
+
81
80
  Returns:
82
81
  True if parameters are valid
83
82
  """
@@ -86,36 +85,38 @@ class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
86
85
  schema = self._definition.input_schema
87
86
  required = schema.get("required", [])
88
87
  properties = schema.get("properties", {})
89
-
88
+
90
89
  # Check required parameters
91
90
  for param in required:
92
91
  if param not in parameters:
93
92
  self.log_error(f"Missing required parameter: {param}")
94
93
  return False
95
-
94
+
96
95
  # Check parameter types (basic validation)
97
96
  for param_name, param_value in parameters.items():
98
97
  if param_name in properties:
99
98
  expected_type = properties[param_name].get("type")
100
99
  if expected_type:
101
100
  if not self._validate_type(param_value, expected_type):
102
- self.log_error(f"Invalid type for parameter {param_name}: expected {expected_type}")
101
+ self.log_error(
102
+ f"Invalid type for parameter {param_name}: expected {expected_type}"
103
+ )
103
104
  return False
104
-
105
+
105
106
  return True
106
-
107
+
107
108
  except Exception as e:
108
109
  self.log_error(f"Error validating parameters: {e}")
109
110
  return False
110
-
111
+
111
112
  def _validate_type(self, value: Any, expected_type: str) -> bool:
112
113
  """
113
114
  Validate a value against an expected JSON Schema type.
114
-
115
+
115
116
  Args:
116
117
  value: Value to validate
117
118
  expected_type: Expected type (string, number, boolean, array, object)
118
-
119
+
119
120
  Returns:
120
121
  True if type matches
121
122
  """
@@ -125,22 +126,22 @@ class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
125
126
  "boolean": bool,
126
127
  "array": list,
127
128
  "object": dict,
128
- "null": type(None)
129
+ "null": type(None),
129
130
  }
130
-
131
+
131
132
  expected_python_type = type_map.get(expected_type)
132
133
  if expected_python_type:
133
134
  return isinstance(value, expected_python_type)
134
-
135
+
135
136
  return True # Unknown type, allow it
136
-
137
+
137
138
  async def initialize(self) -> bool:
138
139
  """
139
140
  Initialize the tool adapter.
140
-
141
+
141
142
  Default implementation marks as initialized.
142
143
  Override for custom initialization logic.
143
-
144
+
144
145
  Returns:
145
146
  True if initialization successful
146
147
  """
@@ -148,49 +149,49 @@ class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
148
149
  self.log_info(f"Initializing tool: {self._definition.name}")
149
150
  self._initialized = True
150
151
  return True
151
-
152
+
152
153
  except Exception as e:
153
154
  self.log_error(f"Failed to initialize tool: {e}")
154
155
  return False
155
-
156
+
156
157
  async def shutdown(self) -> None:
157
158
  """
158
159
  Shutdown the tool adapter and clean up resources.
159
-
160
+
160
161
  Default implementation marks as not initialized.
161
162
  Override for custom cleanup logic.
162
163
  """
163
164
  try:
164
165
  self.log_info(f"Shutting down tool: {self._definition.name}")
165
166
  self._initialized = False
166
-
167
+
167
168
  except Exception as e:
168
169
  self.log_error(f"Error during tool shutdown: {e}")
169
-
170
+
170
171
  def get_metrics(self) -> Dict[str, Any]:
171
172
  """
172
173
  Get tool metrics.
173
-
174
+
174
175
  Returns:
175
176
  Metrics dictionary
176
177
  """
177
178
  return self._metrics.copy()
178
-
179
+
179
180
  def _update_metrics(self, success: bool, execution_time: float) -> None:
180
181
  """
181
182
  Update tool metrics after invocation.
182
-
183
+
183
184
  Args:
184
185
  success: Whether invocation was successful
185
186
  execution_time: Execution time in seconds
186
187
  """
187
188
  self._metrics["invocations"] += 1
188
-
189
+
189
190
  if success:
190
191
  self._metrics["successes"] += 1
191
192
  else:
192
193
  self._metrics["failures"] += 1
193
-
194
+
194
195
  self._metrics["total_execution_time"] += execution_time
195
196
  self._metrics["average_execution_time"] = (
196
197
  self._metrics["total_execution_time"] / self._metrics["invocations"]
@@ -201,10 +202,10 @@ class BaseToolAdapter(BaseMCPService, IMCPToolAdapter, ABC):
201
202
  class EchoToolAdapter(BaseToolAdapter):
202
203
  """
203
204
  Example tool adapter that echoes input back.
204
-
205
+
205
206
  This is a simple example showing how to implement a concrete tool adapter.
206
207
  """
207
-
208
+
208
209
  def __init__(self):
209
210
  """Initialize the echo tool."""
210
211
  definition = MCPToolDefinition(
@@ -213,73 +214,70 @@ class EchoToolAdapter(BaseToolAdapter):
213
214
  input_schema={
214
215
  "type": "object",
215
216
  "properties": {
216
- "message": {
217
- "type": "string",
218
- "description": "The message to echo"
219
- },
217
+ "message": {"type": "string", "description": "The message to echo"},
220
218
  "uppercase": {
221
219
  "type": "boolean",
222
220
  "description": "Whether to convert to uppercase",
223
- "default": False
224
- }
221
+ "default": False,
222
+ },
225
223
  },
226
- "required": ["message"]
227
- }
224
+ "required": ["message"],
225
+ },
228
226
  )
229
227
  super().__init__(definition)
230
-
228
+
231
229
  async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
232
230
  """
233
231
  Invoke the echo tool.
234
-
232
+
235
233
  Args:
236
234
  invocation: Tool invocation request
237
-
235
+
238
236
  Returns:
239
237
  Tool execution result with echoed message
240
238
  """
241
239
  start_time = datetime.now()
242
-
240
+
243
241
  try:
244
242
  # Get parameters
245
243
  message = invocation.parameters.get("message", "")
246
244
  uppercase = invocation.parameters.get("uppercase", False)
247
-
245
+
248
246
  # Process message
249
247
  result = message.upper() if uppercase else message
250
-
248
+
251
249
  # Calculate execution time
252
250
  execution_time = (datetime.now() - start_time).total_seconds()
253
-
251
+
254
252
  # Update metrics
255
253
  self._update_metrics(True, execution_time)
256
-
254
+
257
255
  return MCPToolResult(
258
256
  success=True,
259
257
  data=result,
260
258
  execution_time=execution_time,
261
- metadata={"tool": "echo", "length": len(result)}
259
+ metadata={"tool": "echo", "length": len(result)},
262
260
  )
263
-
261
+
264
262
  except Exception as e:
265
263
  execution_time = (datetime.now() - start_time).total_seconds()
266
264
  self._update_metrics(False, execution_time)
267
265
  self._metrics["last_error"] = str(e)
268
-
266
+
269
267
  return MCPToolResult(
270
268
  success=False,
271
269
  error=f"Echo tool failed: {str(e)}",
272
- execution_time=execution_time
270
+ execution_time=execution_time,
273
271
  )
274
272
 
275
273
 
276
274
  class CalculatorToolAdapter(BaseToolAdapter):
277
275
  """
278
276
  Example calculator tool adapter.
279
-
277
+
280
278
  Demonstrates a more complex tool with multiple operations.
281
279
  """
282
-
280
+
283
281
  def __init__(self):
284
282
  """Initialize the calculator tool."""
285
283
  definition = MCPToolDefinition(
@@ -291,53 +289,47 @@ class CalculatorToolAdapter(BaseToolAdapter):
291
289
  "operation": {
292
290
  "type": "string",
293
291
  "enum": ["add", "subtract", "multiply", "divide"],
294
- "description": "The mathematical operation to perform"
295
- },
296
- "a": {
297
- "type": "number",
298
- "description": "First operand"
292
+ "description": "The mathematical operation to perform",
299
293
  },
300
- "b": {
301
- "type": "number",
302
- "description": "Second operand"
303
- }
294
+ "a": {"type": "number", "description": "First operand"},
295
+ "b": {"type": "number", "description": "Second operand"},
304
296
  },
305
- "required": ["operation", "a", "b"]
297
+ "required": ["operation", "a", "b"],
306
298
  },
307
299
  output_schema={
308
300
  "type": "object",
309
301
  "properties": {
310
302
  "result": {
311
303
  "type": "number",
312
- "description": "The calculation result"
304
+ "description": "The calculation result",
313
305
  },
314
306
  "expression": {
315
307
  "type": "string",
316
- "description": "The mathematical expression"
317
- }
318
- }
319
- }
308
+ "description": "The mathematical expression",
309
+ },
310
+ },
311
+ },
320
312
  )
321
313
  super().__init__(definition)
322
-
314
+
323
315
  async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
324
316
  """
325
317
  Invoke the calculator tool.
326
-
318
+
327
319
  Args:
328
320
  invocation: Tool invocation request
329
-
321
+
330
322
  Returns:
331
323
  Tool execution result with calculation
332
324
  """
333
325
  start_time = datetime.now()
334
-
326
+
335
327
  try:
336
328
  # Get parameters
337
329
  operation = invocation.parameters["operation"]
338
330
  a = invocation.parameters["a"]
339
331
  b = invocation.parameters["b"]
340
-
332
+
341
333
  # Perform calculation
342
334
  if operation == "add":
343
335
  result = a + b
@@ -355,42 +347,39 @@ class CalculatorToolAdapter(BaseToolAdapter):
355
347
  expression = f"{a} / {b} = {result}"
356
348
  else:
357
349
  raise ValueError(f"Unknown operation: {operation}")
358
-
350
+
359
351
  # Calculate execution time
360
352
  execution_time = (datetime.now() - start_time).total_seconds()
361
-
353
+
362
354
  # Update metrics
363
355
  self._update_metrics(True, execution_time)
364
-
356
+
365
357
  return MCPToolResult(
366
358
  success=True,
367
- data={
368
- "result": result,
369
- "expression": expression
370
- },
359
+ data={"result": result, "expression": expression},
371
360
  execution_time=execution_time,
372
- metadata={"tool": "calculator", "operation": operation}
361
+ metadata={"tool": "calculator", "operation": operation},
373
362
  )
374
-
363
+
375
364
  except Exception as e:
376
365
  execution_time = (datetime.now() - start_time).total_seconds()
377
366
  self._update_metrics(False, execution_time)
378
367
  self._metrics["last_error"] = str(e)
379
-
368
+
380
369
  return MCPToolResult(
381
370
  success=False,
382
371
  error=f"Calculator tool failed: {str(e)}",
383
- execution_time=execution_time
372
+ execution_time=execution_time,
384
373
  )
385
374
 
386
375
 
387
376
  class SystemInfoToolAdapter(BaseToolAdapter):
388
377
  """
389
378
  Example system information tool adapter.
390
-
379
+
391
380
  Demonstrates async operations and system interaction.
392
381
  """
393
-
382
+
394
383
  def __init__(self):
395
384
  """Initialize the system info tool."""
396
385
  definition = MCPToolDefinition(
@@ -402,33 +391,33 @@ class SystemInfoToolAdapter(BaseToolAdapter):
402
391
  "info_type": {
403
392
  "type": "string",
404
393
  "enum": ["platform", "memory", "cpu", "time"],
405
- "description": "Type of system information to retrieve"
394
+ "description": "Type of system information to retrieve",
406
395
  }
407
396
  },
408
- "required": ["info_type"]
409
- }
397
+ "required": ["info_type"],
398
+ },
410
399
  )
411
400
  super().__init__(definition)
412
-
401
+
413
402
  async def invoke(self, invocation: MCPToolInvocation) -> MCPToolResult:
414
403
  """
415
404
  Invoke the system info tool.
416
-
405
+
417
406
  Args:
418
407
  invocation: Tool invocation request
419
-
408
+
420
409
  Returns:
421
410
  Tool execution result with system information
422
411
  """
423
412
  start_time = datetime.now()
424
-
413
+
425
414
  try:
426
415
  import platform
416
+
427
417
  import psutil
428
- from datetime import datetime
429
-
418
+
430
419
  info_type = invocation.parameters["info_type"]
431
-
420
+
432
421
  if info_type == "platform":
433
422
  result = {
434
423
  "system": platform.system(),
@@ -436,7 +425,7 @@ class SystemInfoToolAdapter(BaseToolAdapter):
436
425
  "version": platform.version(),
437
426
  "machine": platform.machine(),
438
427
  "processor": platform.processor(),
439
- "python_version": platform.python_version()
428
+ "python_version": platform.python_version(),
440
429
  }
441
430
  elif info_type == "memory":
442
431
  mem = psutil.virtual_memory()
@@ -445,53 +434,53 @@ class SystemInfoToolAdapter(BaseToolAdapter):
445
434
  "available": mem.available,
446
435
  "percent": mem.percent,
447
436
  "used": mem.used,
448
- "free": mem.free
437
+ "free": mem.free,
449
438
  }
450
439
  elif info_type == "cpu":
451
440
  result = {
452
441
  "count": psutil.cpu_count(),
453
442
  "percent": psutil.cpu_percent(interval=0.1),
454
- "freq": psutil.cpu_freq()._asdict() if psutil.cpu_freq() else None
443
+ "freq": psutil.cpu_freq()._asdict() if psutil.cpu_freq() else None,
455
444
  }
456
445
  elif info_type == "time":
457
446
  result = {
458
447
  "current": datetime.now().isoformat(),
459
448
  "timestamp": datetime.now().timestamp(),
460
- "timezone": str(datetime.now().astimezone().tzinfo)
449
+ "timezone": str(datetime.now().astimezone().tzinfo),
461
450
  }
462
451
  else:
463
452
  raise ValueError(f"Unknown info type: {info_type}")
464
-
453
+
465
454
  # Calculate execution time
466
455
  execution_time = (datetime.now() - start_time).total_seconds()
467
-
456
+
468
457
  # Update metrics
469
458
  self._update_metrics(True, execution_time)
470
-
459
+
471
460
  return MCPToolResult(
472
461
  success=True,
473
462
  data=result,
474
463
  execution_time=execution_time,
475
- metadata={"tool": "system_info", "info_type": info_type}
464
+ metadata={"tool": "system_info", "info_type": info_type},
476
465
  )
477
-
466
+
478
467
  except ImportError as e:
479
468
  # Handle missing psutil dependency gracefully
480
469
  execution_time = (datetime.now() - start_time).total_seconds()
481
470
  self._update_metrics(False, execution_time)
482
-
471
+
483
472
  return MCPToolResult(
484
473
  success=False,
485
474
  error=f"System info tool requires psutil: {str(e)}",
486
- execution_time=execution_time
475
+ execution_time=execution_time,
487
476
  )
488
477
  except Exception as e:
489
478
  execution_time = (datetime.now() - start_time).total_seconds()
490
479
  self._update_metrics(False, execution_time)
491
480
  self._metrics["last_error"] = str(e)
492
-
481
+
493
482
  return MCPToolResult(
494
483
  success=False,
495
484
  error=f"System info tool failed: {str(e)}",
496
- execution_time=execution_time
497
- )
485
+ execution_time=execution_time,
486
+ )