claude-mpm 3.9.9__py3-none-any.whl → 4.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +155 -0
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +90 -49
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +21 -18
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +143 -762
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1150
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +217 -0
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +36 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +571 -0
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +40 -23
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
  298. claude_mpm/services/mcp_gateway/main.py +307 -127
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
  303. claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +20 -534
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +9 -0
  358. claude_mpm/storage/state_storage.py +552 -0
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/config/memory_guardian_config.py +0 -325
  385. claude_mpm/core/config_paths.py +0 -150
  386. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  387. claude_mpm/deployment_paths.py +0 -261
  388. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  389. claude_mpm/models/state_models.py +0 -433
  390. claude_mpm/services/agent/__init__.py +0 -24
  391. claude_mpm/services/agent/deployment.py +0 -2548
  392. claude_mpm/services/agent/management.py +0 -598
  393. claude_mpm/services/agent/registry.py +0 -813
  394. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  395. claude_mpm/services/communication/socketio.py +0 -1935
  396. claude_mpm/services/communication/websocket.py +0 -479
  397. claude_mpm/services/framework_claude_md_generator.py +0 -624
  398. claude_mpm/services/health_monitor.py +0 -893
  399. claude_mpm/services/infrastructure/memory_guardian.py +0 -770
  400. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
  401. claude_mpm/services/optimized_hook_service.py +0 -542
  402. claude_mpm/services/project_analyzer.py +0 -864
  403. claude_mpm/services/project_registry.py +0 -608
  404. claude_mpm/services/standalone_socketio_server.py +0 -1300
  405. claude_mpm/services/ticket_manager_di.py +0 -318
  406. claude_mpm/services/ticketing_service_original.py +0 -510
  407. claude_mpm/utils/paths.py +0 -395
  408. claude_mpm/utils/platform_memory.py +0 -524
  409. claude_mpm-3.9.9.dist-info/RECORD +0 -293
  410. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  411. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Browser Extension Error Handler
