claude-mpm 4.1.1__py3-none-any.whl → 4.1.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 (389) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +280 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +22 -29
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +500 -680
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -17
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -12,6 +12,7 @@ WHY this is needed:
12
12
  - Ensures consistent event streaming to Socket.IO dashboard
13
13
  """
14
14
 
15
+ import contextlib
15
16
  import json
16
17
  import os
17
18
  import queue
@@ -22,7 +23,6 @@ from datetime import datetime
22
23
  from typing import Any, Dict, Optional
23
24
 
24
25
  from ..core.logger import get_logger
25
- from .config_constants import ConfigConstants
26
26
  from .hook_performance_config import get_hook_performance_config
27
27
  from .unified_paths import get_package_root
28
28
 
@@ -45,14 +45,16 @@ class HookManager:
45
45
  # Initialize background hook processing for async execution
46
46
  self.performance_config = get_hook_performance_config()
47
47
  queue_config = self.performance_config.get_queue_config()
48
- self.hook_queue = queue.Queue(maxsize=queue_config['maxsize'])
48
+ self.hook_queue = queue.Queue(maxsize=queue_config["maxsize"])
49
49
  self.background_thread = None
50
50
  self.shutdown_event = threading.Event()
51
51
 
52
52
  # Start background processing if hook handler is available
53
53
  if self.hook_handler_path:
54
54
  self._start_background_processor()
55
- self.logger.debug(f"Hook handler found with async processing: {self.hook_handler_path}")
55
+ self.logger.debug(
56
+ f"Hook handler found with async processing: {self.hook_handler_path}"
57
+ )
56
58
  else:
57
59
  self.logger.debug("Hook handler not found - hooks will be skipped")
58
60
 
@@ -68,6 +70,7 @@ class HookManager:
68
70
 
69
71
  def _start_background_processor(self):
70
72
  """Start background thread to process hooks asynchronously."""
73
+
71
74
  def process_hooks():
72
75
  """Background thread function to process hook queue."""
73
76
  while not self.shutdown_event.is_set():
@@ -88,9 +91,7 @@ class HookManager:
88
91
  self.logger.error(f"Hook processing error: {e}")
89
92
 
90
93
  self.background_thread = threading.Thread(
91
- target=process_hooks,
92
- name="hook-processor",
93
- daemon=True
94
+ target=process_hooks, name="hook-processor", daemon=True
94
95
  )
95
96
  self.background_thread.start()
96
97
  self.logger.debug("Started background hook processor thread")
@@ -98,14 +99,14 @@ class HookManager:
98
99
  def _execute_hook_sync(self, hook_data: Dict[str, Any]):
99
100
  """Execute a single hook synchronously in the background thread."""
100
101
  try:
101
- hook_type = hook_data['hook_type']
102
- event_data = hook_data['event_data']
102
+ hook_type = hook_data["hook_type"]
103
+ event_data = hook_data["event_data"]
103
104
 
104
105
  # Create the hook event
105
106
  hook_event = {
106
107
  "hook_event_name": hook_type,
107
108
  "session_id": self.session_id,
108
- "timestamp": hook_data.get('timestamp', datetime.utcnow().isoformat()),
109
+ "timestamp": hook_data.get("timestamp", datetime.utcnow().isoformat()),
109
110
  **event_data,
110
111
  }
111
112
 
@@ -121,6 +122,7 @@ class HookManager:
121
122
  capture_output=True,
122
123
  env=env,
123
124
  timeout=self.performance_config.background_timeout,
125
+ check=False,
124
126
  )
125
127
 
126
128
  if result.returncode != 0:
@@ -129,7 +131,9 @@ class HookManager:
129
131
  self.logger.debug(f"Hook stderr: {result.stderr}")
130
132
 
131
133
  except subprocess.TimeoutExpired:
132
- self.logger.debug(f"Hook {hook_data.get('hook_type', 'unknown')} timed out in background")
134
+ self.logger.debug(
135
+ f"Hook {hook_data.get('hook_type', 'unknown')} timed out in background"
136
+ )
133
137
  except Exception as e:
134
138
  self.logger.debug(f"Background hook execution error: {e}")
135
139
 
@@ -138,10 +142,8 @@ class HookManager:
138
142
  if self.background_thread and self.background_thread.is_alive():
139
143
  self.shutdown_event.set()
140
144
  # Signal shutdown by putting None in queue
141
- try:
145
+ with contextlib.suppress(queue.Full):
142
146
  self.hook_queue.put_nowait(None)
143
- except queue.Full:
144
- pass
145
147
 
146
148
  # Wait for thread to finish
147
149
  self.background_thread.join(timeout=2.0)
@@ -157,15 +159,14 @@ class HookManager:
157
159
 
158
160
  if hook_handler.exists():
159
161
  return hook_handler
160
- else:
161
- self.logger.warning(f"Hook handler not found at: {hook_handler}")
162
- return None
162
+ self.logger.warning(f"Hook handler not found at: {hook_handler}")
163
+ return None
163
164
  except Exception as e:
164
165
  self.logger.error(f"Error finding hook handler: {e}")
165
166
  return None
166
167
 
167
168
  def trigger_pre_tool_hook(
168
- self, tool_name: str, tool_args: Dict[str, Any] = None
169
+ self, tool_name: str, tool_args: Optional[Dict[str, Any]] = None
169
170
  ) -> bool:
170
171
  """Trigger PreToolUse hook event.
