claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__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 (357) 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/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +50 -2
  21. claude_mpm/cli/__init__.py +51 -46
  22. claude_mpm/cli/__main__.py +1 -1
  23. claude_mpm/cli/commands/__init__.py +10 -12
  24. claude_mpm/cli/commands/agent_manager.py +186 -181
  25. claude_mpm/cli/commands/agents.py +271 -268
  26. claude_mpm/cli/commands/aggregate.py +30 -29
  27. claude_mpm/cli/commands/cleanup.py +50 -44
  28. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  29. claude_mpm/cli/commands/config.py +162 -127
  30. claude_mpm/cli/commands/doctor.py +52 -62
  31. claude_mpm/cli/commands/info.py +37 -25
  32. claude_mpm/cli/commands/mcp.py +3 -7
  33. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  34. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  35. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  36. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  37. claude_mpm/cli/commands/memory.py +192 -141
  38. claude_mpm/cli/commands/monitor.py +117 -88
  39. claude_mpm/cli/commands/run.py +120 -84
  40. claude_mpm/cli/commands/run_config_checker.py +4 -5
  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 +204 -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 +20 -23
  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 +581 -280
  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 -15
  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 +93 -38
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  117. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  118. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  119. claude_mpm/hooks/memory_integration_hook.py +5 -5
  120. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  121. claude_mpm/hooks/validation_hooks.py +4 -4
  122. claude_mpm/init.py +4 -9
  123. claude_mpm/models/__init__.py +2 -2
  124. claude_mpm/models/agent_session.py +11 -14
  125. claude_mpm/scripts/mcp_server.py +20 -11
  126. claude_mpm/scripts/mcp_wrapper.py +5 -5
  127. claude_mpm/scripts/mpm_doctor.py +321 -0
  128. claude_mpm/scripts/socketio_daemon.py +28 -25
  129. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  130. claude_mpm/scripts/socketio_server_manager.py +116 -95
  131. claude_mpm/services/__init__.py +49 -49
  132. claude_mpm/services/agent_capabilities_service.py +12 -18
  133. claude_mpm/services/agents/__init__.py +22 -22
  134. claude_mpm/services/agents/agent_builder.py +140 -119
  135. claude_mpm/services/agents/deployment/__init__.py +3 -3
  136. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  137. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  138. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  139. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  140. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  141. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  142. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  143. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  144. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  145. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  146. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  147. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  148. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  149. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  150. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  151. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  152. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  153. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  154. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  155. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  156. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  157. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  158. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  159. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  161. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  162. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  163. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  164. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  167. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  168. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  169. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  170. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  172. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  173. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  175. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  176. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  177. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  178. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  179. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  180. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  181. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  182. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  183. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  184. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  186. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  187. claude_mpm/services/agents/loading/__init__.py +1 -1
  188. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  189. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  190. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  191. claude_mpm/services/agents/management/__init__.py +1 -1
  192. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  193. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  194. claude_mpm/services/agents/memory/__init__.py +4 -4
  195. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  196. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  197. claude_mpm/services/agents/memory/content_manager.py +44 -38
  198. claude_mpm/services/agents/memory/template_generator.py +4 -6
  199. claude_mpm/services/agents/registry/__init__.py +10 -6
  200. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  201. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  202. claude_mpm/services/async_session_logger.py +1 -2
  203. claude_mpm/services/claude_session_logger.py +1 -2
  204. claude_mpm/services/command_deployment_service.py +173 -0
  205. claude_mpm/services/command_handler_service.py +20 -22
  206. claude_mpm/services/core/__init__.py +25 -25
  207. claude_mpm/services/core/base.py +0 -5
  208. claude_mpm/services/core/interfaces/__init__.py +32 -32
  209. claude_mpm/services/core/interfaces/agent.py +0 -21
  210. claude_mpm/services/core/interfaces/communication.py +0 -27
  211. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  212. claude_mpm/services/core/interfaces/service.py +0 -29
  213. claude_mpm/services/diagnostics/__init__.py +1 -1
  214. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  215. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  216. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  217. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  218. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  219. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  220. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  221. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  222. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  223. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  224. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  225. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  226. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  227. claude_mpm/services/diagnostics/models.py +21 -19
  228. claude_mpm/services/event_aggregator.py +10 -17
  229. claude_mpm/services/event_bus/__init__.py +1 -1
  230. claude_mpm/services/event_bus/config.py +54 -35
  231. claude_mpm/services/event_bus/event_bus.py +76 -71
  232. claude_mpm/services/event_bus/relay.py +74 -64
  233. claude_mpm/services/events/__init__.py +11 -11
  234. claude_mpm/services/events/consumers/__init__.py +3 -3
  235. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  236. claude_mpm/services/events/consumers/logging.py +39 -37
  237. claude_mpm/services/events/consumers/metrics.py +56 -57
  238. claude_mpm/services/events/consumers/socketio.py +82 -81
  239. claude_mpm/services/events/core.py +110 -99
  240. claude_mpm/services/events/interfaces.py +56 -72
  241. claude_mpm/services/events/producers/__init__.py +1 -1
  242. claude_mpm/services/events/producers/hook.py +38 -38
  243. claude_mpm/services/events/producers/system.py +46 -44
  244. claude_mpm/services/exceptions.py +81 -80
  245. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  246. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  247. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  248. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  249. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  250. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  251. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  252. claude_mpm/services/hook_service.py +6 -9
  253. claude_mpm/services/infrastructure/__init__.py +1 -1
  254. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  255. claude_mpm/services/infrastructure/monitoring.py +21 -23
  256. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  257. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  258. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  259. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  260. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  261. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  262. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  263. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  264. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  265. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  266. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  267. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  268. claude_mpm/services/mcp_gateway/main.py +2 -1
  269. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  270. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  271. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  273. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  274. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  275. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  276. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  277. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  278. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  279. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  280. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  281. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  282. claude_mpm/services/memory/__init__.py +3 -3
  283. claude_mpm/services/memory/builder.py +3 -6
  284. claude_mpm/services/memory/cache/__init__.py +1 -1
  285. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  286. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  287. claude_mpm/services/memory/indexed_memory.py +5 -7
  288. claude_mpm/services/memory/optimizer.py +7 -10
  289. claude_mpm/services/memory/router.py +8 -9
  290. claude_mpm/services/memory_hook_service.py +48 -34
  291. claude_mpm/services/monitor_build_service.py +77 -73
  292. claude_mpm/services/port_manager.py +130 -108
  293. claude_mpm/services/project/analyzer.py +12 -10
  294. claude_mpm/services/project/registry.py +11 -11
  295. claude_mpm/services/recovery_manager.py +10 -19
  296. claude_mpm/services/response_tracker.py +0 -1
  297. claude_mpm/services/runner_configuration_service.py +19 -20
  298. claude_mpm/services/session_management_service.py +7 -11
  299. claude_mpm/services/shared/__init__.py +1 -1
  300. claude_mpm/services/shared/async_service_base.py +58 -50
  301. claude_mpm/services/shared/config_service_base.py +73 -67
  302. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  303. claude_mpm/services/shared/manager_base.py +94 -82
  304. claude_mpm/services/shared/service_factory.py +96 -98
  305. claude_mpm/services/socketio/__init__.py +3 -3
  306. claude_mpm/services/socketio/client_proxy.py +5 -5
  307. claude_mpm/services/socketio/event_normalizer.py +199 -181
  308. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  309. claude_mpm/services/socketio/handlers/base.py +5 -4
  310. claude_mpm/services/socketio/handlers/connection.py +163 -136
  311. claude_mpm/services/socketio/handlers/file.py +13 -14
  312. claude_mpm/services/socketio/handlers/git.py +12 -7
  313. claude_mpm/services/socketio/handlers/hook.py +49 -44
  314. claude_mpm/services/socketio/handlers/memory.py +0 -1
  315. claude_mpm/services/socketio/handlers/project.py +0 -1
  316. claude_mpm/services/socketio/handlers/registry.py +37 -19
  317. claude_mpm/services/socketio/migration_utils.py +98 -84
  318. claude_mpm/services/socketio/server/__init__.py +1 -1
  319. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  320. claude_mpm/services/socketio/server/core.py +65 -54
  321. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  322. claude_mpm/services/socketio/server/main.py +64 -38
  323. claude_mpm/services/socketio_client_manager.py +10 -12
  324. claude_mpm/services/subprocess_launcher_service.py +4 -7
  325. claude_mpm/services/system_instructions_service.py +13 -14
  326. claude_mpm/services/ticket_manager.py +2 -2
  327. claude_mpm/services/utility_service.py +5 -13
  328. claude_mpm/services/version_control/__init__.py +16 -16
  329. claude_mpm/services/version_control/branch_strategy.py +5 -8
  330. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  331. claude_mpm/services/version_control/git_operations.py +5 -7
  332. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  333. claude_mpm/services/version_control/version_parser.py +13 -18
  334. claude_mpm/services/version_service.py +10 -11
  335. claude_mpm/storage/__init__.py +1 -1
  336. claude_mpm/storage/state_storage.py +22 -28
  337. claude_mpm/utils/__init__.py +6 -6
  338. claude_mpm/utils/agent_dependency_loader.py +47 -33
  339. claude_mpm/utils/config_manager.py +11 -14
  340. claude_mpm/utils/dependency_cache.py +1 -1
  341. claude_mpm/utils/dependency_manager.py +13 -17
  342. claude_mpm/utils/dependency_strategies.py +8 -10
  343. claude_mpm/utils/environment_context.py +3 -9
  344. claude_mpm/utils/error_handler.py +3 -13
  345. claude_mpm/utils/file_utils.py +1 -1
  346. claude_mpm/utils/path_operations.py +8 -12
  347. claude_mpm/utils/robust_installer.py +110 -33
  348. claude_mpm/utils/subprocess_utils.py +5 -6
  349. claude_mpm/validation/agent_validator.py +3 -6
  350. claude_mpm/validation/frontmatter_validator.py +1 -1
  351. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  352. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  353. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  354. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  355. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  356. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  357. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -20,10 +20,9 @@ import sys
