claude-mpm 4.1.1__py3-none-any.whl → 4.1.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 (389) hide show
  1. claude_mpm/BUILD_NUMBER +1 -1
  2. claude_mpm/VERSION +1 -1
  3. claude_mpm/__main__.py +1 -1
  4. claude_mpm/agents/BASE_PM.md +74 -46
  5. claude_mpm/agents/INSTRUCTIONS.md +11 -153
  6. claude_mpm/agents/WORKFLOW.md +61 -321
  7. claude_mpm/agents/__init__.py +11 -11
  8. claude_mpm/agents/agent_loader.py +23 -20
  9. claude_mpm/agents/agent_loader_integration.py +1 -1
  10. claude_mpm/agents/agents_metadata.py +27 -0
  11. claude_mpm/agents/async_agent_loader.py +5 -8
  12. claude_mpm/agents/base_agent_loader.py +36 -25
  13. claude_mpm/agents/frontmatter_validator.py +6 -6
  14. claude_mpm/agents/schema/agent_schema.json +1 -1
  15. claude_mpm/agents/system_agent_config.py +9 -9
  16. claude_mpm/agents/templates/api_qa.json +47 -2
  17. claude_mpm/agents/templates/engineer.json +33 -11
  18. claude_mpm/agents/templates/imagemagick.json +256 -0
  19. claude_mpm/agents/templates/qa.json +41 -2
  20. claude_mpm/agents/templates/ticketing.json +5 -5
  21. claude_mpm/agents/templates/web_qa.json +50 -2
  22. claude_mpm/cli/__init__.py +51 -46
  23. claude_mpm/cli/__main__.py +1 -1
  24. claude_mpm/cli/commands/__init__.py +10 -12
  25. claude_mpm/cli/commands/agent_manager.py +186 -181
  26. claude_mpm/cli/commands/agents.py +648 -1098
  27. claude_mpm/cli/commands/aggregate.py +30 -29
  28. claude_mpm/cli/commands/cleanup.py +50 -44
  29. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  30. claude_mpm/cli/commands/config.py +162 -127
  31. claude_mpm/cli/commands/doctor.py +52 -62
  32. claude_mpm/cli/commands/info.py +37 -25
  33. claude_mpm/cli/commands/mcp.py +3 -7
  34. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  35. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  36. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  37. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  38. claude_mpm/cli/commands/memory.py +339 -967
  39. claude_mpm/cli/commands/monitor.py +117 -88
  40. claude_mpm/cli/commands/run.py +233 -542
  41. claude_mpm/cli/commands/socketio_monitor.py +17 -19
  42. claude_mpm/cli/commands/tickets.py +92 -92
  43. claude_mpm/cli/parser.py +1 -5
  44. claude_mpm/cli/parsers/__init__.py +1 -1
  45. claude_mpm/cli/parsers/agent_manager_parser.py +50 -98
  46. claude_mpm/cli/parsers/agents_parser.py +2 -3
  47. claude_mpm/cli/parsers/base_parser.py +7 -5
  48. claude_mpm/cli/parsers/mcp_parser.py +4 -2
  49. claude_mpm/cli/parsers/monitor_parser.py +26 -18
  50. claude_mpm/cli/shared/__init__.py +10 -10
  51. claude_mpm/cli/shared/argument_patterns.py +57 -71
  52. claude_mpm/cli/shared/base_command.py +61 -53
  53. claude_mpm/cli/shared/error_handling.py +62 -58
  54. claude_mpm/cli/shared/output_formatters.py +78 -77
  55. claude_mpm/cli/startup_logging.py +280 -172
  56. claude_mpm/cli/utils.py +10 -11
  57. claude_mpm/cli_module/__init__.py +1 -1
  58. claude_mpm/cli_module/args.py +1 -1
  59. claude_mpm/cli_module/migration_example.py +5 -5
  60. claude_mpm/config/__init__.py +9 -9
  61. claude_mpm/config/agent_config.py +15 -14
  62. claude_mpm/config/experimental_features.py +4 -4
  63. claude_mpm/config/paths.py +0 -1
  64. claude_mpm/config/socketio_config.py +5 -6
  65. claude_mpm/constants.py +1 -2
  66. claude_mpm/core/__init__.py +8 -8
  67. claude_mpm/core/agent_name_normalizer.py +1 -1
  68. claude_mpm/core/agent_registry.py +22 -29
  69. claude_mpm/core/agent_session_manager.py +3 -3
  70. claude_mpm/core/base_service.py +7 -15
  71. claude_mpm/core/cache.py +4 -6
  72. claude_mpm/core/claude_runner.py +85 -113
  73. claude_mpm/core/config.py +43 -28
  74. claude_mpm/core/config_aliases.py +0 -9
  75. claude_mpm/core/config_constants.py +52 -30
  76. claude_mpm/core/constants.py +0 -1
  77. claude_mpm/core/container.py +18 -27
  78. claude_mpm/core/exceptions.py +2 -2
  79. claude_mpm/core/factories.py +10 -12
  80. claude_mpm/core/framework_loader.py +500 -680
  81. claude_mpm/core/hook_manager.py +26 -22
  82. claude_mpm/core/hook_performance_config.py +58 -47
  83. claude_mpm/core/injectable_service.py +1 -1
  84. claude_mpm/core/interactive_session.py +61 -152
  85. claude_mpm/core/interfaces.py +1 -100
  86. claude_mpm/core/lazy.py +5 -5
  87. claude_mpm/core/log_manager.py +587 -0
  88. claude_mpm/core/logger.py +125 -8
  89. claude_mpm/core/logging_config.py +15 -17
  90. claude_mpm/core/minimal_framework_loader.py +5 -8
  91. claude_mpm/core/oneshot_session.py +15 -33
  92. claude_mpm/core/optimized_agent_loader.py +4 -6
  93. claude_mpm/core/optimized_startup.py +2 -1
  94. claude_mpm/core/output_style_manager.py +147 -106
  95. claude_mpm/core/pm_hook_interceptor.py +0 -1
  96. claude_mpm/core/service_registry.py +11 -8
  97. claude_mpm/core/session_manager.py +1 -2
  98. claude_mpm/core/shared/__init__.py +1 -1
  99. claude_mpm/core/shared/config_loader.py +101 -97
  100. claude_mpm/core/shared/path_resolver.py +72 -68
  101. claude_mpm/core/shared/singleton_manager.py +56 -50
  102. claude_mpm/core/socketio_pool.py +26 -6
  103. claude_mpm/core/tool_access_control.py +4 -5
  104. claude_mpm/core/typing_utils.py +50 -59
  105. claude_mpm/core/unified_agent_registry.py +14 -19
  106. claude_mpm/core/unified_config.py +4 -6
  107. claude_mpm/core/unified_paths.py +197 -109
  108. claude_mpm/dashboard/open_dashboard.py +2 -4
  109. claude_mpm/experimental/cli_enhancements.py +51 -36
  110. claude_mpm/generators/agent_profile_generator.py +2 -4
  111. claude_mpm/hooks/base_hook.py +1 -2
  112. claude_mpm/hooks/claude_hooks/connection_pool.py +72 -26
  113. claude_mpm/hooks/claude_hooks/event_handlers.py +99 -154
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +110 -720
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/hook_handler_original.py +1040 -0
  117. claude_mpm/hooks/claude_hooks/hook_handler_refactored.py +347 -0
  118. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  119. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  120. claude_mpm/hooks/claude_hooks/services/__init__.py +13 -0
  121. claude_mpm/hooks/claude_hooks/services/connection_manager.py +190 -0
  122. claude_mpm/hooks/claude_hooks/services/duplicate_detector.py +106 -0
  123. claude_mpm/hooks/claude_hooks/services/state_manager.py +282 -0
  124. claude_mpm/hooks/claude_hooks/services/subagent_processor.py +374 -0
  125. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  126. claude_mpm/hooks/memory_integration_hook.py +5 -5
  127. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  128. claude_mpm/hooks/validation_hooks.py +4 -4
  129. claude_mpm/init.py +4 -9
  130. claude_mpm/models/__init__.py +2 -2
  131. claude_mpm/models/agent_session.py +11 -14
  132. claude_mpm/scripts/mcp_server.py +20 -11
  133. claude_mpm/scripts/mcp_wrapper.py +5 -5
  134. claude_mpm/scripts/mpm_doctor.py +321 -0
  135. claude_mpm/scripts/socketio_daemon.py +28 -25
  136. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  137. claude_mpm/scripts/socketio_server_manager.py +116 -95
  138. claude_mpm/services/__init__.py +49 -49
  139. claude_mpm/services/agent_capabilities_service.py +12 -18
  140. claude_mpm/services/agents/__init__.py +22 -22
  141. claude_mpm/services/agents/agent_builder.py +140 -119
  142. claude_mpm/services/agents/deployment/__init__.py +3 -3
  143. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  144. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  145. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  146. claude_mpm/services/agents/deployment/agent_deployment.py +129 -511
  147. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  148. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  149. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  150. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  151. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  152. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  153. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  154. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  155. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  156. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  157. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  158. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  159. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  160. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  161. claude_mpm/services/agents/deployment/base_agent_locator.py +132 -0
  162. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  163. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  164. claude_mpm/services/agents/deployment/deployment_results_manager.py +185 -0
  165. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  166. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  167. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  168. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  169. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  170. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  171. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  172. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  173. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  174. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  175. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  176. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  177. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  178. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  179. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  180. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  181. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  182. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  183. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  184. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  185. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  186. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  187. claude_mpm/services/agents/deployment/single_agent_deployer.py +315 -0
  188. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  189. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  190. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  191. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  192. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  193. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  194. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  195. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  196. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  197. claude_mpm/services/agents/loading/__init__.py +1 -1
  198. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  199. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  200. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  201. claude_mpm/services/agents/management/__init__.py +1 -1
  202. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  203. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  204. claude_mpm/services/agents/memory/__init__.py +4 -4
  205. claude_mpm/services/agents/memory/agent_memory_manager.py +157 -503
  206. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  207. claude_mpm/services/agents/memory/content_manager.py +44 -38
  208. claude_mpm/services/agents/memory/memory_categorization_service.py +165 -0
  209. claude_mpm/services/agents/memory/memory_file_service.py +103 -0
  210. claude_mpm/services/agents/memory/memory_format_service.py +201 -0
  211. claude_mpm/services/agents/memory/memory_limits_service.py +99 -0
  212. claude_mpm/services/agents/memory/template_generator.py +4 -6
  213. claude_mpm/services/agents/registry/__init__.py +11 -7
  214. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  215. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  216. claude_mpm/services/async_session_logger.py +1 -2
  217. claude_mpm/services/claude_session_logger.py +1 -2
  218. claude_mpm/services/cli/__init__.py +18 -0
  219. claude_mpm/services/cli/agent_cleanup_service.py +407 -0
  220. claude_mpm/services/cli/agent_dependency_service.py +395 -0
  221. claude_mpm/services/cli/agent_listing_service.py +463 -0
  222. claude_mpm/services/cli/agent_output_formatter.py +605 -0
  223. claude_mpm/services/cli/agent_validation_service.py +589 -0
  224. claude_mpm/services/cli/dashboard_launcher.py +424 -0
  225. claude_mpm/services/cli/memory_crud_service.py +617 -0
  226. claude_mpm/services/cli/memory_output_formatter.py +604 -0
  227. claude_mpm/services/cli/session_manager.py +513 -0
  228. claude_mpm/services/cli/socketio_manager.py +498 -0
  229. claude_mpm/services/cli/startup_checker.py +370 -0
  230. claude_mpm/services/command_deployment_service.py +173 -0
  231. claude_mpm/services/command_handler_service.py +20 -22
  232. claude_mpm/services/core/__init__.py +25 -25
  233. claude_mpm/services/core/base.py +0 -5
  234. claude_mpm/services/core/cache_manager.py +311 -0
  235. claude_mpm/services/core/interfaces/__init__.py +32 -32
  236. claude_mpm/services/core/interfaces/agent.py +0 -21
  237. claude_mpm/services/core/interfaces/communication.py +0 -27
  238. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  239. claude_mpm/services/core/interfaces/service.py +0 -29
  240. claude_mpm/services/core/memory_manager.py +637 -0
  241. claude_mpm/services/core/path_resolver.py +498 -0
  242. claude_mpm/services/core/service_container.py +520 -0
  243. claude_mpm/services/core/service_interfaces.py +436 -0
  244. claude_mpm/services/diagnostics/__init__.py +1 -1
  245. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  246. claude_mpm/services/diagnostics/checks/agent_check.py +152 -97
  247. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  248. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  249. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  250. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  251. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  252. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  253. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  254. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  255. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  256. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  257. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  258. claude_mpm/services/diagnostics/models.py +21 -19
  259. claude_mpm/services/event_aggregator.py +10 -17
  260. claude_mpm/services/event_bus/__init__.py +1 -1
  261. claude_mpm/services/event_bus/config.py +54 -35
  262. claude_mpm/services/event_bus/event_bus.py +76 -71
  263. claude_mpm/services/event_bus/relay.py +74 -64
  264. claude_mpm/services/events/__init__.py +11 -11
  265. claude_mpm/services/events/consumers/__init__.py +3 -3
  266. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  267. claude_mpm/services/events/consumers/logging.py +39 -37
  268. claude_mpm/services/events/consumers/metrics.py +56 -57
  269. claude_mpm/services/events/consumers/socketio.py +82 -81
  270. claude_mpm/services/events/core.py +110 -99
  271. claude_mpm/services/events/interfaces.py +56 -72
  272. claude_mpm/services/events/producers/__init__.py +1 -1
  273. claude_mpm/services/events/producers/hook.py +38 -38
  274. claude_mpm/services/events/producers/system.py +46 -44
  275. claude_mpm/services/exceptions.py +81 -80
  276. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  277. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  278. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  279. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  280. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  281. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  283. claude_mpm/services/hook_service.py +6 -9
  284. claude_mpm/services/infrastructure/__init__.py +1 -1
  285. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  286. claude_mpm/services/infrastructure/monitoring.py +21 -23
  287. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  288. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  289. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  290. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  291. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  292. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  293. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  294. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  295. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  296. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  297. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  298. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  299. claude_mpm/services/mcp_gateway/main.py +2 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  302. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  309. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  310. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  311. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  312. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  313. claude_mpm/services/memory/__init__.py +3 -3
  314. claude_mpm/services/memory/builder.py +3 -6
  315. claude_mpm/services/memory/cache/__init__.py +1 -1
  316. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  317. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  318. claude_mpm/services/memory/indexed_memory.py +5 -7
  319. claude_mpm/services/memory/optimizer.py +7 -10
  320. claude_mpm/services/memory/router.py +8 -9
  321. claude_mpm/services/memory_hook_service.py +48 -34
  322. claude_mpm/services/monitor_build_service.py +77 -73
  323. claude_mpm/services/port_manager.py +130 -108
  324. claude_mpm/services/project/analyzer.py +12 -10
  325. claude_mpm/services/project/registry.py +11 -11
  326. claude_mpm/services/recovery_manager.py +10 -19
  327. claude_mpm/services/response_tracker.py +0 -1
  328. claude_mpm/services/runner_configuration_service.py +19 -20
  329. claude_mpm/services/session_management_service.py +7 -11
  330. claude_mpm/services/shared/__init__.py +1 -1
  331. claude_mpm/services/shared/async_service_base.py +58 -50
  332. claude_mpm/services/shared/config_service_base.py +73 -67
  333. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  334. claude_mpm/services/shared/manager_base.py +94 -82
  335. claude_mpm/services/shared/service_factory.py +96 -98
  336. claude_mpm/services/socketio/__init__.py +3 -3
  337. claude_mpm/services/socketio/client_proxy.py +5 -5
  338. claude_mpm/services/socketio/event_normalizer.py +199 -181
  339. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  340. claude_mpm/services/socketio/handlers/base.py +5 -4
  341. claude_mpm/services/socketio/handlers/connection.py +163 -136
  342. claude_mpm/services/socketio/handlers/file.py +13 -14
  343. claude_mpm/services/socketio/handlers/git.py +12 -7
  344. claude_mpm/services/socketio/handlers/hook.py +49 -44
  345. claude_mpm/services/socketio/handlers/memory.py +0 -1
  346. claude_mpm/services/socketio/handlers/project.py +0 -1
  347. claude_mpm/services/socketio/handlers/registry.py +37 -19
  348. claude_mpm/services/socketio/migration_utils.py +98 -84
  349. claude_mpm/services/socketio/server/__init__.py +1 -1
  350. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  351. claude_mpm/services/socketio/server/core.py +65 -54
  352. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  353. claude_mpm/services/socketio/server/main.py +64 -38
  354. claude_mpm/services/socketio_client_manager.py +10 -12
  355. claude_mpm/services/subprocess_launcher_service.py +4 -7
  356. claude_mpm/services/system_instructions_service.py +13 -14
  357. claude_mpm/services/ticket_manager.py +2 -2
  358. claude_mpm/services/utility_service.py +5 -13
  359. claude_mpm/services/version_control/__init__.py +16 -16
  360. claude_mpm/services/version_control/branch_strategy.py +5 -8
  361. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  362. claude_mpm/services/version_control/git_operations.py +5 -7
  363. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  364. claude_mpm/services/version_control/version_parser.py +13 -18
  365. claude_mpm/services/version_service.py +10 -11
  366. claude_mpm/storage/__init__.py +1 -1
  367. claude_mpm/storage/state_storage.py +22 -28
  368. claude_mpm/utils/__init__.py +6 -6
  369. claude_mpm/utils/agent_dependency_loader.py +47 -33
  370. claude_mpm/utils/config_manager.py +11 -14
  371. claude_mpm/utils/dependency_cache.py +1 -1
  372. claude_mpm/utils/dependency_manager.py +13 -17
  373. claude_mpm/utils/dependency_strategies.py +8 -10
  374. claude_mpm/utils/environment_context.py +3 -9
  375. claude_mpm/utils/error_handler.py +3 -13
  376. claude_mpm/utils/file_utils.py +1 -1
  377. claude_mpm/utils/path_operations.py +8 -12
  378. claude_mpm/utils/robust_installer.py +110 -33
  379. claude_mpm/utils/subprocess_utils.py +5 -6
  380. claude_mpm/validation/agent_validator.py +3 -6
  381. claude_mpm/validation/frontmatter_validator.py +1 -1
  382. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/METADATA +1 -1
  383. claude_mpm-4.1.3.dist-info/RECORD +528 -0
  384. claude_mpm/cli/commands/run_config_checker.py +0 -160
  385. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  386. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/WHEEL +0 -0
  387. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/entry_points.txt +0 -0
  388. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/licenses/LICENSE +0 -0
  389. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.3.dist-info}/top_level.txt +0 -0
