claude-mpm 3.9.11__py3-none-any.whl โ†’ 4.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info โ†’ claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info โ†’ claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info โ†’ claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info โ†’ claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info โ†’ claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  """
2
4
  Memory cleanup command implementation for claude-mpm.
3
5
 
@@ -12,98 +14,89 @@ DESIGN DECISIONS:
12
14
  - Keep recent conversations (30 days by default) in active memory
13
15
  """
14
16
 
15
- import os
16
- import sys
17
17
  import json
18
18
  import shutil
19
- from pathlib import Path
19
+ import sys
20
20
  from datetime import datetime, timedelta
21
- from typing import Dict, Any, List, Tuple
21
+ from typing import Any, Dict, List, Tuple
22
22
 
23
23
  from ...core.logger import get_logger
24
24
 
25
25
 
26
26
  def add_cleanup_parser(subparsers):
27
27
  """Add cleanup command parser.
28
-
28
+
29
29
  WHY: This command addresses the memory leak issue caused by large .claude.json files.
30
30
  It provides users with tools to manage conversation history and prevent memory issues.
31
31
  """
32
32
  parser = subparsers.add_parser(
33
- 'cleanup-memory',
34
- aliases=['cleanup', 'clean'],
35
- help='Clean up Claude conversation history to reduce memory usage'
33
+ "cleanup-memory",
34
+ aliases=["cleanup", "clean"],
35
+ help="Clean up Claude conversation history to reduce memory usage",
36
36
  )
37
-
37
+
38
38
  parser.add_argument(
39
- '--days',
39
+ "--days",
40
40
  type=int,
41
41
  default=30,
42
- help='Keep conversations from the last N days (default: 30)'
42
+ help="Keep conversations from the last N days (default: 30)",
43
43
  )
44
-
44
+
45
45
  parser.add_argument(
46
- '--max-size',
46
+ "--max-size",
47
47
  type=str,
48
- default='500KB',
49
- help='Maximum size for .claude.json file (e.g., 500KB, 1MB, default: 500KB)'
48
+ default="500KB",
49
+ help="Maximum size for .claude.json file (e.g., 500KB, 1MB, default: 500KB)",
50
50
  )
51
-
51
+
52
52
  parser.add_argument(
53
- '--archive',
54
- action='store_true',
53
+ "--archive",
54
+ action="store_true",
55
55
  default=True,
56
- help='Archive old conversations instead of deleting (default: True)'
56
+ help="Archive old conversations instead of deleting (default: True)",
57
57
  )
58
-
58
+
59
59
  parser.add_argument(
60
- '--no-archive',
61
- dest='archive',
62
- action='store_false',
63
- help='Delete old conversations without archiving'
60
+ "--no-archive",
61
+ dest="archive",
62
+ action="store_false",
63
+ help="Delete old conversations without archiving",
64
64
  )
65
-
65
+
66
66
  parser.add_argument(
67
- '--force',
68
- action='store_true',
69
- help='Skip confirmation prompts'
67
+ "--force", action="store_true", help="Skip confirmation prompts"
70
68
  )
71
-
69
+
72
70
  parser.add_argument(
73
- '--dry-run',
74
- action='store_true',
75
- help='Show what would be cleaned without making changes'
71
+ "--dry-run",
72
+ action="store_true",
73
+ help="Show what would be cleaned without making changes",
76
74
  )
77
-
75
+
78
76
  parser.set_defaults(func=cleanup_memory)
79
77
 
80
78
 
81
79
  def parse_size(size_str: str) -> int:
82
80
  """Parse human-readable size string to bytes.
83
-
81
+
84
82
  Args:
85
83
  size_str: Size string like "500KB", "1MB", "2GB"
86
-
84
+
87
85
  Returns:
88
86
  Size in bytes
89
87
  """
90
88
  size_str = size_str.upper().strip()
91
-
92
- multipliers = {
93
- 'B': 1,
94
- 'KB': 1024,
95
- 'MB': 1024 * 1024,
96
- 'GB': 1024 * 1024 * 1024
97
- }
98
-
89
+
90
+ multipliers = {"B": 1, "KB": 1024, "MB": 1024 * 1024, "GB": 1024 * 1024 * 1024}
91
+
99
92
  for suffix, multiplier in multipliers.items():