20
20
  import time
21
21
  import webbrowser
22
22
  from datetime import datetime
23
- from typing import Dict, Any, Optional
23
+ from typing import Optional
24
24
 
25
25
  from ...constants import LogLevel
26
- from ...core.config import Config
27
26
  from ...core.logger import get_logger
28
27
  from ...core.shared.config_loader import ConfigLoader
29
28
  from ...core.unified_paths import get_package_root, get_scripts_dir
@@ -31,11 +30,12 @@ from ...services.port_manager import PortManager
31
30
  from ...utils.dependency_manager import ensure_socketio_dependencies
32
31
  from ..shared import BaseCommand, CommandResult
33
32
  from ..startup_logging import (
34
- log_startup_status,
33
+ cleanup_old_startup_logs,
34
+ log_startup_status,
35
35
  setup_startup_logging,
36
- cleanup_old_startup_logs
37
36
  )
38
37
  from ..utils import get_user_input, list_agent_versions_at_startup
38
+ from .run_config_checker import RunConfigChecker
39
39
 
40
40
 
41
41
  def filter_claude_mpm_args(claude_args):
@@ -208,13 +208,16 @@ class RunCommand(BaseCommand):
208
208
  success = self._execute_run_session(args)
209
209
 
210
210
  if success:
211
- return CommandResult.success_result("Claude session completed successfully")
212
- else:
213
- return CommandResult.error_result("Claude session failed", exit_code=1)
211
+ return CommandResult.success_result(
212
+ "Claude session completed successfully"
213
+ )
214
+ return CommandResult.error_result("Claude session failed", exit_code=1)
214
215
 