@@ -13,18 +13,14 @@ DESIGN DECISIONS:
13
13
 
14
14
  import json
15
15
  import os
16
- from datetime import datetime
17
16
  from pathlib import Path
18
- from typing import Dict, Any, Optional
17
+ from typing import Any, Dict
19
18
 
20
- import click
21
-
22
- from ...core.config import Config
23
- from ...core.logger import get_logger
24
19
  from ...core.shared.config_loader import ConfigLoader
25
20
  from ...services.agents.memory import AgentMemoryManager
26
- from ..shared.base_command import MemoryCommand, CommandResult
27
- from ..shared.argument_patterns import add_memory_arguments, add_output_arguments
21
+ from ...services.cli.memory_crud_service import MemoryCRUDService
22
+ from ...services.cli.memory_output_formatter import MemoryOutputFormatter
23
+ from ..shared.base_command import CommandResult, MemoryCommand
28
24
 
29
25
 
30
26
  class MemoryManagementCommand(MemoryCommand):
@@ -33,6 +29,8 @@ class MemoryManagementCommand(MemoryCommand):
33
29
  def __init__(self):
34
30
  super().__init__("memory")
35
31
  self._memory_manager = None
32
+ self._formatter = None
33
+ self._crud_service = None
36
34
 
37
35
  @property