100
93
  if size_str.endswith(suffix):
101
94
  try:
102
- number = float(size_str[:-len(suffix)])
95
+ number = float(size_str[: -len(suffix)])
103
96
  return int(number * multiplier)
104
97
  except ValueError:
105
98
  pass
106
-
99
+
107
100
  # Try to parse as raw number (assume bytes)
108
101
  try:
109
102
  return int(size_str)
@@ -113,14 +106,14 @@ def parse_size(size_str: str) -> int:
113
106
 
114
107
  def format_size(size_bytes: int) -> str:
115
108
  """Format bytes as human-readable size.
116
-
109
+
117
110
  Args:
118
111
  size_bytes: Size in bytes
119
-
112
+
120
113
  Returns:
121
114
  Human-readable size string
122
115
  """
123
- for unit in ['B', 'KB', 'MB', 'GB']:
116
+ for unit in ["B", "KB", "MB", "GB"]:
124
117
  if size_bytes < 1024.0:
125
118
  return f"{size_bytes:.1f}{unit}"
126
119
  size_bytes /= 1024.0
@@ -129,139 +122,140 @@ def format_size(size_bytes: int) -> str:
129
122
 
130
123
  def analyze_claude_json(file_path: Path) -> Tuple[Dict[str, Any], List[str]]:
131
124
  """Analyze .claude.json file for cleanup opportunities.
132
-
125
+
133
126
  WHY: We need to understand the structure of the conversation history
134
127
  to identify what can be safely cleaned up.
135
-
128
+
136
129
  Args:
137
130
  file_path: Path to .claude.json file
138
-
131
+
139
132
  Returns:
140
133
  Tuple of (stats dict, issues list)
141
134
  """
142
135
  stats = {
143
- 'file_size': 0,
144
- 'line_count': 0,
145
- 'conversation_count': 0,
146
- 'oldest_conversation': None,
147
- 'newest_conversation': None,
148
- 'large_conversations': [],
149
- 'duplicate_count': 0
136
+ "file_size": 0,
137
+ "line_count": 0,
138
+ "conversation_count": 0,
139
+ "oldest_conversation": None,
140
+ "newest_conversation": None,
141
+ "large_conversations": [],
142
+ "duplicate_count": 0,
150
143
  }
151
-
144
+
152
145
  issues = []
153
-
146
+
154
147
  if not file_path.exists():
155
148
  issues.append(f"File not found: {file_path}")
156
149
  return stats, issues
157
-
150
+
158
151
  # Get file stats
159
152
  file_stat = file_path.stat()
160
- stats['file_size'] = file_stat.st_size
161
-
153
+ stats["file_size"] = file_stat.st_size
154
+
162
155
  # Count lines
163
- with open(file_path, 'r') as f:
164
- stats['line_count'] = sum(1 for _ in f)
165
-
156
+ with open(file_path, "r") as f:
157
+ stats["line_count"] = sum(1 for _ in f)
158
+
166
159
  # Try to parse JSON structure
167
160
  try:
168
- with open(file_path, 'r') as f:
161
+ with open(file_path, "r") as f:
169
162
  data = json.load(f)
170
-
163
+
171
164
  # Analyze conversation structure
172
165
  # Note: The actual structure may vary, this is a best-effort analysis
173
166
  if isinstance(data, dict):
174
167
  # Look for conversation-like structures
175
168
  for key, value in data.items():
176
- if isinstance(value, dict) and 'messages' in value:
177
- stats['conversation_count'] += 1
178
-
169
+ if isinstance(value, dict) and "messages" in value:
170
+ stats["conversation_count"] += 1
171
+
179
172
  # Track conversation sizes
180
173
  conv_size = len(json.dumps(value))
181
174
  if conv_size > 100000: # >100KB per conversation
182
- stats['large_conversations'].append({
183
- 'id': key,
184
- 'size': conv_size,
185
- 'message_count': len(value.get('messages', []))
186
- })
187
-
175
+ stats["large_conversations"].append(
176
+ {
177
+ "id": key,
178
+ "size": conv_size,
179
+ "message_count": len(value.get("messages", [])),
180
+ }
181
+ )
182
+
188
183
  # Sort large conversations by size
189
- stats['large_conversations'].sort(key=lambda x: x['size'], reverse=True)
190
-
184
+ stats["large_conversations"].sort(key=lambda x: x["size"], reverse=True)
185
+
191
186
  except json.JSONDecodeError as e:
