claude-mpm 4.1.1__py3-none-any.whl → 4.1.2__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 (357) 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/imagemagick.json +256 -0
  18. claude_mpm/agents/templates/qa.json +41 -2
  19. claude_mpm/agents/templates/ticketing.json +5 -5
  20. claude_mpm/agents/templates/web_qa.json +50 -2
  21. claude_mpm/cli/__init__.py +51 -46
  22. claude_mpm/cli/__main__.py +1 -1
  23. claude_mpm/cli/commands/__init__.py +10 -12
  24. claude_mpm/cli/commands/agent_manager.py +186 -181
  25. claude_mpm/cli/commands/agents.py +271 -268
  26. claude_mpm/cli/commands/aggregate.py +30 -29
  27. claude_mpm/cli/commands/cleanup.py +50 -44
  28. claude_mpm/cli/commands/cleanup_orphaned_agents.py +25 -25
  29. claude_mpm/cli/commands/config.py +162 -127
  30. claude_mpm/cli/commands/doctor.py +52 -62
  31. claude_mpm/cli/commands/info.py +37 -25
  32. claude_mpm/cli/commands/mcp.py +3 -7
  33. claude_mpm/cli/commands/mcp_command_router.py +14 -18
  34. claude_mpm/cli/commands/mcp_install_commands.py +28 -23
  35. claude_mpm/cli/commands/mcp_pipx_config.py +58 -49
  36. claude_mpm/cli/commands/mcp_server_commands.py +23 -17
  37. claude_mpm/cli/commands/memory.py +192 -141
  38. claude_mpm/cli/commands/monitor.py +117 -88
  39. claude_mpm/cli/commands/run.py +120 -84
  40. claude_mpm/cli/commands/run_config_checker.py +4 -5
  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 +204 -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 +20 -23
  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 +581 -280
  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 -15
  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 +93 -38
  114. claude_mpm/hooks/claude_hooks/hook_handler.py +130 -76
  115. claude_mpm/hooks/claude_hooks/hook_handler_eventbus.py +104 -77
  116. claude_mpm/hooks/claude_hooks/memory_integration.py +2 -4
  117. claude_mpm/hooks/claude_hooks/response_tracking.py +15 -11
  118. claude_mpm/hooks/claude_hooks/tool_analysis.py +12 -18
  119. claude_mpm/hooks/memory_integration_hook.py +5 -5
  120. claude_mpm/hooks/tool_call_interceptor.py +1 -1
  121. claude_mpm/hooks/validation_hooks.py +4 -4
  122. claude_mpm/init.py +4 -9
  123. claude_mpm/models/__init__.py +2 -2
  124. claude_mpm/models/agent_session.py +11 -14
  125. claude_mpm/scripts/mcp_server.py +20 -11
  126. claude_mpm/scripts/mcp_wrapper.py +5 -5
  127. claude_mpm/scripts/mpm_doctor.py +321 -0
  128. claude_mpm/scripts/socketio_daemon.py +28 -25
  129. claude_mpm/scripts/socketio_daemon_hardened.py +298 -258
  130. claude_mpm/scripts/socketio_server_manager.py +116 -95
  131. claude_mpm/services/__init__.py +49 -49
  132. claude_mpm/services/agent_capabilities_service.py +12 -18
  133. claude_mpm/services/agents/__init__.py +22 -22
  134. claude_mpm/services/agents/agent_builder.py +140 -119
  135. claude_mpm/services/agents/deployment/__init__.py +3 -3
  136. claude_mpm/services/agents/deployment/agent_config_provider.py +9 -9
  137. claude_mpm/services/agents/deployment/agent_configuration_manager.py +19 -20
  138. claude_mpm/services/agents/deployment/agent_definition_factory.py +1 -5
  139. claude_mpm/services/agents/deployment/agent_deployment.py +136 -106
  140. claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -8
  141. claude_mpm/services/agents/deployment/agent_environment_manager.py +2 -7
  142. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +6 -10
  143. claude_mpm/services/agents/deployment/agent_format_converter.py +11 -15
  144. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +2 -3
  145. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +5 -5
  146. claude_mpm/services/agents/deployment/agent_metrics_collector.py +13 -19
  147. claude_mpm/services/agents/deployment/agent_restore_handler.py +0 -1
  148. claude_mpm/services/agents/deployment/agent_template_builder.py +26 -35
  149. claude_mpm/services/agents/deployment/agent_validator.py +0 -1
  150. claude_mpm/services/agents/deployment/agent_version_manager.py +7 -9
  151. claude_mpm/services/agents/deployment/agent_versioning.py +3 -3
  152. claude_mpm/services/agents/deployment/agents_directory_resolver.py +6 -7
  153. claude_mpm/services/agents/deployment/async_agent_deployment.py +51 -38
  154. claude_mpm/services/agents/deployment/config/__init__.py +1 -1
  155. claude_mpm/services/agents/deployment/config/deployment_config.py +7 -8
  156. claude_mpm/services/agents/deployment/deployment_type_detector.py +1 -1
  157. claude_mpm/services/agents/deployment/deployment_wrapper.py +18 -18
  158. claude_mpm/services/agents/deployment/facade/__init__.py +1 -1
  159. claude_mpm/services/agents/deployment/facade/deployment_executor.py +0 -3
  160. claude_mpm/services/agents/deployment/facade/deployment_facade.py +3 -4
  161. claude_mpm/services/agents/deployment/interface_adapter.py +5 -7
  162. claude_mpm/services/agents/deployment/multi_source_deployment_service.py +345 -276
  163. claude_mpm/services/agents/deployment/pipeline/__init__.py +2 -2
  164. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +1 -1
  165. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +6 -4
  166. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +3 -3
  167. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +2 -2
  168. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +14 -13
  169. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +0 -1
  170. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +1 -1
  171. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +8 -9
  172. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +1 -1
  173. claude_mpm/services/agents/deployment/processors/__init__.py +1 -1
  174. claude_mpm/services/agents/deployment/processors/agent_processor.py +20 -16
  175. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +5 -12
  176. claude_mpm/services/agents/deployment/results/__init__.py +1 -1
  177. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +1 -1
  178. claude_mpm/services/agents/deployment/strategies/__init__.py +2 -2
  179. claude_mpm/services/agents/deployment/strategies/base_strategy.py +1 -7
  180. claude_mpm/services/agents/deployment/strategies/project_strategy.py +1 -4
  181. claude_mpm/services/agents/deployment/strategies/system_strategy.py +2 -3
  182. claude_mpm/services/agents/deployment/strategies/user_strategy.py +3 -7
  183. claude_mpm/services/agents/deployment/validation/__init__.py +1 -1
  184. claude_mpm/services/agents/deployment/validation/agent_validator.py +1 -1
  185. claude_mpm/services/agents/deployment/validation/template_validator.py +2 -2
  186. claude_mpm/services/agents/deployment/validation/validation_result.py +2 -6
  187. claude_mpm/services/agents/loading/__init__.py +1 -1
  188. claude_mpm/services/agents/loading/agent_profile_loader.py +6 -12
  189. claude_mpm/services/agents/loading/base_agent_manager.py +5 -5
  190. claude_mpm/services/agents/loading/framework_agent_loader.py +2 -4
  191. claude_mpm/services/agents/management/__init__.py +1 -1
  192. claude_mpm/services/agents/management/agent_capabilities_generator.py +1 -3
  193. claude_mpm/services/agents/management/agent_management_service.py +5 -9
  194. claude_mpm/services/agents/memory/__init__.py +4 -4
  195. claude_mpm/services/agents/memory/agent_memory_manager.py +280 -160
  196. claude_mpm/services/agents/memory/agent_persistence_service.py +0 -2
  197. claude_mpm/services/agents/memory/content_manager.py +44 -38
  198. claude_mpm/services/agents/memory/template_generator.py +4 -6
  199. claude_mpm/services/agents/registry/__init__.py +10 -6
  200. claude_mpm/services/agents/registry/deployed_agent_discovery.py +30 -27
  201. claude_mpm/services/agents/registry/modification_tracker.py +3 -6
  202. claude_mpm/services/async_session_logger.py +1 -2
  203. claude_mpm/services/claude_session_logger.py +1 -2
  204. claude_mpm/services/command_deployment_service.py +173 -0
  205. claude_mpm/services/command_handler_service.py +20 -22
  206. claude_mpm/services/core/__init__.py +25 -25
  207. claude_mpm/services/core/base.py +0 -5
  208. claude_mpm/services/core/interfaces/__init__.py +32 -32
  209. claude_mpm/services/core/interfaces/agent.py +0 -21
  210. claude_mpm/services/core/interfaces/communication.py +0 -27
  211. claude_mpm/services/core/interfaces/infrastructure.py +0 -56
  212. claude_mpm/services/core/interfaces/service.py +0 -29
  213. claude_mpm/services/diagnostics/__init__.py +1 -1
  214. claude_mpm/services/diagnostics/checks/__init__.py +6 -6
  215. claude_mpm/services/diagnostics/checks/agent_check.py +89 -80
  216. claude_mpm/services/diagnostics/checks/base_check.py +12 -16
  217. claude_mpm/services/diagnostics/checks/claude_desktop_check.py +84 -81
  218. claude_mpm/services/diagnostics/checks/common_issues_check.py +99 -91
  219. claude_mpm/services/diagnostics/checks/configuration_check.py +82 -77
  220. claude_mpm/services/diagnostics/checks/filesystem_check.py +67 -68
  221. claude_mpm/services/diagnostics/checks/installation_check.py +254 -94
  222. claude_mpm/services/diagnostics/checks/mcp_check.py +90 -88
  223. claude_mpm/services/diagnostics/checks/monitor_check.py +75 -76
  224. claude_mpm/services/diagnostics/checks/startup_log_check.py +67 -73
  225. claude_mpm/services/diagnostics/diagnostic_runner.py +67 -59
  226. claude_mpm/services/diagnostics/doctor_reporter.py +107 -70
  227. claude_mpm/services/diagnostics/models.py +21 -19
  228. claude_mpm/services/event_aggregator.py +10 -17
  229. claude_mpm/services/event_bus/__init__.py +1 -1
  230. claude_mpm/services/event_bus/config.py +54 -35
  231. claude_mpm/services/event_bus/event_bus.py +76 -71
  232. claude_mpm/services/event_bus/relay.py +74 -64
  233. claude_mpm/services/events/__init__.py +11 -11
  234. claude_mpm/services/events/consumers/__init__.py +3 -3
  235. claude_mpm/services/events/consumers/dead_letter.py +71 -63
  236. claude_mpm/services/events/consumers/logging.py +39 -37
  237. claude_mpm/services/events/consumers/metrics.py +56 -57
  238. claude_mpm/services/events/consumers/socketio.py +82 -81
  239. claude_mpm/services/events/core.py +110 -99
  240. claude_mpm/services/events/interfaces.py +56 -72
  241. claude_mpm/services/events/producers/__init__.py +1 -1
  242. claude_mpm/services/events/producers/hook.py +38 -38
  243. claude_mpm/services/events/producers/system.py +46 -44
  244. claude_mpm/services/exceptions.py +81 -80
  245. claude_mpm/services/framework_claude_md_generator/__init__.py +2 -4
  246. claude_mpm/services/framework_claude_md_generator/content_assembler.py +3 -5
  247. claude_mpm/services/framework_claude_md_generator/content_validator.py +1 -1
  248. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +4 -4
  249. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +0 -1
  250. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +0 -2
  251. claude_mpm/services/framework_claude_md_generator/version_manager.py +4 -5
  252. claude_mpm/services/hook_service.py +6 -9
  253. claude_mpm/services/infrastructure/__init__.py +1 -1
  254. claude_mpm/services/infrastructure/context_preservation.py +8 -12
  255. claude_mpm/services/infrastructure/monitoring.py +21 -23
  256. claude_mpm/services/mcp_gateway/__init__.py +37 -37
  257. claude_mpm/services/mcp_gateway/auto_configure.py +95 -103
  258. claude_mpm/services/mcp_gateway/config/__init__.py +1 -1
  259. claude_mpm/services/mcp_gateway/config/config_loader.py +23 -25
  260. claude_mpm/services/mcp_gateway/config/config_schema.py +5 -5
  261. claude_mpm/services/mcp_gateway/config/configuration.py +9 -6
  262. claude_mpm/services/mcp_gateway/core/__init__.py +10 -10
  263. claude_mpm/services/mcp_gateway/core/base.py +0 -3
  264. claude_mpm/services/mcp_gateway/core/interfaces.py +1 -38
  265. claude_mpm/services/mcp_gateway/core/process_pool.py +99 -93
  266. claude_mpm/services/mcp_gateway/core/singleton_manager.py +65 -62
  267. claude_mpm/services/mcp_gateway/core/startup_verification.py +75 -74
  268. claude_mpm/services/mcp_gateway/main.py +2 -1
  269. claude_mpm/services/mcp_gateway/registry/service_registry.py +5 -8
  270. claude_mpm/services/mcp_gateway/registry/tool_registry.py +1 -1
  271. claude_mpm/services/mcp_gateway/server/__init__.py +1 -1
  272. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +12 -19
  273. claude_mpm/services/mcp_gateway/server/stdio_handler.py +4 -3
  274. claude_mpm/services/mcp_gateway/server/stdio_server.py +79 -71
  275. claude_mpm/services/mcp_gateway/tools/__init__.py +2 -2
  276. claude_mpm/services/mcp_gateway/tools/base_adapter.py +5 -6
  277. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +13 -22
  278. claude_mpm/services/mcp_gateway/tools/health_check_tool.py +79 -78
  279. claude_mpm/services/mcp_gateway/tools/hello_world.py +12 -14
  280. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +42 -49
  281. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +51 -55
  282. claude_mpm/services/memory/__init__.py +3 -3
  283. claude_mpm/services/memory/builder.py +3 -6
  284. claude_mpm/services/memory/cache/__init__.py +1 -1
  285. claude_mpm/services/memory/cache/shared_prompt_cache.py +3 -5
  286. claude_mpm/services/memory/cache/simple_cache.py +1 -1
  287. claude_mpm/services/memory/indexed_memory.py +5 -7
  288. claude_mpm/services/memory/optimizer.py +7 -10
  289. claude_mpm/services/memory/router.py +8 -9
  290. claude_mpm/services/memory_hook_service.py +48 -34
  291. claude_mpm/services/monitor_build_service.py +77 -73
  292. claude_mpm/services/port_manager.py +130 -108
  293. claude_mpm/services/project/analyzer.py +12 -10
  294. claude_mpm/services/project/registry.py +11 -11
  295. claude_mpm/services/recovery_manager.py +10 -19
  296. claude_mpm/services/response_tracker.py +0 -1
  297. claude_mpm/services/runner_configuration_service.py +19 -20
  298. claude_mpm/services/session_management_service.py +7 -11
  299. claude_mpm/services/shared/__init__.py +1 -1
  300. claude_mpm/services/shared/async_service_base.py +58 -50
  301. claude_mpm/services/shared/config_service_base.py +73 -67
  302. claude_mpm/services/shared/lifecycle_service_base.py +82 -78
  303. claude_mpm/services/shared/manager_base.py +94 -82
  304. claude_mpm/services/shared/service_factory.py +96 -98
  305. claude_mpm/services/socketio/__init__.py +3 -3
  306. claude_mpm/services/socketio/client_proxy.py +5 -5
  307. claude_mpm/services/socketio/event_normalizer.py +199 -181
  308. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  309. claude_mpm/services/socketio/handlers/base.py +5 -4
  310. claude_mpm/services/socketio/handlers/connection.py +163 -136
  311. claude_mpm/services/socketio/handlers/file.py +13 -14
  312. claude_mpm/services/socketio/handlers/git.py +12 -7
  313. claude_mpm/services/socketio/handlers/hook.py +49 -44
  314. claude_mpm/services/socketio/handlers/memory.py +0 -1
  315. claude_mpm/services/socketio/handlers/project.py +0 -1
  316. claude_mpm/services/socketio/handlers/registry.py +37 -19
  317. claude_mpm/services/socketio/migration_utils.py +98 -84
  318. claude_mpm/services/socketio/server/__init__.py +1 -1
  319. claude_mpm/services/socketio/server/broadcaster.py +81 -87
  320. claude_mpm/services/socketio/server/core.py +65 -54
  321. claude_mpm/services/socketio/server/eventbus_integration.py +95 -56
  322. claude_mpm/services/socketio/server/main.py +64 -38
  323. claude_mpm/services/socketio_client_manager.py +10 -12
  324. claude_mpm/services/subprocess_launcher_service.py +4 -7
  325. claude_mpm/services/system_instructions_service.py +13 -14
  326. claude_mpm/services/ticket_manager.py +2 -2
  327. claude_mpm/services/utility_service.py +5 -13
  328. claude_mpm/services/version_control/__init__.py +16 -16
  329. claude_mpm/services/version_control/branch_strategy.py +5 -8
  330. claude_mpm/services/version_control/conflict_resolution.py +9 -23
  331. claude_mpm/services/version_control/git_operations.py +5 -7
  332. claude_mpm/services/version_control/semantic_versioning.py +16 -17
  333. claude_mpm/services/version_control/version_parser.py +13 -18
  334. claude_mpm/services/version_service.py +10 -11
  335. claude_mpm/storage/__init__.py +1 -1
  336. claude_mpm/storage/state_storage.py +22 -28
  337. claude_mpm/utils/__init__.py +6 -6
  338. claude_mpm/utils/agent_dependency_loader.py +47 -33
  339. claude_mpm/utils/config_manager.py +11 -14
  340. claude_mpm/utils/dependency_cache.py +1 -1
  341. claude_mpm/utils/dependency_manager.py +13 -17
  342. claude_mpm/utils/dependency_strategies.py +8 -10
  343. claude_mpm/utils/environment_context.py +3 -9
  344. claude_mpm/utils/error_handler.py +3 -13
  345. claude_mpm/utils/file_utils.py +1 -1
  346. claude_mpm/utils/path_operations.py +8 -12
  347. claude_mpm/utils/robust_installer.py +110 -33
  348. claude_mpm/utils/subprocess_utils.py +5 -6
  349. claude_mpm/validation/agent_validator.py +3 -6
  350. claude_mpm/validation/frontmatter_validator.py +1 -1
  351. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/METADATA +1 -1
  352. claude_mpm-4.1.2.dist-info/RECORD +498 -0
  353. claude_mpm-4.1.1.dist-info/RECORD +0 -494
  354. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/WHEEL +0 -0
  355. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/entry_points.txt +0 -0
  356. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/licenses/LICENSE +0 -0
  357. {claude_mpm-4.1.1.dist-info → claude_mpm-4.1.2.dist-info}/top_level.txt +0 -0
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env python3
2
2
 