215
216
  except KeyboardInterrupt:
216
217
  self.logger.info("Session interrupted by user")
217
- return CommandResult.error_result("Session cancelled by user", exit_code=130)
218
+ return CommandResult.error_result(
219
+ "Session cancelled by user", exit_code=130
220
+ )
218
221
  except Exception as e:
219
222
  self.logger.error(f"Error running Claude session: {e}", exc_info=True)
220
223
  return CommandResult.error_result(f"Error running Claude session: {e}")
@@ -248,7 +251,9 @@ class RunCommand(BaseCommand):
248
251
  self._check_claude_json_memory(args)
249
252
 
250
253
  # Handle session management
251
- session_manager, resume_session_id, resume_context = self._setup_session_management(args)
254
+ session_manager, resume_session_id, resume_context = (
255
+ self._setup_session_management(args)
256
+ )
252
257
 
253
258
  # Handle dependency checking
254
259
  self._handle_dependency_checking(args)
@@ -260,7 +265,9 @@ class RunCommand(BaseCommand):
260
265
  runner = self._setup_claude_runner(args, monitor_mode, websocket_port)
261
266
 
262
267
  # Create context and run session
263
- context = self._create_session_context(args, session_manager, resume_session_id, resume_context)
268
+ context = self._create_session_context(
269
+ args, session_manager, resume_session_id, resume_context
270
+ )
264
271
 
265
272
  # Execute the session
266
273
  return self._execute_session(args, runner, context)
@@ -271,13 +278,11 @@ class RunCommand(BaseCommand):
271
278
 
272
279
  def _check_configuration_health(self):
273
280
  """Check configuration health at startup."""
274
- from .run_config_checker import RunConfigChecker
275
281
  checker = RunConfigChecker(self.logger)
276
282
  checker.check_configuration_health()
277
283
 
278
284
  def _check_claude_json_memory(self, args):
279
285
  """Check .claude.json file size and warn about memory issues."""
280
- from .run_config_checker import RunConfigChecker
281
286
  checker = RunConfigChecker(self.logger)
282
287
  checker.check_claude_json_memory(args)
283
288
 
@@ -300,8 +305,12 @@ class RunCommand(BaseCommand):
300
305
  session_data = session_manager.get_session_by_id(resume_session_id)
301
306
  if session_data:
302
307
  resume_context = session_data.get("context", "default")
303
- self.logger.info(f"Resuming session {resume_session_id} (context: {resume_context})")
304
- print(f"🔄 Resuming session {resume_session_id[:8]}... (created: {session_data.get('created_at', 'unknown')})")
308
+ self.logger.info(
309
+ f"Resuming session {resume_session_id} (context: {resume_context})"
310
+ )
311
+ print(
312
+ f"🔄 Resuming session {resume_session_id[:8]}... (created: {session_data.get('created_at', 'unknown')})"
313
+ )
305
314
  else:
306
315
  self.logger.warning(f"Session {resume_session_id} not found")
307
316
  else:
@@ -313,8 +322,12 @@ class RunCommand(BaseCommand):
313
322
  session_data = session_manager.get_session_by_id(resume_session_id)
314
323
  if session_data:
315
324
  resume_context = session_data.get("context", "default")
316
- self.logger.info(f"Resuming session {resume_session_id} (context: {resume_context})")
317
- print(f"🔄 Resuming session {resume_session_id[:8]}... (context: {resume_context})")
325
+ self.logger.info(
326
+ f"Resuming session {resume_session_id} (context: {resume_context})"
327
+ )
328
+ print(
329
+ f"🔄 Resuming session {resume_session_id[:8]}... (context: {resume_context})"
330
+ )
318
331
  else:
319
332
  self.logger.error(f"Session {resume_session_id} not found")
320
333
  print(f"❌ Session {resume_session_id} not found")
@@ -355,17 +368,25 @@ class RunCommand(BaseCommand):
355
368
  # Check dependencies and prompt for installation if needed
356
369
  missing_deps = loader.check_dependencies()
357
370
  if missing_deps:
358
- self.logger.info(f"Found {len(missing_deps)} missing dependencies")
371
+ self.logger.info(
372
+ f"Found {len(missing_deps)} missing dependencies"
373
+ )
359
374
 
360
375
  # Prompt user for installation
361
- print(f"\n📦 Found {len(missing_deps)} missing dependencies:")
376
+ print(
377
+ f"\n📦 Found {len(missing_deps)} missing dependencies:"
378
+ )
362
379
  for dep in missing_deps[:5]: # Show first 5
363
380
  print(f" • {dep}")
364
381
  if len(missing_deps) > 5:
365
382
  print(f" ... and {len(missing_deps) - 5} more")
366
383
 
367
- response = input("\nInstall missing dependencies? (y/N): ").strip().lower()
368
- if response in ['y', 'yes']:
384
+ response = (
385
+ input("\nInstall missing dependencies? (y/N): ")
386
+ .strip()
387
+ .lower()
388
+ )
389
+ if response in ["y", "yes"]:
369
390
  loader.auto_install = True
370
391
  loader.install_dependencies(missing_deps)
371
392
  print("✅ Dependencies installed successfully")
@@ -375,8 +396,12 @@ class RunCommand(BaseCommand):
375
396
  # Just check without prompting
376
397
  missing_deps = loader.check_dependencies()
377
398
  if missing_deps:
378
- self.logger.warning(f"Found {len(missing_deps)} missing dependencies")
379
- print(f"⚠️ Found {len(missing_deps)} missing dependencies. Use --force-check-dependencies to install.")
399
+ self.logger.warning(
400
+ f"Found {len(missing_deps)} missing dependencies"
401
+ )
402
+ print(
403
+ f"⚠️ Found {len(missing_deps)} missing dependencies. Use --force-check-dependencies to install."
404
+ )
380
405
 
381
406
  # Update cache
382
407
  smart_checker.update_cache(deployment_hash)
@@ -396,7 +421,9 @@ class RunCommand(BaseCommand):
396
421
  if monitor_mode:
397
422
  # Ensure Socket.IO dependencies are available
398
423
  if not ensure_socketio_dependencies():
399
- self.logger.warning("Socket.IO dependencies not available, disabling monitor mode")
424
+ self.logger.warning(
425
+ "Socket.IO dependencies not available, disabling monitor mode"
426
+ )
400
427
  monitor_mode = False
401
428
  else:
402
429
  # Get available port
@@ -405,8 +432,10 @@ class RunCommand(BaseCommand):
405
432
 
406
433
  # Start Socket.IO server if not running
407
434
  if not self._is_socketio_server_running(websocket_port):
408
- if not _start_socketio_server(websocket_port, self.logger):
409
- self.logger.warning("Failed to start Socket.IO server, disabling monitor mode")
435
+ if not self._start_socketio_server(websocket_port, self.logger):
436
+ self.logger.warning(
437
+ "Failed to start Socket.IO server, disabling monitor mode"
438
+ )
410
439
  monitor_mode = False
411
440
  else:
412
441
  # Give server time to start
@@ -461,11 +490,15 @@ class RunCommand(BaseCommand):
461
490
  # Set browser opening flag for monitor mode
462
491
  if monitor_mode:
463
492
  runner._should_open_monitor_browser = True
464
- runner._browser_opened_by_cli = getattr(args, "_browser_opened_by_cli", False)
493
+ runner._browser_opened_by_cli = getattr(
494
+ args, "_browser_opened_by_cli", False
495
+ )
465
496
 