192
187
  issues.append(f"JSON parsing error: {e}")
193
188
  except Exception as e:
194
189
  issues.append(f"Error analyzing file: {e}")
195
-
190
+
196
191
  return stats, issues
197
192
 
198
193
 
199
194
  def create_archive(source_path: Path, archive_dir: Path) -> Path:
200
195
  """Create an archive of the current .claude.json file.
201
-
196
+
202
197
  WHY: We want to preserve conversation history in case users need to
203
198
  reference it later, while still cleaning up active memory usage.
204
-
199
+
205
200
  Args:
206
201
  source_path: Path to source file
207
202
  archive_dir: Directory for archives
208
-
203
+
209
204
  Returns:
210
205
  Path to created archive
211
206
  """
212
207
  archive_dir.mkdir(parents=True, exist_ok=True)
213
-
208
+
214
209
  # Create timestamped archive name
215
210
  timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
216
211
  archive_name = f"claude_archive_{timestamp}.json"
217
212
  archive_path = archive_dir / archive_name
218
-
213
+
219
214
  # Copy file to archive
220
215
  shutil.copy2(source_path, archive_path)
221
-
216
+
222
217
  # Optionally compress large archives
223
218
  if archive_path.stat().st_size > 10 * 1024 * 1024: # >10MB
224
219
  import gzip
225
- compressed_path = archive_path.with_suffix('.json.gz')
226
- with open(archive_path, 'rb') as f_in:
227
- with gzip.open(compressed_path, 'wb') as f_out:
220
+
221
+ compressed_path = archive_path.with_suffix(".json.gz")
222
+ with open(archive_path, "rb") as f_in:
223
+ with gzip.open(compressed_path, "wb") as f_out:
228
224
  shutil.copyfileobj(f_in, f_out)
229
225
  archive_path.unlink() # Remove uncompressed version
230
226
  return compressed_path
231
-
227
+
232
228
  return archive_path
233
229
 
234
230
 
235
- def clean_claude_json(file_path: Path, keep_days: int, dry_run: bool = False) -> Tuple[int, int]:
231
+ def clean_claude_json(
232
+ file_path: Path, keep_days: int, dry_run: bool = False
233
+ ) -> Tuple[int, int]:
236
234
  """Clean up old conversations from .claude.json file.
237
-
235
+
238
236
  WHY: This function removes old conversation data while preserving recent
239
237
  conversations, reducing memory usage when Claude loads the file.
240
-
238
+
241
239
  Args:
242
240
  file_path: Path to .claude.json file
243
241
  keep_days: Number of days of history to keep
244
242
  dry_run: If True, don't make actual changes
245
-
243
+
246
244
  Returns:
247
245
  Tuple of (original_size, new_size) in bytes
248
246
  """
249
247
  if not file_path.exists():
250
248
  return 0, 0
251
-
249
+
252
250
  original_size = file_path.stat().st_size
253
-
251
+
254
252
  # For now, return a simple implementation
255
253
  # In a real implementation, we would:
256
254
  # 1. Parse the JSON structure
257
255
  # 2. Filter conversations by date
258
256
  # 3. Remove old conversations
259
257
  # 4. Write back the cleaned data
260
-
261
- # Since we don't know the exact structure of .claude.json,
262
- # we'll implement a safer approach: create a new minimal file
263
- # if the current one is too large
264
-
258
+
265
259
  if dry_run:
266
260
  # Estimate new size (roughly 10% of original for very large files)
267
261
  if original_size > 1024 * 1024: # >1MB
@@ -269,7 +263,7 @@ def clean_claude_json(file_path: Path, keep_days: int, dry_run: bool = False) ->
269
263
  else:
270
264
  estimated_new_size = original_size
271
265
  return original_size, estimated_new_size
272
-
266
+
273
267
  # For actual cleanup, we would need to understand the file structure better
274
268
  # For now, we'll just report the size without making changes
275
269
  return original_size, original_size
@@ -277,40 +271,40 @@ def clean_claude_json(file_path: Path, keep_days: int, dry_run: bool = False) ->
277
271
 
278
272
  def cleanup_memory(args):
