claude-mpm 3.4.10__py3-none-any.whl → 5.4.55__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (950) hide show
  1. claude_mpm/BUILD_NUMBER +1 -0
  2. claude_mpm/VERSION +1 -0
  3. claude_mpm/__init__.py +50 -12
  4. claude_mpm/__main__.py +7 -2
  5. claude_mpm/agents/BASE_AGENT.md +164 -0
  6. claude_mpm/agents/BASE_ENGINEER.md +658 -0
  7. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +290 -0
  8. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +2002 -0
  9. claude_mpm/agents/MEMORY.md +72 -0
  10. claude_mpm/agents/PM_INSTRUCTIONS.md +1402 -0
  11. claude_mpm/agents/WORKFLOW.md +111 -0
  12. claude_mpm/agents/__init__.py +92 -80
  13. claude_mpm/agents/agent-template.yaml +83 -0
  14. claude_mpm/agents/agent_loader.py +560 -745
  15. claude_mpm/agents/agent_loader_integration.py +53 -55
  16. claude_mpm/agents/agents_metadata.py +186 -27
  17. claude_mpm/agents/async_agent_loader.py +436 -0
  18. claude_mpm/agents/base_agent.json +8 -4
  19. claude_mpm/agents/frontmatter_validator.py +754 -0
  20. claude_mpm/agents/system_agent_config.py +222 -155
  21. claude_mpm/agents/templates/README.md +465 -0
  22. claude_mpm/agents/templates/__init__.py +17 -13
  23. claude_mpm/agents/templates/circuit-breakers.md +1391 -0
  24. claude_mpm/agents/templates/context-management-examples.md +544 -0
  25. claude_mpm/agents/templates/git-file-tracking.md +584 -0
  26. claude_mpm/agents/templates/pm-examples.md +474 -0
  27. claude_mpm/agents/templates/pm-red-flags.md +310 -0
  28. claude_mpm/agents/templates/pr-workflow-examples.md +427 -0
  29. claude_mpm/agents/templates/research-gate-examples.md +669 -0
  30. claude_mpm/agents/templates/response-format.md +583 -0
  31. claude_mpm/agents/templates/structured-questions-examples.md +615 -0
  32. claude_mpm/agents/templates/ticket-completeness-examples.md +139 -0
  33. claude_mpm/agents/templates/ticketing-examples.md +277 -0
  34. claude_mpm/agents/templates/validation-templates.md +312 -0
  35. claude_mpm/cli/__init__.py +90 -128
  36. claude_mpm/cli/__main__.py +33 -0
  37. claude_mpm/cli/chrome_devtools_installer.py +175 -0
  38. claude_mpm/cli/commands/__init__.py +36 -12
  39. claude_mpm/cli/commands/agent_manager.py +1403 -0
  40. claude_mpm/cli/commands/agent_source.py +774 -0
  41. claude_mpm/cli/commands/agent_state_manager.py +335 -0
  42. claude_mpm/cli/commands/agents.py +2503 -168
  43. claude_mpm/cli/commands/agents_cleanup.py +210 -0
  44. claude_mpm/cli/commands/agents_discover.py +338 -0
  45. claude_mpm/cli/commands/aggregate.py +540 -0
  46. claude_mpm/cli/commands/analyze.py +553 -0
  47. claude_mpm/cli/commands/analyze_code.py +528 -0
  48. claude_mpm/cli/commands/auto_configure.py +1053 -0
  49. claude_mpm/cli/commands/cleanup.py +588 -0
  50. claude_mpm/cli/commands/cleanup_orphaned_agents.py +150 -0
  51. claude_mpm/cli/commands/config.py +586 -0
  52. claude_mpm/cli/commands/configure.py +2654 -0
  53. claude_mpm/cli/commands/configure_agent_display.py +282 -0
  54. claude_mpm/cli/commands/configure_behavior_manager.py +204 -0
  55. claude_mpm/cli/commands/configure_hook_manager.py +225 -0
  56. claude_mpm/cli/commands/configure_models.py +18 -0
  57. claude_mpm/cli/commands/configure_navigation.py +184 -0
  58. claude_mpm/cli/commands/configure_paths.py +104 -0
  59. claude_mpm/cli/commands/configure_persistence.py +254 -0
  60. claude_mpm/cli/commands/configure_startup_manager.py +646 -0
  61. claude_mpm/cli/commands/configure_template_editor.py +497 -0
  62. claude_mpm/cli/commands/configure_validators.py +73 -0
  63. claude_mpm/cli/commands/dashboard.py +286 -0
  64. claude_mpm/cli/commands/debug.py +1386 -0
  65. claude_mpm/cli/commands/doctor.py +243 -0
  66. claude_mpm/cli/commands/hook_errors.py +277 -0
  67. claude_mpm/cli/commands/info.py +195 -74
  68. claude_mpm/cli/commands/local_deploy.py +534 -0
  69. claude_mpm/cli/commands/mcp.py +205 -0
  70. claude_mpm/cli/commands/mcp_command_router.py +161 -0
  71. claude_mpm/cli/commands/mcp_config.py +154 -0
  72. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  73. claude_mpm/cli/commands/mcp_external_commands.py +249 -0
  74. claude_mpm/cli/commands/mcp_install_commands.py +346 -0
  75. claude_mpm/cli/commands/mcp_pipx_config.py +208 -0
  76. claude_mpm/cli/commands/mcp_server_commands.py +155 -0
  77. claude_mpm/cli/commands/mcp_setup_external.py +868 -0
  78. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  79. claude_mpm/cli/commands/memory.py +585 -846
  80. claude_mpm/cli/commands/monitor.py +228 -310
  81. claude_mpm/cli/commands/mpm_init/__init__.py +73 -0
  82. claude_mpm/cli/commands/mpm_init/core.py +759 -0
  83. claude_mpm/cli/commands/mpm_init/display.py +341 -0
  84. claude_mpm/cli/commands/mpm_init/git_activity.py +427 -0
  85. claude_mpm/cli/commands/mpm_init/knowledge_extractor.py +481 -0
  86. claude_mpm/cli/commands/mpm_init/modes.py +397 -0
  87. claude_mpm/cli/commands/mpm_init/prompts.py +722 -0
  88. claude_mpm/cli/commands/mpm_init_cli.py +396 -0
  89. claude_mpm/cli/commands/mpm_init_handler.py +195 -0
  90. claude_mpm/cli/commands/postmortem.py +401 -0
  91. claude_mpm/cli/commands/profile.py +276 -0
  92. claude_mpm/cli/commands/run.py +910 -488
  93. claude_mpm/cli/commands/search.py +458 -0
  94. claude_mpm/cli/commands/skill_source.py +694 -0
  95. claude_mpm/cli/commands/skills.py +1246 -0
  96. claude_mpm/cli/commands/summarize.py +413 -0
  97. claude_mpm/cli/commands/tickets.py +536 -53
  98. claude_mpm/cli/commands/uninstall.py +176 -0
  99. claude_mpm/cli/commands/upgrade.py +152 -0
  100. claude_mpm/cli/commands/verify.py +119 -0
  101. claude_mpm/cli/executor.py +297 -0
  102. claude_mpm/cli/helpers.py +105 -0
  103. claude_mpm/cli/interactive/__init__.py +21 -0
  104. claude_mpm/cli/interactive/agent_wizard.py +1947 -0
  105. claude_mpm/cli/interactive/skills_wizard.py +491 -0
  106. claude_mpm/cli/parser.py +87 -563
  107. claude_mpm/cli/parsers/__init__.py +35 -0
  108. claude_mpm/cli/parsers/agent_manager_parser.py +393 -0
  109. claude_mpm/cli/parsers/agent_source_parser.py +171 -0
  110. claude_mpm/cli/parsers/agents_parser.py +575 -0
  111. claude_mpm/cli/parsers/analyze_code_parser.py +170 -0
  112. claude_mpm/cli/parsers/analyze_parser.py +135 -0
  113. claude_mpm/cli/parsers/auto_configure_parser.py +120 -0
  114. claude_mpm/cli/parsers/base_parser.py +644 -0
  115. claude_mpm/cli/parsers/config_parser.py +208 -0
  116. claude_mpm/cli/parsers/configure_parser.py +138 -0
  117. claude_mpm/cli/parsers/dashboard_parser.py +113 -0
  118. claude_mpm/cli/parsers/debug_parser.py +319 -0
  119. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  120. claude_mpm/cli/parsers/mcp_parser.py +195 -0
  121. claude_mpm/cli/parsers/memory_parser.py +138 -0
  122. claude_mpm/cli/parsers/monitor_parser.py +142 -0
  123. claude_mpm/cli/parsers/mpm_init_parser.py +311 -0
  124. claude_mpm/cli/parsers/profile_parser.py +147 -0
  125. claude_mpm/cli/parsers/run_parser.py +157 -0
  126. claude_mpm/cli/parsers/search_parser.py +245 -0
  127. claude_mpm/cli/parsers/skill_source_parser.py +169 -0
  128. claude_mpm/cli/parsers/skills_parser.py +277 -0
  129. claude_mpm/cli/parsers/source_parser.py +138 -0
  130. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  131. claude_mpm/cli/shared/__init__.py +40 -0
  132. claude_mpm/cli/shared/argument_patterns.py +205 -0
  133. claude_mpm/cli/shared/base_command.py +242 -0
  134. claude_mpm/cli/shared/error_handling.py +242 -0
  135. claude_mpm/cli/shared/output_formatters.py +241 -0
  136. claude_mpm/cli/startup.py +1743 -0
  137. claude_mpm/cli/startup_display.py +480 -0
  138. claude_mpm/cli/startup_logging.py +839 -0
  139. claude_mpm/cli/utils.py +136 -47
  140. claude_mpm/cli_module/__init__.py +6 -6
  141. claude_mpm/cli_module/args.py +188 -140
  142. claude_mpm/cli_module/commands.py +79 -70
  143. claude_mpm/cli_module/migration_example.py +42 -64
  144. claude_mpm/commands/__init__.py +14 -0
  145. claude_mpm/commands/mpm-config.md +28 -0
  146. claude_mpm/commands/mpm-doctor.md +20 -0
  147. claude_mpm/commands/mpm-help.md +20 -0
  148. claude_mpm/commands/mpm-init.md +120 -0
  149. claude_mpm/commands/mpm-monitor.md +31 -0
  150. claude_mpm/commands/mpm-organize.md +120 -0
  151. claude_mpm/commands/mpm-postmortem.md +21 -0
  152. claude_mpm/commands/mpm-session-resume.md +30 -0
  153. claude_mpm/commands/mpm-status.md +20 -0
  154. claude_mpm/commands/mpm-ticket-view.md +109 -0
  155. claude_mpm/commands/mpm-version.md +20 -0
  156. claude_mpm/commands/mpm.md +31 -0
  157. claude_mpm/config/__init__.py +42 -2
  158. claude_mpm/config/agent_config.py +402 -0
  159. claude_mpm/config/agent_presets.py +488 -0
  160. claude_mpm/config/agent_sources.py +352 -0
  161. claude_mpm/config/experimental_features.py +217 -0
  162. claude_mpm/config/model_config.py +428 -0
  163. claude_mpm/config/paths.py +258 -0
  164. claude_mpm/config/skill_presets.py +392 -0
  165. claude_mpm/config/skill_sources.py +590 -0
  166. claude_mpm/config/socketio_config.py +125 -83
  167. claude_mpm/constants.py +132 -22
  168. claude_mpm/core/__init__.py +62 -36
  169. claude_mpm/core/agent_name_normalizer.py +71 -73
  170. claude_mpm/core/agent_registry.py +385 -492
  171. claude_mpm/core/agent_session_manager.py +81 -70
  172. claude_mpm/core/api_validator.py +330 -0
  173. claude_mpm/core/base_service.py +159 -122
  174. claude_mpm/core/cache.py +560 -0
  175. claude_mpm/core/claude_runner.py +696 -916
  176. claude_mpm/core/config.py +613 -122
  177. claude_mpm/core/config_aliases.py +74 -73
  178. claude_mpm/core/config_constants.py +314 -0
  179. claude_mpm/core/constants.py +361 -0
  180. claude_mpm/core/container.py +646 -104
  181. claude_mpm/core/enums.py +452 -0
  182. claude_mpm/core/error_handler.py +623 -0
  183. claude_mpm/core/exceptions.py +536 -0
  184. claude_mpm/core/factories.py +105 -109
  185. claude_mpm/core/file_utils.py +764 -0
  186. claude_mpm/core/framework/__init__.py +25 -0
  187. claude_mpm/core/framework/formatters/__init__.py +11 -0
  188. claude_mpm/core/framework/formatters/capability_generator.py +367 -0
  189. claude_mpm/core/framework/formatters/content_formatter.py +278 -0
  190. claude_mpm/core/framework/formatters/context_generator.py +185 -0
  191. claude_mpm/core/framework/loaders/__init__.py +13 -0
  192. claude_mpm/core/framework/loaders/agent_loader.py +213 -0
  193. claude_mpm/core/framework/loaders/file_loader.py +176 -0
  194. claude_mpm/core/framework/loaders/instruction_loader.py +222 -0
  195. claude_mpm/core/framework/loaders/packaged_loader.py +232 -0
  196. claude_mpm/core/framework/processors/__init__.py +11 -0
  197. claude_mpm/core/framework/processors/memory_processor.py +230 -0
  198. claude_mpm/core/framework/processors/metadata_processor.py +146 -0
  199. claude_mpm/core/framework/processors/template_processor.py +244 -0
  200. claude_mpm/core/framework_loader.py +485 -414
  201. claude_mpm/core/hook_error_memory.py +381 -0
  202. claude_mpm/core/hook_manager.py +246 -86
  203. claude_mpm/core/hook_performance_config.py +147 -0
  204. claude_mpm/core/injectable_service.py +72 -63
  205. claude_mpm/core/instruction_reinforcement_hook.py +267 -0
  206. claude_mpm/core/interactive_session.py +670 -0
  207. claude_mpm/core/interfaces.py +570 -164
  208. claude_mpm/core/lazy.py +467 -0
  209. claude_mpm/core/log_manager.py +707 -0
  210. claude_mpm/core/logger.py +295 -134
  211. claude_mpm/core/logging_config.py +474 -0
  212. claude_mpm/core/logging_utils.py +520 -0
  213. claude_mpm/core/minimal_framework_loader.py +24 -22
  214. claude_mpm/core/mixins.py +30 -29
  215. claude_mpm/core/oneshot_session.py +594 -0
  216. claude_mpm/core/optimized_agent_loader.py +479 -0
  217. claude_mpm/core/optimized_startup.py +554 -0
  218. claude_mpm/core/output_style_manager.py +483 -0
  219. claude_mpm/core/pm_hook_interceptor.py +197 -82
  220. claude_mpm/core/protocols/__init__.py +23 -0
  221. claude_mpm/core/protocols/runner_protocol.py +103 -0
  222. claude_mpm/core/protocols/session_protocol.py +131 -0
  223. claude_mpm/core/service_registry.py +153 -116
  224. claude_mpm/core/session_manager.py +179 -64
  225. claude_mpm/core/shared/__init__.py +17 -0
  226. claude_mpm/core/shared/config_loader.py +326 -0
  227. claude_mpm/core/shared/path_resolver.py +281 -0
  228. claude_mpm/core/shared/singleton_manager.py +221 -0
  229. claude_mpm/core/socketio_pool.py +400 -137
  230. claude_mpm/core/system_context.py +38 -0
  231. claude_mpm/core/tool_access_control.py +64 -57
  232. claude_mpm/core/types.py +307 -0
  233. claude_mpm/core/typing_utils.py +553 -0
  234. claude_mpm/core/unified_agent_registry.py +969 -0
  235. claude_mpm/core/unified_config.py +570 -0
  236. claude_mpm/core/unified_paths.py +941 -0
  237. claude_mpm/dashboard/__init__.py +12 -0
  238. claude_mpm/dashboard/api/simple_directory.py +261 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
  240. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +1 -0
  241. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +1 -0
  242. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +1 -0
  243. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +24 -0
  244. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B0uc0UOD.js +36 -0
  245. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7RN905-.js +1 -0
  246. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B7xVLGWV.js +2 -0
  247. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BIF9m_hv.js +61 -0
  248. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +1 -0
  249. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BPYeabCQ.js +1 -0
  250. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  251. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BSNlmTZj.js +1 -0
  252. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Be7GpZd6.js +7 -0
  253. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bh0LDWpI.js +145 -0
  254. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BofRWZRR.js +10 -0
  255. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BovzEFCE.js +30 -0
  256. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C30mlcqg.js +165 -0
  257. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4B-KCzX.js +1 -0
  258. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C4JcI4KD.js +122 -0
  259. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CBBdVcY8.js +1 -0
  260. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CDuw-vjf.js +1 -0
  261. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C_Usid8X.js +15 -0
  262. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cfqx1Qun.js +10 -0
  263. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CiIAseT4.js +128 -0
  264. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  265. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CnA0NrzZ.js +1 -0
  266. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cs_tUR18.js +24 -0
  267. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  268. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CyWMqx4W.js +43 -0
  269. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzZX-COe.js +220 -0
  270. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CzeYkLYB.js +65 -0
  271. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D3k0OPJN.js +4 -0
  272. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9lljYKQ.js +1 -0
  273. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DGkLK5U1.js +267 -0
  274. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DI7hHRFL.js +1 -0
  275. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DLVjFsZ3.js +139 -0
  276. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUrLdbGD.js +89 -0
  277. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  278. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DY1XQ8fi.js +2 -0
  279. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DZX00Y4g.js +1 -0
  280. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +1 -0
  281. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DaimHw_p.js +68 -0
  282. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +323 -0
  283. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dhb8PKl3.js +1 -0
  284. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dle-35c7.js +64 -0
  285. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DmxopI1J.js +1 -0
  286. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DwBR2MJi.js +60 -0
  287. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/GYwsonyD.js +1 -0
  288. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  289. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/NqQ1dWOy.js +1 -0
  290. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/RJiighC3.js +1 -0
  291. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Vzk33B_K.js +2 -0
  292. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ZGh7QtNv.js +7 -0
  293. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bT1r9zLR.js +1 -0
  294. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/bTOqqlTd.js +1 -0
  295. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/eNVUfhuA.js +1 -0
  296. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/iEWssX7S.js +162 -0
  297. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/sQeU3Y1z.js +1 -0
  298. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/uuIeMWc-.js +1 -0
  299. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.D6-I5TpK.js +2 -0
  300. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +1 -0
  301. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/0.m1gL8KXf.js +1 -0
  302. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.CgNOuw-d.js +1 -0
  303. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +1 -0
  304. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -0
  305. claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
  306. claude_mpm/dashboard/static/svelte-build/index.html +36 -0
  307. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  308. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  309. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  310. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  311. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  312. claude_mpm/experimental/__init__.py +10 -0
  313. claude_mpm/experimental/cli_enhancements.py +104 -89
  314. claude_mpm/generators/__init__.py +1 -1
  315. claude_mpm/generators/agent_profile_generator.py +76 -66
  316. claude_mpm/hooks/__init__.py +37 -1
  317. claude_mpm/hooks/base_hook.py +37 -32
  318. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  319. claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
  320. claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
  321. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  322. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  323. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  324. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  325. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  326. claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
  327. claude_mpm/hooks/claude_hooks/connection_pool.py +250 -0
  328. claude_mpm/hooks/claude_hooks/correlation_manager.py +60 -0
  329. claude_mpm/hooks/claude_hooks/event_handlers.py +888 -0
  330. claude_mpm/hooks/claude_hooks/hook_handler.py +652 -875
  331. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +10 -7
  332. claude_mpm/hooks/claude_hooks/installer.py +806 -0
  333. claude_mpm/hooks/claude_hooks/memory_integration.py +249 -0
  334. claude_mpm/hooks/claude_hooks/response_tracking.py +412 -0
  335. claude_mpm/hooks/claude_hooks/services/__init__.py +15 -0
  336. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  337. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  338. claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
  339. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  340. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  341. claude_mpm/hooks/claude_hooks/services/connection_manager.py +229 -0
  342. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +254 -0
  343. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  344. claude_mpm/hooks/claude_hooks/services/state_manager.py +284 -0
  345. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  346. claude_mpm/hooks/claude_hooks/tool_analysis.py +224 -0
  347. claude_mpm/hooks/failure_learning/__init__.py +54 -0
  348. claude_mpm/hooks/failure_learning/failure_detection_hook.py +230 -0
  349. claude_mpm/hooks/failure_learning/fix_detection_hook.py +212 -0
  350. claude_mpm/hooks/failure_learning/learning_extraction_hook.py +281 -0
  351. claude_mpm/hooks/instruction_reinforcement.py +301 -0
  352. claude_mpm/hooks/kuzu_enrichment_hook.py +263 -0
  353. claude_mpm/hooks/kuzu_memory_hook.py +386 -0
  354. claude_mpm/hooks/kuzu_response_hook.py +179 -0
  355. claude_mpm/hooks/memory_integration_hook.py +201 -107
  356. claude_mpm/hooks/session_resume_hook.py +121 -0
  357. claude_mpm/hooks/templates/pre_tool_use_simple.py +78 -0
  358. claude_mpm/hooks/templates/pre_tool_use_template.py +323 -0
  359. claude_mpm/hooks/tool_call_interceptor.py +92 -76
  360. claude_mpm/hooks/validation_hooks.py +62 -54
  361. claude_mpm/init.py +518 -83
  362. claude_mpm/models/__init__.py +9 -9
  363. claude_mpm/models/agent_definition.py +40 -23
  364. claude_mpm/models/agent_session.py +538 -0
  365. claude_mpm/models/git_repository.py +198 -0
  366. claude_mpm/models/resume_log.py +340 -0
  367. claude_mpm/schemas/__init__.py +12 -0
  368. claude_mpm/scripts/__init__.py +15 -0
  369. claude_mpm/scripts/claude-hook-handler.sh +227 -0
  370. claude_mpm/scripts/launch_monitor.py +165 -0
  371. claude_mpm/scripts/mpm_doctor.py +322 -0
  372. claude_mpm/scripts/socketio_daemon.py +189 -200
  373. claude_mpm/scripts/start_activity_logging.py +91 -0
  374. claude_mpm/services/__init__.py +208 -39
  375. claude_mpm/services/agent_capabilities_service.py +266 -0
  376. claude_mpm/services/agents/__init__.py +89 -0
  377. claude_mpm/services/agents/agent_builder.py +514 -0
  378. claude_mpm/services/agents/agent_preset_service.py +238 -0
  379. claude_mpm/services/agents/agent_recommendation_service.py +278 -0
  380. claude_mpm/services/agents/agent_review_service.py +280 -0
  381. claude_mpm/services/agents/agent_selection_service.py +484 -0
  382. claude_mpm/services/agents/auto_config_manager.py +796 -0
  383. claude_mpm/services/agents/auto_deploy_index_parser.py +569 -0
  384. claude_mpm/services/agents/cache_git_manager.py +621 -0
  385. claude_mpm/services/agents/deployment/__init__.py +21 -0
  386. claude_mpm/services/agents/deployment/agent_config_provider.py +410 -0
  387. claude_mpm/services/agents/deployment/agent_configuration_manager.py +358 -0
  388. claude_mpm/services/agents/deployment/agent_definition_factory.py +80 -0
  389. claude_mpm/services/agents/deployment/agent_deployment.py +1037 -0
  390. claude_mpm/services/agents/deployment/agent_discovery_service.py +546 -0
  391. claude_mpm/services/agents/deployment/agent_environment_manager.py +288 -0
  392. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +383 -0
  393. claude_mpm/services/agents/deployment/agent_format_converter.py +505 -0
  394. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +160 -0
  395. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +957 -0
  396. claude_mpm/services/agents/deployment/agent_metrics_collector.py +273 -0
  397. claude_mpm/services/agents/deployment/agent_operation_service.py +573 -0
  398. claude_mpm/services/agents/deployment/agent_record_service.py +418 -0
  399. claude_mpm/services/agents/deployment/agent_restore_handler.py +84 -0
  400. claude_mpm/services/agents/deployment/agent_state_service.py +381 -0
  401. claude_mpm/services/agents/deployment/agent_template_builder.py +1369 -0
  402. claude_mpm/services/agents/deployment/agent_validator.py +376 -0
  403. claude_mpm/services/agents/deployment/agent_version_manager.py +322 -0
  404. claude_mpm/services/{agent_versioning.py → agents/deployment/agent_versioning.py} +10 -13
  405. claude_mpm/services/agents/deployment/agents_directory_resolver.py +149 -0
  406. claude_mpm/services/agents/deployment/async_agent_deployment.py +768 -0
  407. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  408. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  409. claude_mpm/services/agents/deployment/config/deployment_config.py +181 -0
  410. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  411. claude_mpm/services/agents/deployment/deployment_config_loader.py +178 -0
  412. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  413. claude_mpm/services/agents/deployment/deployment_type_detector.py +120 -0
  414. claude_mpm/services/agents/deployment/deployment_wrapper.py +129 -0
  415. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  416. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  417. claude_mpm/services/agents/deployment/facade/deployment_executor.py +70 -0
  418. claude_mpm/services/agents/deployment/facade/deployment_facade.py +269 -0
  419. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  420. claude_mpm/services/agents/deployment/interface_adapter.py +226 -0
  421. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  422. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  423. claude_mpm/services/agents/deployment/local_template_deployment.py +362 -0
  424. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +1478 -0
  425. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  426. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  427. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +162 -0
  428. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  429. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  430. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +240 -0
  431. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +110 -0
  432. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +80 -0
  433. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +92 -0
  434. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +101 -0
  435. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  436. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +102 -0
  437. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  438. claude_mpm/services/agents/deployment/processors/agent_processor.py +269 -0
  439. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +311 -0
  440. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +862 -0
  441. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  442. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  443. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  444. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  445. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  446. claude_mpm/services/agents/deployment/strategies/base_strategy.py +113 -0
  447. claude_mpm/services/agents/deployment/strategies/project_strategy.py +148 -0
  448. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  449. claude_mpm/services/agents/deployment/strategies/system_strategy.py +131 -0
  450. claude_mpm/services/agents/deployment/strategies/user_strategy.py +130 -0
  451. claude_mpm/services/agents/deployment/system_instructions_deployer.py +228 -0
  452. claude_mpm/services/agents/deployment/validation/__init__.py +21 -0
  453. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  454. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  455. claude_mpm/services/agents/deployment/validation/template_validator.py +319 -0
  456. claude_mpm/services/agents/deployment/validation/validation_result.py +214 -0
  457. claude_mpm/services/agents/git_source_manager.py +682 -0
  458. claude_mpm/services/agents/loading/__init__.py +11 -0
  459. claude_mpm/services/{agent_profile_loader.py → agents/loading/agent_profile_loader.py} +306 -228
  460. claude_mpm/services/{base_agent_manager.py → agents/loading/base_agent_manager.py} +106 -91
  461. claude_mpm/services/agents/loading/framework_agent_loader.py +433 -0
  462. claude_mpm/services/agents/local_template_manager.py +784 -0
  463. claude_mpm/services/agents/management/__init__.py +9 -0
  464. claude_mpm/services/{agent_capabilities_generator.py → agents/management/agent_capabilities_generator.py} +92 -69
  465. claude_mpm/services/{agent_management_service.py → agents/management/agent_management_service.py} +219 -168
  466. claude_mpm/services/agents/memory/__init__.py +22 -0
  467. claude_mpm/services/agents/memory/agent_memory_manager.py +784 -0
  468. claude_mpm/services/{agent_persistence_service.py → agents/memory/agent_persistence_service.py} +20 -18
  469. claude_mpm/services/agents/memory/content_manager.py +470 -0
  470. claude_mpm/services/agents/memory/memory_categorization_service.py +167 -0
  471. claude_mpm/services/agents/memory/memory_file_service.py +129 -0
  472. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  473. claude_mpm/services/agents/memory/memory_limits_service.py +101 -0
  474. claude_mpm/services/agents/memory/template_generator.py +83 -0
  475. claude_mpm/services/agents/observers.py +547 -0
  476. claude_mpm/services/agents/recommender.py +617 -0
  477. claude_mpm/services/agents/registry/__init__.py +30 -0
  478. claude_mpm/services/agents/registry/deployed_agent_discovery.py +273 -0
  479. claude_mpm/services/{agent_modification_tracker.py → agents/registry/modification_tracker.py} +370 -295
  480. claude_mpm/services/agents/single_tier_deployment_service.py +696 -0
  481. claude_mpm/services/agents/sources/__init__.py +13 -0
  482. claude_mpm/services/agents/sources/agent_sync_state.py +516 -0
  483. claude_mpm/services/agents/sources/git_source_sync_service.py +1202 -0
  484. claude_mpm/services/agents/startup_sync.py +259 -0
  485. claude_mpm/services/agents/toolchain_detector.py +478 -0
  486. claude_mpm/services/analysis/__init__.py +35 -0
  487. claude_mpm/services/analysis/clone_detector.py +1030 -0
  488. claude_mpm/services/analysis/postmortem_reporter.py +474 -0
  489. claude_mpm/services/analysis/postmortem_service.py +765 -0
  490. claude_mpm/services/async_session_logger.py +665 -0
  491. claude_mpm/services/claude_session_logger.py +321 -0
  492. claude_mpm/services/cli/__init__.py +18 -0
  493. claude_mpm/services/cli/agent_cleanup_service.py +408 -0
  494. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  495. claude_mpm/services/cli/agent_listing_service.py +463 -0
  496. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  497. claude_mpm/services/cli/agent_validation_service.py +590 -0
  498. claude_mpm/services/cli/memory_crud_service.py +622 -0
  499. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  500. claude_mpm/services/cli/resume_service.py +617 -0
  501. claude_mpm/services/cli/session_manager.py +604 -0
  502. claude_mpm/services/cli/session_pause_manager.py +504 -0
  503. claude_mpm/services/cli/session_resume_helper.py +372 -0
  504. claude_mpm/services/cli/startup_checker.py +362 -0
  505. claude_mpm/services/cli/unified_dashboard_manager.py +439 -0
  506. claude_mpm/services/command_deployment_service.py +446 -0
  507. claude_mpm/services/command_handler_service.py +221 -0
  508. claude_mpm/services/communication/__init__.py +22 -0
  509. claude_mpm/services/core/__init__.py +108 -0
  510. claude_mpm/services/core/base.py +269 -0
  511. claude_mpm/services/core/cache_manager.py +309 -0
  512. claude_mpm/services/core/interfaces/__init__.py +273 -0
  513. claude_mpm/services/core/interfaces/agent.py +514 -0
  514. claude_mpm/services/core/interfaces/communication.py +316 -0
  515. claude_mpm/services/core/interfaces/health.py +169 -0
  516. claude_mpm/services/core/interfaces/infrastructure.py +357 -0
  517. claude_mpm/services/core/interfaces/model.py +281 -0
  518. claude_mpm/services/core/interfaces/process.py +372 -0
  519. claude_mpm/services/core/interfaces/project.py +121 -0
  520. claude_mpm/services/core/interfaces/restart.py +307 -0
  521. claude_mpm/services/core/interfaces/service.py +405 -0
  522. claude_mpm/services/core/interfaces/stability.py +260 -0
  523. claude_mpm/services/core/interfaces.py +81 -0
  524. claude_mpm/services/core/memory_manager.py +682 -0
  525. claude_mpm/services/core/models/__init__.py +70 -0
  526. claude_mpm/services/core/models/agent_config.py +384 -0
  527. claude_mpm/services/core/models/health.py +162 -0
  528. claude_mpm/services/core/models/process.py +239 -0
  529. claude_mpm/services/core/models/restart.py +302 -0
  530. claude_mpm/services/core/models/stability.py +264 -0
  531. claude_mpm/services/core/models/toolchain.py +306 -0
  532. claude_mpm/services/core/path_resolver.py +517 -0
  533. claude_mpm/services/core/service_container.py +520 -0
  534. claude_mpm/services/core/service_interfaces.py +436 -0
  535. claude_mpm/services/diagnostics/__init__.py +18 -0
  536. claude_mpm/services/diagnostics/checks/__init__.py +38 -0
  537. claude_mpm/services/diagnostics/checks/agent_check.py +370 -0
  538. claude_mpm/services/diagnostics/checks/agent_sources_check.py +577 -0
  539. claude_mpm/services/diagnostics/checks/base_check.py +60 -0
  540. claude_mpm/services/diagnostics/checks/claude_code_check.py +270 -0
  541. claude_mpm/services/diagnostics/checks/common_issues_check.py +363 -0
  542. claude_mpm/services/diagnostics/checks/configuration_check.py +306 -0
  543. claude_mpm/services/diagnostics/checks/filesystem_check.py +233 -0
  544. claude_mpm/services/diagnostics/checks/installation_check.py +520 -0
  545. claude_mpm/services/diagnostics/checks/instructions_check.py +415 -0
  546. claude_mpm/services/diagnostics/checks/mcp_check.py +330 -0
  547. claude_mpm/services/diagnostics/checks/mcp_services_check.py +1058 -0
  548. claude_mpm/services/diagnostics/checks/monitor_check.py +281 -0
  549. claude_mpm/services/diagnostics/checks/skill_sources_check.py +587 -0
  550. claude_mpm/services/diagnostics/checks/startup_log_check.py +319 -0
  551. claude_mpm/services/diagnostics/diagnostic_runner.py +286 -0
  552. claude_mpm/services/diagnostics/doctor_reporter.py +578 -0
  553. claude_mpm/services/diagnostics/models.py +138 -0
  554. claude_mpm/services/event_aggregator.py +582 -0
  555. claude_mpm/services/event_bus/__init__.py +18 -0
  556. claude_mpm/services/event_bus/config.py +186 -0
  557. claude_mpm/services/event_bus/direct_relay.py +312 -0
  558. claude_mpm/services/event_bus/event_bus.py +396 -0
  559. claude_mpm/services/event_bus/relay.py +326 -0
  560. claude_mpm/services/events/__init__.py +44 -0
  561. claude_mpm/services/events/consumers/__init__.py +18 -0
  562. claude_mpm/services/events/consumers/dead_letter.py +306 -0
  563. claude_mpm/services/events/consumers/logging.py +184 -0
  564. claude_mpm/services/events/consumers/metrics.py +241 -0
  565. claude_mpm/services/events/consumers/socketio.py +377 -0
  566. claude_mpm/services/events/core.py +480 -0
  567. claude_mpm/services/events/interfaces.py +214 -0
  568. claude_mpm/services/events/producers/__init__.py +14 -0
  569. claude_mpm/services/events/producers/hook.py +269 -0
  570. claude_mpm/services/events/producers/system.py +329 -0
  571. claude_mpm/services/exceptions.py +433 -353
  572. claude_mpm/services/framework_claude_md_generator/__init__.py +81 -80
  573. claude_mpm/services/framework_claude_md_generator/content_assembler.py +74 -67
  574. claude_mpm/services/framework_claude_md_generator/content_validator.py +66 -62
  575. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +82 -60
  576. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +36 -37
  577. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +41 -40
  578. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +15 -15
  579. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +5 -4
  580. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  581. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  582. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  583. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  584. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +5 -4
  585. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  586. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  587. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +26 -30
  588. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +6 -5
  589. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  590. claude_mpm/services/framework_claude_md_generator/version_manager.py +31 -30
  591. claude_mpm/services/git/__init__.py +21 -0
  592. claude_mpm/services/git/git_operations_service.py +579 -0
  593. claude_mpm/services/github/__init__.py +21 -0
  594. claude_mpm/services/github/github_cli_service.py +397 -0
  595. claude_mpm/services/hook_installer_service.py +506 -0
  596. claude_mpm/services/hook_service.py +159 -111
  597. claude_mpm/services/infrastructure/__init__.py +52 -0
  598. claude_mpm/services/infrastructure/context_preservation.py +569 -0
  599. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  600. claude_mpm/services/infrastructure/logging.py +209 -0
  601. claude_mpm/services/infrastructure/monitoring/__init__.py +39 -0
  602. claude_mpm/services/infrastructure/monitoring/aggregator.py +432 -0
  603. claude_mpm/services/infrastructure/monitoring/base.py +122 -0
  604. claude_mpm/services/infrastructure/monitoring/legacy.py +203 -0
  605. claude_mpm/services/infrastructure/monitoring/network.py +219 -0
  606. claude_mpm/services/infrastructure/monitoring/process.py +343 -0
  607. claude_mpm/services/infrastructure/monitoring/resources.py +244 -0
  608. claude_mpm/services/infrastructure/monitoring/service.py +368 -0
  609. claude_mpm/services/infrastructure/monitoring.py +71 -0
  610. claude_mpm/services/infrastructure/resume_log_generator.py +439 -0
  611. claude_mpm/services/instructions/__init__.py +9 -0
  612. claude_mpm/services/instructions/instruction_cache_service.py +374 -0
  613. claude_mpm/services/local_ops/__init__.py +155 -0
  614. claude_mpm/services/local_ops/crash_detector.py +257 -0
  615. claude_mpm/services/local_ops/health_checks/__init__.py +26 -0
  616. claude_mpm/services/local_ops/health_checks/http_check.py +224 -0
  617. claude_mpm/services/local_ops/health_checks/process_check.py +236 -0
  618. claude_mpm/services/local_ops/health_checks/resource_check.py +255 -0
  619. claude_mpm/services/local_ops/health_manager.py +427 -0
  620. claude_mpm/services/local_ops/log_monitor.py +396 -0
  621. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  622. claude_mpm/services/local_ops/process_manager.py +595 -0
  623. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  624. claude_mpm/services/local_ops/restart_manager.py +401 -0
  625. claude_mpm/services/local_ops/restart_policy.py +387 -0
  626. claude_mpm/services/local_ops/state_manager.py +372 -0
  627. claude_mpm/services/local_ops/unified_manager.py +600 -0
  628. claude_mpm/services/mcp_config_manager.py +1542 -0
  629. claude_mpm/services/mcp_service_verifier.py +732 -0
  630. claude_mpm/services/memory/__init__.py +19 -0
  631. claude_mpm/services/{memory_builder.py → memory/builder.py} +465 -373
  632. claude_mpm/services/memory/cache/__init__.py +14 -0
  633. claude_mpm/services/{shared_prompt_cache.py → memory/cache/shared_prompt_cache.py} +237 -200
  634. claude_mpm/services/memory/cache/simple_cache.py +331 -0
  635. claude_mpm/services/memory/failure_tracker.py +578 -0
  636. claude_mpm/services/memory/indexed_memory.py +648 -0
  637. claude_mpm/services/{memory_optimizer.py → memory/optimizer.py} +272 -243
  638. claude_mpm/services/memory/router.py +951 -0
  639. claude_mpm/services/memory_hook_service.py +470 -0
  640. claude_mpm/services/model/__init__.py +147 -0
  641. claude_mpm/services/model/base_provider.py +365 -0
  642. claude_mpm/services/model/claude_provider.py +412 -0
  643. claude_mpm/services/model/model_router.py +452 -0
  644. claude_mpm/services/model/ollama_provider.py +415 -0
  645. claude_mpm/services/monitor/__init__.py +20 -0
  646. claude_mpm/services/monitor/daemon.py +698 -0
  647. claude_mpm/services/monitor/daemon_manager.py +1076 -0
  648. claude_mpm/services/monitor/event_emitter.py +350 -0
  649. claude_mpm/services/monitor/handlers/__init__.py +21 -0
  650. claude_mpm/services/monitor/handlers/code_analysis.py +332 -0
  651. claude_mpm/services/monitor/handlers/dashboard.py +299 -0
  652. claude_mpm/services/monitor/handlers/file.py +264 -0
  653. claude_mpm/services/monitor/handlers/hooks.py +512 -0
  654. claude_mpm/services/monitor/management/__init__.py +18 -0
  655. claude_mpm/services/monitor/management/health.py +124 -0
  656. claude_mpm/services/monitor/management/lifecycle.py +730 -0
  657. claude_mpm/services/monitor/server.py +1493 -0
  658. claude_mpm/services/monitor_build_service.py +349 -0
  659. claude_mpm/services/native_agent_converter.py +356 -0
  660. claude_mpm/services/orphan_detection.py +786 -0
  661. claude_mpm/services/pm_skills_deployer.py +707 -0
  662. claude_mpm/services/port_manager.py +597 -0
  663. claude_mpm/services/pr/__init__.py +14 -0
  664. claude_mpm/services/pr/pr_template_service.py +329 -0
  665. claude_mpm/services/profile_manager.py +337 -0
  666. claude_mpm/services/project/__init__.py +44 -0
  667. claude_mpm/services/{project_analyzer.py → project/analyzer.py} +541 -291
  668. claude_mpm/services/project/analyzer_v2.py +566 -0
  669. claude_mpm/services/project/architecture_analyzer.py +461 -0
  670. claude_mpm/services/project/archive_manager.py +1045 -0
  671. claude_mpm/services/project/dependency_analyzer.py +462 -0
  672. claude_mpm/services/project/detection_strategies.py +719 -0
  673. claude_mpm/services/project/documentation_manager.py +554 -0
  674. claude_mpm/services/project/enhanced_analyzer.py +572 -0
  675. claude_mpm/services/project/language_analyzer.py +265 -0
  676. claude_mpm/services/project/metrics_collector.py +407 -0
  677. claude_mpm/services/project/project_organizer.py +1009 -0
  678. claude_mpm/services/project/registry.py +636 -0
  679. claude_mpm/services/project/toolchain_analyzer.py +583 -0
  680. claude_mpm/services/project_port_allocator.py +596 -0
  681. claude_mpm/services/recovery_manager.py +293 -240
  682. claude_mpm/services/response_tracker.py +267 -0
  683. claude_mpm/services/runner_configuration_service.py +605 -0
  684. claude_mpm/services/self_upgrade_service.py +608 -0
  685. claude_mpm/services/session_management_service.py +314 -0
  686. claude_mpm/services/session_manager.py +380 -0
  687. claude_mpm/services/shared/__init__.py +21 -0
  688. claude_mpm/services/shared/async_service_base.py +216 -0
  689. claude_mpm/services/shared/config_service_base.py +301 -0
  690. claude_mpm/services/shared/lifecycle_service_base.py +308 -0
  691. claude_mpm/services/shared/manager_base.py +315 -0
  692. claude_mpm/services/shared/service_factory.py +309 -0
  693. claude_mpm/services/skills/__init__.py +21 -0
  694. claude_mpm/services/skills/git_skill_source_manager.py +1324 -0
  695. claude_mpm/services/skills/selective_skill_deployer.py +744 -0
  696. claude_mpm/services/skills/skill_discovery_service.py +568 -0
  697. claude_mpm/services/skills/skill_to_agent_mapper.py +406 -0
  698. claude_mpm/services/skills_config.py +547 -0
  699. claude_mpm/services/skills_deployer.py +1168 -0
  700. claude_mpm/services/socketio/__init__.py +25 -0
  701. claude_mpm/services/socketio/client_proxy.py +229 -0
  702. claude_mpm/services/socketio/dashboard_server.py +362 -0
  703. claude_mpm/services/socketio/event_normalizer.py +798 -0
  704. claude_mpm/services/socketio/handlers/__init__.py +30 -0
  705. claude_mpm/services/socketio/handlers/base.py +136 -0
  706. claude_mpm/services/socketio/handlers/code_analysis.py +682 -0
  707. claude_mpm/services/socketio/handlers/connection.py +643 -0
  708. claude_mpm/services/socketio/handlers/connection_handler.py +333 -0
  709. claude_mpm/services/socketio/handlers/file.py +263 -0
  710. claude_mpm/services/socketio/handlers/git.py +962 -0
  711. claude_mpm/services/socketio/handlers/hook.py +211 -0
  712. claude_mpm/services/socketio/handlers/memory.py +26 -0
  713. claude_mpm/services/socketio/handlers/project.py +24 -0
  714. claude_mpm/services/socketio/handlers/registry.py +214 -0
  715. claude_mpm/services/socketio/migration_utils.py +343 -0
  716. claude_mpm/services/socketio/monitor_client.py +364 -0
  717. claude_mpm/services/socketio/server/__init__.py +18 -0
  718. claude_mpm/services/socketio/server/broadcaster.py +569 -0
  719. claude_mpm/services/socketio/server/connection_manager.py +579 -0
  720. claude_mpm/services/socketio/server/core.py +1079 -0
  721. claude_mpm/services/socketio/server/eventbus_integration.py +245 -0
  722. claude_mpm/services/socketio/server/main.py +501 -0
  723. claude_mpm/services/socketio_client_manager.py +173 -143
  724. claude_mpm/services/socketio_server.py +38 -1657
  725. claude_mpm/services/subprocess_launcher_service.py +322 -0
  726. claude_mpm/services/system_instructions_service.py +270 -0
  727. claude_mpm/services/ticket_manager.py +25 -209
  728. claude_mpm/services/ticket_services/__init__.py +26 -0
  729. claude_mpm/services/ticket_services/crud_service.py +328 -0
  730. claude_mpm/services/ticket_services/formatter_service.py +290 -0
  731. claude_mpm/services/ticket_services/search_service.py +324 -0
  732. claude_mpm/services/ticket_services/validation_service.py +303 -0
  733. claude_mpm/services/ticket_services/workflow_service.py +244 -0
  734. claude_mpm/services/unified/__init__.py +65 -0
  735. claude_mpm/services/unified/analyzer_strategies/__init__.py +44 -0
  736. claude_mpm/services/unified/analyzer_strategies/code_analyzer.py +518 -0
  737. claude_mpm/services/unified/analyzer_strategies/dependency_analyzer.py +680 -0
  738. claude_mpm/services/unified/analyzer_strategies/performance_analyzer.py +900 -0
  739. claude_mpm/services/unified/analyzer_strategies/security_analyzer.py +745 -0
  740. claude_mpm/services/unified/analyzer_strategies/structure_analyzer.py +733 -0
  741. claude_mpm/services/unified/config_strategies/__init__.py +175 -0
  742. claude_mpm/services/unified/config_strategies/config_schema.py +731 -0
  743. claude_mpm/services/unified/config_strategies/context_strategy.py +747 -0
  744. claude_mpm/services/unified/config_strategies/error_handling_strategy.py +1005 -0
  745. claude_mpm/services/unified/config_strategies/file_loader_strategy.py +881 -0
  746. claude_mpm/services/unified/config_strategies/unified_config_service.py +823 -0
  747. claude_mpm/services/unified/config_strategies/validation_strategy.py +1148 -0
  748. claude_mpm/services/unified/deployment_strategies/__init__.py +97 -0
  749. claude_mpm/services/unified/deployment_strategies/base.py +553 -0
  750. claude_mpm/services/unified/deployment_strategies/cloud_strategies.py +573 -0
  751. claude_mpm/services/unified/deployment_strategies/local.py +607 -0
  752. claude_mpm/services/unified/deployment_strategies/utils.py +667 -0
  753. claude_mpm/services/unified/deployment_strategies/vercel.py +471 -0
  754. claude_mpm/services/unified/interfaces.py +475 -0
  755. claude_mpm/services/unified/migration.py +509 -0
  756. claude_mpm/services/unified/strategies.py +534 -0
  757. claude_mpm/services/unified/unified_analyzer.py +542 -0
  758. claude_mpm/services/unified/unified_config.py +691 -0
  759. claude_mpm/services/unified/unified_deployment.py +466 -0
  760. claude_mpm/services/utility_service.py +280 -0
  761. claude_mpm/services/version_control/__init__.py +34 -37
  762. claude_mpm/services/version_control/branch_strategy.py +26 -17
  763. claude_mpm/services/version_control/conflict_resolution.py +52 -36
  764. claude_mpm/services/version_control/git_operations.py +183 -49
  765. claude_mpm/services/version_control/semantic_versioning.py +172 -61
  766. claude_mpm/services/version_control/version_parser.py +546 -0
  767. claude_mpm/services/version_service.py +379 -0
  768. claude_mpm/services/visualization/__init__.py +15 -0
  769. claude_mpm/services/visualization/mermaid_generator.py +937 -0
  770. claude_mpm/skills/__init__.py +42 -0
  771. claude_mpm/skills/agent_skills_injector.py +324 -0
  772. claude_mpm/skills/bundled/LICENSE_ATTRIBUTIONS.md +79 -0
  773. claude_mpm/skills/bundled/__init__.py +6 -0
  774. claude_mpm/skills/bundled/api-documentation.md +393 -0
  775. claude_mpm/skills/bundled/async-testing.md +571 -0
  776. claude_mpm/skills/bundled/code-review.md +143 -0
  777. claude_mpm/skills/bundled/database-migration.md +199 -0
  778. claude_mpm/skills/bundled/docker-containerization.md +194 -0
  779. claude_mpm/skills/bundled/express-local-dev.md +1429 -0
  780. claude_mpm/skills/bundled/fastapi-local-dev.md +1199 -0
  781. claude_mpm/skills/bundled/git-workflow.md +414 -0
  782. claude_mpm/skills/bundled/imagemagick.md +204 -0
  783. claude_mpm/skills/bundled/infrastructure/env-manager/scripts/validate_env.py +576 -0
  784. claude_mpm/skills/bundled/json-data-handling.md +223 -0
  785. claude_mpm/skills/bundled/main/mcp-builder/scripts/connections.py +157 -0
  786. claude_mpm/skills/bundled/main/mcp-builder/scripts/evaluation.py +425 -0
  787. claude_mpm/skills/bundled/main/skill-creator/scripts/init_skill.py +303 -0
  788. claude_mpm/skills/bundled/main/skill-creator/scripts/package_skill.py +113 -0
  789. claude_mpm/skills/bundled/main/skill-creator/scripts/quick_validate.py +72 -0
  790. claude_mpm/skills/bundled/nextjs-local-dev.md +807 -0
  791. claude_mpm/skills/bundled/pdf.md +141 -0
  792. claude_mpm/skills/bundled/performance-profiling.md +573 -0
  793. claude_mpm/skills/bundled/refactoring-patterns.md +180 -0
  794. claude_mpm/skills/bundled/security-scanning.md +439 -0
  795. claude_mpm/skills/bundled/systematic-debugging.md +473 -0
  796. claude_mpm/skills/bundled/test-driven-development.md +378 -0
  797. claude_mpm/skills/bundled/testing/webapp-testing/examples/console_logging.py +35 -0
  798. claude_mpm/skills/bundled/testing/webapp-testing/examples/element_discovery.py +44 -0
  799. claude_mpm/skills/bundled/testing/webapp-testing/examples/static_html_automation.py +34 -0
  800. claude_mpm/skills/bundled/testing/webapp-testing/scripts/with_server.py +129 -0
  801. claude_mpm/skills/bundled/vite-local-dev.md +1061 -0
  802. claude_mpm/skills/bundled/web-performance-optimization.md +2305 -0
  803. claude_mpm/skills/bundled/xlsx.md +157 -0
  804. claude_mpm/skills/registry.py +286 -0
  805. claude_mpm/skills/skill_manager.py +405 -0
  806. claude_mpm/skills/skills_registry.py +347 -0
  807. claude_mpm/skills/skills_service.py +739 -0
  808. claude_mpm/storage/__init__.py +9 -0
  809. claude_mpm/storage/state_storage.py +546 -0
  810. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  811. claude_mpm/templates/questions/__init__.py +38 -0
  812. claude_mpm/templates/questions/base.py +193 -0
  813. claude_mpm/templates/questions/pr_strategy.py +311 -0
  814. claude_mpm/templates/questions/project_init.py +385 -0
  815. claude_mpm/templates/questions/ticket_mgmt.py +394 -0
  816. claude_mpm/ticket_wrapper.py +2 -2
  817. claude_mpm/tools/__init__.py +10 -0
  818. claude_mpm/tools/__main__.py +208 -0
  819. claude_mpm/tools/code_tree_analyzer/__init__.py +45 -0
  820. claude_mpm/tools/code_tree_analyzer/analysis.py +299 -0
  821. claude_mpm/tools/code_tree_analyzer/cache.py +131 -0
  822. claude_mpm/tools/code_tree_analyzer/core.py +380 -0
  823. claude_mpm/tools/code_tree_analyzer/discovery.py +403 -0
  824. claude_mpm/tools/code_tree_analyzer/events.py +168 -0
  825. claude_mpm/tools/code_tree_analyzer/gitignore.py +308 -0
  826. claude_mpm/tools/code_tree_analyzer/models.py +39 -0
  827. claude_mpm/tools/code_tree_analyzer/multilang_analyzer.py +224 -0
  828. claude_mpm/tools/code_tree_analyzer/python_analyzer.py +284 -0
  829. claude_mpm/tools/code_tree_builder.py +631 -0
  830. claude_mpm/tools/code_tree_events.py +420 -0
  831. claude_mpm/tools/socketio_debug.py +671 -0
  832. claude_mpm/utils/__init__.py +8 -8
  833. claude_mpm/utils/agent_dependency_loader.py +1090 -0
  834. claude_mpm/utils/agent_filters.py +261 -0
  835. claude_mpm/utils/common.py +544 -0
  836. claude_mpm/utils/config_manager.py +168 -126
  837. claude_mpm/utils/console.py +11 -0
  838. claude_mpm/utils/database_connector.py +298 -0
  839. claude_mpm/utils/dependency_cache.py +373 -0
  840. claude_mpm/utils/dependency_manager.py +60 -59
  841. claude_mpm/utils/dependency_strategies.py +381 -0
  842. claude_mpm/utils/display_helper.py +260 -0
  843. claude_mpm/utils/environment_context.py +313 -0
  844. claude_mpm/utils/error_handler.py +78 -66
  845. claude_mpm/utils/file_utils.py +305 -0
  846. claude_mpm/utils/framework_detection.py +12 -11
  847. claude_mpm/utils/git_analyzer.py +407 -0
  848. claude_mpm/utils/gitignore.py +244 -0
  849. claude_mpm/utils/import_migration_example.py +12 -60
  850. claude_mpm/utils/imports.py +48 -45
  851. claude_mpm/utils/log_cleanup.py +627 -0
  852. claude_mpm/utils/migration.py +372 -0
  853. claude_mpm/utils/path_operations.py +110 -104
  854. claude_mpm/utils/progress.py +387 -0
  855. claude_mpm/utils/robust_installer.py +823 -0
  856. claude_mpm/utils/session_logging.py +121 -0
  857. claude_mpm/utils/structured_questions.py +619 -0
  858. claude_mpm/utils/subprocess_utils.py +343 -0
  859. claude_mpm/validation/__init__.py +1 -1
  860. claude_mpm/validation/agent_validator.py +214 -108
  861. claude_mpm/validation/frontmatter_validator.py +252 -0
  862. claude_mpm-5.4.55.dist-info/METADATA +999 -0
  863. claude_mpm-5.4.55.dist-info/RECORD +868 -0
  864. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/entry_points.txt +1 -3
  865. claude_mpm-5.4.55.dist-info/licenses/LICENSE +94 -0
  866. claude_mpm-5.4.55.dist-info/licenses/LICENSE-FAQ.md +153 -0
  867. claude_mpm/agents/BASE_AGENT_TEMPLATE.md +0 -88
  868. claude_mpm/agents/INSTRUCTIONS.md +0 -352
  869. claude_mpm/agents/backups/INSTRUCTIONS.md +0 -352
  870. claude_mpm/agents/base_agent_loader.py +0 -529
  871. claude_mpm/agents/schema/agent_schema.json +0 -314
  872. claude_mpm/agents/templates/.claude-mpm/memories/README.md +0 -36
  873. claude_mpm/agents/templates/backup/data_engineer_agent_20250726_234551.json +0 -46
  874. claude_mpm/agents/templates/backup/documentation_agent_20250726_234551.json +0 -45
  875. claude_mpm/agents/templates/backup/engineer_agent_20250726_234551.json +0 -49
  876. claude_mpm/agents/templates/backup/ops_agent_20250726_234551.json +0 -46
  877. claude_mpm/agents/templates/backup/qa_agent_20250726_234551.json +0 -45
  878. claude_mpm/agents/templates/backup/research_agent_20250726_234551.json +0 -49
  879. claude_mpm/agents/templates/backup/security_agent_20250726_234551.json +0 -46
  880. claude_mpm/agents/templates/backup/version_control_agent_20250726_234551.json +0 -46
  881. claude_mpm/agents/templates/data_engineer.json +0 -110
  882. claude_mpm/agents/templates/documentation.json +0 -109
  883. claude_mpm/agents/templates/engineer.json +0 -113
  884. claude_mpm/agents/templates/ops.json +0 -109
  885. claude_mpm/agents/templates/pm.json +0 -25
  886. claude_mpm/agents/templates/qa.json +0 -111
  887. claude_mpm/agents/templates/research.json +0 -65
  888. claude_mpm/agents/templates/security.json +0 -113
  889. claude_mpm/agents/templates/test_integration.json +0 -112
  890. claude_mpm/agents/templates/version_control.json +0 -107
  891. claude_mpm/cli/commands/ui.py +0 -57
  892. claude_mpm/core/simple_runner.py +0 -1046
  893. claude_mpm/dashboard/open_dashboard.py +0 -34
  894. claude_mpm/deployment_paths.py +0 -261
  895. claude_mpm/hooks/builtin/__init__.py +0 -1
  896. claude_mpm/hooks/builtin/logging_hook_example.py +0 -165
  897. claude_mpm/hooks/builtin/memory_hooks_example.py +0 -67
  898. claude_mpm/hooks/builtin/mpm_command_hook.py +0 -125
  899. claude_mpm/hooks/builtin/post_delegation_hook_example.py +0 -124
  900. claude_mpm/hooks/builtin/pre_delegation_hook_example.py +0 -125
  901. claude_mpm/hooks/builtin/submit_hook_example.py +0 -100
  902. claude_mpm/hooks/builtin/ticket_extraction_hook_example.py +0 -237
  903. claude_mpm/hooks/builtin/todo_agent_prefix_hook.py +0 -240
  904. claude_mpm/hooks/builtin/workflow_start_hook.py +0 -181
  905. claude_mpm/orchestration/__init__.py +0 -6
  906. claude_mpm/orchestration/archive/direct_orchestrator.py +0 -195
  907. claude_mpm/orchestration/archive/factory.py +0 -215
  908. claude_mpm/orchestration/archive/hook_enabled_orchestrator.py +0 -188
  909. claude_mpm/orchestration/archive/hook_integration_example.py +0 -178
  910. claude_mpm/orchestration/archive/interactive_subprocess_orchestrator.py +0 -826
  911. claude_mpm/orchestration/archive/orchestrator.py +0 -501
  912. claude_mpm/orchestration/archive/pexpect_orchestrator.py +0 -252
  913. claude_mpm/orchestration/archive/pty_orchestrator.py +0 -270
  914. claude_mpm/orchestration/archive/simple_orchestrator.py +0 -82
  915. claude_mpm/orchestration/archive/subprocess_orchestrator.py +0 -801
  916. claude_mpm/orchestration/archive/system_prompt_orchestrator.py +0 -278
  917. claude_mpm/orchestration/archive/wrapper_orchestrator.py +0 -187
  918. claude_mpm/schemas/workflow_validator.py +0 -411
  919. claude_mpm/services/agent_deployment.py +0 -1534
  920. claude_mpm/services/agent_lifecycle_manager.py +0 -1169
  921. claude_mpm/services/agent_memory_manager.py +0 -1415
  922. claude_mpm/services/agent_registry.py +0 -676
  923. claude_mpm/services/deployed_agent_discovery.py +0 -226
  924. claude_mpm/services/framework_agent_loader.py +0 -337
  925. claude_mpm/services/framework_claude_md_generator.py +0 -621
  926. claude_mpm/services/health_monitor.py +0 -892
  927. claude_mpm/services/memory_router.py +0 -538
  928. claude_mpm/services/parent_directory_manager/__init__.py +0 -577
  929. claude_mpm/services/parent_directory_manager/backup_manager.py +0 -258
  930. claude_mpm/services/parent_directory_manager/config_manager.py +0 -210
  931. claude_mpm/services/parent_directory_manager/deduplication_manager.py +0 -279
  932. claude_mpm/services/parent_directory_manager/framework_protector.py +0 -143
  933. claude_mpm/services/parent_directory_manager/operations.py +0 -186
  934. claude_mpm/services/parent_directory_manager/state_manager.py +0 -624
  935. claude_mpm/services/parent_directory_manager/template_deployer.py +0 -579
  936. claude_mpm/services/parent_directory_manager/validation_manager.py +0 -378
  937. claude_mpm/services/parent_directory_manager/version_control_helper.py +0 -339
  938. claude_mpm/services/parent_directory_manager/version_manager.py +0 -222
  939. claude_mpm/services/standalone_socketio_server.py +0 -1300
  940. claude_mpm/services/ticket_manager_di.py +0 -318
  941. claude_mpm/services/ticketing_service_original.py +0 -508
  942. claude_mpm/ui/__init__.py +0 -1
  943. claude_mpm/ui/rich_terminal_ui.py +0 -295
  944. claude_mpm/ui/terminal_ui.py +0 -328
  945. claude_mpm/utils/paths.py +0 -289
  946. claude_mpm-3.4.10.dist-info/METADATA +0 -183
  947. claude_mpm-3.4.10.dist-info/RECORD +0 -201
  948. claude_mpm-3.4.10.dist-info/licenses/LICENSE +0 -21
  949. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/WHEEL +0 -0
  950. {claude_mpm-3.4.10.dist-info → claude_mpm-5.4.55.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1079 @@
1
+ """
2
+ SocketIO Server Core for claude-mpm.
3
+
4
+ WHY: This module contains the core server management functionality extracted from
5
+ the monolithic socketio_server.py file. It handles server lifecycle, static file
6
+ serving, and basic server setup.
7
+
8
+ DESIGN DECISION: Separated core server logic from event handling and broadcasting
9
+ to create focused, maintainable modules.
10
+ """
11
+
12
+ import asyncio
13
+ import threading
14
+ import time
15
+ from collections import deque
16
+ from datetime import datetime, timezone
17
+ from pathlib import Path
18
+ from typing import Any, Dict, Set
19
+
20
+ try:
21
+ import aiohttp
22
+ import socketio
23
+ from aiohttp import web
24
+
25
+ SOCKETIO_AVAILABLE = True
26
+ except ImportError:
27
+ SOCKETIO_AVAILABLE = False
28
+ socketio = None
29
+ aiohttp = None
30
+ web = None
31
+
32
+ # Import VersionService for dynamic version retrieval
33
+ import contextlib
34
+
35
+ from claude_mpm.services.version_service import VersionService
36
+
37
+ from ....core.constants import SystemLimits, TimeoutConfig
38
+ from ....core.logging_config import get_logger
39
+ from ....core.unified_paths import get_project_root, get_scripts_dir
40
+ from ...exceptions import SocketIOServerError as MPMConnectionError
41
+
42
+
43
+ class SocketIOServerCore:
44
+ """Core server management functionality for SocketIO server.
45
+
46
+ WHY: This class handles the basic server lifecycle, static file serving,
47
+ and core server setup. It's separated from event handling to reduce complexity.
48
+ """
49
+
50
+ def __init__(self, host: str = "localhost", port: int = 8765):
51
+ self.host = host
52
+ self.port = port
53
+ self.logger = get_logger(__name__ + ".SocketIOServer")
54
+ self.running = False
55
+ self.server_thread = None
56
+ self.loop = None
57
+ self.app = None
58
+ self.runner = None
59
+ self.site = None
60
+
61
+ # Socket.IO server instance
62
+ self.sio = None
63
+
64
+ # Connection tracking
65
+ self.connected_clients: Set[str] = set()
66
+ self.client_info: Dict[str, Dict[str, Any]] = {}
67
+
68
+ # Event buffering for reliability
69
+ self.event_buffer = deque(
70
+ maxlen=getattr(SystemLimits, "MAX_EVENTS_BUFFER", 1000)
71
+ )
72
+ self.buffer_lock = threading.Lock()
73
+
74
+ # Performance tracking
75
+ self.stats = {
76
+ "events_sent": 0,
77
+ "events_buffered": 0,
78
+ "connections_total": 0,
79
+ "start_time": None,
80
+ }
81
+
82
+ # Static files path
83
+ self.static_path = None
84
+
85
+ # Heartbeat task
86
+ self.heartbeat_task = None
87
+ self.heartbeat_interval = 60 # seconds
88
+ self.main_server = None # Reference to main server for session data
89
+
90
+ def start_sync(self):
91
+ """Start the Socket.IO server in a background thread (synchronous version)."""
92
+ if not SOCKETIO_AVAILABLE:
93
+ self.logger.warning("Socket.IO not available - server not started")
94
+ return
95
+
96
+ if self.running:
97
+ self.logger.warning("Socket.IO server already running")
98
+ return
99
+
100
+ self.logger.info(f"Starting Socket.IO server on {self.host}:{self.port}")
101
+
102
+ # Start server in background thread
103
+ self.server_thread = threading.Thread(target=self._run_server, daemon=True)
104
+ self.server_thread.start()
105
+
106
+ # Wait for server to start
107
+ max_wait = getattr(TimeoutConfig, "SERVER_START_TIMEOUT", 30)
108
+ wait_time = 0
109
+ while not self.running and wait_time < max_wait:
110
+ time.sleep(0.1)
111
+ wait_time += 0.1
112
+
113
+ if not self.running:
114
+ raise MPMConnectionError(
115
+ f"Failed to start Socket.IO server within {max_wait}s"
116
+ )
117
+
118
+ self.logger.info(
119
+ f"Socket.IO server started successfully on {self.host}:{self.port}"
120
+ )
121
+
122
+ def stop_sync(self):
123
+ """Stop the Socket.IO server (synchronous version)."""
124
+ if not self.running:
125
+ return
126
+
127
+ self.logger.info("Stopping Socket.IO server...")
128
+ self.running = False
129
+
130
+ # Stop the server gracefully
131
+ if self.loop and not self.loop.is_closed():
132
+ asyncio.run_coroutine_threadsafe(self._stop_server(), self.loop)
133
+
134
+ def _run_server(self):
135
+ """Run the server event loop."""
136
+ try:
137
+ # Create new event loop for this thread
138
+ # WHY: We create and assign the loop immediately to minimize the race
139
+ # condition window where other threads might try to access it.
140
+ self.loop = asyncio.new_event_loop()
141
+ asyncio.set_event_loop(self.loop)
142
+
143
+ self.logger.debug("Event loop created and set for background thread")
144
+
145
+ # Run the server
146
+ self.loop.run_until_complete(self._start_server())
147
+
148
+ except Exception as e:
149
+ self.logger.error(f"Socket.IO server error: {e}")
150
+ self.running = False
151
+ finally:
152
+ if self.loop and not self.loop.is_closed():
153
+ self.loop.close()
154
+
155
+ async def _start_server(self):
156
+ """Start the Socket.IO server with aiohttp."""
157
+ try:
158
+ # Import centralized configuration for consistency
159
+ from ....config.socketio_config import CONNECTION_CONFIG
160
+
161
+ # Create Socket.IO server with centralized configuration
162
+ # CRITICAL: These values MUST match client settings to prevent disconnections
163
+ self.sio = socketio.AsyncServer(
164
+ cors_allowed_origins="*",
165
+ logger=False, # Disable Socket.IO's own logging
166
+ engineio_logger=False,
167
+ ping_interval=CONNECTION_CONFIG[
168
+ "ping_interval"
169
+ ], # 45 seconds from config
170
+ ping_timeout=CONNECTION_CONFIG[
171
+ "ping_timeout"
172
+ ], # 20 seconds from config
173
+ max_http_buffer_size=CONNECTION_CONFIG[
174
+ "max_http_buffer_size"
175
+ ], # 100MB from config
176
+ )
177
+
178
+ # Create aiohttp application
179
+ self.app = web.Application()
180
+ self.sio.attach(self.app)
181
+
182
+ # CRITICAL: Register event handlers BEFORE starting the server
183
+ # This ensures handlers are ready when clients connect
184
+ if self.main_server and hasattr(self.main_server, "_register_events_async"):
185
+ self.logger.info(
186
+ "Registering Socket.IO event handlers before server start"
187
+ )
188
+ await self.main_server._register_events_async()
189
+ else:
190
+ self.logger.warning("Main server not available for event registration")
191
+
192
+ # Setup HTTP API endpoints for receiving events from hook handlers
193
+ self._setup_http_api()
194
+
195
+ # Setup simple directory API
196
+ self._setup_directory_api()
197
+
198
+ # Find and serve static files
199
+ self._setup_static_files()
200
+
201
+ # Create and start the server
202
+ self.runner = web.AppRunner(self.app)
203
+ await self.runner.setup()
204
+
205
+ self.site = web.TCPSite(
206
+ self.runner, self.host, self.port, reuse_address=True, reuse_port=True
207
+ )
208
+ await self.site.start()
209
+
210
+ self.running = True
211
+ self.stats["start_time"] = datetime.now(timezone.utc)
212
+
213
+ self.logger.info(
214
+ f"Socket.IO server listening on http://{self.host}:{self.port}"
215
+ )
216
+ if self.static_path:
217
+ self.logger.info(f"Serving static files from: {self.static_path}")
218
+
219
+ # Conditionally start heartbeat task based on configuration
220
+ from ....config.socketio_config import CONNECTION_CONFIG
221
+
222
+ if CONNECTION_CONFIG.get("enable_extra_heartbeat", False):
223
+ self.heartbeat_task = asyncio.create_task(self._heartbeat_loop())
224
+ self.logger.info("Started system heartbeat task")
225
+ else:
226
+ self.logger.info(
227
+ "System heartbeat disabled (using Socket.IO ping/pong instead)"
228
+ )
229
+
230
+ # Keep the server running
231
+ while self.running:
232
+ await asyncio.sleep(1)
233
+
234
+ except Exception as e:
235
+ self.logger.error(f"Failed to start Socket.IO server: {e}")
236
+ self.running = False
237
+ raise
238
+
239
+ async def _stop_server(self):
240
+ """Stop the server gracefully."""
241
+ try:
242
+ # Cancel heartbeat task
243
+ if self.heartbeat_task and not self.heartbeat_task.done():
244
+ self.heartbeat_task.cancel()
245
+ with contextlib.suppress(asyncio.CancelledError):
246
+ await self.heartbeat_task
247
+ self.logger.info("Stopped system heartbeat task")
248
+
249
+ if self.site:
250
+ await self.site.stop()
251
+ self.site = None
252
+
253
+ if self.runner:
254
+ await self.runner.cleanup()
255
+ self.runner = None
256
+
257
+ self.logger.info("Socket.IO server stopped")
258
+
259
+ except Exception as e:
260
+ self.logger.error(f"Error stopping Socket.IO server: {e}")
261
+
262
+ def _setup_http_api(self):
263
+ """Setup HTTP API endpoints for receiving events from hook handlers.
264
+
265
+ WHY: Hook handlers are ephemeral processes that spawn and die quickly.
266
+ Using HTTP POST allows them to send events without managing persistent
267
+ connections, eliminating disconnection issues.
268
+ """
269
+
270
+ async def api_events_handler(request):
271
+ """Handle POST /api/events from hook handlers."""
272
+ try:
273
+ # Parse JSON payload
274
+ payload = await request.json()
275
+
276
+ # Extract event data from payload (handles both direct and wrapped formats)
277
+ # ConnectionManagerService sends: {"namespace": "...", "event": "...", "data": {...}}
278
+ # Direct hook events may send data directly
279
+ # CRITICAL: Check if payload has the expected event structure (type, subtype, timestamp)
280
+ # If it does, use it directly. Only extract 'data' field if it's a wrapper object.
281
+ if "type" in payload and "subtype" in payload:
282
+ # Payload is already in normalized format, use it directly
283
+ event_data = payload
284
+ elif "data" in payload and isinstance(payload.get("data"), dict):
285
+ # Payload is a wrapper with 'data' field (from ConnectionManagerService)
286
+ event_data = payload["data"]
287
+ else:
288
+ # Fallback: use entire payload
289
+ event_data = payload
290
+
291
+ # Log receipt with more detail
292
+ event_type = (
293
+ event_data.get("subtype")
294
+ or event_data.get("hook_event_name")
295
+ or "unknown"
296
+ )
297
+ self.logger.info(f"📨 Received HTTP event: {event_type}")
298
+ self.logger.debug(f"Event data keys: {list(event_data.keys())}")
299
+ self.logger.debug(f"Connected clients: {len(self.connected_clients)}")
300
+
301
+ # Transform hook event format to claude_event format if needed
302
+ if "hook_event_name" in event_data and "event" not in event_data:
303
+ # This is a raw hook event, transform it
304
+ from claude_mpm.services.socketio.event_normalizer import (
305
+ EventNormalizer,
306
+ )
307
+
308
+ normalizer = EventNormalizer()
309
+
310
+ # Map hook event names to dashboard subtypes
311
+ # Comprehensive mapping of all known Claude Code hook event types
312
+ subtype_map = {
313
+ # User interaction events
314
+ "UserPromptSubmit": "user_prompt_submit",
315
+ "UserPromptCancel": "user_prompt_cancel",
316
+ # Tool execution events
317
+ "PreToolUse": "pre_tool_use",
318
+ "PostToolUse": "post_tool_use",
319
+ "ToolStart": "tool_start",
320
+ "ToolUse": "tool_use",
321
+ # Assistant events
322
+ "AssistantResponse": "assistant_response",
323
+ # Session lifecycle events
324
+ "Start": "start",
325
+ "Stop": "stop",
326
+ "SessionStart": "session_start",
327
+ # Subagent events
328
+ "SubagentStart": "subagent_start",
329
+ "SubagentStop": "subagent_stop",
330
+ "SubagentEvent": "subagent_event",
331
+ # Task events
332
+ "Task": "task",
333
+ "TaskStart": "task_start",
334
+ "TaskComplete": "task_complete",
335
+ # File operation events
336
+ "FileWrite": "file_write",
337
+ "Write": "write",
338
+ # System events
339
+ "Notification": "notification",
340
+ }
341
+
342
+ # Helper function to convert PascalCase to snake_case
343
+ def to_snake_case(name: str) -> str:
344
+ """Convert PascalCase event names to snake_case.
345
+
346
+ Examples:
347
+ UserPromptSubmit → user_prompt_submit
348
+ PreToolUse → pre_tool_use
349
+ TaskComplete → task_complete
350
+ """
351
+ import re
352
+
353
+ return re.sub(r"(?<!^)(?=[A-Z])", "_", name).lower()
354
+
355
+ # Get hook event name and map to subtype
356
+ hook_event_name = event_data.get("hook_event_name", "unknown")
357
+ subtype = subtype_map.get(
358
+ hook_event_name, to_snake_case(hook_event_name)
359
+ )
360
+
361
+ # Debug log for unmapped events to discover new event types
362
+ if (
363
+ hook_event_name not in subtype_map
364
+ and hook_event_name != "unknown"
365
+ ):
366
+ self.logger.debug(
367
+ f"Unmapped hook event: {hook_event_name} → {subtype}"
368
+ )
369
+
370
+ # Create the format expected by normalizer
371
+ raw_event = {
372
+ "type": "hook",
373
+ "subtype": subtype,
374
+ "timestamp": event_data.get("timestamp"),
375
+ "data": event_data.get("hook_input_data", {}),
376
+ "source": "claude_hooks",
377
+ "session_id": event_data.get("session_id"),
378
+ }
379
+
380
+ normalized = normalizer.normalize(raw_event, source="hook")
381
+ event_data = normalized.to_dict()
382
+ self.logger.debug(
383
+ f"Normalized event: type={event_data.get('type')}, subtype={event_data.get('subtype')}"
384
+ )
385
+
386
+ # Publish to EventBus for cross-component communication
387
+ # WHY: This allows other parts of the system to react to hook events
388
+ # without coupling to Socket.IO directly
389
+ try:
390
+ from claude_mpm.services.event_bus import EventBus
391
+
392
+ event_bus = EventBus.get_instance()
393
+ event_type = f"hook.{event_data.get('subtype', 'unknown')}"
394
+ event_bus.publish(event_type, event_data)
395
+ self.logger.debug(f"Published to EventBus: {event_type}")
396
+ except Exception as e:
397
+ # Non-fatal: EventBus publication failure shouldn't break event flow
398
+ self.logger.warning(f"Failed to publish to EventBus: {e}")
399
+
400
+ # Broadcast to all connected dashboard clients via SocketIO
401
+ if self.sio:
402
+ # CRITICAL: Use the main server's broadcaster for proper event handling
403
+ # The broadcaster handles retries, connection management, and buffering
404
+ if (
405
+ self.main_server
406
+ and hasattr(self.main_server, "broadcaster")
407
+ and self.main_server.broadcaster
408
+ ):
409
+ # The broadcaster expects raw event data and will normalize it
410
+ # Since we already normalized it, we need to pass it in a way that won't double-normalize
411
+ # We'll emit directly through the broadcaster's sio with proper handling
412
+
413
+ # Add to event buffer and history
414
+ with self.buffer_lock:
415
+ self.event_buffer.append(event_data)
416
+ self.stats["events_buffered"] = len(self.event_buffer)
417
+
418
+ # Add to main server's event history UNCONDITIONALLY
419
+ # WHY: event_history is always initialized in SocketIOServer.__init__
420
+ # This ensures events persist for new clients who connect later
421
+ if self.main_server and hasattr(
422
+ self.main_server, "event_history"
423
+ ):
424
+ self.main_server.event_history.append(event_data)
425
+ self.logger.debug(
426
+ f"Added to history (total: {len(self.main_server.event_history)})"
427
+ )
428
+ else:
429
+ # CRITICAL: Log warning if event_history is not available
430
+ # This indicates a configuration or initialization problem
431
+ self.logger.warning(
432
+ "event_history not initialized on main_server! "
433
+ "Events will not persist for new clients."
434
+ )
435
+
436
+ # Use the broadcaster's sio to emit (it's the same as self.sio)
437
+ # This ensures the event goes through the proper channels
438
+ await self.sio.emit("claude_event", event_data)
439
+
440
+ # Update broadcaster stats
441
+ if hasattr(self.main_server.broadcaster, "stats"):
442
+ self.main_server.broadcaster.stats["events_sent"] = (
443
+ self.main_server.broadcaster.stats.get("events_sent", 0)
444
+ + 1
445
+ )
446
+
447
+ self.logger.info(
448
+ f"✅ Event broadcasted: {event_data.get('subtype', 'unknown')} to {len(self.connected_clients)} clients"
449
+ )
450
+ self.logger.debug(
451
+ f"Connected client IDs: {list(self.connected_clients) if self.connected_clients else 'None'}"
452
+ )
453
+ else:
454
+ # Fallback: Direct emit if broadcaster not available (shouldn't happen)
455
+ self.logger.warning(
456
+ "Broadcaster not available, using direct emit"
457
+ )
458
+ await self.sio.emit("claude_event", event_data)
459
+
460
+ # Update stats manually if using fallback
461
+ self.stats["events_sent"] = self.stats.get("events_sent", 0) + 1
462
+
463
+ # Add to event buffer for late-joining clients
464
+ with self.buffer_lock:
465
+ self.event_buffer.append(event_data)
466
+ self.stats["events_buffered"] = len(self.event_buffer)
467
+
468
+ # Add to main server's event history (fallback path)
469
+ # WHY: Ensure events persist even when broadcaster is unavailable
470
+ if self.main_server and hasattr(
471
+ self.main_server, "event_history"
472
+ ):
473
+ self.main_server.event_history.append(event_data)
474
+ self.logger.debug(
475
+ f"Added to history via fallback (total: {len(self.main_server.event_history)})"
476
+ )
477
+ else:
478
+ self.logger.warning(
479
+ "event_history not initialized on main_server (fallback path)! "
480
+ "Events will not persist for new clients."
481
+ )
482
+
483
+ # Return 204 No Content for success
484
+ self.logger.debug(f"✅ HTTP event processed successfully: {event_type}")
485
+ return web.Response(status=204)
486
+
487
+ except Exception as e:
488
+ self.logger.error(f"Error handling HTTP event: {e}")
489
+ return web.Response(status=500, text=str(e))
490
+
491
+ # Register the HTTP POST endpoint
492
+ self.app.router.add_post("/api/events", api_events_handler)
493
+ self.logger.info("✅ HTTP API endpoint registered at /api/events")
494
+
495
+ # Add health check endpoint
496
+ async def health_handler(request):
497
+ """Handle GET /api/health for health checks."""
498
+ try:
499
+ # Get server status
500
+ uptime_seconds = 0
501
+ if self.stats.get("start_time"):
502
+ uptime_seconds = int(
503
+ (
504
+ datetime.now(timezone.utc) - self.stats["start_time"]
505
+ ).total_seconds()
506
+ )
507
+
508
+ health_data = {
509
+ "status": "healthy",
510
+ "service": "claude-mpm-socketio",
511
+ "timestamp": datetime.now(timezone.utc).isoformat(),
512
+ "uptime_seconds": uptime_seconds,
513
+ "connected_clients": len(self.connected_clients),
514
+ "total_events": self.stats.get("events_sent", 0),
515
+ "buffered_events": self.stats.get("events_buffered", 0),
516
+ }
517
+
518
+ return web.json_response(health_data)
519
+ except Exception as e:
520
+ self.logger.error(f"Error in health check: {e}")
521
+ return web.json_response(
522
+ {
523
+ "status": "unhealthy",
524
+ "service": "claude-mpm-socketio",
525
+ "error": str(e),
526
+ },
527
+ status=503,
528
+ )
529
+
530
+ self.app.router.add_get("/api/health", health_handler)
531
+ self.app.router.add_get("/health", health_handler) # Alias for convenience
532
+ self.logger.info(
533
+ "✅ Health check endpoints registered at /api/health and /health"
534
+ )
535
+
536
+ # Add working directory endpoint
537
+ async def working_directory_handler(request):
538
+ """Handle GET /api/working-directory to provide current working directory."""
539
+ from pathlib import Path
540
+
541
+ try:
542
+ working_dir = str(Path.cwd())
543
+ home_dir = str(Path.home())
544
+
545
+ return web.json_response(
546
+ {
547
+ "working_directory": working_dir,
548
+ "home_directory": home_dir,
549
+ "process_cwd": working_dir,
550
+ "session_id": getattr(self, "session_id", None),
551
+ }
552
+ )
553
+ except Exception as e:
554
+ self.logger.error(f"Error getting working directory: {e}")
555
+ return web.json_response(
556
+ {
557
+ "working_directory": "/Users/masa/Projects/claude-mpm",
558
+ "home_directory": "/Users/masa",
559
+ "error": str(e),
560
+ },
561
+ status=500,
562
+ )
563
+
564
+ self.app.router.add_get("/api/working-directory", working_directory_handler)
565
+ self.logger.info(
566
+ "✅ Working directory endpoint registered at /api/working-directory"
567
+ )
568
+
569
+ # Add file reading endpoint for source viewer
570
+ async def file_read_handler(request):
571
+ """Handle GET /api/file/read for reading source files."""
572
+
573
+ file_path = request.query.get("path", "")
574
+
575
+ if not file_path:
576
+ return web.json_response({"error": "No path provided"}, status=400)
577
+
578
+ abs_path = Path(Path(file_path).resolve().expanduser())
579
+
580
+ # Security check - ensure file is within the project
581
+ try:
582
+ project_root = Path.cwd()
583
+ if not abs_path.startswith(project_root):
584
+ return web.json_response({"error": "Access denied"}, status=403)
585
+ except Exception:
586
+ pass
587
+
588
+ if not Path(abs_path).exists():
589
+ return web.json_response({"error": "File not found"}, status=404)
590
+
591
+ if not Path(abs_path).is_file():
592
+ return web.json_response({"error": "Not a file"}, status=400)
593
+
594
+ try:
595
+ # Read file with appropriate encoding
596
+ encodings = ["utf-8", "latin-1", "cp1252"]
597
+ content = None
598
+
599
+ for encoding in encodings:
600
+ try:
601
+ with Path(abs_path).open(
602
+ encoding=encoding,
603
+ ) as f:
604
+ content = f.read()
605
+ break
606
+ except UnicodeDecodeError:
607
+ continue
608
+
609
+ if content is None:
610
+ return web.json_response(
611
+ {"error": "Could not decode file"}, status=400
612
+ )
613
+
614
+ return web.json_response(
615
+ {
616
+ "path": abs_path,
617
+ "name": Path(abs_path).name,
618
+ "content": content,
619
+ "lines": len(content.splitlines()),
620
+ "size": Path(abs_path).stat().st_size,
621
+ }
622
+ )
623
+
624
+ except PermissionError:
625
+ return web.json_response({"error": "Permission denied"}, status=403)
626
+ except Exception as e:
627
+ return web.json_response({"error": str(e)}, status=500)
628
+
629
+ self.app.router.add_get("/api/file/read", file_read_handler)
630
+ self.logger.info("✅ File reading API registered at /api/file/read")
631
+
632
+ # Add files listing endpoint for file browser
633
+ async def files_list_handler(request):
634
+ """Handle GET /api/files for listing files in working directory."""
635
+
636
+ try:
637
+ # Get working directory from query params or use current directory
638
+ working_dir = request.query.get("path", str(Path.cwd()))
639
+ abs_working_dir = Path(working_dir).resolve().expanduser()
640
+
641
+ # Security check - ensure directory is accessible
642
+ if not abs_working_dir.exists():
643
+ return web.json_response(
644
+ {"error": "Directory not found"}, status=404
645
+ )
646
+
647
+ if not abs_working_dir.is_dir():
648
+ return web.json_response(
649
+ {"error": "Path is not a directory"}, status=400
650
+ )
651
+
652
+ # Collect files and directories
653
+ files = []
654
+ directories = []
655
+
656
+ # Common patterns to exclude
657
+ exclude_patterns = {
658
+ ".git",
659
+ ".venv",
660
+ "venv",
661
+ "node_modules",
662
+ "__pycache__",
663
+ ".pytest_cache",
664
+ ".mypy_cache",
665
+ "dist",
666
+ "build",
667
+ ".next",
668
+ "coverage",
669
+ ".coverage",
670
+ ".tox",
671
+ ".eggs",
672
+ "*.egg-info",
673
+ }
674
+
675
+ for entry in abs_working_dir.iterdir():
676
+ # Skip hidden files and excluded patterns
677
+ if entry.name.startswith("."):
678
+ # Allow .py, .ts, .md, etc. files but skip directories like .git
679
+ if entry.is_dir():
680
+ continue
681
+
682
+ # Skip excluded directories
683
+ if entry.name in exclude_patterns:
684
+ continue
685
+
686
+ try:
687
+ stat_info = entry.stat()
688
+ entry_data = {
689
+ "name": entry.name,
690
+ "path": str(entry),
691
+ "type": "directory" if entry.is_dir() else "file",
692
+ "size": stat_info.st_size if entry.is_file() else 0,
693
+ "modified": stat_info.st_mtime,
694
+ }
695
+
696
+ if entry.is_dir():
697
+ directories.append(entry_data)
698
+ else:
699
+ # Add file extension for syntax highlighting
700
+ entry_data["extension"] = entry.suffix.lower()
701
+ files.append(entry_data)
702
+ except (PermissionError, OSError):
703
+ # Skip files we can't access
704
+ continue
705
+
706
+ # Sort directories and files alphabetically
707
+ directories.sort(key=lambda x: x["name"].lower())
708
+ files.sort(key=lambda x: x["name"].lower())
709
+
710
+ return web.json_response(
711
+ {
712
+ "success": True,
713
+ "path": str(abs_working_dir),
714
+ "directories": directories,
715
+ "files": files,
716
+ "total_files": len(files),
717
+ "total_directories": len(directories),
718
+ }
719
+ )
720
+
721
+ except Exception as e:
722
+ self.logger.error(f"Error listing files: {e}")
723
+ return web.json_response({"error": str(e)}, status=500)
724
+
725
+ self.app.router.add_get("/api/files", files_list_handler)
726
+ self.logger.info("✅ Files listing API registered at /api/files")
727
+
728
+ # Add git history endpoint
729
+ async def git_history_handler(request):
730
+ """Handle POST /api/git-history for getting file git history."""
731
+ import subprocess
732
+
733
+ try:
734
+ # Parse JSON body
735
+ data = await request.json()
736
+ file_path = data.get("path", "")
737
+ limit = data.get("limit", 10)
738
+
739
+ if not file_path:
740
+ return web.json_response(
741
+ {"success": False, "error": "No path provided", "commits": []},
742
+ status=400,
743
+ )
744
+
745
+ abs_path = Path(Path(file_path).resolve().expanduser())
746
+
747
+ if not Path(abs_path).exists():
748
+ return web.json_response(
749
+ {"success": False, "error": "File not found", "commits": []},
750
+ status=404,
751
+ )
752
+
753
+ # Get git log for file
754
+ result = subprocess.run(
755
+ [
756
+ "git",
757
+ "log",
758
+ f"-{limit}",
759
+ "--pretty=format:%H|%an|%ar|%s",
760
+ "--",
761
+ abs_path,
762
+ ],
763
+ check=False,
764
+ capture_output=True,
765
+ text=True,
766
+ cwd=Path(abs_path).parent,
767
+ )
768
+
769
+ commits = []
770
+ if result.returncode == 0 and result.stdout:
771
+ for line in result.stdout.strip().split("\n"):
772
+ if line:
773
+ parts = line.split("|", 3)
774
+ if len(parts) == 4:
775
+ commits.append(
776
+ {
777
+ "hash": parts[0][:7], # Short hash
778
+ "author": parts[1],
779
+ "date": parts[2],
780
+ "message": parts[3],
781
+ }
782
+ )
783
+
784
+ return web.json_response({"success": True, "commits": commits})
785
+
786
+ except Exception as e:
787
+ self.logger.error(f"Error getting git history: {e}")
788
+ return web.json_response(
789
+ {"success": False, "error": str(e), "commits": []}, status=500
790
+ )
791
+
792
+ self.app.router.add_post("/api/git-history", git_history_handler)
793
+ self.logger.info("✅ Git history API registered at /api/git-history")
794
+
795
+ def _setup_directory_api(self):
796
+ """Setup simple directory listing API.
797
+
798
+ WHY: Provides a dead-simple way to list directory contents via HTTP GET
799
+ without complex WebSocket interactions.
800
+ """
801
+ try:
802
+ from claude_mpm.dashboard.api.simple_directory import register_routes
803
+
804
+ register_routes(self.app)
805
+ self.logger.info(
806
+ "✅ Simple directory API registered at /api/directory/list"
807
+ )
808
+ except Exception as e:
809
+ self.logger.error(f"Failed to setup directory API: {e}")
810
+
811
+ def _setup_static_files(self):
812
+ """Setup static file serving for the Svelte dashboard."""
813
+ try:
814
+ # Add debug logging for deployment context
815
+ try:
816
+ from ....core.unified_paths import PathContext
817
+
818
+ deployment_context = PathContext.detect_deployment_context()
819
+ self.logger.debug(
820
+ f"Setting up static files in {deployment_context.value} mode"
821
+ )
822
+ except Exception as e:
823
+ self.logger.debug(f"Could not detect deployment context: {e}")
824
+
825
+ # Find Svelte build directory
826
+ svelte_build_path = self._find_static_path()
827
+
828
+ if svelte_build_path and svelte_build_path.exists():
829
+ self.logger.info(f"✅ Svelte dashboard found at: {svelte_build_path}")
830
+ self.dashboard_path = svelte_build_path
831
+
832
+ # Serve Svelte index.html at root
833
+ async def index_handler(request):
834
+ index_file = svelte_build_path / "index.html"
835
+ if index_file.exists():
836
+ self.logger.debug(
837
+ f"Serving Svelte dashboard from: {index_file}"
838
+ )
839
+ return web.FileResponse(index_file)
840
+ self.logger.warning(f"Svelte index.html not found at: {index_file}")
841
+ return web.Response(text="Dashboard not available", status=404)
842
+
843
+ self.app.router.add_get("/", index_handler)
844
+
845
+ # Serve Svelte app assets at /_app/ (needed for SvelteKit builds)
846
+ svelte_app_path = svelte_build_path / "_app"
847
+ if svelte_app_path.exists():
848
+ self.app.router.add_static(
849
+ "/_app/", svelte_app_path, name="svelte_app"
850
+ )
851
+ self.logger.info(
852
+ f"✅ Svelte dashboard available at http://{self.host}:{self.port}/ (build: {svelte_build_path})"
853
+ )
854
+ else:
855
+ self.logger.warning(
856
+ f"⚠️ Svelte _app directory not found at: {svelte_app_path}"
857
+ )
858
+
859
+ # Serve version.json from Svelte build directory
860
+ async def version_handler(request):
861
+ version_file = svelte_build_path / "version.json"
862
+ if version_file.exists():
863
+ self.logger.debug(f"Serving version.json from: {version_file}")
864
+ return web.FileResponse(version_file)
865
+ # Return default version info if file doesn't exist
866
+ return web.json_response(
867
+ {
868
+ "version": "1.0.0",
869
+ "build": 1,
870
+ "formatted_build": "0001",
871
+ "full_version": "v1.0.0-0001",
872
+ }
873
+ )
874
+
875
+ self.app.router.add_get("/version.json", version_handler)
876
+
877
+ else:
878
+ self.logger.warning(
879
+ "⚠️ Svelte dashboard not found, serving fallback response"
880
+ )
881
+
882
+ # Fallback handler
883
+ async def fallback_handler(request):
884
+ return web.Response(
885
+ text="Socket.IO server running - Dashboard not available",
886
+ status=200,
887
+ )
888
+
889
+ self.app.router.add_get("/", fallback_handler)
890
+
891
+ except Exception as e:
892
+ self.logger.error(f"❌ Error setting up static files: {e}")
893
+ import traceback
894
+
895
+ self.logger.debug(f"Static file setup traceback: {traceback.format_exc()}")
896
+
897
+ # Ensure we always have a basic handler
898
+ async def error_handler(request):
899
+ return web.Response(
900
+ text="Socket.IO server running - Static files unavailable",
901
+ status=200,
902
+ )
903
+
904
+ self.app.router.add_get("/", error_handler)
905
+
906
+ def _find_static_path(self):
907
+ """Find the Svelte build directory using multiple approaches.
908
+
909
+ WHY: The dashboard is now pure Svelte, located at dashboard/static/svelte-build/.
910
+ We search for this specific structure across different deployment contexts.
911
+ """
912
+ # Get deployment-context-aware paths
913
+ try:
914
+ from ....core.unified_paths import get_path_manager
915
+
916
+ path_manager = get_path_manager()
917
+
918
+ # Use package root for installed packages (including pipx)
919
+ package_root = path_manager.package_root
920
+ self.logger.debug(f"Package root: {package_root}")
921
+
922
+ # Use project root for development
923
+ project_root = get_project_root()
924
+ self.logger.debug(f"Project root: {project_root}")
925
+
926
+ except Exception as e:
927
+ self.logger.debug(f"Could not get path manager: {e}")
928
+ package_root = None
929
+ project_root = get_project_root()
930
+
931
+ # Try multiple possible locations for Svelte build directory
932
+ possible_paths = [
933
+ # Package-based paths (for pipx and pip installations)
934
+ package_root / "dashboard" / "static" / "svelte-build"
935
+ if package_root
936
+ else None,
937
+ # Project-based paths (for development)
938
+ project_root
939
+ / "src"
940
+ / "claude_mpm"
941
+ / "dashboard"
942
+ / "static"
943
+ / "svelte-build",
944
+ project_root / "dashboard" / "static" / "svelte-build",
945
+ # Package installation locations (fallback)
946
+ Path(__file__).parent.parent.parent
947
+ / "dashboard"
948
+ / "static"
949
+ / "svelte-build",
950
+ # Scripts directory (for standalone installations)
951
+ get_scripts_dir() / "dashboard" / "static" / "svelte-build",
952
+ # Current working directory
953
+ Path.cwd() / "src" / "claude_mpm" / "dashboard" / "static" / "svelte-build",
954
+ Path.cwd() / "dashboard" / "static" / "svelte-build",
955
+ ]
956
+
957
+ # Filter out None values
958
+ possible_paths = [p for p in possible_paths if p is not None]
959
+ self.logger.debug(
960
+ f"Searching {len(possible_paths)} possible Svelte build locations"
961
+ )
962
+
963
+ for path in possible_paths:
964
+ self.logger.debug(f"Checking for Svelte build at: {path}")
965
+ try:
966
+ if path.exists() and path.is_dir():
967
+ # Check if it contains expected Svelte build files
968
+ if (path / "index.html").exists():
969
+ self.logger.info(f"✅ Found Svelte build at: {path}")
970
+ return path
971
+ self.logger.debug(f"Directory exists but no index.html: {path}")
972
+ else:
973
+ self.logger.debug(f"Path does not exist: {path}")
974
+ except Exception as e:
975
+ self.logger.debug(f"Error checking path {path}: {e}")
976
+
977
+ self.logger.warning(
978
+ "⚠️ Svelte build not found - dashboard will not be available"
979
+ )
980
+ self.logger.debug(f"Searched paths: {[str(p) for p in possible_paths]}")
981
+ return None
982
+
983
+ def get_connection_count(self) -> int:
984
+ """Get number of connected clients.
985
+
986
+ WHY: Provides interface compliance for monitoring.
987
+
988
+ Returns:
989
+ Number of connected clients
990
+ """
991
+ return len(self.connected_clients)
992
+
993
+ def is_running(self) -> bool:
994
+ """Check if server is running.
995
+
996
+ WHY: Provides interface compliance for status checking.
997
+
998
+ Returns:
999
+ True if server is active
1000
+ """
1001
+ return self.running
1002
+
1003
+ async def _heartbeat_loop(self):
1004
+ """Send periodic heartbeat events to connected clients.
1005
+
1006
+ WHY: This provides a way to verify the event flow is working and
1007
+ track server health and active sessions without relying on hook events.
1008
+ """
1009
+ while self.running:
1010
+ try:
1011
+ # Wait for the interval
1012
+ await asyncio.sleep(self.heartbeat_interval)
1013
+
1014
+ if not self.sio:
1015
+ continue
1016
+
1017
+ # Calculate uptime
1018
+ uptime_seconds = 0
1019
+ if self.stats.get("start_time"):
1020
+ uptime_seconds = int(
1021
+ (
1022
+ datetime.now(timezone.utc) - self.stats["start_time"]
1023
+ ).total_seconds()
1024
+ )
1025
+
1026
+ # Get active sessions from main server if available
1027
+ active_sessions = []
1028
+ if self.main_server and hasattr(
1029
+ self.main_server, "get_active_sessions"
1030
+ ):
1031
+ try:
1032
+ active_sessions = self.main_server.get_active_sessions()
1033
+ except Exception as e:
1034
+ self.logger.debug(f"Could not get active sessions: {e}")
1035
+
1036
+ # Prepare heartbeat data (using new schema)
1037
+ heartbeat_data = {
1038
+ "type": "system",
1039
+ "subtype": "heartbeat",
1040
+ "timestamp": datetime.now(timezone.utc).isoformat(),
1041
+ "source": "server",
1042
+ "data": {
1043
+ "uptime_seconds": uptime_seconds,
1044
+ "connected_clients": len(self.connected_clients),
1045
+ "total_events": self.stats.get("events_sent", 0),
1046
+ "active_sessions": active_sessions,
1047
+ "server_info": {
1048
+ "version": VersionService().get_version(),
1049
+ "port": self.port,
1050
+ },
1051
+ },
1052
+ }
1053
+
1054
+ # Add to event history UNCONDITIONALLY
1055
+ # WHY: Heartbeat events should persist for new clients too
1056
+ if self.main_server and hasattr(self.main_server, "event_history"):
1057
+ self.main_server.event_history.append(heartbeat_data)
1058
+ self.logger.debug(
1059
+ f"Heartbeat added to history (total: {len(self.main_server.event_history)})"
1060
+ )
1061
+ else:
1062
+ self.logger.warning("event_history not initialized for heartbeat!")
1063
+
1064
+ # Emit heartbeat to all connected clients (already using new schema)
1065
+ await self.sio.emit("system_event", heartbeat_data)
1066
+
1067
+ self.logger.info(
1068
+ f"System heartbeat sent - clients: {len(self.connected_clients)}, "
1069
+ f"uptime: {uptime_seconds}s, events: {self.stats.get('events_sent', 0)}, "
1070
+ f"sessions: {len(active_sessions)}"
1071
+ )
1072
+
1073
+ except asyncio.CancelledError:
1074
+ # Task was cancelled, exit gracefully
1075
+ break
1076
+ except Exception as e:
1077
+ self.logger.error(f"Error in heartbeat loop: {e}")
1078
+ # Continue running even if one heartbeat fails
1079
+ await asyncio.sleep(5) # Short delay before retry