466
497
  return runner
467
498
 
468
- def _create_session_context(self, args, session_manager, resume_session_id, resume_context):
499
+ def _create_session_context(
500
+ self, args, session_manager, resume_session_id, resume_context
501
+ ):
469
502
  """Create session context."""
470
503
  try:
471
504
  from ...core.claude_runner import create_simple_context
@@ -476,7 +509,9 @@ class RunCommand(BaseCommand):
476
509
  # For resumed sessions, create enhanced context with session information
477
510
  context = create_session_context(resume_session_id, session_manager)
478
511
  # Update session usage
479
- session_manager.active_sessions[resume_session_id]["last_used"] = datetime.now().isoformat()
512
+ session_manager.active_sessions[resume_session_id][
513
+ "last_used"
514
+ ] = datetime.now().isoformat()
480
515
  session_manager.active_sessions[resume_session_id]["use_count"] += 1
481
516
  session_manager._save_sessions()
482
517
  else:
@@ -501,18 +536,19 @@ class RunCommand(BaseCommand):
501
536
  if not success:
502
537
  self.logger.error("Session failed")
503
538
  return False
504
- else:
505
- # Interactive mode
506
- if getattr(args, "intercept_commands", False):
507
- wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
508
- if wrapper_path.exists():
509
- print("Starting interactive session with command interception...")
510
- subprocess.run([sys.executable, str(wrapper_path)])
511
- else:
512
- self.logger.warning("Interactive wrapper not found, falling back to normal mode")
513
- runner.run_interactive(context)
539
+ # Interactive mode
540
+ elif getattr(args, "intercept_commands", False):
541
+ wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
542
+ if wrapper_path.exists():
543
+ print("Starting interactive session with command interception...")
544
+ subprocess.run([sys.executable, str(wrapper_path)], check=False)
514
545
  else:
546
+ self.logger.warning(
547
+ "Interactive wrapper not found, falling back to normal mode"
548
+ )
515
549
  runner.run_interactive(context)
550
+ else:
551
+ runner.run_interactive(context)
516
552
 
517
553
  return True
518
554
 
@@ -524,9 +560,10 @@ class RunCommand(BaseCommand):
524
560
  """Check if Socket.IO server is running on the specified port."""
525
561
  try:
526
562
  import socket
563
+
527
564
  with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
528
565
  s.settimeout(1)
529
- result = s.connect_ex(('localhost', port))
566
+ result = s.connect_ex(("localhost", port))
530
567
  return result == 0
531
568
  except Exception:
532
569
  return False
@@ -561,14 +598,14 @@ def run_session_legacy(args):
561
598
  args: Parsed command line arguments