3
3
  from pathlib import Path
4
+
4
5
  """
5
6
  Agent Memory Manager Service
6
7
  ===========================
@@ -28,6 +29,7 @@ from typing import Any, Dict, List, Optional, Tuple
28
29
  from claude_mpm.core.config import Config
29
30
  from claude_mpm.core.interfaces import MemoryServiceInterface
30
31
  from claude_mpm.core.unified_paths import get_path_manager
32
+
31
33
  from .content_manager import MemoryContentManager
32
34
  from .template_generator import MemoryTemplateGenerator
33
35
 
@@ -74,13 +76,13 @@ class AgentMemoryManager(MemoryServiceInterface):
74
76
  self.project_root = get_path_manager().project_root
75
77
  # Use current working directory by default, not project root
76
78
  self.working_directory = working_directory or Path(os.getcwd())
77
-
79
+
78
80
  # Use only project memory directory
79
81
  self.project_memories_dir = self.working_directory / ".claude-mpm" / "memories"
80
-
82
+
81
83
  # Primary memories_dir points to project
82
84
  self.memories_dir = self.project_memories_dir
83
-
85
+
84
86
  # Ensure project directory exists
85
87
  self._ensure_memories_directory()
86
88
 
@@ -185,14 +187,14 @@ class AgentMemoryManager(MemoryServiceInterface):
185
187
 
186
188
  def _get_memory_file_with_migration(self, directory: Path, agent_id: str) -> Path:
187
189
  """Get memory file path, migrating from old naming if needed.