38
36
  def memory_manager(self):
@@ -46,11 +44,36 @@ class MemoryManagementCommand(MemoryCommand):
46
44
  self._memory_manager = AgentMemoryManager(config, current_dir)
47
45
  return self._memory_manager
48
46
 
47
+ @property
48
+ def formatter(self):
49
+ """Get formatter instance (lazy loaded)."""
50
+ if self._formatter is None:
51
+ # Check if quiet mode is requested
52
+ quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
53
+ self._formatter = MemoryOutputFormatter(quiet=quiet)
54
+ return self._formatter
55
+
56
+ @property
57
+ def crud_service(self):
58
+ """Get CRUD service instance (lazy loaded)."""
59
+ if self._crud_service is None:
60
+ self._crud_service = MemoryCRUDService(memory_manager=self.memory_manager)
61
+ return self._crud_service
62
+
49
63
  def validate_args(self, args) -> str:
50
64
  """Validate command arguments."""
51
65
  # Check if memory command is valid
52
- if hasattr(args, 'memory_command') and args.memory_command:
53
- valid_commands = ['init', 'view', 'add', 'clean', 'optimize', 'build', 'cross-ref', 'route']
66
+ if hasattr(args, "memory_command") and args.memory_command:
67
+ valid_commands = [
68
+ "init",
69
+ "view",
70
+ "add",
71
+ "clean",
72
+ "optimize",
73
+ "build",
74
+ "cross-ref",
75
+ "route",
76
+ ]
54
77
  if args.memory_command not in valid_commands:
55
78
  return f"Unknown memory command: {args.memory_command}. Valid commands: {', '.join(valid_commands)}"
56
79
  return None
@@ -59,7 +82,7 @@ class MemoryManagementCommand(MemoryCommand):
59
82
  """Execute the memory command."""
60
83
  try:
61
84
  # Handle default case (no subcommand)
62
- if not hasattr(args, 'memory_command') or not args.memory_command:
85
+ if not hasattr(args, "memory_command") or not args.memory_command:
63
86
  return self._show_status(args)
64
87
 
65
88
  # Route to specific subcommand handlers
@@ -78,20 +101,17 @@ class MemoryManagementCommand(MemoryCommand):
78
101
 
79
102
  if args.memory_command in command_map:
80
103
  return command_map[args.memory_command](args)
81
- else:
82
- available_commands = list(command_map.keys())
83
- error_msg = f"Unknown memory command: {args.memory_command}"
104
+ available_commands = list(command_map.keys())
105
+ error_msg = f"Unknown memory command: {args.memory_command}"
84
106
 
85
- output_format = getattr(args, 'format', 'text')
86
- if output_format in ['json', 'yaml']:
87
- return CommandResult.error_result(
88
- error_msg,
89
- data={"available_commands": available_commands}
90
- )
91
- else:
92
- print(f"❌ {error_msg}")
93
- print(f"Available commands: {', '.join(available_commands)}")
94
- return CommandResult.error_result(error_msg)
107
+ output_format = getattr(args, "format", "text")
108
+ if output_format in ["json", "yaml"]:
109
+ return CommandResult.error_result(
110
+ error_msg, data={"available_commands": available_commands}
111
+ )
112
+ print(f"❌ {error_msg}")
113
+ print(f"Available commands: {', '.join(available_commands)}")
114
+ return CommandResult.error_result(error_msg)
95
115
 
96
116
  except Exception as e:
97
117
  self.logger.error(f"Error managing memory: {e}", exc_info=True)
@@ -100,16 +120,19 @@ class MemoryManagementCommand(MemoryCommand):
100
120
  def _show_status(self, args) -> CommandResult:
101
121
  """Show memory system status."""
102
122
  try:
103
- output_format = getattr(args, 'format', 'text')
123
+ output_format = getattr(args, "format", "text")
104
124
 
105
- if output_format in ['json', 'yaml']:
125
+ if output_format in ["json", "yaml"]:
106
126
  # Structured output
107
127
  status_data = self._get_status_data()
108
- return CommandResult.success_result("Memory status retrieved", data=status_data)
109
- else:
110
- # Text output using existing function
111
- _show_status(self.memory_manager)
112
- return CommandResult.success_result("Memory status displayed")
128
+ return CommandResult.success_result(
129
+ "Memory status retrieved", data=status_data
130
+ )
131
+ # Text output using formatter
132
+ status = self.memory_manager.get_memory_status()
133
+ output = self.formatter.format_status(status)
134
+ print(output)
135
+ return CommandResult.success_result("Memory status displayed")
113
136
 
114
137
  except Exception as e:
115
138
  self.logger.error(f"Error showing memory status: {e}", exc_info=True)
@@ -117,110 +140,151 @@ class MemoryManagementCommand(MemoryCommand):
117
140
 
118
141
  def _get_status_data(self) -> Dict[str, Any]:
119
142
  """Get memory status as structured data."""
120
- memory_dir = self.memory_manager.memories_dir
143
+ # Use CRUD service to list memories with stats
144
+ result = self.crud_service.list_memories(include_stats=True)
121
145
 
122
- if not memory_dir.exists():
146
+ if not result.get("success"):
123
147
  return {
124
- "memory_directory": str(memory_dir),
148
+ "error": result.get("error", "Failed to get status"),
125
149
  "exists": False,
126
150
  "agents": [],
127
151
  "total_size_kb": 0,
128
- "total_files": 0
152
+ "total_files": 0,
129
153
  }
130
154
 
131
- agents = []
132
- total_size = 0
133
-
134
- for memory_file in memory_dir.glob("*.md"):
135
- if memory_file.is_file():
136
- size = memory_file.stat().st_size
137
- total_size += size
138
-
139
- agents.append({
140
- "agent_id": memory_file.stem,
141
- "file": memory_file.name,
142
- "size_kb": size / 1024,
143
- "path": str(memory_file)
144
- })
155
+ # Transform CRUD service result to expected format
156
+ memories = result.get("memories", [])
157
+ agents = [
158
+ {
159
+ "agent_id": mem["agent_id"],
160
+ "file": mem["file"],
161
+ "size_kb": mem.get("size_kb", 0),
162
+ "path": mem["path"],
163
+ }
164
+ for mem in memories
165
+ ]
145
166
 
146
167
  return {
147
- "memory_directory": str(memory_dir),
148
- "exists": True,
168
+ "memory_directory": result.get("memory_directory", ""),
169
+ "exists": result.get("exists", False),
149
170
  "agents": agents,
150
- "total_size_kb": total_size / 1024,
151
- "total_files": len(agents)
171
+ "total_size_kb": result.get("total_size_kb", 0),
172
+ "total_files": result.get("total_files", 0),
152
173
  }
153
174
 
154
175
  def _show_memories(self, args) -> CommandResult:
155
176
  """Show agent memories."""
156
177
  try:
157
- output_format = getattr(args, 'format', 'text')
178
+ output_format = getattr(args, "format", "text")
179
+ agent_id = getattr(args, "agent_id", None)
180
+ raw_output = getattr(args, "raw", False)
158
181
 
159
- if output_format in ['json', 'yaml']:
160
- # Structured output
161
- memories_data = self._get_memories_data(args)
162
- return CommandResult.success_result("Memories retrieved", data=memories_data)
182
+ if output_format in ["json", "yaml"] or raw_output:
183
+ # Use CRUD service for structured output
184
+ result = self.crud_service.read_memory(agent_id)
185
+
186
+ if not result.get("success"):
187
+ return CommandResult.error_result(
188
+ result.get("error", "Failed to read memories")
189
+ )
190
+
191
+ if raw_output:
192
+ # Output raw JSON for external tools
193
+ print(json.dumps(result, indent=2, ensure_ascii=False))
194
+ return CommandResult.success_result("Raw memory data output")
195
+
196
+ return CommandResult.success_result("Memories retrieved", data=result)
197
+
198
+ # Text output
199
+ result = self.crud_service.read_memory(agent_id)
200
+
201
+ if not result.get("success"):
202
+ print(f"❌ {result.get('error', 'Failed to read memories')}")
203
+ return CommandResult.error_result(result.get("error"))
204
+
205
+ print("🧠 Agent Memories Display")
206
+ print("-" * 80)
207
+
208
+ if agent_id:
209
+ # Single agent memory
210
+ content = result.get("content", "")
211
+ if content:
212
+ output = self.formatter.format_memory_view(
213
+ agent_id, content, getattr(args, "format", "detailed")
214
+ )
215
+ print(output)
216
+ else:
217
+ print(f"📭 No memory found for agent: {agent_id}")
163
218
  else:
164
- # Text output using existing function
165
- _show_memories(args, self.memory_manager)
166
- return CommandResult.success_result("Memories displayed")
219
+ # All agent memories
220
+ agents = result.get("agents", {})
221
+ if agents:
222
+ # Parse and format all memories
223
+ agent_memories = {}
224
+ for aid, data in agents.items():
225
+ sections = self.formatter._parse_memory_content(
226
+ data.get("content", "")
227
+ )
228
+ agent_memories[aid] = sections
229
+
230
+ output = self.formatter.format_agent_memories_summary(
231
+ agent_memories, getattr(args, "format", "detailed")
232
+ )
233
+ print(output)
234
+ else:
235
+ print("📭 No agent memories found")
236
+
237
+ return CommandResult.success_result("Memories displayed")
167
238
 
168
239
  except Exception as e:
169
240
  self.logger.error(f"Error showing memories: {e}", exc_info=True)
170
241
  return CommandResult.error_result(f"Error showing memories: {e}")
171
242
 