279
273
  """Clean up Claude conversation history to reduce memory usage.
280
-
274
+
281
275
  WHY: This command addresses the 2GB memory leak issue when using --resume
282
276
  with large .claude.json files. It provides users with tools to manage
283
277
  their conversation history and prevent memory issues.
284
-
278
+
285
279
  Args:
286
280
  args: Parsed command line arguments
287
281
  """
288
282
  logger = get_logger("cleanup")
289
-
283
+
290
284
  # File paths
291
285
  claude_json = Path.home() / ".claude.json"
292
286
  archive_dir = Path.home() / ".claude-mpm" / "archives"
293
-
287
+
294
288
  print("๐Ÿงน Claude Memory Cleanup Tool")
295
289
  print("=" * 50)
296
-
290
+
297
291
  # Check if .claude.json exists
298
292
  if not claude_json.exists():
299
293
  print("โœ… No .claude.json file found - nothing to clean up")
300
294
  return
301
-
295
+
302
296
  # Analyze current state
303
297
  print("\n๐Ÿ“Š Analyzing current conversation history...")
304
298
  stats, issues = analyze_claude_json(claude_json)
305
-
299
+
306
300
  # Display current status
307
301
  print(f"\n๐Ÿ“ File: {claude_json}")
308
302
  print(f"๐Ÿ“ Size: {format_size(stats['file_size'])} ({stats['line_count']:,} lines)")
309
-
303
+
310
304
  # Check if cleanup is needed
311
305
  max_size = parse_size(args.max_size)
312
- needs_cleanup = stats['file_size'] > max_size
313
-
306
+ needs_cleanup = stats["file_size"] > max_size
307
+
314
308
  if not needs_cleanup:
315
309
  print(f"โœ… File size is within limits ({format_size(max_size)})")
316
310
  if not args.force:
@@ -319,13 +313,15 @@ def cleanup_memory(args):
319
313
  else:
320
314
  print(f"โš ๏ธ File size exceeds recommended limit of {format_size(max_size)}")
321
315
  print(f" This can cause memory issues when using --resume")
322
-
316
+
323
317
  # Show large conversations if any
324
- if stats['large_conversations']:
318
+ if stats["large_conversations"]:
325
319
  print(f"\n๐Ÿ” Found {len(stats['large_conversations'])} large conversations:")
326
- for conv in stats['large_conversations'][:3]:
327
- print(f" โ€ข {format_size(conv['size'])} - {conv['message_count']} messages")
328
-
320
+ for conv in stats["large_conversations"][:3]:
321
+ print(
322
+ f" โ€ข {format_size(conv['size'])} - {conv['message_count']} messages"
323
+ )
324
+
329
325
  # Show cleanup plan
330
326
  print(f"\n๐Ÿ“‹ Cleanup Plan:")
331
327
  print(f" โ€ข Keep conversations from last {args.days} days")
@@ -333,17 +329,17 @@ def cleanup_memory(args):
333
329
  print(f" โ€ข Archive old conversations to: {archive_dir}")
334
330
  else:
335
331
  print(f" โ€ข Delete old conversations (no archive)")
336
-
332
+
337
333
  if args.dry_run:
338
334
  print("\n๐Ÿ” DRY RUN MODE - No changes will be made")
339
-
335
+
340
336
  # Get confirmation unless forced
341
337
  if not args.force and not args.dry_run:
342
338
  print("\nโš ๏ธ This will modify your conversation history")
343
-
339
+
344
340
  # Ensure stdout is flushed before reading input
345
341
  sys.stdout.flush()
346
-
342
+
347
343
  # Check if we're in a TTY environment
348
344
  if not sys.stdin.isatty():
349
345
  # In non-TTY environment (like pipes), we need special handling
@@ -352,20 +348,20 @@ def cleanup_memory(args):
352
348
  # Use readline for better compatibility in non-TTY environments
353
349
  response = sys.stdin.readline().strip().lower()
354
350
  except (EOFError, KeyboardInterrupt):
355
- response = 'n'
351
+ response = "n"
356
352
  else:
357
353
  # In TTY environment, use normal input()
358
354
  try:
359
355
  response = input("Continue? [y/N]: ").strip().lower()
360
356
  except (EOFError, KeyboardInterrupt):
361
- response = 'n'
362
-
357
+ response = "n"
358
+
363
359
  # Handle various line endings and control characters