188
-
190
+
189
191
  WHY: Supports backward compatibility by automatically migrating from
190
192
  the old {agent_id}_agent.md and {agent_id}.md formats to the new {agent_id}_memories.md format.
191
-
193
+
192
194
  Args:
193
195
  directory: Directory containing memory files
194
196
  agent_id: The agent identifier
195
-
197
+
196
198
  Returns:
197
199
  Path: Path to the memory file (may not exist)
198
200
  """
@@ -200,7 +202,7 @@ class AgentMemoryManager(MemoryServiceInterface):
200
202
  # Support migration from both old formats
201
203
  old_file_agent = directory / f"{agent_id}_agent.md"
202
204
  old_file_simple = directory / f"{agent_id}.md"
203
-
205
+
204
206
  # Migrate from old formats if needed
205
207
  if not new_file.exists():
206
208
  # Try migrating from {agent_id}_agent.md first
@@ -208,26 +210,34 @@ class AgentMemoryManager(MemoryServiceInterface):
208
210
  try:
209
211
  content = old_file_agent.read_text(encoding="utf-8")
210
212
  new_file.write_text(content, encoding="utf-8")
211
-
213
+
212
214
  # Delete old file for all agents
213
215
  old_file_agent.unlink()
214
- self.logger.info(f"Migrated memory file from {old_file_agent.name} to {new_file.name}")
216
+ self.logger.info(
217
+ f"Migrated memory file from {old_file_agent.name} to {new_file.name}"
218
+ )
215
219
  except Exception as e:
216
- self.logger.error(f"Failed to migrate memory file for {agent_id}: {e}")
220
+ self.logger.error(
221
+ f"Failed to migrate memory file for {agent_id}: {e}"
222
+ )
217
223
  return old_file_agent
218
224
  # Try migrating from {agent_id}.md
219
225
  elif old_file_simple.exists():
220
226
  try:
221
227
  content = old_file_simple.read_text(encoding="utf-8")
222
228
  new_file.write_text(content, encoding="utf-8")
223
-
229
+
224
230
  # Delete old file for all agents
225
231
  old_file_simple.unlink()
226
- self.logger.info(f"Migrated memory file from {old_file_simple.name} to {new_file.name}")
232
+ self.logger.info(
233
+ f"Migrated memory file from {old_file_simple.name} to {new_file.name}"
234
+ )
227
235
  except Exception as e:
228
- self.logger.error(f"Failed to migrate memory file for {agent_id}: {e}")
236
+ self.logger.error(
237
+ f"Failed to migrate memory file for {agent_id}: {e}"
238
+ )
229
239
  return old_file_simple
230
-
240
+
231
241
  return new_file
232
242
 
233
243
  def load_agent_memory(self, agent_id: str) -> str:
@@ -244,18 +254,24 @@ class AgentMemoryManager(MemoryServiceInterface):
244
254
  str: The memory file content, creating default if doesn't exist
245
255
  """