172
- def _get_memories_data(self, args) -> Dict[str, Any]:
173
- """Get memories as structured data."""
174
- agent_id = getattr(args, 'agent', None)
175
-
176
- if agent_id:
177
- # Single agent memory
178
- memory_content = self.memory_manager.load_agent_memory(agent_id)
179
- return {
180
- "agent_id": agent_id,
181
- "memory_content": memory_content,
182
- "has_memory": bool(memory_content)
183
- }
184
- else:
185
- # All agent memories
186
- memory_dir = self.memory_manager.memories_dir
187
- if not memory_dir.exists():
188
- return {"agents": [], "memory_directory": str(memory_dir), "exists": False}
189
-
190
- agents = {}
191
- for memory_file in memory_dir.glob("*.md"):
192
- if memory_file.is_file():
193
- agent_id = memory_file.stem
194
- memory_content = self.memory_manager.load_agent_memory(agent_id)
195
- agents[agent_id] = {
196
- "memory_content": memory_content,
197
- "file_path": str(memory_file)
198
- }
199
-
200
- return {
201
- "agents": agents,
202
- "memory_directory": str(memory_dir),
203
- "exists": True,
204
- "agent_count": len(agents)
205
- }
243
+ # Removed _get_memories_data - now handled inline with CRUD service
206
244
 
207
245
  def _init_memory(self, args) -> CommandResult:
208
246
  """Initialize project-specific memories."""
209
247
  try:
210
- output_format = getattr(args, 'format', 'text')
211
-
212
- if output_format in ['json', 'yaml']:
213
- # For structured output, return the initialization task
214
- task_data = {
215
- "task": "Initialize project-specific agent memories",
216
- "description": "Analyze project structure and create targeted memories for agents",
217
- "suggested_command": "claude-mpm memory add --agent <agent_name> --learning '<insight>'"
218
- }
219
- return CommandResult.success_result("Memory initialization task created", data=task_data)
220
- else:
221
- # Text output using existing function
222
- _init_memory(args, self.memory_manager)
223
- return CommandResult.success_result("Memory initialization task displayed")
248
+ output_format = getattr(args, "format", "text")
249
+
250
+ # Use CRUD service for initialization task
251
+ result = self.crud_service.init_project_memories()
252
+
253
+ if not result.get("success"):
254
+ return CommandResult.error_result(
255
+ result.get("error", "Failed to create initialization task")
256
+ )
257
+
258
+ if output_format in ["json", "yaml"]:
259
+ # Return structured task data
260
+ return CommandResult.success_result(
261
+ "Memory initialization task created", data=result.get("task_data")
262
+ )
263
+
264
+ # Text output - display the task
265
+ task = result.get("task_data", {})
266
+ print("🚀 Initializing project-specific memories...")
267
+ print("=" * 80)
268
+ print()
269
+ print("This will analyze the project to:")
270
+ for idx, instruction in enumerate(task.get("instructions", []), 1):
271
+ print(f" {idx}. {instruction}")
272
+ print()
273
+ print("The analysis will cover:")
274
+ for area in task.get("focus_areas", []):
275
+ print(f" • {area}")
276
+ print()
277
+ print("Example commands to use:")
278
+ for cmd in task.get("example_commands", []):
279
+ print(f" {cmd}")
280
+ print()
281
+ print("=" * 80)
282
+ print()
283
+ print(
284
+ "📝 Note: Copy the task above to execute the memory initialization process."
285
+ )
286
+
287
+ return CommandResult.success_result("Memory initialization task displayed")
224
288
 
225
289
  except Exception as e:
226
290
  self.logger.error(f"Error initializing memory: {e}", exc_info=True)
@@ -229,17 +293,38 @@ class MemoryManagementCommand(MemoryCommand):
229
293
  def _add_learning(self, args) -> CommandResult:
230
294
  """Add learning to agent memory."""
231
295
  try:
232
- output_format = getattr(args, 'format', 'text')
296
+ output_format = getattr(args, "format", "text")
233
297
 
234
- if output_format in ['json', 'yaml']:
235
- # For structured output, we'd need to implement the actual learning addition
236
- # For now, delegate to existing function and return success
237
- _add_learning(args, self.memory_manager)
238
- return CommandResult.success_result("Learning added to agent memory")
239
- else:
240
- # Text output using existing function
241
- _add_learning(args, self.memory_manager)
242
- return CommandResult.success_result("Learning added")
298
+ # Extract arguments
299
+ agent_id = getattr(args, "agent_id", None)
300
+ learning_type = getattr(args, "learning_type", "context")
301
+ content = getattr(args, "content", "")
302
+
303
+ if not agent_id or not content:
304
+ return CommandResult.error_result(
305
+ "Agent ID and content are required for adding learning"
306
+ )
307
+
308
+ # Use CRUD service to add learning
309
+ result = self.crud_service.update_memory(agent_id, learning_type, content)
310
+
311
+ if not result.get("success"):
312
+ return CommandResult.error_result(
313
+ result.get("error", "Failed to add learning")
314
+ )
315
+
316
+ if output_format in ["json", "yaml"]:
317
+ # Return structured result
318
+ return CommandResult.success_result(
319
+ "Learning added to agent memory", data=result
320
+ )
321
+
322
+ # Text output
323
+ print(f"✅ Added {learning_type} to {agent_id} memory")
324
+ print(f" Section: {result.get('section', 'Unknown')}")
325
+ print(f" Content: {result.get('content_preview', content[:100])}")
326
+
327
+ return CommandResult.success_result("Learning added")
243
328
 
244
329
  except Exception as e:
245
330
  self.logger.error(f"Error adding learning: {e}", exc_info=True)
@@ -248,16 +333,49 @@ class MemoryManagementCommand(MemoryCommand):
248
333
  def _clean_memory(self, args) -> CommandResult:
249
334
  """Clean up old/unused memory files."""
250
335
  try:
251
- output_format = getattr(args, 'format', 'text')
336
+ output_format = getattr(args, "format", "text")
337
+ agent_id = getattr(args, "agent_id", None)
338
+ dry_run = getattr(args, "dry_run", True)
339
+
340
+ # Use CRUD service for cleanup
341
+ result = self.crud_service.clean_memory(agent_id=agent_id, dry_run=dry_run)
342
+
343
+ if not result.get("success"):
344
+ return CommandResult.error_result(result.get("error", "Cleanup failed"))
252
345
 
253
- if output_format in ['json', 'yaml']:
254
- # For structured output, return cleanup results
255
- cleanup_data = {"cleaned_files": [], "errors": [], "summary": "Memory cleanup completed"}
256
- return CommandResult.success_result("Memory cleanup completed", data=cleanup_data)
346
+ if output_format in ["json", "yaml"]:
347
+ # Return structured cleanup results
348
+ return CommandResult.success_result(
349
+ result.get("message", "Memory cleanup completed"), data=result
350
+ )
351
+
352
+ # Text output
353
+ print("🧹 Memory cleanup")
354
+ print("-" * 80)
355
+
356
+ if dry_run:
357
+ print("📊 Cleanup preview (dry run)")
358
+ candidates = result.get("cleanup_candidates", [])
359
+ if candidates:
360
+ print(f"Found {len(candidates)} files eligible for cleanup:")
361
+ for candidate in candidates:
362
+ print(
363
+ f" • {candidate['agent_id']}: {candidate['size_kb']:.1f} KB, {candidate['age_days']} days old"
364
+ )
365
+ print(f" Reason: {candidate['reason']}")
366
+ else:
367
+ print("No files eligible for cleanup")
257
368
  else:
258
- # Text output using existing function
259
- _clean_memory(args, self.memory_manager)
260
- return CommandResult.success_result("Memory cleanup completed")
369
+ cleaned = result.get("cleaned_files", [])
370
+ if cleaned:
371
+ print(f"Cleaned {len(cleaned)} files")
372
+ else:
373
+ print(result.get("message", "No files cleaned"))
374
+
375
+ if result.get("note"):
376
+ print(f"\n⚠️ {result['note']}")
377
+
378
+ return CommandResult.success_result("Memory cleanup completed")
261
379
 
262
380
  except Exception as e:
263
381
  self.logger.error(f"Error cleaning memory: {e}", exc_info=True)
@@ -266,16 +384,33 @@ class MemoryManagementCommand(MemoryCommand):
266
384
  def _optimize_memory(self, args) -> CommandResult:
267
385
  """Optimize memory files."""
268
386
  try:
269
- output_format = getattr(args, 'format', 'text')
387
+ output_format = getattr(args, "format", "text")
388
+ agent_id = getattr(args, "agent_id", None)
270
389
 
271
- if output_format in ['json', 'yaml']:
272
- # For structured output, return optimization results
273
- optimization_data = {"optimized_agents": [], "size_reduction": 0, "summary": "Memory optimization completed"}
274
- return CommandResult.success_result("Memory optimization completed", data=optimization_data)
390
+ if output_format in ["json", "yaml"]:
391
+ # For structured output, perform optimization and return results
392
+ if agent_id:
393
+ result = self.memory_manager.optimize_memory(agent_id)
394
+ else:
395
+ result = self.memory_manager.optimize_memory()
396
+ return CommandResult.success_result(
397
+ "Memory optimization completed", data=result
398
+ )
399
+ # Text output using formatter
400
+ if agent_id:
401
+ print(f"📊 Optimizing memory for agent: {agent_id}")
402
+ result = self.memory_manager.optimize_memory(agent_id)
403
+ output = self.formatter.format_optimization_results(
404
+ result, is_single_agent=True
405
+ )
275
406
  else:
276
- # Text output using existing function
277
- _optimize_memory(args, self.memory_manager)
278
- return CommandResult.success_result("Memory optimization completed")
407
+ print("📊 Optimizing all agent memories...")
408
+ result = self.memory_manager.optimize_memory()
409
+ output = self.formatter.format_optimization_results(
410
+ result, is_single_agent=False
411
+ )
412
+ print(output)
413
+ return CommandResult.success_result("Memory optimization completed")
279
414
 
280
415
  except Exception as e:
281
416
  self.logger.error(f"Error optimizing memory: {e}", exc_info=True)
@@ -284,16 +419,21 @@ class MemoryManagementCommand(MemoryCommand):
284
419
  def _build_memory(self, args) -> CommandResult:
285
420
  """Build agent memories from project documentation."""
286
421
  try:
287
- output_format = getattr(args, 'format', 'text')
422
+ output_format = getattr(args, "format", "text")
288
423
 
289
- if output_format in ['json', 'yaml']:
424
+ if output_format in ["json", "yaml"]:
290
425
  # For structured output, return build results
