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
@@ -7,11 +7,9 @@ with proper separation of concerns and reduced complexity.
7
7
  import os
8
8
  import subprocess
9
9
  import sys
10
- from pathlib import Path
11
- from typing import Optional, Dict, Any, Tuple
12
10
  import uuid
13
11
  from datetime import datetime
14
- import json
12
+ from typing import Any, Dict, Optional, Tuple
15
13
 
16
14
  from claude_mpm.core.logger import get_logger
17
15
 
@@ -19,19 +17,19 @@ from claude_mpm.core.logger import get_logger
19
17
  class InteractiveSession:
20
18
  """
21
19
  Handles interactive Claude sessions with proper separation of concerns.
22
-
20
+
23
21
  WHY: The original run_interactive() method had complexity of 39 and 262 lines.
24
22
  This class breaks down that functionality into smaller, focused methods with
25
23
  complexity <10 and lines <80 each, improving maintainability and testability.
26
-
24
+
27
25
  DESIGN DECISION: Uses composition over inheritance - takes ClaudeRunner as
28
26
  dependency rather than inheriting from it. This maintains loose coupling
29
27
  and makes testing easier while preserving all original functionality.
30
28
  """
31
-
29
+
32
30
  def __init__(self, runner):
33
31
  """Initialize interactive session handler.
34
-
32
+
35
33
  Args:
36
34
  runner: ClaudeRunner instance with all necessary services
37
35
  """
@@ -39,86 +37,93 @@ class InteractiveSession:
39
37
  self.logger = get_logger("interactive_session")
40
38
  self.session_id = None
41
39
  self.original_cwd = os.getcwd()
42
-
40
+
43
41
  # Initialize response tracking for interactive sessions
44
42
  # WHY: Interactive sessions need response logging just like oneshot sessions.
45
43
  # The hook system captures events, but we need the ResponseTracker to be
46
44
  # initialized to actually store them.
47
45
  self.response_tracker = None
48
-
46
+
49
47
  # Check if response logging is enabled in configuration
50
48
  try:
51
- response_config = self.runner.config.get('response_logging', {})
52
- response_logging_enabled = response_config.get('enabled', False)
49
+ response_config = self.runner.config.get("response_logging", {})
50
+ response_logging_enabled = response_config.get("enabled", False)
53
51
  except (AttributeError, TypeError):
54
52
  # Handle mock or missing config gracefully
55
53
  response_logging_enabled = False
56
-
54
+
57
55
  if response_logging_enabled:
58
56
  try:
59
57
  from claude_mpm.services.response_tracker import ResponseTracker
58
+
60
59
  self.response_tracker = ResponseTracker(self.runner.config)
61
- self.logger.info("Response tracking initialized for interactive session")
60
+ self.logger.info(
61
+ "Response tracking initialized for interactive session"
62
+ )
62
63
  except Exception as e:
63
64
  self.logger.warning(f"Failed to initialize response tracker: {e}")
64
65
  # Continue without response tracking - not fatal
65
-
66
+
66
67
  def initialize_interactive_session(self) -> Tuple[bool, Optional[str]]:
67
68
  """Initialize the interactive session environment.
68
-
69
+
69
70
  Sets up WebSocket connections, generates session IDs, and prepares
70
71
  the session for launch.
71
-
72
+
72
73
  Returns:
73
74
  Tuple of (success, error_message)
74
75
  """
75
76
  try:
76
77
  # Generate session ID
77
78
  self.session_id = str(uuid.uuid4())
78
-
79
+
79
80
  # Initialize WebSocket if enabled
80
81
  if self.runner.enable_websocket:
81
82
  success, error = self._initialize_websocket()
82
83
  if not success:
83
84
  self.logger.warning(f"WebSocket initialization failed: {error}")
84
85
  # Continue without WebSocket - not a fatal error
85
-
86
+
86
87
  # Display welcome message
87
88
  self._display_welcome_message()
88
-
89
+
89
90
  # Log session start
90
91
  if self.runner.project_logger:
91
92
  self.runner.project_logger.log_system(
92
- "Starting interactive session",
93
- level="INFO",
94
- component="session"
93
+ "Starting interactive session", level="INFO", component="session"
95
94
  )
96
-
97
- # Initialize response tracking session if enabled
98
- # WHY: The ResponseTracker needs to know about the session to properly
99
- # correlate prompts and responses during the interactive session.
95
+
100
96
  if self.response_tracker and self.response_tracker.enabled:
101
97
  try:
102
98
  # Set the session ID in the tracker for correlation