171
172
 
@@ -247,14 +248,16 @@ class HookManager:
247
248
  try:
248
249
  # Queue hook for background processing
249
250
  hook_data = {
250
- 'hook_type': hook_type,
251
- 'event_data': event_data,
252
- 'timestamp': datetime.utcnow().isoformat()
251
+ "hook_type": hook_type,
252
+ "event_data": event_data,
253
+ "timestamp": datetime.utcnow().isoformat(),
253
254
  }
254
255
 
255
256
  # Try to queue without blocking
256
257
  self.hook_queue.put_nowait(hook_data)
257
- self.logger.debug(f"Successfully queued {hook_type} hook for background processing")
258
+ self.logger.debug(
259
+ f"Successfully queued {hook_type} hook for background processing"
260
+ )
258
261
  return True
259
262
 
260
263
  except queue.Full:
@@ -276,6 +279,7 @@ def get_hook_manager() -> HookManager:
276
279
  _hook_manager = HookManager()
277
280
  # Register cleanup on exit
278
281
  import atexit
282
+
279
283
  atexit.register(_cleanup_hook_manager)
280
284
  return _hook_manager
281
285
 
@@ -290,7 +294,7 @@ def _cleanup_hook_manager():
290
294
 
291
295
  def trigger_tool_hooks(
292
296
  tool_name: str,
293
- tool_args: Dict[str, Any] = None,
297
+ tool_args: Optional[Dict[str, Any]] = None,
294
298
  result: Any = None,
295
299
  exit_code: int = 0,
296
300
  ):
@@ -10,72 +10,83 @@ from typing import Dict, Optional
10
10
 
11
11
  class HookPerformanceConfig:
12
12
  """Configuration for hook performance optimization."""
13
-
13
+
14
14
  def __init__(self):
15
15
  """Initialize hook performance configuration from environment."""
16
16
  self._load_config()
17
-
17
+
18
18
  def _load_config(self):
19
19
  """Load configuration from environment variables."""
20
20
  # Performance mode - disables all hooks for maximum speed
21
- self.performance_mode = os.getenv('CLAUDE_MPM_PERFORMANCE_MODE', 'false').lower() == 'true'
22
-
21
+ self.performance_mode = (
22
+ os.getenv("CLAUDE_MPM_PERFORMANCE_MODE", "false").lower() == "true"
23
+ )
24
+
23
25
  # Individual hook type controls
24
- self.enable_pre_tool_hooks = os.getenv('CLAUDE_MPM_HOOKS_PRE_TOOL', 'true').lower() == 'true'
25
- self.enable_post_tool_hooks = os.getenv('CLAUDE_MPM_HOOKS_POST_TOOL', 'true').lower() == 'true'
26
- self.enable_user_prompt_hooks = os.getenv('CLAUDE_MPM_HOOKS_USER_PROMPT', 'true').lower() == 'true'
27
- self.enable_delegation_hooks = os.getenv('CLAUDE_MPM_HOOKS_DELEGATION', 'true').lower() == 'true'
28
-
26
+ self.enable_pre_tool_hooks = (
27
+ os.getenv("CLAUDE_MPM_HOOKS_PRE_TOOL", "true").lower() == "true"
28
+ )
29
+ self.enable_post_tool_hooks = (
30
+ os.getenv("CLAUDE_MPM_HOOKS_POST_TOOL", "true").lower() == "true"
31
+ )
32
+ self.enable_user_prompt_hooks = (
33
+ os.getenv("CLAUDE_MPM_HOOKS_USER_PROMPT", "true").lower() == "true"
34
+ )
35
+ self.enable_delegation_hooks = (
36
+ os.getenv("CLAUDE_MPM_HOOKS_DELEGATION", "true").lower() == "true"
37
+ )
38
+
29
39
  # Background processing settings