291
- build_data = {"built_memories": [], "processed_files": [], "summary": "Memory build completed"}
292
- return CommandResult.success_result("Memory build completed", data=build_data)
293
- else:
294
- # Text output using existing function
295
- _build_memory(args, self.memory_manager)
296
- return CommandResult.success_result("Memory build completed")
426
+ build_data = {
427
+ "built_memories": [],
428
+ "processed_files": [],
429
+ "summary": "Memory build completed",
430
+ }
431
+ return CommandResult.success_result(
432
+ "Memory build completed", data=build_data
433
+ )
434
+ # Text output using existing function
435
+ _build_memory(args, self.memory_manager)
436
+ return CommandResult.success_result("Memory build completed")
297
437
 
298
438
  except Exception as e:
299
439
  self.logger.error(f"Error building memory: {e}", exc_info=True)
@@ -302,16 +442,21 @@ class MemoryManagementCommand(MemoryCommand):
302
442
  def _cross_reference_memory(self, args) -> CommandResult:
303
443
  """Find cross-references and common patterns."""
304
444
  try:
305
- output_format = getattr(args, 'format', 'text')
445
+ output_format = getattr(args, "format", "text")
306
446
 
307
- if output_format in ['json', 'yaml']:
447
+ if output_format in ["json", "yaml"]:
308
448
  # For structured output, return cross-reference results
309
- crossref_data = {"common_patterns": [], "agent_similarities": [], "summary": "Cross-reference analysis completed"}
310
- return CommandResult.success_result("Cross-reference analysis completed", data=crossref_data)
311
- else:
312
- # Text output using existing function
313
- _cross_reference_memory(args, self.memory_manager)
314
- return CommandResult.success_result("Cross-reference analysis completed")
449
+ crossref_data = {
450
+ "common_patterns": [],
451
+ "agent_similarities": [],
452
+ "summary": "Cross-reference analysis completed",
453
+ }
454
+ return CommandResult.success_result(
455
+ "Cross-reference analysis completed", data=crossref_data
456
+ )
457
+ # Text output using existing function
458
+ _cross_reference_memory(args, self.memory_manager)
459
+ return CommandResult.success_result("Cross-reference analysis completed")
315
460
 
316
461
  except Exception as e:
317
462
  self.logger.error(f"Error cross-referencing memory: {e}", exc_info=True)
@@ -320,38 +465,27 @@ class MemoryManagementCommand(MemoryCommand):
320
465
  def _route_memory_command(self, args) -> CommandResult:
321
466
  """Route memory command to appropriate agent."""
322
467
  try:
323
- output_format = getattr(args, 'format', 'text')
468
+ output_format = getattr(args, "format", "text")
324
469
 
325
- if output_format in ['json', 'yaml']:
470
+ if output_format in ["json", "yaml"]:
326
471
  # For structured output, return routing results
327
- routing_data = {"routed_to": "memory_agent", "command": getattr(args, 'command', ''), "summary": "Command routed successfully"}
328
- return CommandResult.success_result("Command routed successfully", data=routing_data)
329
- else:
330
- # Text output using existing function
331
- _route_memory_command(args, self.memory_manager)
332
- return CommandResult.success_result("Command routed successfully")
472
+ routing_data = {
473
+ "routed_to": "memory_agent",
474
+ "command": getattr(args, "command", ""),
475
+ "summary": "Command routed successfully",
476
+ }
477
+ return CommandResult.success_result(
478
+ "Command routed successfully", data=routing_data
479
+ )
480
+ # Text output using existing function
481
+ _route_memory_command(args, self.memory_manager)
482
+ return CommandResult.success_result("Command routed successfully")
333
483
 
334
484
  except Exception as e:
335
485
  self.logger.error(f"Error routing memory command: {e}", exc_info=True)
336
486
  return CommandResult.error_result(f"Error routing memory command: {e}")
337
487
 
338
488
 
339
- def manage_memory(args):
340
- """
341
- Main entry point for memory management commands.
342
-
343
- This function maintains backward compatibility while using the new MemoryCommand pattern.
344
- """
345
- command = MemoryManagementCommand()
346
- result = command.execute(args)
347
-
348
- # Print result if structured output format is requested
349
- if hasattr(args, 'format') and args.format in ['json', 'yaml']:
350
- command.print_result(result, args)
351
-
352
- return result.exit_code
353
-
354
-
355
489
  def manage_memory(args) -> int:
356
490
  """Main entry point for memory management commands.
357
491
 
@@ -361,377 +495,31 @@ def manage_memory(args) -> int:
361
495
  result = command.execute(args)
362
496
 
363
497
  # Print result if structured output format is requested
364
- if hasattr(args, 'format') and args.format in ['json', 'yaml']:
498
+ if hasattr(args, "format") and args.format in ["json", "yaml"]:
365
499
  command.print_result(result, args)
366
500
 
367
501
  return result.exit_code
368
502
 
369
503
 
370
- def _init_memory(args, memory_manager):
371
- """
372
- Initialize project-specific memories via agent delegation.
373
-
374
- WHY: When starting with a new project, agents need project-specific knowledge
375
- beyond what automatic analysis provides. This command triggers an agent task
376
- to comprehensively scan the project and create custom memories.
377
-
378
- Args:
379
- args: Command line arguments (unused but kept for consistency)
380
- memory_manager: AgentMemoryManager instance
381
- """
382
- logger = get_logger("cli")
383
-
384
- print("🚀 Initializing project-specific memories...")
385
- print("=" * 80)
386
- print()
387
- print("This will analyze the project to:")
388
- print(" 1. Scan project structure and documentation")
389
- print(" 2. Analyze source code for patterns and conventions")
390
- print(" 3. Create targeted memories for each agent type")
391
- print(" 4. Add insights using 'claude-mpm memory add' commands")
392
- print()
393
- print("The analysis will cover:")
394
- print(" • Project architecture and design patterns")
395
- print(" • Coding conventions and standards")
396
- print(" • Key modules and integration points")
397
- print(" • Testing patterns and quality standards")
398
- print(" • Performance considerations")
399
- print(" • Domain-specific terminology")
400
- print()
401
- print("=" * 80)
402
- print()
403
- print("[Agent Task: Initialize Project-Specific Memories]")
404
- print()
405
- print("Please analyze this project and create custom memories for all agents.")
406
- print()
407
- print("Instructions:")
408
- print("1. Scan the project structure, documentation, and source code")
409
- print("2. Identify key patterns, conventions, and project-specific knowledge")
410
- print("3. Create targeted memories for each agent type")
411
- print("4. Use 'claude-mpm memory add <agent> <type> \"<content>\"' commands")
412
- print()
413
- print("Focus areas:")
414
- print(" • Architectural patterns and design decisions")
415
- print(" • Coding conventions from actual source code")
416
- print(" • Key modules, APIs, and integration points")
417
- print(" • Testing patterns and quality standards")
418
- print(" • Performance considerations specific to this project")
419
- print(" • Common pitfalls based on the codebase")
420
- print(" • Domain-specific terminology and concepts")
421
- print()
422
- print("Example commands to use:")
423
- print(
424
- ' claude-mpm memory add engineer pattern "Use dependency injection with @inject"'
425
- )
426
- print(
427
- ' claude-mpm memory add qa pattern "Test files follow test_<module>_<feature>.py"'
428
- )
429
- print(
430
- ' claude-mpm memory add research context "Project uses microservices architecture"'
431
- )
432
- print()
433
- print("Begin by examining the project structure and key files.")
434
- print()
435
- print("=" * 80)
436
- print()
437
- print("📝 Note: Copy the task above to execute the memory initialization process.")
438
- print(" Use 'claude-mpm memory add' commands to add discovered insights.")
439
-
440
-
441
- def _show_status(memory_manager):
442
- """
443
- Show comprehensive memory system status.
444
-
445
- WHY: Users need to see memory system health, file sizes, optimization
446
- opportunities, and agent-specific statistics to understand the system state.
447
-
448
- Args:
449
- memory_manager: AgentMemoryManager instance
450
- """
451
- print("Agent Memory System Status")
452
- print("-" * 80)
453
-
454
- try:
455
- # Get comprehensive status from memory manager
456
- status = memory_manager.get_memory_status()
457
-
458
- if not status.get("success", True):
459
- print(f"❌ Error getting status: {status.get('error', 'Unknown error')}")
460
- return
504
+ # Removed _init_memory - now handled by MemoryCRUDService.init_project_memories()
461
505
 
462
- # Show system overview
463
- system_health = status.get("system_health", "unknown")
464
- health_emoji = {
465
- "healthy": "✅",
466
- "needs_optimization": "⚠️",
467
- "high_usage": "📊",
468
- "no_memory_dir": "📁",
469
- }.get(system_health, "❓")
470
-
471
- print(f"🧠 Memory System Health: {health_emoji} {system_health}")
472
- print(f"📁 Memory Directory: {status.get('memory_directory', 'Unknown')}")
473
- print(
474
- f"🔧 System Enabled: {'Yes' if status.get('system_enabled', True) else 'No'}"
475
- )
476
- print(
477
- f"📚 Auto Learning: {'Yes' if status.get('auto_learning', True) else 'No'}"
478
- )
479
- print(f"📊 Total Agents: {status.get('total_agents', 0)}")
480
- print(f"💾 Total Size: {status.get('total_size_kb', 0):.1f} KB")
481
- print()
482
-
483
- # Show optimization opportunities
484
- opportunities = status.get("optimization_opportunities", [])
485
- if opportunities:
486
- print(f"⚠️ Optimization Opportunities ({len(opportunities)}):")
487
- for opportunity in opportunities[:5]: # Show top 5
488
- print(f" • {opportunity}")
489
- if len(opportunities) > 5:
490
- print(f" ... and {len(opportunities) - 5} more")
491
- print()
492
506
 
493
- # Show per-agent details
494
- agents = status.get("agents", {})
495
- if agents:
496
- print(f"📋 Agent Memory Details:")
497
- for agent_id, agent_info in sorted(agents.items()):
498
- if "error" in agent_info:
499
- print(f" ❌ {agent_id}: Error - {agent_info['error']}")
500
- continue
501
-
502
- size_kb = agent_info.get("size_kb", 0)
503
- size_limit = agent_info.get("size_limit_kb", 8)
504
- utilization = agent_info.get("size_utilization", 0)
505
- sections = agent_info.get("sections", 0)
506
- items = agent_info.get("items", 0)
507
- last_modified = agent_info.get("last_modified", "Unknown")
508
- auto_learning = agent_info.get("auto_learning", True)
509
-
510
- # Format last modified time
511
- try:
512
- from datetime import datetime
513
-
514
- dt = datetime.fromisoformat(last_modified.replace("Z", "+00:00"))
515
- last_modified_str = dt.strftime("%Y-%m-%d %H:%M:%S")
516
- except:
517
- last_modified_str = last_modified
518
-
519
- # Status indicator based on usage
520
- if utilization > 90:
521
- status_emoji = "🔴" # High usage
522
- elif utilization > 70:
523
- status_emoji = "🟡" # Medium usage
524
- else:
525
- status_emoji = "🟢" # Low usage
507
+ # Removed _show_status - functionality moved to MemoryManagementCommand._show_status()
526
508
 
527
- print(f" {status_emoji} {agent_id}")
528
- print(
529
- f" Size: {size_kb:.1f} KB / {size_limit} KB ({utilization:.1f}%)"
530
- )
531
- print(f" Content: {sections} sections, {items} items")
532
- print(f" Auto-learning: {'On' if auto_learning else 'Off'}")
533
- print(f" Last modified: {last_modified_str}")
534
- else:
535
- print("📭 No agent memories found")
536
509
 
537
- except Exception as e:
538
- print(f"❌ Error showing status: {e}")
539
- # Fallback to basic status display
540
- _show_basic_status(memory_manager)
541
-
542
-
543
- def _show_basic_status(memory_manager):
544
- """Fallback basic status display if comprehensive status fails."""
545
- print("\n--- Basic Status (Fallback) ---")
546
-
547
- memory_dir = memory_manager.memories_dir
548
- if not memory_dir.exists():
549
- print("📁 Memory directory not found - no agent memories stored yet")
550
- print(f" Expected location: {memory_dir}")
551
- return
510
+ # Removed _show_basic_status - functionality integrated into MemoryManagementCommand
552
511
 
553
- # Support both old and new formats
554
- memory_files = list(memory_dir.glob("*_memories.md"))
555
- # Also check for old formats for backward compatibility
556
- memory_files.extend(memory_dir.glob("*_agent.md"))
557
- memory_files.extend([f for f in memory_dir.glob("*.md")
558
- if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
559
512
 
560
- if not memory_files:
561
- print("📭 No memory files found")
562
- print(f" Memory directory: {memory_dir}")
563
- return
513
+ # Removed _view_memory - functionality moved to MemoryCRUDService.read_memory()
564
514
 
565
- print(f"📁 Memory directory: {memory_dir}")
566
- print(f"📊 Total memory files: {len(memory_files)}")
567
515
 
568
- total_size = 0
569
- for file_path in sorted(memory_files):
570
- stat = file_path.stat()
571
- size_kb = stat.st_size / 1024
572
- total_size += stat.st_size
516
+ # Removed _add_learning - now handled by MemoryCRUDService.update_memory()
573
517
 
574
- # Extract agent name from various formats
575
- if file_path.name.endswith("_memories.md"):
576
- agent_id = file_path.stem[:-9] # Remove "_memories"
577
- elif file_path.name.endswith("_agent.md"):
578
- agent_id = file_path.stem[:-6] # Remove "_agent"
579
- else:
580
- agent_id = file_path.stem
581
- print(f" {agent_id}: {size_kb:.1f} KB")
582
518
 
583
- print(f"💾 Total size: {total_size / 1024:.1f} KB")
519
+ # Removed _clean_memory - now handled by MemoryCRUDService.clean_memory()
584
520
 
585
521
 
586
- def _view_memory(args, memory_manager):
587
- """
588
- View agent memory file contents.
589
-
590
- WHY: Users need to inspect what learnings an agent has accumulated
591
- to understand its behavior and debug issues.
592
-
593
- Args:
594
- args: Command arguments with agent_id
595
- memory_manager: AgentMemoryManager instance
596
- """
597
- agent_id = args.agent_id
598
-
599
- try:
600
- memory_content = memory_manager.load_agent_memory(agent_id)
601
-
602
- if not memory_content:
603
- print(f"📭 No memory found for agent: {agent_id}")
604
- return
605
-
606
- print(f"🧠 Memory for agent: {agent_id}")
607
- print("-" * 80)
608
- print(memory_content)
609
-
610
- except FileNotFoundError:
611
- print(f"📭 No memory file found for agent: {agent_id}")
612
- except Exception as e:
613
- print(f"❌ Error viewing memory: {e}")
614
-
615
-
616
- def _add_learning(args, memory_manager):
617
- """
618
- Manually add learning to agent memory.
619
-
620
- WHY: Allows manual injection of learnings for testing or correction
621
- purposes, useful for debugging and development.
622
-
623
- Args:
624
- args: Command arguments with agent_id, learning_type, and content
625
- memory_manager: AgentMemoryManager instance
626
- """
627
- agent_id = args.agent_id
628
- section = args.learning_type # Map learning_type to section name
629
- content = args.content
630
-
631
- # Map learning types to appropriate sections
632
- section_map = {
633
- "pattern": "Project Architecture",
634
- "error": "Common Mistakes to Avoid",
635
- "optimization": "Implementation Guidelines",
636
- "preference": "Implementation Guidelines",
637
- "context": "Current Technical Context",
638
- }
639
-
640
- section_name = section_map.get(section, "Current Technical Context")
641
-
642
- try:
643
- success = memory_manager.update_agent_memory(agent_id, section_name, content)
644
-
645
- if success:
646
- print(f"✅ Added {section} to {agent_id} memory in section: {section_name}")
647
- print(f" Content: {content[:100]}{'...' if len(content) > 100 else ''}")
648
- else:
649
- print(f"❌ Failed to add learning to {agent_id} memory")
650
- print(" Memory file may be at size limit or section may be full")
651
-
652
- except Exception as e:
653
- print(f"❌ Error adding learning: {e}")
654
-
655
-
656
- def _clean_memory(args, memory_manager):
657
- """
658
- Clean up old/unused memory files.
659
-
660
- WHY: Memory files can accumulate over time. This provides a way to
661
- clean up old or unused files to save disk space.
662
-
663
- DESIGN DECISION: For Phase 1, this is a stub implementation.
664
- Full cleanup logic will be implemented based on usage patterns.
665
-
666
- Args:
667
- args: Command arguments
668
- memory_manager: AgentMemoryManager instance
669
- """
670
- print("🧹 Memory cleanup")
671
- print("-" * 80)
672
-
673
- # For Phase 1, just show what would be cleaned
674
- memory_dir = memory_manager.memories_dir
675
- if not memory_dir.exists():
676
- print("📁 No memory directory found - nothing to clean")
677
- return
678
-
679
- # Support both old and new formats
680
- memory_files = list(memory_dir.glob("*_memories.md"))
681
- # Also check for old formats for backward compatibility
682
- memory_files.extend(memory_dir.glob("*_agent.md"))
683
- memory_files.extend([f for f in memory_dir.glob("*.md")
684
- if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
685
- if not memory_files:
686
- print("📭 No memory files found - nothing to clean")
687
- return
688
-
689
- print(f"📊 Found {len(memory_files)} memory files")
690
- print()
691
- print("⚠️ Cleanup not yet implemented in Phase 1")
692
- print(" Future cleanup will remove:")
693
- print(" - Memory files older than 30 days with no recent access")
694
- print(" - Corrupted memory files")
695
- print(" - Memory files for non-existent agents")
696
-
697
-
698
- def _optimize_memory(args, memory_manager):
699
- """
700
- Optimize memory files by removing duplicates and consolidating similar items.
701
-
702
- WHY: Memory files can become cluttered over time with duplicate or redundant
703
- information. This command provides automated cleanup while preserving
704
- important learnings.
705
-
706
- Args:
707
- args: Command arguments with optional agent_id
708
- memory_manager: AgentMemoryManager instance
709
- """
710
- print("🔧 Memory Optimization")
711
- print("-" * 80)
712
-
713
- agent_id = getattr(args, "agent_id", None)
714
-
715
- try:
716
- if agent_id:
717
- print(f"📊 Optimizing memory for agent: {agent_id}")
718
- result = memory_manager.optimize_memory(agent_id)
719
- else:
720
- print("📊 Optimizing all agent memories...")
721
- result = memory_manager.optimize_memory()
722
-
723
- if result.get("success"):
724
- if agent_id:
725
- # Single agent results
726
- _display_single_optimization_result(result)
727
- else:
728
- # All agents results
729
- _display_bulk_optimization_results(result)
730
- else:
731
- print(f"❌ Optimization failed: {result.get('error', 'Unknown error')}")
732
-
733
- except Exception as e:
734
- print(f"❌ Error during optimization: {e}")
522
+ # Removed _optimize_memory - functionality moved to MemoryManagementCommand._optimize_memory()
735
523
 
736
524
 
737
525
  def _build_memory(args, memory_manager):
@@ -755,35 +543,11 @@ def _build_memory(args, memory_manager):
755
543
  print("🔍 Analyzing project documentation...")
756
544
  result = memory_manager.build_memories_from_docs(force_rebuild)
757
545
 
758
- if result.get("success"):
759
- print(f" Successfully processed documentation")
760
- print(f" Files processed: {result.get('files_processed', 0)}")
761
- print(f" Memories created: {result.get('memories_created', 0)}")
762
- print(f" Memories updated: {result.get('memories_updated', 0)}")
763
- print(f" Agents affected: {result.get('total_agents_affected', 0)}")
764
-
765
- if result.get("agents_affected"):
766
- print(f" Affected agents: {', '.join(result['agents_affected'])}")
767
-
768
- # Show file-specific results
769
- files_results = result.get("files", {})
770
- if files_results:
771
- print("\n📄 File processing details:")
772
- for file_path, file_result in files_results.items():
773
- if file_result.get("success"):
774
- extracted = file_result.get("items_extracted", 0)
775
- created = file_result.get("memories_created", 0)
776
- print(
777
- f" {file_path}: {extracted} items extracted, {created} memories created"
778
- )
779
-
780
- if result.get("errors"):
781
- print("\n⚠️ Errors encountered:")
782
- for error in result["errors"]:
783
- print(f" {error}")
784
-
785
- else:
786
- print(f"❌ Build failed: {result.get('error', 'Unknown error')}")
546
+ # Use formatter to display build results
547
+ quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
548
+ formatter = MemoryOutputFormatter(quiet=quiet)
549
+ output = formatter.format_build_results(result)
550
+ print(output)
787
551
 
788
552
  except Exception as e:
789
553
  print(f"❌ Error building memories: {e}")
@@ -800,291 +564,22 @@ def _cross_reference_memory(args, memory_manager):
800
564
  args: Command arguments with optional query
801
565
  memory_manager: AgentMemoryManager instance
802
566
  """