103
- if hasattr(self.response_tracker, 'session_logger') and self.response_tracker.session_logger:
104
- self.response_tracker.session_logger.set_session_id(self.session_id)
105
- self.logger.debug(f"Response tracker session ID set to: {self.session_id}")
99
+ if (
100
+ hasattr(self.response_tracker, "session_logger")
101
+ and self.response_tracker.session_logger
102
+ ):
103
+ self.response_tracker.session_logger.set_session_id(
104
+ self.session_id
105
+ )
106
+ self.logger.debug(
107
+ f"Response tracker session ID set to: {self.session_id}"
108
+ )
106
109
  except Exception as e:
107
- self.logger.debug(f"Could not set session ID in response tracker: {e}")
108
-
110
+ self.logger.debug(
111
+ f"Could not set session ID in response tracker: {e}"
112
+ )
113
+
109
114
  return True, None
110
-
115
+
111
116
  except Exception as e:
112
117
  error_msg = f"Failed to initialize session: {e}"
113
118
  self.logger.error(error_msg)
114
119
  return False, error_msg
115
-
120
+
116
121
  def setup_interactive_environment(self) -> Tuple[bool, Dict[str, Any]]:
117
122
  """Set up the interactive environment including agents and commands.
118
-
123
+
119
124
  Deploys system and project agents, prepares the command line,
120
125
  and sets up the execution environment.
121
-
126
+
122
127
  Returns:
123
128
  Tuple of (success, environment_dict)
124
129
  """
@@ -126,64 +131,63 @@ class InteractiveSession:
126
131
  # Deploy system agents
127
132
  if not self.runner.setup_agents():
128
133
  print("Continuing without native agents...")
129
-
134
+
130
135
  # Deploy project-specific agents
131
136
  self.runner.deploy_project_agents_to_claude()
132
-
137
+
133
138
  # Build command
134
139
  cmd = self._build_claude_command()
135
-
140
+
136
141
  # Prepare environment
137
142
  env = self._prepare_environment()
138
-
143
+
139
144
  # Change to user directory if needed
140
145
  self._change_to_user_directory(env)
141
-
146
+
142
147
  return True, {
143
- 'command': cmd,
144
- 'environment': env,
145
- 'session_id': self.session_id
148
+ "command": cmd,
149
+ "environment": env,
150
+ "session_id": self.session_id,
146
151
  }
147
-
152
+
148
153
  except Exception as e:
149
154
  error_msg = f"Failed to setup environment: {e}"
150
155
  self.logger.error(error_msg)
151
156
  return False, {}
152
-
157
+
153
158
  def handle_interactive_input(self, environment: Dict[str, Any]) -> bool:
154
159
  """Handle the interactive input/output loop.
155
-
160
+
156
161
  Launches Claude and manages the interactive session using either
157
162
  exec or subprocess method based on configuration.
158
-
163
+
159
164
  Args:
160
165
  environment: Dictionary with command, env vars, and session info
161
-
166
+
162
167
  Returns:
163
168
  bool: True if successful, False otherwise
164
169
  """
165
170
  try:
166
- cmd = environment['command']
167
- env = environment['environment']
168
-
171
+ cmd = environment["command"]
172
+ env = environment["environment"]
173
+
169
174
  print("Launching Claude...")
170
-
175
+
171
176
  # Log launch attempt
172
177
  self._log_launch_attempt(cmd)
173
-
178
+
174
179
  # Notify WebSocket if connected
175
180
  if self.runner.websocket_server:
176
181
  self.runner.websocket_server.claude_status_changed(
177
- status="starting",
178
- message="Launching Claude interactive session"
182
+ status="starting", message="Launching Claude interactive session"
179
183
  )
180
-
184
+
181
185
  # Launch using selected method
182
186
  if self.runner.launch_method == "subprocess":
183
187
  return self._launch_subprocess_mode(cmd, env)
184
188
  else:
185
189
  return self._launch_exec_mode(cmd, env)
186
-
190
+
187
191
  except FileNotFoundError as e:
188
192
  self._handle_launch_error("FileNotFoundError", e)
189
193
  return False
@@ -199,26 +203,26 @@ class InteractiveSession:
199
203
  except Exception as e:
200
204
  self._handle_launch_error("Exception", e)
201
205
  return self._attempt_fallback_launch(environment)
202
-
206
+
203
207
  def process_interactive_command(self, prompt: str) -> Optional[bool]:
204
208
  """Process special interactive commands like /agents.
205
-
209
+
206
210
  Args:
207
211
  prompt: User input command
208
-
212
+
209
213
  Returns:
210
214
  Optional[bool]: True if handled, False if error, None if not a special command
211
215
  """
212
216
  # Check for special commands