30
- self.queue_size = int(os.getenv('CLAUDE_MPM_HOOK_QUEUE_SIZE', '1000'))
31
- self.background_timeout = float(os.getenv('CLAUDE_MPM_HOOK_BG_TIMEOUT', '2.0'))
32
-
40
+ self.queue_size = int(os.getenv("CLAUDE_MPM_HOOK_QUEUE_SIZE", "1000"))
41
+ self.background_timeout = float(os.getenv("CLAUDE_MPM_HOOK_BG_TIMEOUT", "2.0"))
42
+
33
43
  # Batching settings (for future implementation)
34
- self.enable_batching = os.getenv('CLAUDE_MPM_HOOK_BATCHING', 'false').lower() == 'true'
35
- self.batch_size = int(os.getenv('CLAUDE_MPM_HOOK_BATCH_SIZE', '10'))
36
- self.batch_timeout_ms = int(os.getenv('CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS', '100'))
37
-
44
+ self.enable_batching = (
45
+ os.getenv("CLAUDE_MPM_HOOK_BATCHING", "false").lower() == "true"
46
+ )
47
+ self.batch_size = int(os.getenv("CLAUDE_MPM_HOOK_BATCH_SIZE", "10"))
48
+ self.batch_timeout_ms = int(
49
+ os.getenv("CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS", "100")
50
+ )
51
+
38
52
  def is_hook_enabled(self, hook_type: str) -> bool:
39
53
  """Check if a specific hook type is enabled.
40
-
54
+
41
55
  Args:
42
56
  hook_type: Type of hook (PreToolUse, PostToolUse, UserPromptSubmit, etc.)
43
-
57
+
44
58
  Returns:
45
59
  bool: True if hook should be processed
46
60
  """
47
61
  if self.performance_mode:
48
62
  return False
49
-
63
+
50
64
  hook_type_lower = hook_type.lower()
51
-
52
- if 'pretool' in hook_type_lower or 'pre_tool' in hook_type_lower:
65
+
66
+ if "pretool" in hook_type_lower or "pre_tool" in hook_type_lower:
53
67
  return self.enable_pre_tool_hooks
54
- elif 'posttool' in hook_type_lower or 'post_tool' in hook_type_lower:
68
+ if "posttool" in hook_type_lower or "post_tool" in hook_type_lower:
55
69
  return self.enable_post_tool_hooks
56
- elif 'userprompt' in hook_type_lower or 'user_prompt' in hook_type_lower:
70
+ if "userprompt" in hook_type_lower or "user_prompt" in hook_type_lower:
57
71
  return self.enable_user_prompt_hooks
58
- elif 'delegation' in hook_type_lower:
72
+ if "delegation" in hook_type_lower:
59
73
  return self.enable_delegation_hooks
60
-
74
+
61
75
  # Default to enabled for unknown hook types
62
76
  return True
63
-
77
+
64
78
  def get_queue_config(self) -> Dict[str, int]:
65
79
  """Get queue configuration for background processing."""
66
- return {
67
- 'maxsize': self.queue_size,
68
- 'timeout': self.background_timeout
69
- }
70
-
80
+ return {"maxsize": self.queue_size, "timeout": self.background_timeout}
81
+
71
82
  def get_batch_config(self) -> Dict[str, any]:
72
83
  """Get batching configuration (for future use)."""
73
84
  return {
74
- 'enabled': self.enable_batching,
75
- 'batch_size': self.batch_size,
76
- 'timeout_ms': self.batch_timeout_ms
85
+ "enabled": self.enable_batching,
86
+ "batch_size": self.batch_size,
87
+ "timeout_ms": self.batch_timeout_ms,
77
88
  }