803
- print("🔗 Memory Cross-Reference Analysis")
804
- print("-" * 80)
805
-
806
567
  query = getattr(args, "query", None)
807
568
 
808
569
  try:
809
- if query:
810
- print(f"🔍 Searching for: '{query}'")
811
- else:
812
- print("🔍 Analyzing all agent memories for patterns...")
813
-
814
570
  result = memory_manager.cross_reference_memories(query)
815
571
 
816
- if result.get("success") is False:
817
- print(f"❌ Analysis failed: {result.get('error', 'Unknown error')}")
818
- return
819
-
820
- # Display common patterns
821
- common_patterns = result.get("common_patterns", [])
822
- if common_patterns:
823
- print(f"\n🔄 Common patterns found ({len(common_patterns)}):")
824
- for pattern in common_patterns[:10]: # Show top 10
825
- agents = ", ".join(pattern["agents"])
826
- print(f" • {pattern['pattern']}")
827
- print(f" Found in: {agents} ({pattern['count']} instances)")
828
- else:
829
- print("\n🔄 No common patterns found")
830
-
831
- # Display query matches if query was provided
832
- if query and result.get("query_matches"):
833
- print(f"\n🎯 Query matches for '{query}':")
834
- for match in result["query_matches"]:
835
- print(f" 📋 {match['agent']}:")
836
- for line in match["matches"][:3]: # Show first 3 matches
837
- print(f" • {line}")
838
-
839
- # Display agent correlations
840
- correlations = result.get("agent_correlations", {})
841
- if correlations:
842
- print(f"\n🤝 Agent knowledge correlations:")
843
- sorted_correlations = sorted(
844
- correlations.items(), key=lambda x: x[1], reverse=True
845
- )
846
- for agents, count in sorted_correlations[:5]: # Show top 5
847
- print(f" {agents}: {count} common items")
848
- else:
849
- print("\n🤝 No significant correlations found")
572
+ # Use formatter to display cross-reference results
573
+ quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
574
+ formatter = MemoryOutputFormatter(quiet=quiet)
575
+ output = formatter.format_cross_reference(result, query)
576
+ print(output)
850
577
 
851
578
  except Exception as e:
852
579
  print(f"❌ Error during cross-reference analysis: {e}")
853
580
 
854
581
 
855
- def _show_memories(args, memory_manager):
856
- """
857
- Show agent memories in a user-friendly format with cross-references and patterns.
858
-
859
- WHY: Users need to see agent memories in a readable format to understand
860
- what agents have learned and identify common patterns across agents.
861
-
862
- DESIGN DECISION: Added --raw flag to output structured JSON data for
863
- programmatic processing, enabling external tools and scripts to access
864
- all agent memories in a structured format.
865
-
866
- Args:
867
- args: Command arguments with optional agent_id, format, and raw flag
868
- memory_manager: AgentMemoryManager instance
869
- """
870
- agent_id = getattr(args, "agent_id", None)
871
- format_type = getattr(args, "format", "detailed")
872
- raw_output = getattr(args, "raw", False)
873
-
874
- try:
875
- if raw_output:
876
- # Output structured JSON data
877
- if agent_id:
878
- # Get single agent memory in raw format
879
- _output_single_agent_raw(agent_id, memory_manager)
880
- else:
881
- # Get all agent memories in raw format
882
- _output_all_memories_raw(memory_manager)
883
- else:
884
- # Normal user-friendly display
885
- print("🧠 Agent Memories Display")
886
- print("-" * 80)
887
-
888
- if agent_id:
889
- _show_single_agent_memory(agent_id, format_type, memory_manager)
890
- else:
891
- _show_all_agent_memories(format_type, memory_manager)
892
-
893
- except Exception as e:
894
- if raw_output:
895
- # Output error in JSON format for consistency
896
- error_output = {
897
- "success": False,
898
- "error": str(e),
899
- "timestamp": datetime.now().isoformat(),
900
- }
901
- print(json.dumps(error_output, indent=2))
902
- else:
903
- print(f"❌ Error showing memories: {e}")
904
-
905
-
906
- def _show_single_agent_memory(agent_id, format_type, memory_manager):
907
- """Show memory for a single agent in the specified format."""
908
- memory_content = memory_manager.load_agent_memory(agent_id)
909
-
910
- if not memory_content:
911
- print(f"📭 No memory found for agent: {agent_id}")
912
- return
913
-
914
- print(f"🤖 Agent: {agent_id}")
915
- print("-" * 40)
916
-
917
- if format_type == "full":
918
- print(memory_content)
919
- else:
920
- # Parse and display memory sections
921
- sections = _parse_memory_content(memory_content)
922
-
923
- for section_name, items in sections.items():
924
- if items:
925
- print(f"\n📚 {section_name} ({len(items)} items):")
926
- for i, item in enumerate(items[:5], 1): # Show first 5 items
927
- print(f" {i}. {item}")
928
- if len(items) > 5:
929
- print(f" ... and {len(items) - 5} more")
930
-
931
-
932
- def _show_all_agent_memories(format_type, memory_manager):
933
- """Show memories for all agents with cross-references."""
934
- # Get all available agent memory files
935
- memory_dir = memory_manager.memories_dir
936
- if not memory_dir.exists():
937
- print("📁 No memory directory found")
938
- return
939
-
940
- # Support both old and new formats
941
- memory_files = list(memory_dir.glob("*_memories.md"))
942
- # Also check for old formats for backward compatibility
943
- memory_files.extend(memory_dir.glob("*_agent.md"))
944
- memory_files.extend([f for f in memory_dir.glob("*.md")
945
- if f.name != "README.md" and not f.name.endswith("_memories.md") and not f.name.endswith("_agent.md")])
946
- if not memory_files:
947
- print("📭 No agent memories found")
948
- return
949
-
950
- print(f"📊 Found memories for {len(memory_files)} agents")
951
- print()
952
-
953
- agent_memories = {}
954
- total_items = 0
955
-
956
- # Load all agent memories
957
- for file_path in sorted(memory_files):
958
- # Extract agent name from various formats
959
- if file_path.name.endswith("_memories.md"):
960
- agent_id = file_path.stem[:-9] # Remove "_memories"
961
- elif file_path.name.endswith("_agent.md"):
962
- agent_id = file_path.stem[:-6] # Remove "_agent"
963
- else:
964
- agent_id = file_path.stem
965
- try:
966
- memory_content = memory_manager.load_agent_memory(agent_id)
967
- if memory_content:
968
- sections = _parse_memory_content(memory_content)
969
- agent_memories[agent_id] = sections
970
-
971
- # Count items
972
- item_count = sum(len(items) for items in sections.values())
973
- total_items += item_count
974
-
975
- if format_type == "summary":
976
- print(f"🤖 {agent_id}")
977
- print(f" 📚 {len(sections)} sections, {item_count} total items")
978
-
979
- # Show section summary
980
- for section_name, items in sections.items():
981
- if items:
982
- print(f" • {section_name}: {len(items)} items")
983
- print()
984
- elif format_type == "detailed":
985
- print(f"🤖 {agent_id}")
986
- print(f" 📚 {len(sections)} sections, {item_count} total items")
987
-
988
- for section_name, items in sections.items():
989
- if items:
990
- print(f"\n 📖 {section_name}:")
991
- for item in items[:3]: # Show first 3 items
992
- print(f" • {item}")
993
- if len(items) > 3:
994
- print(f" ... and {len(items) - 3} more")
995
- print()
996
- except Exception as e:
997
- print(f"❌ Error loading memory for {agent_id}: {e}")
998
-
999
- print(f"📊 Total: {total_items} memory items across {len(agent_memories)} agents")
1000
-
1001
- # Show cross-references if we have multiple agents
1002
- if len(agent_memories) > 1:
1003
- print("\n🔗 Cross-References and Common Patterns:")
1004
- _find_common_patterns(agent_memories)
1005
-
1006
-
1007
- def _parse_memory_content(content):
1008
- """Parse memory content into sections and items."""
1009
- sections = {}
1010
- current_section = None
1011
- current_items = []
1012
-
1013
- for line in content.split("\n"):
1014
- line = line.strip()
1015
-
1016
- if line.startswith("## ") and not line.startswith("## Memory Usage"):
1017
- # New section
1018
- if current_section and current_items:
1019
- sections[current_section] = current_items.copy()
1020
-
1021
- current_section = line[3:].strip()
1022
- current_items = []
1023
- elif line.startswith("- ") and current_section:
1024
- # Item in current section
1025
- item = line[2:].strip()
1026
- if item and len(item) > 5: # Filter out very short items
1027
- current_items.append(item)
1028
-
1029
- # Add final section
1030
- if current_section and current_items:
1031
- sections[current_section] = current_items
1032
-
1033
- return sections
1034
-
1035
-
1036
- def _find_common_patterns(agent_memories):
1037
- """Find common patterns across agent memories."""
1038
- pattern_count = {}
1039
- agent_patterns = {}
1040
-
1041
- # Collect all patterns and which agents have them
1042
- for agent_id, sections in agent_memories.items():
1043
- agent_patterns[agent_id] = set()
1044
-
1045
- for section_name, items in sections.items():
1046
- for item in items:
1047
- # Normalize item for comparison (lowercase, basic cleanup)
1048
- normalized = item.lower().strip()
1049
- if len(normalized) > 10: # Skip very short items
1050
- pattern_count[normalized] = pattern_count.get(normalized, 0) + 1
1051
- agent_patterns[agent_id].add(normalized)
1052
-
1053
- # Find patterns that appear in multiple agents
1054
- common_patterns = [
1055
- (pattern, count) for pattern, count in pattern_count.items() if count > 1
1056
- ]
1057
- common_patterns.sort(key=lambda x: x[1], reverse=True)
1058
-
1059
- if common_patterns:
1060
- print("\n🔄 Most Common Patterns:")
1061
- for pattern, count in common_patterns[:5]:
1062
- # Find which agents have this pattern
1063
- agents_with_pattern = [
1064
- agent
1065
- for agent, patterns in agent_patterns.items()
1066
- if pattern in patterns
1067
- ]
1068
- print(f" • {pattern[:80]}{'...' if len(pattern) > 80 else ''}")
1069
- print(f" Found in: {', '.join(agents_with_pattern)} ({count} agents)")
1070
- print()
1071
- else:
1072
- print(" No common patterns found across agents")
1073
-
1074
- # Show agent similarities
1075
- print("\n🤝 Agent Knowledge Similarity:")
1076
- agents = list(agent_memories.keys())
1077
- for i, agent1 in enumerate(agents):
1078
- for agent2 in agents[i + 1 :]:
1079
- common_items = len(agent_patterns[agent1] & agent_patterns[agent2])
1080
- if common_items > 0:
1081
- total_items = len(agent_patterns[agent1] | agent_patterns[agent2])
1082
- similarity = (
1083
- (common_items / total_items) * 100 if total_items > 0 else 0
1084
- )
1085
- print(
1086
- f" {agent1} ↔ {agent2}: {common_items} common items ({similarity:.1f}% similarity)"
1087
- )
582
+ # Note: Memory display functions have been moved to MemoryManagementCommand and MemoryCRUDService
1088
583
 
