claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__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 (490) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
  3. claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
  4. claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
  5. claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
  6. claude_mpm/agents/WORKFLOW.md +2 -0
  7. claude_mpm/agents/templates/circuit-breakers.md +26 -17
  8. claude_mpm/auth/__init__.py +35 -0
  9. claude_mpm/auth/callback_server.py +328 -0
  10. claude_mpm/auth/models.py +104 -0
  11. claude_mpm/auth/oauth_manager.py +266 -0
  12. claude_mpm/auth/providers/__init__.py +12 -0
  13. claude_mpm/auth/providers/base.py +165 -0
  14. claude_mpm/auth/providers/google.py +261 -0
  15. claude_mpm/auth/token_storage.py +252 -0
  16. claude_mpm/cli/__init__.py +5 -1
  17. claude_mpm/cli/commands/agents.py +2 -4
  18. claude_mpm/cli/commands/agents_reconcile.py +197 -0
  19. claude_mpm/cli/commands/autotodos.py +566 -0
  20. claude_mpm/cli/commands/commander.py +216 -0
  21. claude_mpm/cli/commands/configure.py +620 -21
  22. claude_mpm/cli/commands/configure_agent_display.py +3 -1
  23. claude_mpm/cli/commands/hook_errors.py +60 -60
  24. claude_mpm/cli/commands/mcp.py +29 -17
  25. claude_mpm/cli/commands/mcp_command_router.py +39 -0
  26. claude_mpm/cli/commands/mcp_service_commands.py +304 -0
  27. claude_mpm/cli/commands/monitor.py +2 -2
  28. claude_mpm/cli/commands/mpm_init/core.py +15 -8
  29. claude_mpm/cli/commands/oauth.py +481 -0
  30. claude_mpm/cli/commands/profile.py +9 -10
  31. claude_mpm/cli/commands/run.py +35 -3
  32. claude_mpm/cli/commands/skill_source.py +51 -2
  33. claude_mpm/cli/commands/skills.py +182 -32
  34. claude_mpm/cli/executor.py +129 -16
  35. claude_mpm/cli/helpers.py +1 -1
  36. claude_mpm/cli/interactive/__init__.py +10 -0
  37. claude_mpm/cli/interactive/agent_wizard.py +30 -50
  38. claude_mpm/cli/interactive/questionary_styles.py +65 -0
  39. claude_mpm/cli/interactive/skill_selector.py +481 -0
  40. claude_mpm/cli/parsers/base_parser.py +89 -1
  41. claude_mpm/cli/parsers/commander_parser.py +116 -0
  42. claude_mpm/cli/parsers/mcp_parser.py +79 -0
  43. claude_mpm/cli/parsers/oauth_parser.py +165 -0
  44. claude_mpm/cli/parsers/profile_parser.py +0 -1
  45. claude_mpm/cli/parsers/run_parser.py +10 -0
  46. claude_mpm/cli/parsers/skill_source_parser.py +4 -0
  47. claude_mpm/cli/parsers/skills_parser.py +2 -3
  48. claude_mpm/cli/startup.py +662 -524
  49. claude_mpm/cli/startup_display.py +76 -7
  50. claude_mpm/cli/startup_logging.py +2 -2
  51. claude_mpm/cli/utils.py +7 -3
  52. claude_mpm/commander/__init__.py +78 -0
  53. claude_mpm/commander/adapters/__init__.py +60 -0
  54. claude_mpm/commander/adapters/auggie.py +260 -0
  55. claude_mpm/commander/adapters/base.py +288 -0
  56. claude_mpm/commander/adapters/claude_code.py +392 -0
  57. claude_mpm/commander/adapters/codex.py +237 -0
  58. claude_mpm/commander/adapters/communication.py +366 -0
  59. claude_mpm/commander/adapters/example_usage.py +310 -0
  60. claude_mpm/commander/adapters/mpm.py +389 -0
  61. claude_mpm/commander/adapters/registry.py +204 -0
  62. claude_mpm/commander/api/__init__.py +16 -0
  63. claude_mpm/commander/api/app.py +121 -0
  64. claude_mpm/commander/api/errors.py +133 -0
  65. claude_mpm/commander/api/routes/__init__.py +8 -0
  66. claude_mpm/commander/api/routes/events.py +184 -0
  67. claude_mpm/commander/api/routes/inbox.py +171 -0
  68. claude_mpm/commander/api/routes/messages.py +148 -0
  69. claude_mpm/commander/api/routes/projects.py +271 -0
  70. claude_mpm/commander/api/routes/sessions.py +226 -0
  71. claude_mpm/commander/api/routes/work.py +296 -0
  72. claude_mpm/commander/api/schemas.py +186 -0
  73. claude_mpm/commander/chat/__init__.py +7 -0
  74. claude_mpm/commander/chat/cli.py +149 -0
  75. claude_mpm/commander/chat/commands.py +122 -0
  76. claude_mpm/commander/chat/repl.py +1821 -0
  77. claude_mpm/commander/config.py +51 -0
  78. claude_mpm/commander/config_loader.py +115 -0
  79. claude_mpm/commander/core/__init__.py +10 -0
  80. claude_mpm/commander/core/block_manager.py +325 -0
  81. claude_mpm/commander/core/response_manager.py +323 -0
  82. claude_mpm/commander/daemon.py +603 -0
  83. claude_mpm/commander/env_loader.py +59 -0
  84. claude_mpm/commander/events/__init__.py +26 -0
  85. claude_mpm/commander/events/manager.py +392 -0
  86. claude_mpm/commander/frameworks/__init__.py +12 -0
  87. claude_mpm/commander/frameworks/base.py +233 -0
  88. claude_mpm/commander/frameworks/claude_code.py +58 -0
  89. claude_mpm/commander/frameworks/mpm.py +57 -0
  90. claude_mpm/commander/git/__init__.py +5 -0
  91. claude_mpm/commander/git/worktree_manager.py +212 -0
  92. claude_mpm/commander/inbox/__init__.py +16 -0
  93. claude_mpm/commander/inbox/dedup.py +128 -0
  94. claude_mpm/commander/inbox/inbox.py +224 -0
  95. claude_mpm/commander/inbox/models.py +70 -0
  96. claude_mpm/commander/instance_manager.py +865 -0
  97. claude_mpm/commander/llm/__init__.py +6 -0
  98. claude_mpm/commander/llm/openrouter_client.py +167 -0
  99. claude_mpm/commander/llm/summarizer.py +70 -0
  100. claude_mpm/commander/memory/__init__.py +45 -0
  101. claude_mpm/commander/memory/compression.py +347 -0
  102. claude_mpm/commander/memory/embeddings.py +230 -0
  103. claude_mpm/commander/memory/entities.py +310 -0
  104. claude_mpm/commander/memory/example_usage.py +290 -0
  105. claude_mpm/commander/memory/integration.py +325 -0
  106. claude_mpm/commander/memory/search.py +381 -0
  107. claude_mpm/commander/memory/store.py +657 -0
  108. claude_mpm/commander/models/__init__.py +18 -0
  109. claude_mpm/commander/models/events.py +127 -0
  110. claude_mpm/commander/models/project.py +162 -0
  111. claude_mpm/commander/models/work.py +214 -0
  112. claude_mpm/commander/parsing/__init__.py +20 -0
  113. claude_mpm/commander/parsing/extractor.py +132 -0
  114. claude_mpm/commander/parsing/output_parser.py +270 -0
  115. claude_mpm/commander/parsing/patterns.py +100 -0
  116. claude_mpm/commander/persistence/__init__.py +11 -0
  117. claude_mpm/commander/persistence/event_store.py +274 -0
  118. claude_mpm/commander/persistence/state_store.py +403 -0
  119. claude_mpm/commander/persistence/work_store.py +164 -0
  120. claude_mpm/commander/polling/__init__.py +13 -0
  121. claude_mpm/commander/polling/event_detector.py +104 -0
  122. claude_mpm/commander/polling/output_buffer.py +49 -0
  123. claude_mpm/commander/polling/output_poller.py +153 -0
  124. claude_mpm/commander/project_session.py +268 -0
  125. claude_mpm/commander/proxy/__init__.py +12 -0
  126. claude_mpm/commander/proxy/formatter.py +89 -0
  127. claude_mpm/commander/proxy/output_handler.py +191 -0
  128. claude_mpm/commander/proxy/relay.py +155 -0
  129. claude_mpm/commander/registry.py +410 -0
  130. claude_mpm/commander/runtime/__init__.py +10 -0
  131. claude_mpm/commander/runtime/executor.py +191 -0
  132. claude_mpm/commander/runtime/monitor.py +346 -0
  133. claude_mpm/commander/session/__init__.py +6 -0
  134. claude_mpm/commander/session/context.py +81 -0
  135. claude_mpm/commander/session/manager.py +59 -0
  136. claude_mpm/commander/tmux_orchestrator.py +362 -0
  137. claude_mpm/commander/web/__init__.py +1 -0
  138. claude_mpm/commander/work/__init__.py +30 -0
  139. claude_mpm/commander/work/executor.py +207 -0
  140. claude_mpm/commander/work/queue.py +405 -0
  141. claude_mpm/commander/workflow/__init__.py +27 -0
  142. claude_mpm/commander/workflow/event_handler.py +241 -0
  143. claude_mpm/commander/workflow/notifier.py +146 -0
  144. claude_mpm/commands/mpm-config.md +8 -0
  145. claude_mpm/commands/mpm-doctor.md +8 -0
  146. claude_mpm/commands/mpm-help.md +8 -0
  147. claude_mpm/commands/mpm-init.md +8 -0
  148. claude_mpm/commands/mpm-monitor.md +8 -0
  149. claude_mpm/commands/mpm-organize.md +8 -0
  150. claude_mpm/commands/mpm-postmortem.md +8 -0
  151. claude_mpm/commands/mpm-session-resume.md +9 -1
  152. claude_mpm/commands/mpm-status.md +8 -0
  153. claude_mpm/commands/mpm-ticket-view.md +8 -0
  154. claude_mpm/commands/mpm-version.md +8 -0
  155. claude_mpm/commands/mpm.md +8 -0
  156. claude_mpm/config/agent_presets.py +8 -7
  157. claude_mpm/config/skill_sources.py +16 -0
  158. claude_mpm/constants.py +6 -0
  159. claude_mpm/core/claude_runner.py +154 -2
  160. claude_mpm/core/config.py +35 -22
  161. claude_mpm/core/config_constants.py +74 -9
  162. claude_mpm/core/constants.py +56 -12
  163. claude_mpm/core/hook_manager.py +53 -4
  164. claude_mpm/core/interactive_session.py +12 -11
  165. claude_mpm/core/logger.py +26 -9
  166. claude_mpm/core/logging_utils.py +39 -13
  167. claude_mpm/core/network_config.py +148 -0
  168. claude_mpm/core/oneshot_session.py +7 -6
  169. claude_mpm/core/optimized_startup.py +3 -1
  170. claude_mpm/core/output_style_manager.py +66 -18
  171. claude_mpm/core/shared/config_loader.py +3 -1
  172. claude_mpm/core/socketio_pool.py +47 -15
  173. claude_mpm/core/unified_config.py +54 -8
  174. claude_mpm/core/unified_paths.py +95 -90
  175. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
  176. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
  177. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
  178. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
  179. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
  180. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
  181. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
  182. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
  183. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
  184. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
  185. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
  186. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
  187. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
  188. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
  189. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
  190. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
  191. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
  192. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
  193. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
  194. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
  195. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
  196. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
  197. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
  198. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
  199. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
  200. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
  201. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
  202. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
  203. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
  204. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
  205. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
  206. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
  207. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
  208. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
  209. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
  210. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
  211. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
  212. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
  213. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
  214. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
  215. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
  216. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
  217. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
  218. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
  219. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
  220. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
  221. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
  222. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
  223. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
  224. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
  225. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
  226. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
  227. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
  228. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
  229. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
  230. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
  231. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
  232. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
  233. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
  234. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
  235. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
  236. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
  237. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
  238. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
  239. claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
  240. claude_mpm/dashboard/static/svelte-build/index.html +11 -11
  241. claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
  242. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
  243. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
  244. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
  245. claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
  246. claude_mpm/experimental/cli_enhancements.py +2 -1
  247. claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
  248. claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
  249. claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
  250. claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
  251. claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
  252. claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
  253. claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
  254. claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
  255. claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
  256. claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
  257. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
  258. claude_mpm/hooks/claude_hooks/installer.py +291 -59
  259. claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
  260. claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
  261. claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
  262. claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
  263. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
  264. claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
  265. claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
  266. claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
  267. claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
  268. claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
  269. claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
  270. claude_mpm/hooks/claude_hooks/services/container.py +326 -0
  271. claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
  272. claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
  273. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
  274. claude_mpm/hooks/kuzu_memory_hook.py +5 -5
  275. claude_mpm/hooks/session_resume_hook.py +89 -1
  276. claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
  277. claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
  278. claude_mpm/init.py +224 -4
  279. claude_mpm/mcp/__init__.py +9 -0
  280. claude_mpm/mcp/google_workspace_server.py +610 -0
  281. claude_mpm/scripts/claude-hook-handler.sh +46 -19
  282. claude_mpm/services/agents/agent_recommendation_service.py +8 -8
  283. claude_mpm/services/agents/agent_selection_service.py +2 -2
  284. claude_mpm/services/agents/cache_git_manager.py +1 -1
  285. claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
  286. claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
  287. claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
  288. claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
  289. claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
  290. claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
  291. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
  292. claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
  293. claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
  294. claude_mpm/services/agents/git_source_manager.py +21 -2
  295. claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
  296. claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
  297. claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
  298. claude_mpm/services/agents/startup_sync.py +5 -2
  299. claude_mpm/services/cli/__init__.py +3 -0
  300. claude_mpm/services/cli/incremental_pause_manager.py +561 -0
  301. claude_mpm/services/cli/session_resume_helper.py +10 -2
  302. claude_mpm/services/command_deployment_service.py +44 -26
  303. claude_mpm/services/delegation_detector.py +175 -0
  304. claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
  305. claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
  306. claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
  307. claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
  308. claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
  309. claude_mpm/services/diagnostics/models.py +14 -1
  310. claude_mpm/services/event_log.py +325 -0
  311. claude_mpm/services/hook_installer_service.py +77 -8
  312. claude_mpm/services/infrastructure/__init__.py +4 -0
  313. claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
  314. claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
  315. claude_mpm/services/mcp_config_manager.py +99 -19
  316. claude_mpm/services/mcp_service_registry.py +294 -0
  317. claude_mpm/services/monitor/daemon_manager.py +15 -4
  318. claude_mpm/services/monitor/management/lifecycle.py +8 -3
  319. claude_mpm/services/monitor/server.py +111 -16
  320. claude_mpm/services/pm_skills_deployer.py +302 -94
  321. claude_mpm/services/profile_manager.py +10 -4
  322. claude_mpm/services/skills/git_skill_source_manager.py +192 -29
  323. claude_mpm/services/skills/selective_skill_deployer.py +211 -46
  324. claude_mpm/services/skills/skill_discovery_service.py +74 -4
  325. claude_mpm/services/skills_deployer.py +192 -70
  326. claude_mpm/services/socketio/handlers/hook.py +14 -7
  327. claude_mpm/services/socketio/server/main.py +12 -4
  328. claude_mpm/skills/__init__.py +2 -1
  329. claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
  330. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
  331. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
  332. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
  333. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
  334. claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
  335. claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
  336. claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
  337. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
  338. claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
  339. claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
  340. claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
  341. claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
  342. claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
  343. claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
  344. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
  345. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
  346. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
  347. claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
  348. claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
  349. claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
  350. claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
  351. claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
  352. claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
  353. claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
  354. claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
  355. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
  356. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
  357. claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
  358. claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
  359. claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
  360. claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
  361. claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
  362. claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
  363. claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
  364. claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
  365. claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
  366. claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
  367. claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
  368. claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
  369. claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
  370. claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
  371. claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
  372. claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
  373. claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
  374. claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
  375. claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
  376. claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
  377. claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
  378. claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
  379. claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
  380. claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
  381. claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
  382. claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
  383. claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
  384. claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
  385. claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
  386. claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
  387. claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
  388. claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
  389. claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
  390. claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
  391. claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
  392. claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
  393. claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
  394. claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
  395. claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
  396. claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
  397. claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
  398. claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
  399. claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
  400. claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
  401. claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
  402. claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
  403. claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
  404. claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
  405. claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
  406. claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
  407. claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
  408. claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
  409. claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
  410. claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
  411. claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
  412. claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
  413. claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
  414. claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
  415. claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
  416. claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
  417. claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
  418. claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
  419. claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
  420. claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
  421. claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
  422. claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
  423. claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
  424. claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
  425. claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
  426. claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
  427. claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
  428. claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
  429. claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
  430. claude_mpm/skills/bundled/security-scanning.md +112 -0
  431. claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
  432. claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
  433. claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
  434. claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
  435. claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
  436. claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
  437. claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
  438. claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
  439. claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
  440. claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
  441. claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
  442. claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
  443. claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
  444. claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
  445. claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
  446. claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
  447. claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
  448. claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
  449. claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
  450. claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
  451. claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
  452. claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
  453. claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
  454. claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
  455. claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
  456. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
  457. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
  458. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
  459. claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
  460. claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
  461. claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
  462. claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
  463. claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
  464. claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
  465. claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
  466. claude_mpm/skills/registry.py +295 -90
  467. claude_mpm/skills/skill_manager.py +29 -23
  468. claude_mpm/templates/.pre-commit-config.yaml +112 -0
  469. claude_mpm/utils/agent_dependency_loader.py +103 -4
  470. claude_mpm/utils/robust_installer.py +45 -24
  471. claude_mpm-5.6.72.dist-info/METADATA +416 -0
  472. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
  473. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
  474. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
  475. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
  476. claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
  477. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
  478. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
  479. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
  480. claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
  481. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
  482. claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
  483. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
  484. claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
  485. claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
  486. claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
  487. claude_mpm-5.4.41.dist-info/METADATA +0 -998
  488. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
  489. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
  490. {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,657 @@
1
+ """Conversation storage with SQLite and vector support.
2
+
3
+ This module provides CRUD operations for conversations with vector embeddings
4
+ for semantic search. Uses SQLite with optional sqlite-vec extension.
5
+ """
6
+
7
+ import asyncio
8
+ import json
9
+ import logging
10
+ import sqlite3
11
+ from dataclasses import dataclass, field
12
+ from datetime import datetime, timezone
13
+ from pathlib import Path
14
+ from typing import Any, Dict, List, Optional
15
+
16
+ from ..models.project import ThreadMessage
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+
21
+ def _utc_now() -> datetime:
22
+ """Return current UTC time with timezone awareness."""
23
+ return datetime.now(timezone.utc)
24
+
25
+
26
+ @dataclass
27
+ class ConversationMessage:
28
+ """Single message in a conversation.
29
+
30
+ Attributes:
31
+ role: Message sender role ('user', 'assistant', 'system', 'tool')
32
+ content: Message content
33
+ timestamp: Message creation timestamp
34
+ token_count: Approximate token count (content length / 4)
35
+ entities: Extracted entities (files, functions, errors)
36
+ metadata: Additional metadata (tool name, error type, etc.)
37
+
38
+ Example:
39
+ >>> msg = ConversationMessage(
40
+ ... role="user",
41
+ ... content="Fix the login bug in auth.py",
42
+ ... entities=[{"type": "file", "value": "auth.py"}]
43
+ ... )
44
+ """
45
+
46
+ role: str
47
+ content: str
48
+ timestamp: datetime = field(default_factory=_utc_now)
49
+ token_count: int = field(default=0)
50
+ entities: List[Dict[str, Any]] = field(default_factory=list)
51
+ metadata: Dict[str, Any] = field(default_factory=dict)
52
+
53
+ def __post_init__(self) -> None:
54
+ """Calculate token count if not provided."""
55
+ if self.token_count == 0:
56
+ # Rough approximation: 1 token ≈ 4 characters
57
+ self.token_count = len(self.content) // 4
58
+
59
+ @classmethod
60
+ def from_thread_message(cls, msg: ThreadMessage) -> "ConversationMessage":
61
+ """Convert ThreadMessage to ConversationMessage.
62
+
63
+ Args:
64
+ msg: ThreadMessage from project thread
65
+
66
+ Returns:
67
+ ConversationMessage with extracted data
68
+ """
69
+ return cls(
70
+ role=msg.role,
71
+ content=msg.content,
72
+ timestamp=msg.timestamp,
73
+ entities=[],
74
+ metadata={
75
+ "thread_message_id": msg.id,
76
+ "session_id": msg.session_id,
77
+ "event_id": msg.event_id,
78
+ },
79
+ )
80
+
81
+
82
+ @dataclass
83
+ class Conversation:
84
+ """Complete conversation thread.
85
+
86
+ Attributes:
87
+ id: Unique conversation identifier (UUID)
88
+ project_id: Parent project ID
89
+ instance_name: Instance name (e.g., "claude-code-1")
90
+ session_id: Session ID from ToolSession
91
+ messages: List of conversation messages
92
+ summary: Optional compressed summary
93
+ embedding: Optional vector embedding for semantic search
94
+ created_at: Conversation creation timestamp
95
+ updated_at: Last update timestamp
96
+ metadata: Additional metadata (framework, version, etc.)
97
+
98
+ Example:
99
+ >>> conversation = Conversation(
100
+ ... id="conv-abc123",
101
+ ... project_id="proj-xyz",
102
+ ... instance_name="claude-code-1",
103
+ ... session_id="sess-123",
104
+ ... messages=[msg1, msg2, msg3]
105
+ ... )
106
+ """
107
+
108
+ id: str
109
+ project_id: str
110
+ instance_name: str
111
+ session_id: str
112
+ messages: List[ConversationMessage] = field(default_factory=list)
113
+ summary: Optional[str] = None
114
+ embedding: Optional[List[float]] = None
115
+ created_at: datetime = field(default_factory=_utc_now)
116
+ updated_at: datetime = field(default_factory=_utc_now)
117
+ metadata: Dict[str, Any] = field(default_factory=dict)
118
+
119
+ @property
120
+ def total_tokens(self) -> int:
121
+ """Calculate total token count across all messages."""
122
+ return sum(msg.token_count for msg in self.messages)
123
+
124
+ @property
125
+ def message_count(self) -> int:
126
+ """Return number of messages in conversation."""
127
+ return len(self.messages)
128
+
129
+ def get_full_text(self) -> str:
130
+ """Get full conversation as text.
131
+
132
+ Returns:
133
+ Formatted conversation text with role prefixes
134
+ """
135
+ lines = []
136
+ for msg in self.messages:
137
+ lines.append(f"{msg.role.upper()}: {msg.content}")
138
+ return "\n\n".join(lines)
139
+
140
+
141
+ class ConversationStore:
142
+ """Persists conversations to SQLite with vector support.
143
+
144
+ Provides CRUD operations and vector search capabilities using
145
+ SQLite with optional sqlite-vec extension.
146
+
147
+ Attributes:
148
+ db_path: Path to SQLite database file
149
+ enable_vector: Whether to enable vector extension
150
+
151
+ Example:
152
+ >>> store = ConversationStore()
153
+ >>> await store.save(conversation)
154
+ >>> results = await store.search("login bug", limit=5)
155
+ """
156
+
157
+ def __init__(
158
+ self,
159
+ db_path: Optional[Path] = None,
160
+ enable_vector: bool = True,
161
+ ):
162
+ """Initialize conversation store.
163
+
164
+ Args:
165
+ db_path: Path to database file (default: ~/.claude-mpm/commander/conversations.db)
166
+ enable_vector: Enable vector extension for semantic search
167
+ """
168
+ if db_path is None:
169
+ db_path = Path("~/.claude-mpm/commander/conversations.db").expanduser()
170
+
171
+ self.db_path = db_path
172
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
173
+ self.enable_vector = enable_vector
174
+
175
+ # Initialize schema
176
+ asyncio.create_task(self._init_schema())
177
+
178
+ logger.info(
179
+ "ConversationStore initialized at %s (vector: %s)",
180
+ self.db_path,
181
+ enable_vector,
182
+ )
183
+
184
+ async def _init_schema(self) -> None:
185
+ """Initialize database schema.
186
+
187
+ Creates tables for conversations and messages if they don't exist.
188
+ Optionally loads sqlite-vec extension for vector operations.
189
+ """
190
+
191
+ def _create_schema(conn: sqlite3.Connection) -> None:
192
+ """Create schema in sync context."""
193
+ # Try to load sqlite-vec extension
194
+ if self.enable_vector:
195
+ try:
196
+ conn.enable_load_extension(True)
197
+ # Try common locations for sqlite-vec
198
+ # Users need to install: pip install sqlite-vec
199
+ try:
200
+ conn.load_extension("vec0")
201
+ logger.info("Loaded sqlite-vec extension")
202
+ except sqlite3.OperationalError:
203
+ logger.warning(
204
+ "sqlite-vec extension not found. "
205
+ "Install with: pip install sqlite-vec. "
206
+ "Falling back to non-vector search."
207
+ )
208
+ self.enable_vector = False
209
+ except Exception as e:
210
+ logger.warning("Cannot load extensions: %s", e)
211
+ self.enable_vector = False
212
+
213
+ # Create conversations table
214
+ conn.execute(
215
+ """
216
+ CREATE TABLE IF NOT EXISTS conversations (
217
+ id TEXT PRIMARY KEY,
218
+ project_id TEXT NOT NULL,
219
+ instance_name TEXT NOT NULL,
220
+ session_id TEXT NOT NULL,
221
+ summary TEXT,
222
+ created_at TEXT NOT NULL,
223
+ updated_at TEXT NOT NULL,
224
+ metadata TEXT,
225
+ UNIQUE(session_id)
226
+ )
227
+ """
228
+ )
229
+
230
+ # Create messages table
231
+ conn.execute(
232
+ """
233
+ CREATE TABLE IF NOT EXISTS messages (
234
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
235
+ conversation_id TEXT NOT NULL,
236
+ role TEXT NOT NULL,
237
+ content TEXT NOT NULL,
238
+ timestamp TEXT NOT NULL,
239
+ token_count INTEGER NOT NULL,
240
+ entities TEXT,
241
+ metadata TEXT,
242
+ FOREIGN KEY(conversation_id) REFERENCES conversations(id)
243
+ )
244
+ """
245
+ )
246
+
247
+ # Create embeddings table (if vector enabled)
248
+ if self.enable_vector:
249
+ conn.execute(
250
+ """
251
+ CREATE VIRTUAL TABLE IF NOT EXISTS conversation_embeddings
252
+ USING vec0(
253
+ conversation_id TEXT PRIMARY KEY,
254
+ embedding FLOAT[384]
255
+ )
256
+ """
257
+ )
258
+
259
+ # Create indexes
260
+ conn.execute(
261
+ "CREATE INDEX IF NOT EXISTS idx_conversations_project "
262
+ "ON conversations(project_id)"
263
+ )
264
+ conn.execute(
265
+ "CREATE INDEX IF NOT EXISTS idx_conversations_session "
266
+ "ON conversations(session_id)"
267
+ )
268
+ conn.execute(
269
+ "CREATE INDEX IF NOT EXISTS idx_messages_conversation "
270
+ "ON messages(conversation_id)"
271
+ )
272
+ conn.execute(
273
+ "CREATE INDEX IF NOT EXISTS idx_conversations_updated "
274
+ "ON conversations(updated_at)"
275
+ )
276
+
277
+ conn.commit()
278
+
279
+ # Run in executor to avoid blocking
280
+ await asyncio.get_event_loop().run_in_executor(
281
+ None,
282
+ lambda: self._execute_sync(_create_schema),
283
+ )
284
+
285
+ def _execute_sync(self, func: Any) -> Any:
286
+ """Execute synchronous database operation.
287
+
288
+ Args:
289
+ func: Function that takes connection and executes queries
290
+
291
+ Returns:
292
+ Result from func
293
+ """
294
+ conn = sqlite3.connect(str(self.db_path))
295
+ try:
296
+ return func(conn)
297
+ finally:
298
+ conn.close()
299
+
300
+ async def save(self, conversation: Conversation) -> None:
301
+ """Save conversation to database.
302
+
303
+ Updates existing conversation or inserts new one.
304
+
305
+ Args:
306
+ conversation: Conversation to persist
307
+
308
+ Example:
309
+ >>> await store.save(conversation)
310
+ """
311
+
312
+ def _save(conn: sqlite3.Connection) -> None:
313
+ """Save in sync context."""
314
+ # Upsert conversation
315
+ conn.execute(
316
+ """
317
+ INSERT OR REPLACE INTO conversations
318
+ (id, project_id, instance_name, session_id, summary,
319
+ created_at, updated_at, metadata)
320
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
321
+ """,
322
+ (
323
+ conversation.id,
324
+ conversation.project_id,
325
+ conversation.instance_name,
326
+ conversation.session_id,
327
+ conversation.summary,
328
+ conversation.created_at.isoformat(),
329
+ conversation.updated_at.isoformat(),
330
+ json.dumps(conversation.metadata),
331
+ ),
332
+ )
333
+
334
+ # Delete old messages
335
+ conn.execute(
336
+ "DELETE FROM messages WHERE conversation_id = ?",
337
+ (conversation.id,),
338
+ )
339
+
340
+ # Insert messages
341
+ for msg in conversation.messages:
342
+ conn.execute(
343
+ """
344
+ INSERT INTO messages
345
+ (conversation_id, role, content, timestamp,
346
+ token_count, entities, metadata)
347
+ VALUES (?, ?, ?, ?, ?, ?, ?)
348
+ """,
349
+ (
350
+ conversation.id,
351
+ msg.role,
352
+ msg.content,
353
+ msg.timestamp.isoformat(),
354
+ msg.token_count,
355
+ json.dumps(msg.entities),
356
+ json.dumps(msg.metadata),
357
+ ),
358
+ )
359
+
360
+ # Save embedding if available
361
+ if self.enable_vector and conversation.embedding:
362
+ conn.execute(
363
+ """
364
+ INSERT OR REPLACE INTO conversation_embeddings
365
+ (conversation_id, embedding)
366
+ VALUES (?, ?)
367
+ """,
368
+ (conversation.id, json.dumps(conversation.embedding)),
369
+ )
370
+
371
+ conn.commit()
372
+
373
+ await asyncio.get_event_loop().run_in_executor(
374
+ None, lambda: self._execute_sync(_save)
375
+ )
376
+
377
+ logger.debug(
378
+ "Saved conversation %s (%d messages)",
379
+ conversation.id,
380
+ len(conversation.messages),
381
+ )
382
+
383
+ async def load(self, conversation_id: str) -> Optional[Conversation]:
384
+ """Load conversation by ID.
385
+
386
+ Args:
387
+ conversation_id: Conversation ID to load
388
+
389
+ Returns:
390
+ Conversation if found, None otherwise
391
+
392
+ Example:
393
+ >>> conv = await store.load("conv-abc123")
394
+ """
395
+
396
+ def _load(conn: sqlite3.Connection) -> Optional[Conversation]:
397
+ """Load in sync context."""
398
+ # Load conversation
399
+ cursor = conn.execute(
400
+ """
401
+ SELECT id, project_id, instance_name, session_id, summary,
402
+ created_at, updated_at, metadata
403
+ FROM conversations
404
+ WHERE id = ?
405
+ """,
406
+ (conversation_id,),
407
+ )
408
+
409
+ row = cursor.fetchone()
410
+ if not row:
411
+ return None
412
+
413
+ # Load messages
414
+ messages_cursor = conn.execute(
415
+ """
416
+ SELECT role, content, timestamp, token_count, entities, metadata
417
+ FROM messages
418
+ WHERE conversation_id = ?
419
+ ORDER BY timestamp ASC
420
+ """,
421
+ (conversation_id,),
422
+ )
423
+
424
+ messages = []
425
+ for msg_row in messages_cursor.fetchall():
426
+ messages.append(
427
+ ConversationMessage(
428
+ role=msg_row[0],
429
+ content=msg_row[1],
430
+ timestamp=datetime.fromisoformat(msg_row[2]),
431
+ token_count=msg_row[3],
432
+ entities=json.loads(msg_row[4]) if msg_row[4] else [],
433
+ metadata=json.loads(msg_row[5]) if msg_row[5] else {},
434
+ )
435
+ )
436
+
437
+ # Load embedding if available
438
+ embedding = None
439
+ if self.enable_vector:
440
+ emb_cursor = conn.execute(
441
+ "SELECT embedding FROM conversation_embeddings WHERE conversation_id = ?",
442
+ (conversation_id,),
443
+ )
444
+ emb_row = emb_cursor.fetchone()
445
+ if emb_row:
446
+ embedding = json.loads(emb_row[0])
447
+
448
+ return Conversation(
449
+ id=row[0],
450
+ project_id=row[1],
451
+ instance_name=row[2],
452
+ session_id=row[3],
453
+ summary=row[4],
454
+ created_at=datetime.fromisoformat(row[5]),
455
+ updated_at=datetime.fromisoformat(row[6]),
456
+ metadata=json.loads(row[7]) if row[7] else {},
457
+ messages=messages,
458
+ embedding=embedding,
459
+ )
460
+
461
+ return await asyncio.get_event_loop().run_in_executor(
462
+ None, lambda: self._execute_sync(_load)
463
+ )
464
+
465
+ async def list_by_project(
466
+ self,
467
+ project_id: str,
468
+ limit: Optional[int] = None,
469
+ ) -> List[Conversation]:
470
+ """List conversations for a project.
471
+
472
+ Args:
473
+ project_id: Project ID to filter by
474
+ limit: Maximum number of results
475
+
476
+ Returns:
477
+ List of conversations ordered by updated_at descending
478
+
479
+ Example:
480
+ >>> conversations = await store.list_by_project("proj-xyz", limit=10)
481
+ """
482
+
483
+ def _list(conn: sqlite3.Connection) -> List[Conversation]:
484
+ """List in sync context."""
485
+ query = """
486
+ SELECT id FROM conversations
487
+ WHERE project_id = ?
488
+ ORDER BY updated_at DESC
489
+ """
490
+ if limit:
491
+ query += f" LIMIT {limit}"
492
+
493
+ cursor = conn.execute(query, (project_id,))
494
+ conversation_ids = [row[0] for row in cursor.fetchall()]
495
+
496
+ # Load full conversations
497
+ conversations = []
498
+ for conv_id in conversation_ids:
499
+ conv = self._execute_sync(lambda c: self._load_conversation(c, conv_id))
500
+ if conv:
501
+ conversations.append(conv)
502
+
503
+ return conversations
504
+
505
+ return await asyncio.get_event_loop().run_in_executor(
506
+ None, lambda: self._execute_sync(_list)
507
+ )
508
+
509
+ def _load_conversation(
510
+ self, conn: sqlite3.Connection, conversation_id: str
511
+ ) -> Optional[Conversation]:
512
+ """Load conversation in sync context (helper for list operations)."""
513
+ cursor = conn.execute(
514
+ """
515
+ SELECT id, project_id, instance_name, session_id, summary,
516
+ created_at, updated_at, metadata
517
+ FROM conversations
518
+ WHERE id = ?
519
+ """,
520
+ (conversation_id,),
521
+ )
522
+
523
+ row = cursor.fetchone()
524
+ if not row:
525
+ return None
526
+
527
+ # Load messages
528
+ messages_cursor = conn.execute(
529
+ """
530
+ SELECT role, content, timestamp, token_count, entities, metadata
531
+ FROM messages
532
+ WHERE conversation_id = ?
533
+ ORDER BY timestamp ASC
534
+ """,
535
+ (conversation_id,),
536
+ )
537
+
538
+ messages = []
539
+ for msg_row in messages_cursor.fetchall():
540
+ messages.append(
541
+ ConversationMessage(
542
+ role=msg_row[0],
543
+ content=msg_row[1],
544
+ timestamp=datetime.fromisoformat(msg_row[2]),
545
+ token_count=msg_row[3],
546
+ entities=json.loads(msg_row[4]) if msg_row[4] else [],
547
+ metadata=json.loads(msg_row[5]) if msg_row[5] else {},
548
+ )
549
+ )
550
+
551
+ return Conversation(
552
+ id=row[0],
553
+ project_id=row[1],
554
+ instance_name=row[2],
555
+ session_id=row[3],
556
+ summary=row[4],
557
+ created_at=datetime.fromisoformat(row[5]),
558
+ updated_at=datetime.fromisoformat(row[6]),
559
+ metadata=json.loads(row[7]) if row[7] else {},
560
+ messages=messages,
561
+ )
562
+
563
+ async def search_by_text(
564
+ self,
565
+ query: str,
566
+ project_id: Optional[str] = None,
567
+ limit: int = 10,
568
+ ) -> List[Conversation]:
569
+ """Search conversations by text (fallback when vectors unavailable).
570
+
571
+ Uses SQLite FTS5 full-text search on conversation content.
572
+
573
+ Args:
574
+ query: Search query
575
+ project_id: Optional project ID filter
576
+ limit: Maximum results
577
+
578
+ Returns:
579
+ List of matching conversations
580
+
581
+ Example:
582
+ >>> results = await store.search_by_text("login bug fix")
583
+ """
584
+
585
+ def _search(conn: sqlite3.Connection) -> List[str]:
586
+ """Search in sync context."""
587
+ # Simple LIKE search (can be improved with FTS5)
588
+ if project_id:
589
+ cursor = conn.execute(
590
+ """
591
+ SELECT DISTINCT c.id
592
+ FROM conversations c
593
+ JOIN messages m ON c.id = m.conversation_id
594
+ WHERE c.project_id = ? AND (
595
+ c.summary LIKE ? OR m.content LIKE ?
596
+ )
597
+ ORDER BY c.updated_at DESC
598
+ LIMIT ?
599
+ """,
600
+ (project_id, f"%{query}%", f"%{query}%", limit),
601
+ )
602
+ else:
603
+ cursor = conn.execute(
604
+ """
605
+ SELECT DISTINCT c.id
606
+ FROM conversations c
607
+ JOIN messages m ON c.id = m.conversation_id
608
+ WHERE c.summary LIKE ? OR m.content LIKE ?
609
+ ORDER BY c.updated_at DESC
610
+ LIMIT ?
611
+ """,
612
+ (f"%{query}%", f"%{query}%", limit),
613
+ )
614
+
615
+ return [row[0] for row in cursor.fetchall()]
616
+
617
+ conversation_ids = await asyncio.get_event_loop().run_in_executor(
618
+ None, lambda: self._execute_sync(_search)
619
+ )
620
+
621
+ # Load full conversations
622
+ conversations = []
623
+ for conv_id in conversation_ids:
624
+ conv = await self.load(conv_id)
625
+ if conv:
626
+ conversations.append(conv)
627
+
628
+ return conversations
629
+
630
+ async def delete(self, conversation_id: str) -> None:
631
+ """Delete conversation and all messages.
632
+
633
+ Args:
634
+ conversation_id: Conversation ID to delete
635
+
636
+ Example:
637
+ >>> await store.delete("conv-abc123")
638
+ """
639
+
640
+ def _delete(conn: sqlite3.Connection) -> None:
641
+ """Delete in sync context."""
642
+ conn.execute(
643
+ "DELETE FROM messages WHERE conversation_id = ?", (conversation_id,)
644
+ )
645
+ conn.execute("DELETE FROM conversations WHERE id = ?", (conversation_id,))
646
+ if self.enable_vector:
647
+ conn.execute(
648
+ "DELETE FROM conversation_embeddings WHERE conversation_id = ?",
649
+ (conversation_id,),
650
+ )
651
+ conn.commit()
652
+
653
+ await asyncio.get_event_loop().run_in_executor(
654
+ None, lambda: self._execute_sync(_delete)
655
+ )
656
+
657
+ logger.debug("Deleted conversation %s", conversation_id)
@@ -0,0 +1,18 @@
1
+ """Data models for MPM Commander.
2
+
3
+ This module exports core data structures for project management,
4
+ sessions, conversation threads, and work items.
5
+ """
6
+
7
+ from .project import Project, ProjectState, ThreadMessage, ToolSession
8
+ from .work import WorkItem, WorkPriority, WorkState
9
+
10
+ __all__ = [
11
+ "Project",
12
+ "ProjectState",
13
+ "ThreadMessage",
14
+ "ToolSession",
15
+ "WorkItem",
16
+ "WorkPriority",
17
+ "WorkState",
18
+ ]