213
217
  if prompt.strip() == "/agents":
214
218
  return self._show_available_agents()
215
-
219
+
216
220
  # Not a special command
217
221
  return None
218
-
222
+
219
223
  def cleanup_interactive_session(self) -> None:
220
224
  """Clean up resources after interactive session ends.
221
-
225
+
222
226
  Restores original directory, closes connections, and logs session end.
223
227
  """
224
228
  try:
@@ -228,222 +232,227 @@ class InteractiveSession:
228
232
  os.chdir(self.original_cwd)
229
233
  except OSError:
230
234
  pass
231
-
235
+
232
236
  # Close WebSocket if connected
233
237
  if self.runner.websocket_server:
234
238
  self.runner.websocket_server.session_ended()
235
239
  self.runner.websocket_server = None
236
-
240
+
237
241
  # Log session end
238
242
  if self.runner.project_logger:
239
243
  self.runner.project_logger.log_system(
240
- "Interactive session ended",
241
- level="INFO",
242
- component="session"
244
+ "Interactive session ended", level="INFO", component="session"
243
245
  )
244
-
246
+
245
247
  # Log session event
246
248
  if self.runner.session_log_file:
247
- self.runner._log_session_event({
248
- "event": "session_end",
249
- "session_id": self.session_id
250
- })
251
-
252
- # Clean up response tracker if initialized
253
- # WHY: Ensure proper cleanup of response tracking resources and
254
- # finalize any pending response logs.
249
+ self.runner._log_session_event(
250
+ {"event": "session_end", "session_id": self.session_id}
251
+ )
252
+
255
253
  if self.response_tracker:
256
254
  try:
257
255
  # Clear the session ID to stop tracking this session
258
- if hasattr(self.response_tracker, 'session_logger') and self.response_tracker.session_logger:
256
+ if (
257
+ hasattr(self.response_tracker, "session_logger")
258
+ and self.response_tracker.session_logger
259
+ ):
259
260
  self.response_tracker.session_logger.set_session_id(None)
260
261
  self.logger.debug("Response tracker session cleared")
261
262
  except Exception as e:
262
263
  self.logger.debug(f"Error clearing response tracker session: {e}")
263
-
264
+
264
265
  except Exception as e:
265
266
  self.logger.debug(f"Error during cleanup: {e}")
266
-
267
+
267
268
  # Private helper methods (each <80 lines, complexity <10)
268
-
269
+
269
270
  def _initialize_websocket(self) -> Tuple[bool, Optional[str]]:
270
271
  """Initialize WebSocket connection for monitoring."""
271
272
  try:
272
273
  from claude_mpm.services.socketio_server import SocketIOClientProxy
273
- self.runner.websocket_server = SocketIOClientProxy(port=self.runner.websocket_port)
274
+
275
+ self.runner.websocket_server = SocketIOClientProxy(
276
+ port=self.runner.websocket_port
277
+ )
274
278
  self.runner.websocket_server.start()
275
279
  self.logger.info("Connected to Socket.IO monitoring server")
276
-
280
+
277
281
  # Notify session start
278
282
  self.runner.websocket_server.session_started(
279
283
  session_id=self.session_id,
280
284
  launch_method=self.runner.launch_method,
281
- working_dir=os.getcwd()
285
+ working_dir=os.getcwd(),
282
286
  )
283
287
  return True, None
284
-
288
+
285
289
  except ImportError as e:
286
290
  return False, f"Socket.IO module not available: {e}"
287
291
  except ConnectionError as e:
288
292
  return False, f"Cannot connect to Socket.IO server: {e}"
289
293
  except Exception as e:
290
294
  return False, f"Unexpected error with Socket.IO: {e}"
291
-
295
+
292
296
  def _display_welcome_message(self) -> None:
293
297
  """Display the interactive session welcome message."""
294
298
  version_str = self.runner._get_version()
295
-
299
+
296
300
  print("\033[32m╭───────────────────────────────────────────────────╮\033[0m")
297
- print("\033[32m│\033[0m ✻ Claude MPM - Interactive Session \033[32m│\033[0m")
301
+ print(
302
+ "\033[32m│\033[0m ✻ Claude MPM - Interactive Session \033[32m│\033[0m"
303
+ )
298
304
  print(f"\033[32m│\033[0m Version {version_str:<40}\033[32m│\033[0m")
299
305
  print("\033[32m│ │\033[0m")
300
- print("\033[32m│\033[0m Type '/agents' to see available agents \033[32m│\033[0m")
306
+ print(
307
+ "\033[32m│\033[0m Type '/agents' to see available agents \033[32m│\033[0m"
308
+ )
301
309
  print("\033[32m╰───────────────────────────────────────────────────╯\033[0m")