246
256
  # All agents use project directory
247
- project_memory_file = self._get_memory_file_with_migration(self.project_memories_dir, agent_id)
248
-
257
+ project_memory_file = self._get_memory_file_with_migration(
258
+ self.project_memories_dir, agent_id
259
+ )
260
+
249
261
  # Load project-level memory if exists
250
262
  if project_memory_file.exists():
251
263
  try:
252
264
  project_memory = project_memory_file.read_text(encoding="utf-8")
253
- project_memory = self.content_manager.validate_and_repair(project_memory, agent_id)
265
+ project_memory = self.content_manager.validate_and_repair(
266
+ project_memory, agent_id
267
+ )
254
268
  self.logger.debug(f"Loaded project-level memory for {agent_id}")
255
269
  return project_memory
256
270
  except Exception as e:
257
- self.logger.error(f"Error reading project memory file for {agent_id}: {e}")
258
-
271
+ self.logger.error(
272
+ f"Error reading project memory file for {agent_id}: {e}"
273
+ )
274
+
259
275
  # Memory doesn't exist - create default in project directory
260
276
  self.logger.info(f"Creating default memory for agent: {agent_id}")
261
277
  return self._create_default_memory(agent_id)
@@ -343,14 +359,16 @@ class AgentMemoryManager(MemoryServiceInterface):
343
359
  try:
344
360
  # All agents save to project directory
345
361
  target_dir = self.project_memories_dir
346
-
362
+
347
363
  # Ensure directory exists
348
364
  target_dir.mkdir(parents=True, exist_ok=True)
349
-
365
+
350
366
  memory_file = target_dir / f"{agent_id}_memories.md"
351
367
  memory_file.write_text(content, encoding="utf-8")
352
-
353
- self.logger.info(f"Saved {agent_id} memory to project directory: {memory_file}")
368
+
369
+ self.logger.info(
370
+ f"Saved {agent_id} memory to project directory: {memory_file}"
371
+ )
354
372
  return True
355
373
  except Exception as e:
356
374
  self.logger.error(f"Error saving memory for {agent_id}: {e}")
@@ -459,25 +477,25 @@ class AgentMemoryManager(MemoryServiceInterface):
459
477
  try:
460
478
  import json
461
479
  import re
462
-
480
+
463
481
  # Log that we're processing memory for this agent
464
482
  is_pm = agent_id.upper() == "PM"
465
483
  self.logger.debug(f"Extracting memory for {agent_id} (is_pm={is_pm})")