364
- response = response.replace('\r', '').replace('\n', '').strip()
365
- if response != 'y':
360
+ response = response.replace("\r", "").replace("\n", "").strip()
361
+ if response != "y":
366
362
  print("โŒ Cleanup cancelled")
367
363
  return
368
-
364
+
369
365
  # Create backup/archive
370
366
  if args.archive and not args.dry_run:
371
367
  print(f"\n๐Ÿ“ฆ Creating archive...")
@@ -380,71 +376,75 @@ def cleanup_memory(args):
380
376
  if not args.force:
381
377
  print("โŒ Cleanup cancelled for safety")
382
378
  return
383
-
379
+
384
380
  # Perform cleanup
385
381
  print(f"\n๐Ÿงน Cleaning up conversation history...")
386
-
382
+
387
383
  try:
388
384
  original_size, new_size = clean_claude_json(
389
- claude_json,
390
- keep_days=args.days,
391
- dry_run=args.dry_run
385
+ claude_json, keep_days=args.days, dry_run=args.dry_run
392
386
  )
393
-
387
+
394
388
  if args.dry_run:
395
- print(f"๐Ÿ“Š Would reduce size from {format_size(original_size)} to ~{format_size(new_size)}")
389
+ print(
390
+ f"๐Ÿ“Š Would reduce size from {format_size(original_size)} to ~{format_size(new_size)}"
391
+ )
396
392
  print(f"๐Ÿ’พ Estimated savings: {format_size(original_size - new_size)}")
397
393
  else:
398
394
  if new_size < original_size:
399
395
  print(f"โœ… Cleanup complete!")
400
- print(f"๐Ÿ“Š Reduced size from {format_size(original_size)} to {format_size(new_size)}")
396
+ print(
397
+ f"๐Ÿ“Š Reduced size from {format_size(original_size)} to {format_size(new_size)}"
398
+ )
401
399
  print(f"๐Ÿ’พ Saved: {format_size(original_size - new_size)}")
402
400
  else:
403
401
  print(f"โ„น๏ธ No conversations were old enough to clean up")
404
- print(f"๐Ÿ’ก Try using --days with a smaller value to clean more aggressively")
405
-
402
+ print(
403
+ f"๐Ÿ’ก Try using --days with a smaller value to clean more aggressively"
404
+ )
405
+
406
406
  except Exception as e:
407
407
  logger.error(f"Cleanup failed: {e}")
408
408
  print(f"โŒ Cleanup failed: {e}")
409
409
  return
410
-
410
+
411
411
  # Clean up old archive files
412
412
  if args.archive and not args.dry_run:
413
413
  print(f"\n๐Ÿ—‘๏ธ Cleaning up old archives...")
414
414
  old_archives = clean_old_archives(archive_dir, keep_days=90)
415
415
  if old_archives:
416
416
  print(f"โœ… Removed {len(old_archives)} old archive files")
417
-
417
+
418
418
  print("\nโœจ Memory cleanup complete!")
419
419
  print("๐Ÿ’ก You can now use 'claude-mpm run --resume' without memory issues")
420
420
 
421
421
 
422
422
  def clean_old_archives(archive_dir: Path, keep_days: int = 90) -> List[Path]:
423
423
  """Clean up old archive files.
424
-
424
+
425
425
  WHY: Archive files can accumulate over time. We keep them for a reasonable
426
426
  period (90 days by default) then clean them up to save disk space.
427
-
427
+
428
428
  Args:
429
429
  archive_dir: Directory containing archives
430
430
  keep_days: Number of days to keep archives
431
-
431
+
432
432
  Returns:
433
433
  List of removed archive paths
434
434
  """
435
435
  if not archive_dir.exists():
436
436
  return []
437
-
437
+
438
438
  removed = []
439
439
  cutoff_date = datetime.now() - timedelta(days=keep_days)
440
-
440
+
441
441
  for archive_file in archive_dir.glob("claude_archive_*.json*"):
442
442
  # Check file age
443
443
  file_stat = archive_file.stat()
444
444
  file_time = datetime.fromtimestamp(file_stat.st_mtime)
445
-
445
+
446
446
  if file_time < cutoff_date:
447
447
  archive_file.unlink()
448
448
  removed.append(archive_file)
449
-
450
- return removed
449
+
450
+ return removed