3
+ *
4
+ * WHY: Browser extensions (like password managers, ad blockers, etc.) often inject
5
+ * scripts that use Chrome's message passing API. When these extensions have bugs
6
+ * or async handlers that don't properly respond, they generate console errors.
7
+ *
8
+ * This module prevents those external errors from affecting our dashboard and
9
+ * provides clean error handling for known browser extension issues.
10
+ *
11
+ * DESIGN DECISION: Rather than trying to fix third-party extension bugs, we:
12
+ * 1. Detect and suppress known harmless extension errors
13
+ * 2. Log them separately for debugging if needed
14
+ * 3. Ensure our dashboard remains functional regardless of extension conflicts
15
+ */
16
+
17
+ class ExtensionErrorHandler {
18
+ constructor() {
19
+ this.extensionErrors = [];
20
+ this.suppressedPatterns = [
21
+ // Chrome extension message passing error
22
+ /listener indicated an asynchronous response.*message channel closed/i,
23
+ // Other common extension errors
24
+ /Extension context invalidated/i,
25
+ /Unchecked runtime\.lastError/i,
26
+ /Cannot access contents of url.*Extension/i,
27
+ /Blocked a frame with origin.*from accessing a cross-origin frame/i
28
+ ];
29
+
30
+ this.setupErrorHandling();
31
+ }
32
+
33
+ /**
34
+ * Set up global error handling to catch and suppress extension errors
35
+ */
36
+ setupErrorHandling() {
37
+ // Store original console.error
38
+ const originalConsoleError = console.error;
39
+
40
+ // Override console.error to filter extension errors
41
+ console.error = (...args) => {
42
+ const errorString = args.join(' ');
43
+
44
+ // Check if this is a known extension error
45
+ if (this.isExtensionError(errorString)) {
46
+ // Log to our internal list for debugging
47
+ this.extensionErrors.push({
48
+ timestamp: new Date().toISOString(),
49
+ error: errorString,
50
+ suppressed: true
51
+ });
52
+
53
+ // Optionally log with a prefix if debug mode is enabled
54
+ if (window.DEBUG_EXTENSION_ERRORS) {
55
+ originalConsoleError.call(console, '[SUPPRESSED EXTENSION ERROR]:', ...args);
56
+ }
57
+
58
+ // Don't propagate the error
59
+ return;
60
+ }
61
+
62
+ // Pass through non-extension errors
63
+ originalConsoleError.call(console, ...args);
64
+ };
65
+
66
+ // Handle uncaught promise rejections that might come from extensions
67
+ window.addEventListener('unhandledrejection', (event) => {
68
+ const errorString = event.reason?.toString() || '';
69
+
70
+ if (this.isExtensionError(errorString)) {
71
+ // Prevent the default error handling
72
+ event.preventDefault();
73
+
74
+ this.extensionErrors.push({
75
+ timestamp: new Date().toISOString(),
76
+ error: errorString,
77
+ type: 'unhandled_rejection',
78
+ suppressed: true
79
+ });
80
+
81
+ if (window.DEBUG_EXTENSION_ERRORS) {
82
+ console.warn('[SUPPRESSED EXTENSION REJECTION]:', event.reason);
83
+ }
84
+ }
85
+ });
86
+
87
+ // Add a global message event listener with proper error handling
88
+ // This prevents our app from being affected by misbehaving extensions
89
+ window.addEventListener('message', (event) => {
90
+ // Only process messages from our own origin
91
+ if (event.origin !== window.location.origin) {
92
+ return;
93
+ }
94
+
95
+ // Add timeout protection for any async operations
96
+ if (event.data && event.data.requiresResponse) {
97
+ const timeoutId = setTimeout(() => {
98
+ console.warn('Message handler timeout - no response sent');
99
+ }, 5000);
100
+
101
+ // Clear timeout when response is sent
102
+ if (event.ports && event.ports[0]) {
103
+ const originalPostMessage = event.ports[0].postMessage;
104
+ event.ports[0].postMessage = function(...args) {
105
+ clearTimeout(timeoutId);
106
+ return originalPostMessage.apply(this, args);
107
+ };
108
+ }
109
+ }
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Check if an error string matches known extension error patterns
115
+ * @param {string} errorString - The error message to check
116
+ * @returns {boolean} - True if this is a known extension error
117
+ */
118
+ isExtensionError(errorString) {
119
+ return this.suppressedPatterns.some(pattern => pattern.test(errorString));
120
+ }
121
+
122
+ /**
123
+ * Get suppressed extension errors for debugging
124
+ * @returns {Array} - List of suppressed errors
125
+ */
126
+ getSuppressedErrors() {
127
+ return this.extensionErrors;
128
+ }
129
+
130
+ /**
131
+ * Clear the suppressed errors list
132
+ */
133
+ clearSuppressedErrors() {
134
+ this.extensionErrors = [];
135
+ }
136
+
137
+ /**
138
+ * Enable or disable debug logging of extension errors
139
+ * @param {boolean} enabled - Whether to enable debug logging
140
+ */
141
+ setDebugMode(enabled) {
142
+ window.DEBUG_EXTENSION_ERRORS = enabled;
143
+
144
+ if (enabled) {
145
+ console.log('Extension error debug mode enabled. Suppressed errors will be logged with [SUPPRESSED] prefix.');
146
+ console.log('Current suppressed errors:', this.getSuppressedErrors());
147
+ } else {
148
+ console.log('Extension error debug mode disabled. Extension errors will be silently suppressed.');
149
+ }
150
+ }
151
+ }
152
+
153
+ // Create and export singleton instance
154
+ const extensionErrorHandler = new ExtensionErrorHandler();
155
+
156
+ // Add to window for debugging access
157
+ window.extensionErrorHandler = extensionErrorHandler;
158
+
159
+ // Export for ES6 modules
160
+ export { ExtensionErrorHandler, extensionErrorHandler };
161
+ export default extensionErrorHandler;
162
+
163
+ // Log initialization
164
+ console.log('Extension error handler initialized. Use window.extensionErrorHandler.setDebugMode(true) to see suppressed errors.');
@@ -3,6 +3,9 @@
3
3
  * Handles WebSocket connections and event processing
4
4
  */
5
5
 
6
+ // Access the global io from window object in ES6 module context
7
+ const io = window.io;
8
+
6
9
  class SocketClient {
7
10
  constructor() {
8
11
  this.socket = null;
@@ -13,16 +16,16 @@ class SocketClient {
13
16
  error: [],
14
17
  event: []
15
18
  };
16
-
19
+
17
20
  // Connection state
18
21
  this.isConnected = false;
19
22
  this.isConnecting = false;
20
-
23
+
21
24
  // Event processing
22
25
  this.events = [];
23
26
  this.sessions = new Map();
24
27
  this.currentSessionId = null;
25
-
28
+
26
29
  // Start periodic status check as fallback mechanism
27
30
  this.startStatusCheckFallback();
28
31
  }
@@ -35,7 +38,7 @@ class SocketClient {
35
38
  // Store the port for later use
36
39
  this.port = port;
37
40
  const url = `http://localhost:${port}`;
38
-
41
+
39
42
  // Prevent multiple simultaneous connections
40
43
  if (this.socket && (this.socket.connected || this.socket.connecting)) {
41
44
  console.log('Already connected or connecting, disconnecting first...');
@@ -44,7 +47,7 @@ class SocketClient {
44
47
  setTimeout(() => this.doConnect(url), 100);
45
48
  return;
46
49
  }
47
-
50
+
48
51
  this.doConnect(url);
49
52
  }
50
53
 
@@ -54,9 +57,17 @@ class SocketClient {
54
57
  */
55
58
  doConnect(url) {
56
59
  console.log(`Connecting to Socket.IO server at ${url}`);
60
+
61
+ // Check if io is available
62
+ if (typeof io === 'undefined') {
63
+ console.error('Socket.IO library not loaded! Make sure socket.io.min.js is loaded before this script.');
64
+ this.notifyConnectionStatus('Socket.IO library not loaded', 'error');
65
+ return;
66
+ }
67
+
57
68
  this.isConnecting = true;
58
69
  this.notifyConnectionStatus('Connecting...', 'connecting');
59
-
70
+
60
71
  this.socket = io(url, {
61
72
  autoConnect: true,
62
73
  reconnection: true,
@@ -67,7 +78,7 @@ class SocketClient {
67
78
  forceNew: true,
68
79
  transports: ['websocket', 'polling']
69
80
  });
70
-
81
+
71
82
  this.setupSocketHandlers();
72
83
  }
73
84
 
@@ -80,55 +91,55 @@ class SocketClient {
80
91
  this.isConnected = true;
81
92
  this.isConnecting = false;
82
93
  this.notifyConnectionStatus('Connected', 'connected');
83
-
94
+
84
95
  // Emit connect callback
85
- this.connectionCallbacks.connect.forEach(callback =>
96
+ this.connectionCallbacks.connect.forEach(callback =>
86
97
  callback(this.socket.id)
87
98
  );
88
-
99
+
89
100
  this.requestStatus();
90
101
  // History is now automatically sent by server on connection
91
102
  // No need to explicitly request it
92
103
  });
93
-
104
+
94
105
  this.socket.on('disconnect', (reason) => {
95
106
  console.log('Disconnected from server:', reason);
96
107
  this.isConnected = false;
97
108
  this.isConnecting = false;
98
109
  this.notifyConnectionStatus(`Disconnected: ${reason}`, 'disconnected');
99
-
110
+
100
111
  // Emit disconnect callback
101
- this.connectionCallbacks.disconnect.forEach(callback =>
112
+ this.connectionCallbacks.disconnect.forEach(callback =>
102
113
  callback(reason)
103
114
  );
104
115
  });
105
-
116
+
106
117
  this.socket.on('connect_error', (error) => {
107
118
  console.error('Connection error:', error);
108
119
  this.isConnecting = false;
109
120
  const errorMsg = error.message || error.description || 'Unknown error';
110
121
  this.notifyConnectionStatus(`Connection Error: ${errorMsg}`, 'disconnected');
111
-
122
+
112
123
  // Add error event
113
124
  this.addEvent({
114
125
  type: 'connection.error',
115
126
  timestamp: new Date().toISOString(),
116
127
  data: { error: errorMsg, url: this.socket.io.uri }
117
128
  });
118
-
129
+
119
130
  // Emit error callback
120
- this.connectionCallbacks.error.forEach(callback =>
131
+ this.connectionCallbacks.error.forEach(callback =>
121
132
  callback(errorMsg)
122
133
  );
123
134
  });
124
135
 
125
136
  // Primary event handler - this is what the server actually emits
126
137
  this.socket.on('claude_event', (data) => {
127
- console.log('Received claude_event:', data);
128
-
138
+ // console.log('Received claude_event:', data);
139
+
129
140
  // Transform event to match expected format
130
141
  const transformedEvent = this.transformEvent(data);
131
- console.log('Transformed event:', transformedEvent);
142
+ // console.log('Transformed event:', transformedEvent);
132
143
  this.addEvent(transformedEvent);
133
144
  });
134
145
 
@@ -310,7 +321,7 @@ class SocketClient {
310
321
  this.sessions.clear();
311
322
  this.notifyEventUpdate();
312
323
  }
313
-
324
+
314
325
  /**
315
326
  * Clear events and request fresh history from server
316
327
  * @param {Object} options - History request options (same as requestHistory)
@@ -329,7 +340,7 @@ class SocketClient {
329
340
  if (!sessionId) {
330
341
  return this.events;
331
342
  }
332
- return this.events.filter(event =>
343
+ return this.events.filter(event =>
333
344
  event.data && event.data.session_id === sessionId
334
345
  );
335
346
  }
@@ -360,10 +371,10 @@ class SocketClient {
360
371
  */
361
372
  notifyConnectionStatus(status, type) {
362
373
  console.log(`SocketClient: Connection status changed to '${status}' (${type})`);
363
-
374
+
364
375
  // Direct DOM update - immediate and reliable
365
376
  this.updateConnectionStatusDOM(status, type);
366
-
377
+
367
378
  // Also dispatch custom event for other modules
368
379
  document.dispatchEvent(new CustomEvent('socketConnectionStatus', {
369
380
  detail: { status, type }
@@ -380,10 +391,10 @@ class SocketClient {
380
391
  if (statusElement) {
381
392
  // Update the text content while preserving the indicator span
382
393
  statusElement.innerHTML = `<span>●</span> ${status}`;
383
-
394
+
384
395
  // Update the CSS class for styling
385
396
  statusElement.className = `status-badge status-${type}`;
386
-
397
+
387
398
  console.log(`SocketClient: Direct DOM update - status: '${status}' (${type})`);
388
399
  } else {
389
400
  console.warn('SocketClient: Could not find connection-status element in DOM');
@@ -394,10 +405,10 @@ class SocketClient {
394
405
  * Notify event update
395
406
  */
396
407
  notifyEventUpdate() {
397
- this.connectionCallbacks.event.forEach(callback =>
408
+ this.connectionCallbacks.event.forEach(callback =>
398
409
  callback(this.events, this.sessions)
399
410
  );
400
-
411
+
401
412
  // Also dispatch custom event
402
413
  document.dispatchEvent(new CustomEvent('socketEventUpdate', {
403
414
  detail: { events: this.events, sessions: this.sessions }
@@ -422,27 +433,65 @@ class SocketClient {
422
433
  * @returns {Object} Transformed event
423
434
  */
424
435
  transformEvent(eventData) {
425
- // Handle the actual event structure sent from hook_handler.py:
426
- // { type: 'hook.pre_tool', timestamp: '...', data: { tool_name: '...', agent_type: '...', etc } }
427
-
428
- if (!eventData || !eventData.type) {
429
- return eventData; // Return as-is if malformed
436
+ // Handle multiple event structures:
437
+ // 1. Hook events: { type: 'hook.pre_tool', timestamp: '...', data: {...} }
438
+ // 2. Legacy events: { event: 'TestStart', timestamp: '...', ... }
439
+ // 3. Standard events: { type: 'session', subtype: 'started', ... }
440
+
441
+ if (!eventData) {
442
+ return eventData; // Return as-is if null/undefined
430
443
  }
431
444
 
432
- const type = eventData.type;
433
445
  let transformedEvent = { ...eventData };
434
446
 
435
- // Transform 'hook.subtype' format to separate type and subtype
436
- if (type.startsWith('hook.')) {
437
- const subtype = type.substring(5); // Remove 'hook.' prefix
438
- transformedEvent.type = 'hook';
439
- transformedEvent.subtype = subtype;
447
+ // Handle legacy format with 'event' field but no 'type'
448
+ if (!eventData.type && eventData.event) {
449
+ // Map common event names to proper type/subtype
450
+ const eventName = eventData.event;
451
+
452
+ // Check for known event patterns
453
+ if (eventName === 'TestStart' || eventName === 'TestEnd') {
454
+ transformedEvent.type = 'test';
455
+ transformedEvent.subtype = eventName.toLowerCase().replace('test', '');
456
+ } else if (eventName === 'SubagentStart' || eventName === 'SubagentStop') {
457
+ transformedEvent.type = 'subagent';
458
+ transformedEvent.subtype = eventName.toLowerCase().replace('subagent', '');
459
+ } else if (eventName === 'ToolCall') {
460
+ transformedEvent.type = 'tool';
461
+ transformedEvent.subtype = 'call';
462
+ } else if (eventName === 'UserPrompt') {
463
+ transformedEvent.type = 'hook';
464
+ transformedEvent.subtype = 'user_prompt';
465
+ } else {
466
+ // Generic fallback for unknown event names
467
+ transformedEvent.type = 'system';
468
+ transformedEvent.subtype = eventName.toLowerCase();
469
+ }
470
+
471
+ // Remove the 'event' field to avoid confusion
472
+ delete transformedEvent.event;
440
473
  }
441
- // Transform other dotted types like 'session.started' -> type: 'session', subtype: 'started'
442
- else if (type.includes('.')) {
443
- const [mainType, ...subtypeParts] = type.split('.');
444
- transformedEvent.type = mainType;
445
- transformedEvent.subtype = subtypeParts.join('.');
474
+ // Handle standard format with 'type' field
475
+ else if (eventData.type) {
476
+ const type = eventData.type;
477
+
478
+ // Transform 'hook.subtype' format to separate type and subtype
479
+ if (type.startsWith('hook.')) {
480
+ const subtype = type.substring(5); // Remove 'hook.' prefix
481
+ transformedEvent.type = 'hook';
482
+ transformedEvent.subtype = subtype;
483
+ }
484
+ // Transform other dotted types like 'session.started' -> type: 'session', subtype: 'started'
485
+ else if (type.includes('.')) {
486
+ const [mainType, ...subtypeParts] = type.split('.');
487
+ transformedEvent.type = mainType;
488
+ transformedEvent.subtype = subtypeParts.join('.');
489
+ }
490
+ }
491
+ // If no type and no event field, mark as unknown
492
+ else {
493
+ transformedEvent.type = 'unknown';
494
+ transformedEvent.subtype = '';
446
495
  }
447
496
 
448
497
  // Extract and flatten data fields to top level for dashboard compatibility
@@ -450,10 +499,23 @@ class SocketClient {
450
499
  if (eventData.data && typeof eventData.data === 'object') {
451
500
  // Copy all data fields to the top level
452
501
  Object.keys(eventData.data).forEach(key => {
453
- // Only copy if the key doesn't already exist at top level
454
- if (!(key in transformedEvent)) {
455
- transformedEvent[key] = eventData.data[key];
456
- }
502
+ // Always copy data fields to ensure dashboard gets them
503
+ // This overwrites any existing values to ensure data fields take precedence
504
+ transformedEvent[key] = eventData.data[key];
505
+ });
506
+
507
+ // Keep the original data object for backward compatibility
508
+ transformedEvent.data = eventData.data;
509
+ }
510
+
511
+ // Debug logging for tool events
512
+ if (transformedEvent.type === 'hook' && (transformedEvent.subtype === 'pre_tool' || transformedEvent.subtype === 'post_tool')) {
513
+ console.log('Transformed tool event:', {
514
+ type: transformedEvent.type,
515
+ subtype: transformedEvent.subtype,
516
+ tool_name: transformedEvent.tool_name,
517
+ has_data: !!transformedEvent.data,
518
+ keys: Object.keys(transformedEvent).filter(k => k !== 'data')
457
519
  });
458
520
  }
459
521
 
@@ -481,7 +543,7 @@ class SocketClient {
481
543
  setInterval(() => {
482
544
  this.checkAndUpdateStatus();
483
545
  }, 2000);
484
-
546
+
485
547
  // Initial check after DOM is ready
486
548
  if (document.readyState === 'loading') {
487
549
  document.addEventListener('DOMContentLoaded', () => {
@@ -498,7 +560,7 @@ class SocketClient {
498
560
  checkAndUpdateStatus() {
499
561
  let actualStatus = 'Disconnected';
500
562
  let actualType = 'disconnected';
501
-
563
+
502
564
  if (this.socket) {
503
565
  if (this.socket.connected) {
504
566
  actualStatus = 'Connected';
@@ -516,14 +578,14 @@ class SocketClient {
516
578
  this.isConnecting = false;
517
579
  }
518
580
  }
519
-
581
+
520
582
  // Check if UI needs updating
521
583
  const statusElement = document.getElementById('connection-status');
522
584
  if (statusElement) {
523
585
  const currentText = statusElement.textContent.replace('●', '').trim();
524
586
  const currentClass = statusElement.className;
525
587
  const expectedClass = `status-badge status-${actualType}`;
526
-
588
+
527
589
  // Update if status text or class doesn't match
528
590
  if (currentText !== actualStatus || currentClass !== expectedClass) {
529
591
  console.log(`SocketClient: Fallback update - was '${currentText}' (${currentClass}), now '${actualStatus}' (${expectedClass})`);
@@ -533,5 +595,9 @@ class SocketClient {
533
595
  }
534
596
  }
535
597
 
536
- // Export for use in other modules
537
- window.SocketClient = SocketClient;
598
+ // ES6 Module export
599
+ export { SocketClient };
600
+ export default SocketClient;
601
+
602
+ // Backward compatibility - keep window export for non-module usage
603
+ window.SocketClient = SocketClient;