78
-
89
+
79
90
  def print_config(self) -> str:
80
91
  """Return a string representation of current configuration."""
81
92
  config_lines = [
@@ -106,11 +117,11 @@ def get_hook_performance_config() -> HookPerformanceConfig:
106
117
 
107
118
  def set_performance_mode(enabled: bool):
108
119
  """Enable or disable performance mode programmatically.
109
-
120
+
110
121
  Args:
111
122
  enabled: True to enable performance mode (disable all hooks)
112
123
  """
113
- os.environ['CLAUDE_MPM_PERFORMANCE_MODE'] = 'true' if enabled else 'false'
124
+ os.environ["CLAUDE_MPM_PERFORMANCE_MODE"] = "true" if enabled else "false"
114
125
  # Reload configuration
115
126
  global _hook_config
116
127
  _hook_config = None
@@ -123,14 +134,14 @@ def is_performance_mode() -> bool:
123
134
 
124
135
  # Environment variable documentation for users
125
136
  ENVIRONMENT_VARIABLES = {
126
- 'CLAUDE_MPM_PERFORMANCE_MODE': 'Set to "true" to disable all hooks for maximum performance',
127
- 'CLAUDE_MPM_HOOKS_PRE_TOOL': 'Set to "false" to disable pre-tool hooks',
128
- 'CLAUDE_MPM_HOOKS_POST_TOOL': 'Set to "false" to disable post-tool hooks',
129
- 'CLAUDE_MPM_HOOKS_USER_PROMPT': 'Set to "false" to disable user prompt hooks',
130
- 'CLAUDE_MPM_HOOKS_DELEGATION': 'Set to "false" to disable delegation hooks',
131
- 'CLAUDE_MPM_HOOK_QUEUE_SIZE': 'Maximum number of hooks in background queue (default: 1000)',
132
- 'CLAUDE_MPM_HOOK_BG_TIMEOUT': 'Timeout for background hook processing in seconds (default: 2.0)',
133
- 'CLAUDE_MPM_HOOK_BATCHING': 'Set to "true" to enable hook batching (experimental)',
134
- 'CLAUDE_MPM_HOOK_BATCH_SIZE': 'Number of hooks to batch together (default: 10)',
135
- 'CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS': 'Batch timeout in milliseconds (default: 100)',
137
+ "CLAUDE_MPM_PERFORMANCE_MODE": 'Set to "true" to disable all hooks for maximum performance',
138
+ "CLAUDE_MPM_HOOKS_PRE_TOOL": 'Set to "false" to disable pre-tool hooks',
139
+ "CLAUDE_MPM_HOOKS_POST_TOOL": 'Set to "false" to disable post-tool hooks',
140
+ "CLAUDE_MPM_HOOKS_USER_PROMPT": 'Set to "false" to disable user prompt hooks',
141
+ "CLAUDE_MPM_HOOKS_DELEGATION": 'Set to "false" to disable delegation hooks',
142
+ "CLAUDE_MPM_HOOK_QUEUE_SIZE": "Maximum number of hooks in background queue (default: 1000)",
143
+ "CLAUDE_MPM_HOOK_BG_TIMEOUT": "Timeout for background hook processing in seconds (default: 2.0)",
144
+ "CLAUDE_MPM_HOOK_BATCHING": 'Set to "true" to enable hook batching (experimental)',
145
+ "CLAUDE_MPM_HOOK_BATCH_SIZE": "Number of hooks to batch together (default: 10)",
146
+ "CLAUDE_MPM_HOOK_BATCH_TIMEOUT_MS": "Batch timeout in milliseconds (default: 100)",
136
147
  }
@@ -199,7 +199,7 @@ class InjectableService(BaseService, ABC):
199
199
  deps = []
200
200
  annotations = getattr(self.__class__, "__annotations__", {})
201
201
 
202
- for attr_name, attr_type in annotations.items():
202
+ for attr_name, _attr_type in annotations.items():
203
203
  if hasattr(self, attr_name) and not attr_name.startswith("_"):
204
204
  deps.append(
205
205
  f"{attr_name}={getattr(self, attr_name).__class__.__name__}"
@@ -4,11 +4,10 @@ This module provides the InteractiveSession class that manages Claude's interact
4
4
  with proper separation of concerns and reduced complexity.
5
5
  """
6
6
 
7
+ import contextlib
7
8
  import os
8
9
  import subprocess
9
- import sys
10
10
  import uuid
11
- from datetime import datetime
12
11
  from typing import Any, Dict, Optional, Tuple
13
12
 
14
13
  from claude_mpm.core.logger import get_logger
@@ -134,7 +133,6 @@ class InteractiveSession:
134
133
 
135
134
  # Deploy project-specific agents
136
135
  self.runner.deploy_project_agents_to_claude()
137
-
138
136
 
139
137
  # Build command
140
138
  cmd = self._build_claude_command()
@@ -186,8 +184,7 @@ class InteractiveSession:
186
184
  # Launch using selected method
187
185
  if self.runner.launch_method == "subprocess":
188
186
  return self._launch_subprocess_mode(cmd, env)
189
- else:
190
- return self._launch_exec_mode(cmd, env)
187
+ return self._launch_exec_mode(cmd, env)
191
188
 
192
189
  except FileNotFoundError as e:
193
190
  self._handle_launch_error("FileNotFoundError", e)
@@ -206,7 +203,11 @@ class InteractiveSession:
206
203
  return self._attempt_fallback_launch(environment)
207
204
 
208
205
  def process_interactive_command(self, prompt: str) -> Optional[bool]:
209
- """Process special interactive commands like /agents and /mpm-doctor.
206
+ """Process special interactive commands.
207
+
208
+ NOTE: As of v4.1.2, MPM slash commands are deployed as markdown files
209
+ to ~/.claude/commands and handled directly by Claude Code.
210
+ This method is kept for potential future use with non-Claude commands.
210
211
 
211
212
  Args:
212
213
  prompt: User input command
@@ -214,21 +215,7 @@ class InteractiveSession:
214
215
  Returns:
215
216
  Optional[bool]: True if handled, False if error, None if not a special command
216
217
  """
217
- # Parse command and arguments
218
- parts = prompt.strip().split()
219
- if not parts:
220
- return None
221
-
222
- command = parts[0]
223
- args = parts[1:]
224
-
225
- # Check for special commands
226
- if command == "/agents":
227
- return self._show_available_agents()
228
- elif command == "/mpm-doctor":
229
- return self._run_doctor_diagnostics(args)
230
-
231
- # Not a special command
218
+ # Currently no commands are intercepted - all MPM commands are handled by Claude Code
232
219
  return None
233
220
 
234
221
  def cleanup_interactive_session(self) -> None:
@@ -239,10 +226,8 @@ class InteractiveSession:
239
226
  try:
240
227
  # Restore original directory
241
228
  if self.original_cwd and os.path.exists(self.original_cwd):
242
- try:
229
+ with contextlib.suppress(OSError):
243
230
  os.chdir(self.original_cwd)
244
- except OSError:
245
- pass
246
231
 
247
232
  # Close WebSocket if connected
248
233
  if self.runner.websocket_server:
@@ -307,7 +292,7 @@ class InteractiveSession:
307
292
  def _display_welcome_message(self) -> None:
308
293
  """Display the interactive session welcome message."""
309
294
  version_str = self.runner._get_version()
310
-
295
+
311
296
  # Get output style status
312
297
  output_style_info = self._get_output_style_info()
313
298
 
@@ -320,40 +305,47 @@ class InteractiveSession:
320
305
  print(f"\033[32m│\033[0m {output_style_info:<49}\033[32m│\033[0m")
321
306
  print("\033[32m│ │\033[0m")
322
307
  print(
323
- "\033[32m│\033[0m Commands: \033[32m│\033[0m"
308
+ "\033[32m│\033[0m MPM Commands (via Claude Code): \033[32m│\033[0m"
309
+ )
310
+ print(
311
+ "\033[32m│\033[0m /mpm - MPM overview and help \033[32m│\033[0m"
324
312
  )
325
313
  print(
326
- "\033[32m│\033[0m /agents - Show available agents \033[32m│\033[0m"
314
+ "\033[32m│\033[0m /mpm-agents - Show available agents \033[32m│\033[0m"
327
315
  )
328
316
  print(
329
- "\033[32m│\033[0m /mpm-doctor - Run diagnostic checks \033[32m│\033[0m"
317
+ "\033[32m│\033[0m /mpm-doctor - Run diagnostic checks \033[32m│\033[0m"
330
318
  )
319
+ print(
320
+ "\033[32m│\033[0m Type / for autocomplete in Claude Code \033[32m│\033[0m"
321
+ )
322
+
331
323
  print("\033[32m╰───────────────────────────────────────────────────╯\033[0m")
332
324
  print("") # Add blank line after box
333
-
334
-
325
+
335
326
  def _get_output_style_info(self) -> Optional[str]:
336
327
  """Get output style status for display."""
337
328
  try:
338
329
  # Check if output style manager is available through framework loader
339
- if hasattr(self.runner, 'framework_loader') and self.runner.framework_loader:
340
- if hasattr(self.runner.framework_loader, 'output_style_manager'):
341
- osm = self.runner.framework_loader.output_style_manager
342
- if osm:
343
- if osm.claude_version and osm.supports_output_styles():
344
- # Check if claude-mpm style is active
345
- settings_file = osm.settings_file
346
- if settings_file.exists():
347
- import json
348
- settings = json.loads(settings_file.read_text())
349
- active_style = settings.get("activeOutputStyle")
350
- if active_style == "claude-mpm":
351
- return "Output Style: claude-mpm ✅"
352
- else:
353
- return f"Output Style: {active_style or 'none'}"
354
- return "Output Style: Available"
355
- else:
356
- return "Output Style: Injected (legacy)"
330
+ if (
331
+ hasattr(self.runner, "framework_loader")
332
+ and self.runner.framework_loader
333
+ ) and hasattr(self.runner.framework_loader, "output_style_manager"):
334
+ osm = self.runner.framework_loader.output_style_manager
335
+ if osm:
336
+ if osm.claude_version and osm.supports_output_styles():
337
+ # Check if claude-mpm style is active
338
+ settings_file = osm.settings_file
339
+ if settings_file.exists():
340
+ import json
341
+
342
+ settings = json.loads(settings_file.read_text())
343
+ active_style = settings.get("activeOutputStyle")
344
+ if active_style == "claude-mpm":
345
+ return "Output Style: claude-mpm ✅"
346
+ return f"Output Style: {active_style or 'none'}"
347
+ return "Output Style: Available"
348
+ return "Output Style: Injected (legacy)"
357
349
  except Exception:
358
350
  pass
359
351
  return None
@@ -365,7 +357,9 @@ class InteractiveSession:
365
357
 
366
358
  if has_resume:
367
359
  # When resuming, use minimal command to avoid interfering with conversation selection
368
- self.logger.info("🔄 Resume mode detected - using minimal Claude command to preserve conversation selection")
360
+ self.logger.info(
361
+ "🔄 Resume mode detected - using minimal Claude command to preserve conversation selection"
362
+ )
369
363
  cmd = ["claude"]
370
364
 
371
365
  # Add only the claude_args (which includes --resume)
@@ -374,26 +368,25 @@ class InteractiveSession:
374
368
  self.logger.info(f"Resume command: {cmd}")
375
369
 
376
370
  return cmd
377
- else:
378
- # Normal mode - full command with all claude-mpm enhancements
379
- cmd = ["claude", "--model", "opus", "--dangerously-skip-permissions"]
371
+ # Normal mode - full command with all claude-mpm enhancements
372
+ cmd = ["claude", "--model", "opus", "--dangerously-skip-permissions"]
380
373
 
381
- # Add custom arguments
382
- if self.runner.claude_args:
383
- # Enhanced debug logging for --resume flag verification
384
- self.logger.debug(f"Raw claude_args received: {self.runner.claude_args}")
385
- cmd.extend(self.runner.claude_args)
374
+ # Add custom arguments
375
+ if self.runner.claude_args:
376
+ # Enhanced debug logging for --resume flag verification
377
+ self.logger.debug(f"Raw claude_args received: {self.runner.claude_args}")
378
+ cmd.extend(self.runner.claude_args)
386
379
 
387
- # Add system instructions
388
- from claude_mpm.core.claude_runner import create_simple_context
380
+ # Add system instructions
381
+ from claude_mpm.core.claude_runner import create_simple_context
389
382
 
390
- system_prompt = self.runner._create_system_prompt()
391
- if system_prompt and system_prompt != create_simple_context():
392
- cmd.extend(["--append-system-prompt", system_prompt])
383
+ system_prompt = self.runner._create_system_prompt()
384
+ if system_prompt and system_prompt != create_simple_context():
385
+ cmd.extend(["--append-system-prompt", system_prompt])
393
386
 
394
387
  # Final command verification
395
388
  # self.logger.info(f"Final Claude command built: {' '.join(cmd)}")
396
-
389
+
397
390
  # Explicit --resume flag verification
398
391
  if "--resume" in cmd:
399
392
  self.logger.info("✅ VERIFIED: --resume flag IS included in final command")
@@ -520,7 +513,9 @@ class InteractiveSession:
520
513
  cmd = environment["command"]
521
514
  env = environment["environment"]
522
515
 
523
- result = subprocess.run(cmd, stdin=None, stdout=None, stderr=None, env=env)
516
+ result = subprocess.run(
517
+ cmd, stdin=None, stdout=None, stderr=None, env=env, check=False
518
+ )
524
519
 
525
520
  if result.returncode == 0:
526
521
  if self.runner.project_logger:
@@ -530,9 +525,8 @@ class InteractiveSession:
530
525
  component="session",
531
526
  )
532
527
  return True
533
- else:
534
- print(f"⚠️ Claude exited with code {result.returncode}")
535
- return False
528
+ print(f"⚠️ Claude exited with code {result.returncode}")
529
+ return False
536
530
 
537
531
  except FileNotFoundError:
538
532
  print("❌ Fallback failed: Claude CLI not found in PATH")
@@ -546,88 +540,3 @@ class InteractiveSession:
546
540
  except Exception as e:
547
541
  print(f"❌ Fallback failed with unexpected error: {e}")
548
542
  return False
549
-
550
- def _show_available_agents(self) -> bool:
551
- """Show available agents in the system."""
552
- try:
553
- from claude_mpm.cli.utils import get_agent_versions_display
554
-
555
- agent_versions = get_agent_versions_display()
556
-
557
- if agent_versions:
558
- print(agent_versions)
559
- else:
560
- print("No deployed agents found")
561
- print("\nTo deploy agents, run: claude-mpm --mpm:agents deploy")
562
-
563
- return True
564
-
565
- except ImportError:
566
- print("Error: CLI module not available")
567
- return False
568
- except Exception as e:
569
- print(f"Error getting agent versions: {e}")
570
- return False
571
-
572
- def _run_doctor_diagnostics(self, args: list) -> bool:
573
- """Run doctor diagnostics from interactive mode.
574
-
575
- Args:
576
- args: Command arguments (e.g., ['--verbose'])
577
-
578
- Returns:
579
- bool: True if successful, False otherwise
580
- """
581
- try:
582
- from claude_mpm.services.diagnostics import DiagnosticRunner, DoctorReporter
583
-
584
- # Parse arguments
585
- verbose = "--verbose" in args or "-v" in args
586
- no_color = "--no-color" in args
587
-
588
- # Print header
589
- print("\n" + "="*60)
590
- print("Claude MPM Doctor Report")
591
- print("="*60)
592
-
593
- # Create diagnostic runner
594
- runner = DiagnosticRunner(verbose=verbose)
595
-
596
- # Run diagnostics
597
- try:
598
- summary = runner.run_diagnostics()
599
- except KeyboardInterrupt:
600
- print("\nDiagnostics interrupted by user")
601
- return False
602
- except Exception as e:
603
- print(f"\n❌ Diagnostic failed: {str(e)}")
604
- if verbose:
605
- import traceback
606
- traceback.print_exc()
607
- return False
608
-
609
- # Create reporter
610
- reporter = DoctorReporter(
611
- use_color=not no_color,
612
- verbose=verbose
613
- )
614
-
615
- # Display results in terminal format
616
- reporter.report(summary, format="terminal")
617
-
618
- # Return based on status
619
- if summary.error_count > 0:
620
- return False
621
-
622
- return True
623
-
624
- except ImportError as e:
625
- print(f"Error: Diagnostics module not available: {e}")
626
- print("Please ensure claude-mpm is properly installed")
627
- return False
628
- except Exception as e:
629
- print(f"Error running diagnostics: {e}")
630
- if "--verbose" in args or "-v" in args:
631
- import traceback
632
- traceback.print_exc()
633
- return False