302
310
  print("") # Add blank line after box
303
-
311
+
304
312
  def _build_claude_command(self) -> list:
305
313
  """Build the Claude command with all necessary arguments."""
306
- cmd = [
307
- "claude",
308
- "--model", "opus",
309
- "--dangerously-skip-permissions"
310
- ]
311
-
314
+ cmd = ["claude", "--model", "opus", "--dangerously-skip-permissions"]
315
+
312
316
  # Add custom arguments
313
317
  if self.runner.claude_args:
314
318
  cmd.extend(self.runner.claude_args)
315
-
319
+
316
320
  # Add system instructions
317
321
  from claude_mpm.core.claude_runner import create_simple_context
322
+
318
323
  system_prompt = self.runner._create_system_prompt()
319
324
  if system_prompt and system_prompt != create_simple_context():
320
325
  cmd.extend(["--append-system-prompt", system_prompt])
321
-
326
+
322
327
  return cmd
323
-
328
+
324
329
  def _prepare_environment(self) -> dict:
325
330
  """Prepare clean environment variables for Claude."""
326
331
  clean_env = os.environ.copy()
327
-
332
+
328
333
  # Remove Claude-specific variables that might interfere
329
334
  claude_vars_to_remove = [
330
- 'CLAUDE_CODE_ENTRYPOINT', 'CLAUDECODE', 'CLAUDE_CONFIG_DIR',
331
- 'CLAUDE_MAX_PARALLEL_SUBAGENTS', 'CLAUDE_TIMEOUT'
335
+ "CLAUDE_CODE_ENTRYPOINT",
336
+ "CLAUDECODE",
337
+ "CLAUDE_CONFIG_DIR",
338
+ "CLAUDE_MAX_PARALLEL_SUBAGENTS",
339
+ "CLAUDE_TIMEOUT",
332
340
  ]
333
341
  for var in claude_vars_to_remove:
334
342
  clean_env.pop(var, None)
335
-
343
+
336
344
  return clean_env
337
-
345
+
338
346
  def _change_to_user_directory(self, env: dict) -> None:
339
347
  """Change to user's working directory if specified."""
340
- if 'CLAUDE_MPM_USER_PWD' in env:
341
- user_pwd = env['CLAUDE_MPM_USER_PWD']
342
- env['CLAUDE_WORKSPACE'] = user_pwd
343
-
348
+ if "CLAUDE_MPM_USER_PWD" in env:
349
+ user_pwd = env["CLAUDE_MPM_USER_PWD"]
350
+ env["CLAUDE_WORKSPACE"] = user_pwd
351
+
344
352
  try:
345
353
  os.chdir(user_pwd)
346
354
  self.logger.info(f"Changed working directory to: {user_pwd}")
347
355
  except (PermissionError, FileNotFoundError, OSError) as e:
348
356
  self.logger.warning(f"Could not change to directory {user_pwd}: {e}")
349
-
357
+
350
358
  def _log_launch_attempt(self, cmd: list) -> None:
351
359
  """Log the Claude launch attempt."""
352
360
  if self.runner.project_logger:
353
361
  self.runner.project_logger.log_system(
354
362
  f"Launching Claude interactive mode with {self.runner.launch_method}",
355
363
  level="INFO",
356
- component="session"
364
+ component="session",
357
365
  )
358
- self.runner._log_session_event({
359
- "event": "launching_claude_interactive",
360
- "command": " ".join(cmd),
361
- "method": self.runner.launch_method
362
- })
363
-
366
+ self.runner._log_session_event(
367
+ {
368
+ "event": "launching_claude_interactive",
369
+ "command": " ".join(cmd),
370
+ "method": self.runner.launch_method,
371
+ }
372
+ )
373
+
364
374
  def _launch_exec_mode(self, cmd: list, env: dict) -> bool:
365
375
  """Launch Claude using exec mode (replaces current process)."""
366
376
  # Notify WebSocket before exec
367
377
  if self.runner.websocket_server:
368
378
  self.runner.websocket_server.claude_status_changed(
369
- status="running",
370
- message="Claude process started (exec mode)"
379
+ status="running", message="Claude process started (exec mode)"
371
380
  )
372
-
381
+
373
382
  # This will not return if successful
374
383
  os.execvpe(cmd[0], cmd, env)
375
384
  return False # Only reached on failure
376
-
385
+
377
386
  def _launch_subprocess_mode(self, cmd: list, env: dict) -> bool:
378
387
  """Launch Claude as subprocess with PTY."""