562
599
  """
563
600
  # Set up startup logging to file early in the process
564
- startup_log_file = setup_startup_logging(Path.cwd())
565
-
601
+ setup_startup_logging(Path.cwd())
602
+
566
603
  logger = get_logger("cli")
567
604
  if args.logging != LogLevel.OFF.value:
568
605
  logger.info("Starting Claude MPM session")
569
- logger.info(f"Startup log: {startup_log_file}")
570
-
571
- # Clean up old startup logs (keep last 7 days or minimum 10 files)
606
+ # Log file already announced in startup_logging.py when created
607
+
608
+ # Clean up old startup logs (using configured retention count)
572
609
  try:
573
610
  deleted_count = cleanup_old_startup_logs(Path.cwd())
574
611
  if deleted_count > 0:
@@ -637,6 +674,14 @@ def run_session_legacy(args):
637
674
  print("💡 Use 'claude-mpm sessions' to list available sessions")
638
675
  return
639
676
 
677
+ # Deploy MPM slash commands to user's Claude configuration
678
+ try:
679
+ from ...services.command_deployment_service import deploy_commands_on_startup
680
+
681
+ deploy_commands_on_startup(force=False)
682
+ except Exception as e:
683
+ logger.debug(f"Failed to deploy MPM commands (non-critical): {e}")
684
+
640
685
  # Skip native agents if disabled
641
686
  if getattr(args, "no_native_agents", False):
642
687
  print("Native agents disabled")
@@ -689,7 +734,7 @@ def run_session_legacy(args):
689
734
 
690
735
  if can_prompt and missing_count > 0:
691
736
  # Interactive prompt for installation
692
- print(f"\n📦 Missing dependencies detected:")
737
+ print("\n📦 Missing dependencies detected:")
693
738
  for dep in results["summary"]["missing_python"][:5]:
694
739
  print(f" - {dep}")
695
740
  if missing_count > 5:
@@ -774,17 +819,17 @@ def run_session_legacy(args):
774
819
  # Create simple runner
775
820
  enable_tickets = not args.no_tickets
776
821
  raw_claude_args = getattr(args, "claude_args", []) or []
777
-
822
+
778
823
  # Add --resume to claude_args if the flag is set
779
824
  resume_flag_present = getattr(args, "resume", False)
780
825
  if resume_flag_present:
781
826
  logger.info("📌 --resume flag detected in args")
782
827
  if "--resume" not in raw_claude_args:
783
- raw_claude_args = ["--resume"] + raw_claude_args
828
+ raw_claude_args = ["--resume", *raw_claude_args]
784
829
  logger.info("✅ Added --resume to claude_args")
785
830
  else:
786
831
  logger.info("ℹ️ --resume already in claude_args")
787
-
832
+
788
833
  # Filter out claude-mpm specific flags before passing to Claude CLI
789
834
  logger.debug(f"Pre-filter claude_args: {raw_claude_args}")
790
835
  claude_args = filter_claude_mpm_args(raw_claude_args)
@@ -794,9 +839,9 @@ def run_session_legacy(args):
794
839
  if raw_claude_args != claude_args:
795
840
  filtered_out = list(set(raw_claude_args) - set(claude_args))
796
841
  logger.debug(f"Filtered out MPM-specific args: {filtered_out}")
797
-
842
+
798
843
  logger.info(f"Final claude_args being passed: {claude_args}")
799
-
844
+
800
845
  # Explicit verification of --resume flag
801
846
  if resume_flag_present:
802
847
  if "--resume" in claude_args:
@@ -843,7 +888,7 @@ def run_session_legacy(args):
843
888
  websocket_port, logger
844
889
  )
845
890
  if not success:
846
- print(f"⚠️ Failed to launch Socket.IO monitor")
891
+ print("⚠️ Failed to launch Socket.IO monitor")
847
892
  print(
848
893
  f" You can manually run: python scripts/launch_socketio_dashboard.py --port {websocket_port}"
849
894
  )
@@ -905,20 +950,17 @@ def run_session_legacy(args):
905
950
  success = runner.run_oneshot(user_input, context)
906
951
  if not success:
907
952
  logger.error("Session failed")
908
- else:
909
- # Interactive mode
910
- if getattr(args, "intercept_commands", False):
911
- wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
912
- if wrapper_path.exists():
913
- print("Starting interactive session with command interception...")
914
- subprocess.run([sys.executable, str(wrapper_path)])
915
- else:
916
- logger.warning(
917
- "Interactive wrapper not found, falling back to normal mode"
918
- )
919
- runner.run_interactive(context)
953
+ # Interactive mode
954
+ elif getattr(args, "intercept_commands", False):
955
+ wrapper_path = get_scripts_dir() / "interactive_wrapper.py"
956
+ if wrapper_path.exists():
957
+ print("Starting interactive session with command interception...")
958
+ subprocess.run([sys.executable, str(wrapper_path)], check=False)
920
959
  else:
960
+ logger.warning("Interactive wrapper not found, falling back to normal mode")
921
961
  runner.run_interactive(context)
962
+ else:
963
+ runner.run_interactive(context)
922
964
 
923
965
 
924
966
  def launch_socketio_monitor(port, logger):
@@ -967,8 +1009,6 @@ def _start_standalone_socketio_server(port, logger):
967
1009
  try:
968
1010
  import subprocess
969
1011
 
970
- from ...core.unified_paths import get_scripts_dir
971
-
972
1012
  # Get path to daemon script in package
973
1013
  daemon_script = get_package_root() / "scripts" / "socketio_daemon.py"
974
1014
 
@@ -983,6 +1023,7 @@ def _start_standalone_socketio_server(port, logger):
983
1023
  [sys.executable, str(daemon_script), "start"],
984
1024
  capture_output=True,
985
1025
  text=True,
1026
+ check=False,
986
1027
  )
987
1028
 
988
1029
  if result.returncode != 0:
@@ -1025,29 +1066,28 @@ def _start_standalone_socketio_server(port, logger):
1025
1066
  logger.info(
1026
1067
  f"✅ Standalone Socket.IO server started successfully on port {port}"
1027
1068
  )
1028
- logger.info(f"🕐 Server ready after {attempt} attempts ({elapsed:.1f}s)")
1029
- return True
1030
- else:
1031
- logger.debug(
1032
- f"Server not yet accepting connections on attempt {attempt}"
1069
+ logger.info(
1070
+ f"🕐 Server ready after {attempt} attempts ({elapsed:.1f}s)"
1033
1071
  )
1072
+ return True
1073
+ logger.debug(f"Server not yet accepting connections on attempt {attempt}")
1034
1074
 
1035
1075
  # Timeout reached
1036
- elapsed_total = time.time() - start_time
1076
+ time.time() - start_time
1037
1077
  logger.error(
1038
1078
  f"❌ Socket.IO server health check failed after {max_wait_time}s timeout ({attempt} attempts)"
1039
1079
  )
1040
1080
  logger.warning(
1041
- f"⏱️ Server may still be starting - try waiting a few more seconds"
1081
+ "⏱️ Server may still be starting - try waiting a few more seconds"
1042
1082
  )
1043
1083
  logger.warning(
1044
- f"💡 The daemon process might be running but not yet accepting HTTP connections"
1084
+ "💡 The daemon process might be running but not yet accepting HTTP connections"
1045
1085
  )
1046
- logger.error(f"🔧 Troubleshooting steps:")
1047
- logger.error(f" - Wait a few more seconds and try again")
1086
+ logger.error("🔧 Troubleshooting steps:")
1087
+ logger.error(" - Wait a few more seconds and try again")
1048
1088
  logger.error(f" - Check for port conflicts: lsof -i :{port}")
1049
- logger.error(f" - Try a different port with --websocket-port")
1050
- logger.error(f" - Verify dependencies: pip install python-socketio aiohttp")
1089
+ logger.error(" - Try a different port with --websocket-port")
1090
+ logger.error(" - Verify dependencies: pip install python-socketio aiohttp")
1051
1091
  return False
1052
1092
 
1053
1093
  except Exception as e:
@@ -1056,7 +1096,7 @@ def _start_standalone_socketio_server(port, logger):
1056
1096
 
1057
1097
  logger.error(f"📋 Stack trace: {traceback.format_exc()}")
1058
1098
  logger.error(
1059
- f"💡 This may be a dependency issue - try: pip install python-socketio aiohttp"
1099
+ "💡 This may be a dependency issue - try: pip install python-socketio aiohttp"
1060
1100
  )
1061
1101
  return False
1062
1102
 
@@ -1124,8 +1164,6 @@ def open_in_browser_tab(url, logger):
1124
1164
 
1125
1165
  def _check_claude_json_memory(args, logger):
1126
1166
  """Check .claude.json file size and warn about memory issues."""
1127
- from .run_config_checker import RunConfigChecker
1128
-
1129
1167
  checker = RunConfigChecker(logger)
1130
1168
  checker.check_claude_json_memory(args)
1131
1169
  """Check .claude.json file size and warn about memory issues.