466
-
484
+
467
485
  # Look for JSON block in the response
468
486
  # Pattern matches ```json ... ``` blocks
469
- json_pattern = r'```json\s*(.*?)\s*```'
487
+ json_pattern = r"```json\s*(.*?)\s*```"
470
488
  json_matches = re.findall(json_pattern, response, re.DOTALL)
471
-
489
+
472
490
  if not json_matches:
473
491
  # Also try to find inline JSON objects
474
492
  json_pattern2 = r'\{[^{}]*"(?:remember|Remember|MEMORIES)"[^{}]*\}'
475
493
  json_matches = re.findall(json_pattern2, response, re.DOTALL)
476
-
494
+
477
495
  for json_str in json_matches:
478
496
  try:
479
497
  data = json.loads(json_str)
480
-
498
+
481
499
  # Check for complete memory replacement in "MEMORIES" field
482
500
  if "MEMORIES" in data and data["MEMORIES"] is not None:
483
501
  memories = data["MEMORIES"]
@@ -491,26 +509,33 @@ class AgentMemoryManager(MemoryServiceInterface):
491
509
  if not item_text.startswith("-"):
492
510
  item_text = f"- {item_text}"
493
511
  valid_items.append(item_text)
494
-
512
+
495
513
  if valid_items:
496
- self.logger.info(f"Replacing all memories for {agent_id} with {len(valid_items)} items")
497
- success = self.replace_agent_memory(agent_id, valid_items)
514
+ self.logger.info(
515
+ f"Replacing all memories for {agent_id} with {len(valid_items)} items"
516
+ )
517
+ success = self.replace_agent_memory(
518
+ agent_id, valid_items
519
+ )
498
520
  if success:
499
- self.logger.info(f"Successfully replaced memories for {agent_id}")
521
+ self.logger.info(
522
+ f"Successfully replaced memories for {agent_id}"
523
+ )
500
524
  return True
501
- else:
502
- self.logger.error(f"Failed to replace memories for {agent_id}")
525
+ self.logger.error(
526
+ f"Failed to replace memories for {agent_id}"
527
+ )
503
528
  continue # Skip checking remember field if MEMORIES was processed
504
-
529
+
505
530
  # Check for incremental memory updates in "remember" field
506
531
  memory_items = None
507
-
532
+
508
533
  # Check both "remember" and "Remember" fields
509
534
  if "remember" in data:
510
535
  memory_items = data["remember"]
511
536
  elif "Remember" in data:
512
537
  memory_items = data["Remember"]
513
-
538
+
514
539
  # Process memory items if found and not null
515
540
  if memory_items is not None and memory_items != "null":
516
541
  # Skip if explicitly null or empty list
@@ -520,129 +545,146 @@ class AgentMemoryManager(MemoryServiceInterface):
520
545
  for item in memory_items:
521
546
  if item and isinstance(item, str) and item.strip():
522
547
  valid_items.append(item.strip())
523
-
548
+
524
549
  # Only proceed if we have valid items
525
550
  if valid_items:
526
- self.logger.info(f"Found {len(valid_items)} memory items for {agent_id}: {valid_items[:2]}...")
527
- success = self._add_learnings_to_memory(agent_id, valid_items)
551
+ self.logger.info(
552
+ f"Found {len(valid_items)} memory items for {agent_id}: {valid_items[:2]}..."
553
+ )
554
+ success = self._add_learnings_to_memory(
555
+ agent_id, valid_items
556
+ )
528
557
  if success:
529
- self.logger.info(f"Successfully saved {len(valid_items)} memories for {agent_id} to project directory")
558
+ self.logger.info(
559
+ f"Successfully saved {len(valid_items)} memories for {agent_id} to project directory"
560
+ )
530
561
  return True
531
- else:
532
- self.logger.error(f"Failed to save memories for {agent_id}")
533
-
562
+ self.logger.error(
563
+ f"Failed to save memories for {agent_id}"
564
+ )
565
+
534
566
  except json.JSONDecodeError as je:
535
567
  # Not valid JSON, continue to next match
536
568
  self.logger.debug(f"JSON decode error for {agent_id}: {je}")
537
569
  continue
538
-
570
+
539
571
  self.logger.debug(f"No memory items found in response for {agent_id}")
540
572
  return False
541
-
573
+
542
574
  except Exception as e:
543
- self.logger.error(f"Error extracting memory from response for {agent_id}: {e}")
575
+ self.logger.error(
576
+ f"Error extracting memory from response for {agent_id}: {e}"
577
+ )
544
578
  return False
545
-
579
+
546
580
  def _add_learnings_to_memory(self, agent_id: str, learnings: List[str]) -> bool:
547
581
  """Add new learnings to agent memory as a simple list.
548
-
582
+
549
583
  WHY: Simplified memory system - all memories are stored as a simple list
550
584
  without categorization, making it easier to manage and understand.
551
585
  Updates timestamp on every update.
552
-
586
+
553
587
  Args:
554
588
  agent_id: The agent identifier
555
589
  learnings: List of new learning strings to add
556
-
590
+
557
591
  Returns:
558
592
  bool: True if memory was successfully updated
559
593
  """
560
594
  try:
561
595
  # Load existing memory
562
596
  current_memory = self.load_agent_memory(agent_id)
563
-
597
+
564
598
  # Parse existing memory into a simple list
565
599
  existing_items = self._parse_memory_list(current_memory)
566
-
600
+
567
601
  # Clean template placeholders if this is a fresh memory
568
602
  existing_items = self._clean_template_placeholders_list(existing_items)
569
-
603
+
570
604
  # Add new learnings, avoiding duplicates
571
605
  updated = False
572
606
  for learning in learnings:
573
607
  if not learning or not isinstance(learning, str):
574
608
  continue
575
-
609
+
576
610
  learning = learning.strip()
577
611
  if not learning:
578
612
  continue
579
-
613
+
580
614
  # Check for duplicates (case-insensitive)
581
615
  normalized_learning = learning.lower()
582
616
  # Strip bullet points from existing items for comparison
583
- existing_normalized = [item.lstrip('- ').strip().lower() for item in existing_items]
584
-
617
+ existing_normalized = [
618
+ item.lstrip("- ").strip().lower() for item in existing_items
619
+ ]
620
+
585
621
  if normalized_learning not in existing_normalized:
586
622
  # Add bullet point if not present
587
623
  if not learning.startswith("-"):
588
624
  learning = f"- {learning}"
589
625
  existing_items.append(learning)