379
388
  # Delegate to runner's existing method
380
389
  self.runner._launch_subprocess_interactive(cmd, env)
381
390
  return True
382
-
391
+
383
392
  def _handle_launch_error(self, error_type: str, error: Exception) -> None:
384
393
  """Handle errors during Claude launch."""
385
394
  error_messages = {
386
395
  "FileNotFoundError": "Claude CLI not found. Please ensure 'claude' is installed and in your PATH",
387
396
  "PermissionError": "Permission denied executing Claude CLI",
388
397
  "OSError": "OS error launching Claude",
389
- "Exception": "Unexpected error launching Claude"
398
+ "Exception": "Unexpected error launching Claude",
390
399
  }
391
-
400
+
392
401
  error_msg = f"{error_messages.get(error_type, 'Error')}: {error}"
393
402
  print(f"❌ {error_msg}")
394
-
403
+
395
404
  if self.runner.project_logger:
396
- self.runner.project_logger.log_system(error_msg, level="ERROR", component="session")
397
- self.runner._log_session_event({
398
- "event": "interactive_launch_failed",
399
- "error": str(error),
400
- "exception_type": error_type
401
- })
402
-
405
+ self.runner.project_logger.log_system(
406
+ error_msg, level="ERROR", component="session"
407
+ )
408
+ self.runner._log_session_event(
409
+ {
410
+ "event": "interactive_launch_failed",
411
+ "error": str(error),
412
+ "exception_type": error_type,
413
+ }
414
+ )
415
+
403
416
  # Notify WebSocket of error
404
417
  if self.runner.websocket_server:
405
418
  self.runner.websocket_server.claude_status_changed(
406
- status="error",
407
- message=f"Failed to launch Claude: {error}"
419
+ status="error", message=f"Failed to launch Claude: {error}"
408
420
  )
409
-
421
+
410
422
  def _handle_keyboard_interrupt(self) -> None:
411
423
  """Handle keyboard interrupt during session."""
412
424
  print("\n⚠️ Session interrupted by user")
413
-
425
+
414
426
  if self.runner.project_logger:
415
427
  self.runner.project_logger.log_system(
416
- "Session interrupted by user",
417
- level="INFO",
418
- component="session"
428
+ "Session interrupted by user", level="INFO", component="session"
429
+ )
430
+ self.runner._log_session_event(
431
+ {"event": "session_interrupted", "reason": "user_interrupt"}
419
432
  )
420
- self.runner._log_session_event({
421
- "event": "session_interrupted",
422
- "reason": "user_interrupt"
423
- })
424
-
433
+
425
434
  def _attempt_fallback_launch(self, environment: Dict[str, Any]) -> bool:
426
435
  """Attempt fallback launch using subprocess."""
427
436
  print("\n🔄 Attempting fallback launch method...")
428
-
437
+
429
438
  try:
430
- cmd = environment['command']
431
- env = environment['environment']
432
-
439
+ cmd = environment["command"]
440
+ env = environment["environment"]
441
+
433
442
  result = subprocess.run(cmd, stdin=None, stdout=None, stderr=None, env=env)
434
-
443
+
435
444
  if result.returncode == 0:
436
445
  if self.runner.project_logger:
437
446
  self.runner.project_logger.log_system(
438
447
  "Interactive session completed (subprocess fallback)",
439
448
  level="INFO",
440
- component="session"
449
+ component="session",
441
450
  )
442
451
  return True
443
452
  else:
444
453
  print(f"⚠️ Claude exited with code {result.returncode}")
445
454
  return False
446
-
455
+
447
456
  except FileNotFoundError:
448
457
  print("❌ Fallback failed: Claude CLI not found in PATH")
449
458
  print("\n💡 To fix this issue:")
@@ -456,24 +465,25 @@ class InteractiveSession:
456
465
  except Exception as e:
457
466
  print(f"❌ Fallback failed with unexpected error: {e}")
458
467
  return False
459
-
468
+
460
469
  def _show_available_agents(self) -> bool:
461
470
  """Show available agents in the system."""
462
471
  try:
463
472
  from claude_mpm.cli import _get_agent_versions_display
473
+
464
474
  agent_versions = _get_agent_versions_display()
465
-
475
+
466
476
  if agent_versions:
467
477
  print(agent_versions)
468
478
  else:
469
479
  print("No deployed agents found")
470
480
  print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
471
-
481
+
472
482
  return True
473
-
483
+
474
484
  except ImportError:
475
485
  print("Error: CLI module not available")
476
486
  return False
477
487
  except Exception as e:
478
488
  print(f"Error getting agent versions: {e}")
479
- return False
489
+ return False