@@ -1187,8 +1225,8 @@ def _check_claude_json_memory(args, logger):
1187
1225
  print(
1188
1226
  f"\n⚠️ CRITICAL: Large .claude.json file detected ({format_size(file_size)})"
1189
1227
  )
1190
- print(f" This WILL cause memory issues when using --resume")
1191
- print(f" Claude Code may consume 2GB+ of memory\n")
1228
+ print(" This WILL cause memory issues when using --resume")
1229
+ print(" Claude Code may consume 2GB+ of memory\n")
1192
1230
 
1193
1231
  if not getattr(args, "force", False):
1194
1232
  print(" Recommended actions:")
@@ -1243,8 +1281,6 @@ def _check_claude_json_memory(args, logger):
1243
1281
 
1244
1282
  def _check_configuration_health(logger):
1245
1283
  """Check configuration health at startup and warn about issues."""
1246
- from .run_config_checker import RunConfigChecker
1247
-
1248
1284
  checker = RunConfigChecker(logger)
1249
1285
  checker.check_configuration_health()
1250
1286
  """Check configuration health at startup and warn about issues.
@@ -40,10 +40,9 @@ class RunConfigChecker:
40
40
  """Format file size in human readable format."""
41
41
  if size_bytes < 1024:
42
42
  return f"{size_bytes} B"
43
- elif size_bytes < 1024 * 1024:
43
+ if size_bytes < 1024 * 1024:
44
44
  return f"{size_bytes / 1024:.1f} KB"
45
- else:
46
- return f"{size_bytes / (1024 * 1024):.1f} MB"
45
+ return f"{size_bytes / (1024 * 1024):.1f} MB"
47
46
 
48
47
  # Warn if file is larger than 500KB
49
48
  if file_size > 500 * 1024: # 500KB threshold
@@ -122,7 +121,7 @@ class RunConfigChecker:
122
121
  print(
123
122
  f"⚠️ Memory cleanup threshold is very low: {cleanup_threshold}MB"
124
123
  )
125
- print(f" Consider increasing to at least 50MB")
124
+ print(" Consider increasing to at least 50MB")
126
125
 
127
126
  # Check for common configuration issues
128
127
  self._check_common_config_issues(config)
@@ -153,7 +152,7 @@ class RunConfigChecker:
153
152
  if config.get(key) is not None:
154
153
  self.logger.warning(f"Deprecated configuration key found: {key}")
155
154
  print(f"⚠️ Deprecated configuration key: {key}")
156
- print(f" Consider removing this key from your configuration")
155
+ print(" Consider removing this key from your configuration")
157
156
 
158
157
  except Exception as e:
159
158
  self.logger.debug(f"Common config issues check failed: {e}")
@@ -7,9 +7,7 @@ Extracted from run.py to reduce complexity and improve maintainability.
7
7
  import os
8
8
  import subprocess
9
9
  import sys
10
- import time
11
10
  import webbrowser
12
- from pathlib import Path
13
11
 
14
12
  from ...core.unified_paths import get_package_root
15
13
  from ...services.port_manager import PortManager
@@ -43,7 +41,7 @@ class SocketIOMonitor:
43
41
  print(" This is unexpected - dependency installation may have failed.")
44
42
  return False, False
45
43
 
46
- print(f"🚀 Setting up Socket.IO monitor...")
44
+ print("🚀 Setting up Socket.IO monitor...")
47
45
  self.logger.info(f"Launching Socket.IO monitor (requested port: {port})")
48
46
 
49
47
  # First, check if there's already a running SocketIO server
@@ -79,55 +77,55 @@ class SocketIOMonitor:
79
77
  try:
80
78
  # Check if we should suppress browser opening (for tests)
81
79
  if os.environ.get("CLAUDE_MPM_NO_BROWSER") != "1":
82
- print(f"🌐 Opening dashboard in browser...")
80
+ print("🌐 Opening dashboard in browser...")
83
81
  self.open_in_browser_tab(dashboard_url)
84
82
  self.logger.info(f"Socket.IO dashboard opened: {dashboard_url}")
85
83
  else:
86
- print(f"🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)")
84
+ print("🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)")
87
85
  self.logger.info(
88
- f"Browser opening suppressed by environment variable"
86
+ "Browser opening suppressed by environment variable"
89
87
  )
90
88
  return True, True
91
89
  except Exception as e:
92
90
  self.logger.warning(f"Failed to open browser: {e}")
93
- print(f"⚠️ Could not open browser automatically")
91
+ print("⚠️ Could not open browser automatically")
94
92
  print(f"📊 Please open manually: {dashboard_url}")
95
93
  return True, False
96
94
  else:
97
95
  # Start standalone Socket.IO server
98
- print(f"🔧 Starting Socket.IO server...")
96
+ print("🔧 Starting Socket.IO server...")
99
97
  server_started = self.start_standalone_server(socketio_port)
100
98
 
101
99
  if server_started:
102
- print(f"✅ Socket.IO server started successfully")
100
+ print("✅ Socket.IO server started successfully")
103
101
  print(f"📊 Dashboard: {dashboard_url}")
104
102
 
105
103
  # Open browser
106
104
  try:
107
105
  if os.environ.get("CLAUDE_MPM_NO_BROWSER") != "1":
108
- print(f"🌐 Opening dashboard in browser...")
106
+ print("🌐 Opening dashboard in browser...")
109
107
  self.open_in_browser_tab(dashboard_url)
110
108
  self.logger.info(
111
109
  f"Socket.IO dashboard opened: {dashboard_url}"
112
110
  )
113
111
  else:
114
112
  print(
115
- f"🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)"
113
+ "🌐 Browser opening suppressed (CLAUDE_MPM_NO_BROWSER=1)"
116
114
  )
117
115
  return True, True
118
116
  except Exception as e:
119
117
  self.logger.warning(f"Failed to open browser: {e}")
120
- print(f"⚠️ Could not open browser automatically")
118
+ print("⚠️ Could not open browser automatically")
121
119
  print(f"📊 Please open manually: {dashboard_url}")
122
120
  return True, False
123
121
  else:
124
- print(f"❌ Failed to start Socket.IO server")
125
- print(f"💡 Troubleshooting tips:")
122
+ print("❌ Failed to start Socket.IO server")
123
+ print("💡 Troubleshooting tips:")
126
124
  print(f" - Check if port {socketio_port} is already in use")
127
125
  print(
128
- f" - Verify Socket.IO dependencies: pip install python-socketio aiohttp"
126
+ " - Verify Socket.IO dependencies: pip install python-socketio aiohttp"
129
127
  )
130
- print(f" - Try a different port with --websocket-port")
128
+ print(" - Try a different port with --websocket-port")
131
129
  return False, False
132
130
 
133
131
  except Exception as e:
@@ -188,6 +186,7 @@ class SocketIOMonitor:
188
186
  capture_output=True,
189
187
  text=True,
190
188
  timeout=30,
189
+ check=False,
191
190
  )
192
191
 
193
192
  if result.returncode == 0:
@@ -195,9 +194,8 @@ class SocketIOMonitor:
195
194
  f"Socket.IO daemon started successfully on port {port}"
196
195
  )
197
196
  return True
198
- else:
199
- self.logger.error(f"Failed to start Socket.IO daemon: {result.stderr}")
200
- return False
197
+ self.logger.error(f"Failed to start Socket.IO daemon: {result.stderr}")
198
+ return False
201
199
 
202
200
  except Exception as e:
203
201
  self.logger.error(f"Failed to start standalone Socket.IO server: {e}")