590
- self.logger.info(f"Added new memory for {agent_id}: {learning[:50]}...")
626
+ self.logger.info(
627
+ f"Added new memory for {agent_id}: {learning[:50]}..."
628
+ )
591
629
  updated = True
592
630
  else:
593
- self.logger.debug(f"Skipping duplicate memory for {agent_id}: {learning}")
594
-
631
+ self.logger.debug(
632
+ f"Skipping duplicate memory for {agent_id}: {learning}"
633
+ )
634
+
595
635
  # Only save if we actually added new items
596
636
  if not updated:
597
637
  self.logger.debug(f"No new memories to add for {agent_id}")
598
638
  return True # Not an error, just nothing new to add
599
-
639
+
600
640
  # Rebuild memory content as simple list with updated timestamp
601
641
  new_content = self._build_simple_memory_content(agent_id, existing_items)
602
-
642
+
603
643
  # Validate and save
604
644
  agent_limits = self._get_agent_limits(agent_id)
605
645
  if self.content_manager.exceeds_limits(new_content, agent_limits):
606
646
  self.logger.debug(f"Memory for {agent_id} exceeds limits, truncating")
607
- new_content = self.content_manager.truncate_simple_list(new_content, agent_limits)
608
-
647
+ new_content = self.content_manager.truncate_simple_list(
648
+ new_content, agent_limits
649
+ )
650
+
609
651
  # All memories go to project directory
610
652
  return self._save_memory_file(agent_id, new_content)
611
-
653
+
612
654
  except Exception as e:
613
655
  self.logger.error(f"Error adding learnings to memory for {agent_id}: {e}")
614
656
  return False
615
-
657
+
616
658
  def _parse_memory_list(self, memory_content: str) -> List[str]:
617
659
  """Parse memory content into a simple list.
618
-
660
+
619
661
  Args:
620
662
  memory_content: Raw memory file content
621
-
663
+
622
664
  Returns:
623
665
  List of memory items
624
666
  """
625
667
  items = []
626
-
627
- for line in memory_content.split('\n'):
668
+
669
+ for line in memory_content.split("\n"):
628
670
  line = line.strip()
629
671
  # Skip metadata lines and headers
630
- if line.startswith('<!-- ') or line.startswith('#') or not line:
672
+ if line.startswith(("<!-- ", "#")) or not line:
631
673
  continue
632
674
  # Collect items (with or without bullet points)
633
- if line.startswith('- '):
675
+ if line.startswith("- "):
634
676
  items.append(line)
635
- elif line and not line.startswith('##'): # Legacy format without bullets
677
+ elif line and not line.startswith("##"): # Legacy format without bullets
636
678
  items.append(f"- {line}")
637
-
679
+
638
680
  return items
639
-
681
+
640
682
  def _clean_template_placeholders_list(self, items: List[str]) -> List[str]:
641
683
  """Remove template placeholder text from item list.
642
-
684
+
643
685
  Args:
644
686
  items: List of memory items
645
-
687
+
646
688
  Returns:
647
689
  List with placeholder text removed
648
690
  """
@@ -653,9 +695,9 @@ class AgentMemoryManager(MemoryServiceInterface):
653
695
  "Extract implementation guidelines from project documentation",
654
696
  "Learn from errors encountered during project work",
655
697
  "Project analysis pending - gather context during tasks",
656
- "claude-mpm: Software project requiring analysis"
698
+ "claude-mpm: Software project requiring analysis",
657
699
  ]
658
-
700
+
659
701
  cleaned = []
660
702
  for item in items:
661
703
  # Remove bullet point for comparison
@@ -663,15 +705,17 @@ class AgentMemoryManager(MemoryServiceInterface):
663
705
  # Keep item if it's not a placeholder
664
706
  if item_text and item_text not in placeholders:
665
707
  cleaned.append(item)
666
-
708
+
667
709
  return cleaned
668
-
669
- def _clean_template_placeholders(self, sections: Dict[str, List[str]]) -> Dict[str, List[str]]:
710
+
711
+ def _clean_template_placeholders(
712
+ self, sections: Dict[str, List[str]]
713
+ ) -> Dict[str, List[str]]:
670
714
  """Remove template placeholder text from sections.
671
-
715
+
672
716
  Args:
673
717
  sections: Dict mapping section names to lists of items
674
-
718
+
675
719
  Returns:
676
720
  Dict with placeholder text removed
677
721
  """
@@ -682,9 +726,9 @@ class AgentMemoryManager(MemoryServiceInterface):
682
726
  "Extract implementation guidelines from project documentation",
683
727
  "Learn from errors encountered during project work",
684
728
  "Project analysis pending - gather context during tasks",
685
- "claude-mpm: Software project requiring analysis"
729
+ "claude-mpm: Software project requiring analysis",
686
730
  ]
687
-
731
+
688
732
  cleaned = {}
689
733
  for section_name, items in sections.items():
690
734
  cleaned_items = []
@@ -694,84 +738,151 @@ class AgentMemoryManager(MemoryServiceInterface):
694
738
  # Keep item if it's not a placeholder
695
739
  if item_text and item_text not in placeholders:
696
740
  cleaned_items.append(item)
697
-
741
+
698
742
  # Only include section if it has real content
699
743
  if cleaned_items:
700
744
  cleaned[section_name] = cleaned_items
701
-
745
+
702
746
  return cleaned
703
-
747
+
704
748
  def _categorize_learning(self, learning: str) -> str:
705
749
  """Categorize a learning item into appropriate section.
706
-
750
+
707
751
  Args:
708
752
  learning: The learning string to categorize
709
-
753
+
710
754
  Returns:
711
755
  str: The section name for this learning
712
756
  """
713
757
  learning_lower = learning.lower()
714
-
758
+
715
759
  # Check for keywords to categorize with improved patterns
716
760
  # Order matters - more specific patterns should come first
717
-
761
+
718
762
  # Architecture keywords
719
- if any(word in learning_lower for word in ["architecture", "structure", "design", "module", "component", "microservices", "service-oriented"]):
763
+ if any(
764
+ word in learning_lower
765
+ for word in [
766
+ "architecture",
767
+ "structure",
768
+ "design",
769
+ "module",
770
+ "component",
771
+ "microservices",
772
+ "service-oriented",
773
+ ]
774
+ ):
720
775
  return "Project Architecture"
721
-
776
+
722
777
  # Integration keywords (check before patterns to avoid "use" conflict)