1089
584
 
1090
585
  def _route_memory_command(args, memory_manager):
@@ -1123,7 +618,7 @@ def _route_memory_command(args, memory_manager):
1123
618
  confidence = result.get("confidence", 0.0)
1124
619
  reasoning = result.get("reasoning", "No reasoning provided")
1125
620
 
1126
- print(f"\n🎯 Routing Decision:")
621
+ print("\n🎯 Routing Decision:")
1127
622
  print(f" Target Agent: {target_agent}")
1128
623
  print(f" Section: {section}")
1129
624
  print(f" Confidence: {confidence:.2f}")
@@ -1132,7 +627,7 @@ def _route_memory_command(args, memory_manager):
1132
627
  # Show agent scores if available
1133
628
  agent_scores = result.get("agent_scores", {})
1134
629
  if agent_scores:
1135
- print(f"\n📊 Agent Relevance Scores:")
630
+ print("\n📊 Agent Relevance Scores:")
1136
631
  sorted_scores = sorted(
1137
632
  [(agent, data["score"]) for agent, data in agent_scores.items()],
1138
633
  key=lambda x: x[1],
@@ -1153,141 +648,18 @@ def _route_memory_command(args, memory_manager):
1153
648
 
1154
649
  def _display_single_optimization_result(result):
1155
650
  """Display optimization results for a single agent."""
1156
- agent_id = result.get("agent_id", "unknown")
1157
- original_size = result.get("original_size", 0)
1158
- optimized_size = result.get("optimized_size", 0)
1159
- size_reduction = result.get("size_reduction", 0)
1160
- size_reduction_percent = result.get("size_reduction_percent", 0)
1161
-
1162
- print(f"✅ Optimization completed for {agent_id}")
1163
- print(f" Original size: {original_size:,} bytes")
1164
- print(f" Optimized size: {optimized_size:,} bytes")
1165
- print(f" Size reduction: {size_reduction:,} bytes ({size_reduction_percent}%)")
1166
-
1167
- duplicates = result.get("duplicates_removed", 0)
1168
- consolidated = result.get("items_consolidated", 0)
1169
- reordered = result.get("items_reordered", 0)
1170
-
1171
- if duplicates > 0:
1172
- print(f" Duplicates removed: {duplicates}")
1173
- if consolidated > 0:
1174
- print(f" Items consolidated: {consolidated}")
1175
- if reordered > 0:
1176
- print(f" Sections reordered: {reordered}")
1177
-
1178
- backup_path = result.get("backup_created")
1179
- if backup_path:
1180
- print(f" Backup created: {backup_path}")
651
+ quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
652
+ formatter = MemoryOutputFormatter(quiet=quiet)
653
+ output = formatter.format_optimization_results(result, is_single_agent=True)
654
+ print(output)
1181
655
 
1182
656
 
1183
657
  def _display_bulk_optimization_results(result):
1184
658
  """Display optimization results for all agents."""
1185
- summary = result.get("summary", {})
1186
-
1187
- print(f"✅ Bulk optimization completed")
1188
- print(f" Agents processed: {summary.get('agents_processed', 0)}")
1189
- print(f" Agents optimized: {summary.get('agents_optimized', 0)}")
1190
- print(f" Total size before: {summary.get('total_size_before', 0):,} bytes")
1191
- print(f" Total size after: {summary.get('total_size_after', 0):,} bytes")
1192
- print(
1193
- f" Total reduction: {summary.get('total_size_reduction', 0):,} bytes ({summary.get('total_size_reduction_percent', 0)}%)"
1194
- )
1195
- print(f" Total duplicates removed: {summary.get('total_duplicates_removed', 0)}")
1196
- print(f" Total items consolidated: {summary.get('total_items_consolidated', 0)}")
1197
-
1198
- # Show per-agent summary
1199
- agents_results = result.get("agents", {})
1200
- if agents_results:
1201
- print(f"\n📊 Per-agent results:")
1202
- for agent_id, agent_result in agents_results.items():
1203
- if agent_result.get("success"):
1204
- reduction = agent_result.get("size_reduction_percent", 0)
1205
- duplicates = agent_result.get("duplicates_removed", 0)
1206
- consolidated = agent_result.get("items_consolidated", 0)
1207
-
1208
- status_parts = []
1209
- if duplicates > 0:
1210
- status_parts.append(f"{duplicates} dupes")
1211
- if consolidated > 0:
1212
- status_parts.append(f"{consolidated} consolidated")
1213
-
1214
- status = f" ({', '.join(status_parts)})" if status_parts else ""
1215
- print(f" {agent_id}: {reduction}% reduction{status}")
1216
- else:
1217
- error = agent_result.get("error", "Unknown error")
1218
- print(f" {agent_id}: ❌ {error}")
1219
-
1220
-
1221
- def _output_all_memories_raw(memory_manager):
1222
- """
1223
- Output all agent memories in raw JSON format.
1224
-
1225
- WHY: Provides programmatic access to all agent memories for external tools,
1226
- scripts, or APIs that need to process or analyze the complete memory state.
1227
-
1228
- Args:
1229
- memory_manager: AgentMemoryManager instance
1230
- """
1231
- try:
1232
- raw_data = memory_manager.get_all_memories_raw()
1233
- print(json.dumps(raw_data, indent=2, ensure_ascii=False))
1234
- except Exception as e:
1235
- error_output = {
1236
- "success": False,
1237
- "error": f"Failed to retrieve all memories: {str(e)}",
1238
- "timestamp": datetime.now().isoformat(),
1239
- }
1240
- print(json.dumps(error_output, indent=2))
1241
-
659
+ quiet = os.environ.get("CLAUDE_MPM_QUIET", "false").lower() == "true"
660
+ formatter = MemoryOutputFormatter(quiet=quiet)
661
+ output = formatter.format_optimization_results(result, is_single_agent=False)
662
+ print(output)
1242
663
 
1243
- def _output_single_agent_raw(agent_id, memory_manager):
1244
- """
1245
- Output single agent memory in raw JSON format.
1246
-
1247
- WHY: Provides programmatic access to a specific agent's memory for
1248
- targeted analysis or processing by external tools.
1249
-
1250
- Args:
1251
- agent_id: ID of the agent to retrieve memory for
1252
- memory_manager: AgentMemoryManager instance
1253
- """
1254
- try:
1255
- # Get all memories and extract the specific agent
1256
- all_memories = memory_manager.get_all_memories_raw()
1257
-
1258
- if not all_memories.get("success", False):
1259
- error_output = {
1260
- "success": False,
1261
- "error": all_memories.get("error", "Failed to retrieve memories"),
1262
- "timestamp": datetime.now().isoformat(),
1263
- }
1264
- print(json.dumps(error_output, indent=2))
1265
- return
1266
664
 
1267
- agents = all_memories.get("agents", {})
1268
- if agent_id not in agents:
1269
- error_output = {
1270
- "success": False,
1271
- "error": f"No memory found for agent: {agent_id}",
1272
- "available_agents": list(agents.keys()),
1273
- "timestamp": datetime.now().isoformat(),
1274
- }
1275
- print(json.dumps(error_output, indent=2))
1276
- return
1277
-
1278
- # Return single agent data with metadata
1279
- single_agent_output = {
1280
- "success": True,
1281
- "timestamp": all_memories["timestamp"],
1282
- "agent": agents[agent_id],
1283
- }
1284
-
1285
- print(json.dumps(single_agent_output, indent=2, ensure_ascii=False))
1286
-
1287
- except Exception as e:
1288
- error_output = {
1289
- "success": False,
1290
- "error": f"Failed to retrieve memory for agent {agent_id}: {str(e)}",
1291
- "timestamp": datetime.now().isoformat(),
1292
- }
1293
- print(json.dumps(error_output, indent=2))
665
+ # Note: Raw output functions have been moved to MemoryCRUDService