723
- elif any(word in learning_lower for word in ["integration", "interface", "api", "connection", "database", "pooling", "via"]):
778
+ if any(
779
+ word in learning_lower
780
+ for word in [
781
+ "integration",
782
+ "interface",
783
+ "api",
784
+ "connection",
785
+ "database",
786
+ "pooling",
787
+ "via",
788
+ ]
789
+ ):
724
790
  return "Integration Points"
725
-
791
+
726
792
  # Mistake keywords (check before patterns to avoid conflicts)
727
- elif any(word in learning_lower for word in ["mistake", "error", "avoid", "don't", "never", "not"]):
793
+ if any(
794
+ word in learning_lower
795
+ for word in ["mistake", "error", "avoid", "don't", "never", "not"]
796
+ ):
728
797
  return "Common Mistakes to Avoid"
729
-
798
+
730
799
  # Context keywords (check before patterns to avoid "working", "version" conflicts)
731
- elif any(word in learning_lower for word in ["context", "current", "currently", "working", "version", "release", "candidate"]):
800
+ if any(
801
+ word in learning_lower
802
+ for word in [
803
+ "context",
804
+ "current",
805
+ "currently",
806
+ "working",
807
+ "version",
808
+ "release",
809
+ "candidate",
810
+ ]
811
+ ):
732
812
  return "Current Technical Context"
733
-
813
+
734
814
  # Guideline keywords (check before patterns to avoid "must", "should" conflicts)
735
- elif any(word in learning_lower for word in ["guideline", "rule", "standard", "practice", "docstring", "documentation", "must", "should", "include", "comprehensive"]):
815
+ if any(
816
+ word in learning_lower
817
+ for word in [
818
+ "guideline",
819
+ "rule",
820
+ "standard",
821
+ "practice",
822
+ "docstring",
823
+ "documentation",
824
+ "must",
825
+ "should",
826
+ "include",
827
+ "comprehensive",
828
+ ]
829
+ ):
736
830
  return "Implementation Guidelines"
737
-
831
+
738
832
  # Pattern keywords (including dependency injection, conventions)
739
- elif any(word in learning_lower for word in ["pattern", "convention", "style", "format", "dependency injection", "instantiation", "use", "implement"]):
833
+ if any(
834
+ word in learning_lower
835
+ for word in [
836
+ "pattern",
837
+ "convention",
838
+ "style",
839
+ "format",
840
+ "dependency injection",
841
+ "instantiation",
842
+ "use",
843
+ "implement",
844
+ ]
845
+ ):
740
846
  return "Coding Patterns Learned"
741
-
742
- # Strategy keywords
743
- elif any(word in learning_lower for word in ["strategy", "approach", "method", "technique", "effective"]):
847
+
848
+ # Strategy keywords
849
+ if any(
850
+ word in learning_lower
851
+ for word in ["strategy", "approach", "method", "technique", "effective"]
852
+ ):
744
853
  return "Effective Strategies"
745
-
854
+
746
855
  # Performance keywords
747
- elif any(word in learning_lower for word in ["performance", "optimization", "speed", "efficiency"]):
856
+ if any(
857
+ word in learning_lower
858
+ for word in ["performance", "optimization", "speed", "efficiency"]
859
+ ):
748
860
  return "Performance Considerations"
749
-
861
+
750
862
  # Domain keywords
751
- elif any(word in learning_lower for word in ["domain", "business", "specific"]):
863
+ if any(word in learning_lower for word in ["domain", "business", "specific"]):
752
864
  return "Domain-Specific Knowledge"
753
-
754
- else:
755
- return "Recent Learnings"
756
-
865
+
866
+ return "Recent Learnings"
867
+
757
868
  def _build_simple_memory_content(self, agent_id: str, items: List[str]) -> str:
758
869
  """Build memory content as a simple list with updated timestamp.
759
-
870
+
760
871
  Args:
761
872
  agent_id: The agent identifier
762
873
  items: List of memory items
763
-
874
+
764
875
  Returns:
765
876
  str: The formatted memory content
766
877
  """
767
878
  lines = []
768
-
879
+
769
880
  # Add header
770
881
  lines.append(f"# Agent Memory: {agent_id}")
771
882
  # Always update timestamp when building new content
772
883
  lines.append(f"<!-- Last Updated: {datetime.now().isoformat()}Z -->")
773
884
  lines.append("")
774
-
885
+
775
886
  # Add all items as a simple list
776
887
  for item in items:
777
888
  if item.strip():
@@ -780,9 +891,9 @@ class AgentMemoryManager(MemoryServiceInterface):
780
891
  lines.append(f"- {item.strip()}")
781
892
  else:
782
893
  lines.append(item.strip())
783
-
784
- return '\n'.join(lines)
785
-
894
+
895
+ return "\n".join(lines)
896
+
786
897
  def replace_agent_memory(self, agent_id: str, memory_items: List[str]) -> bool:
787
898
  """Replace agent's memory with new content as a simple list.
788
899
 
@@ -800,16 +911,18 @@ class AgentMemoryManager(MemoryServiceInterface):
800
911
  try:
801
912
  # Build new memory content as simple list with updated timestamp
802
913
  new_content = self._build_simple_memory_content(agent_id, memory_items)
803
-
914
+
804
915
  # Validate and save
805
916
  agent_limits = self._get_agent_limits(agent_id)
806
917
  if self.content_manager.exceeds_limits(new_content, agent_limits):
807
918
  self.logger.debug(f"Memory for {agent_id} exceeds limits, truncating")
808
- new_content = self.content_manager.truncate_simple_list(new_content, agent_limits)
809
-
919
+ new_content = self.content_manager.truncate_simple_list(
920
+ new_content, agent_limits
921
+ )
922
+
810
923
  # Save the new memory
811
924
  return self._save_memory_file(agent_id, new_content)
812
-
925
+
813
926
  except Exception as e:
814
927
  self.logger.error(f"Error replacing memory for {agent_id}: {e}")
815
928
  return False
@@ -832,13 +945,13 @@ class AgentMemoryManager(MemoryServiceInterface):
832
945
  "total_agents": 0,
833
946
  "total_size_kb": 0,
834
947
  "agents": {},
835
- "system_health": "healthy"
948
+ "system_health": "healthy",
836
949
  }
837
-
950
+
838
951
  if self.memories_dir.exists():
839
952
  memory_files = list(self.memories_dir.glob("*_memories.md"))
840
953
  status["total_agents"] = len(memory_files)
841
-
954
+
842
955
  for file_path in memory_files:
843
956
  if file_path.name != "README.md":
844
957
  size_kb = file_path.stat().st_size / 1024
@@ -846,9 +959,9 @@ class AgentMemoryManager(MemoryServiceInterface):
846
959
  agent_id = file_path.stem.replace("_memories", "")
847
960
  status["agents"][agent_id] = {
848
961
  "file": file_path.name,
849
- "size_kb": round(size_kb, 2)
962
+ "size_kb": round(size_kb, 2),
850
963
  }
851
-
964
+
852
965
  return status
853
966
 
854
967
  def cross_reference_memories(self, query: Optional[str] = None) -> Dict[str, Any]:
@@ -868,7 +981,7 @@ class AgentMemoryManager(MemoryServiceInterface):
868
981
  return {
869
982
  "status": "deprecated",
870
983
  "message": "Cross-reference analysis has been deprecated in favor of simplified memory management",
871
- "suggestion": "Use get_memory_status() for memory overview"
984
+ "suggestion": "Use get_memory_status() for memory overview",
872
985
  }
873
986
 
874
987
  def get_all_memories_raw(self) -> Dict[str, Any]:
@@ -883,9 +996,9 @@ class AgentMemoryManager(MemoryServiceInterface):
883
996
  """
884
997
  # Deprecated - return informative message
885
998
  return {
886
- "status": "deprecated",
999
+ "status": "deprecated",
887
1000
  "message": "Raw memory access has been deprecated in favor of simplified memory management",
888
- "suggestion": "Use load_agent_memory() for specific agent memories"
1001
+ "suggestion": "Use load_agent_memory() for specific agent memories",
889
1002
  }
890
1003
 
891
1004
  def _ensure_memories_directory(self):
@@ -944,43 +1057,43 @@ Standard markdown with structured sections. Agents expect:
944
1057
  self.logger.error(f"Error ensuring memories directory: {e}")
945
1058
  # Continue anyway - memory system should not block operations
946
1059
 
947
-
948
-
949
1060
  def _parse_memory_sections(self, memory_content: str) -> Dict[str, List[str]]:
950
1061
  """Parse memory content into sections and items.
951
-
1062
+
952
1063
  Args:
953
1064
  memory_content: Raw memory file content
954
-
1065
+
955
1066
  Returns:
956
1067
  Dict mapping section names to lists of items
957
1068
  """
958
1069
  sections = {}
959
1070
  current_section = None
960
1071
  current_items = []
961
-
962
- for line in memory_content.split('\n'):
1072
+
1073
+ for line in memory_content.split("\n"):
963
1074
  # Skip metadata lines
964
- if line.startswith('<!-- ') and line.endswith(' -->'):
1075
+ if line.startswith("<!-- ") and line.endswith(" -->"):
965
1076
  continue
966
1077
  # Check for section headers (## Level 2 headers)
967
- elif line.startswith('## '):
1078
+ if line.startswith("## "):
968
1079
  # Save previous section if exists
969
1080
  if current_section and current_items:
970
1081
  sections[current_section] = current_items
971
-
1082
+
972
1083
  # Start new section
973
1084
  current_section = line[3:].strip() # Remove "## " prefix
974
1085
  current_items = []
975
1086
  # Collect non-empty lines as items (but not HTML comments)
976
- elif line.strip() and current_section and not line.strip().startswith('<!--'):
1087
+ elif (
1088
+ line.strip() and current_section and not line.strip().startswith("<!--")
1089
+ ):
977
1090
  # Keep the full line with its formatting
978
1091
  current_items.append(line.strip())
979
-
1092
+
980
1093
  # Save last section
981
1094
  if current_section and current_items:
982
1095
  sections[current_section] = current_items
983
-
1096
+
984
1097
  return sections
985
1098
 
986
1099
  # ================================================================================
@@ -1066,12 +1179,8 @@ Standard markdown with structured sections. Agents expect:
1066
1179
  Dictionary with memory metrics
1067
1180
  """
1068
1181
  # Minimal implementation for interface compliance
1069
- metrics = {
1070
- "total_memory_kb": 0,
1071
- "agent_count": 0,
1072
- "agents": {}
1073
- }
1074
-
1182
+ metrics = {"total_memory_kb": 0, "agent_count": 0, "agents": {}}
1183
+
1075
1184
  if self.memories_dir.exists():
1076
1185
  if agent_id:
1077
1186
  # Metrics for specific agent
@@ -1080,8 +1189,17 @@ Standard markdown with structured sections. Agents expect:
1080
1189
  size_kb = memory_file.stat().st_size / 1024
1081
1190
  metrics["agents"][agent_id] = {
1082
1191
  "size_kb": round(size_kb, 2),
1083
- "limit_kb": self._get_agent_limits(agent_id)["max_file_size_kb"],
1084
- "usage_percent": round((size_kb / self._get_agent_limits(agent_id)["max_file_size_kb"]) * 100, 1)
1192
+ "limit_kb": self._get_agent_limits(agent_id)[
1193
+ "max_file_size_kb"
1194
+ ],
1195
+ "usage_percent": round(
1196
+ (
1197
+ size_kb
1198
+ / self._get_agent_limits(agent_id)["max_file_size_kb"]
1199
+ )
1200
+ * 100,
1201
+ 1,
1202
+ ),
1085
1203
  }
1086
1204
  metrics["total_memory_kb"] = round(size_kb, 2)
1087
1205
  metrics["agent_count"] = 1
@@ -1092,17 +1210,19 @@ Standard markdown with structured sections. Agents expect:
1092
1210
  if file_path.name != "README.md":
1093
1211
  agent_name = file_path.stem.replace("_memories", "")
1094
1212
  size_kb = file_path.stat().st_size / 1024
1095
- limit_kb = self._get_agent_limits(agent_name)["max_file_size_kb"]
1213
+ limit_kb = self._get_agent_limits(agent_name)[
1214
+ "max_file_size_kb"
1215
+ ]
1096
1216
  metrics["agents"][agent_name] = {
1097
1217
  "size_kb": round(size_kb, 2),
1098
1218
  "limit_kb": limit_kb,
1099
- "usage_percent": round((size_kb / limit_kb) * 100, 1)
1219
+ "usage_percent": round((size_kb / limit_kb) * 100, 1),
1100
1220
  }
1101
1221
  metrics["total_memory_kb"] += size_kb
1102
-
1222
+
1103
1223
  metrics["total_memory_kb"] = round(metrics["total_memory_kb"], 2)
1104
1224
  metrics["agent_count"] = len(metrics["agents"])
1105
-
1225
+
1106
1226
  return metrics
1107
1227
 
1108
1228