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
@@ -0,0 +1,617 @@
1
+ """
2
+ Memory CRUD Service
3
+ ===================
4
+
5
+ WHY: This service encapsulates all CRUD operations for agent memories, extracting
6
+ logic from the CLI commands to follow Single Responsibility Principle. It provides
7
+ a clean interface for memory initialization, reading, updating, and deletion operations.
8
+
9
+ DESIGN DECISIONS:
10
+ - Separates memory CRUD logic from CLI command implementation
11
+ - Provides structured data returns for programmatic access
12
+ - Handles memory validation and error recovery
13
+ - Supports both text and structured output formats
14
+ - Integrates with AgentMemoryManager for actual operations
15
+ - Maintains backward compatibility with existing memory formats
16
+ """
17
+
18
+ import os
19
+ from abc import ABC, abstractmethod
20
+ from datetime import datetime
21
+ from pathlib import Path
22
+ from typing import Any, Dict, List, Optional
23
+
24
+ from ...core.logger import get_logger
25
+ from ...services.agents.memory.agent_memory_manager import AgentMemoryManager
26
+
27
+
28
+ class IMemoryCRUDService(ABC):
29
+ """Interface for memory CRUD operations."""
30
+
31
+ @abstractmethod
32
+ def create_memory(
33
+ self, agent_id: str, template_type: str = "default"
34
+ ) -> Dict[str, Any]:
35
+ """
36
+ Create new memory file for an agent.
37
+
38
+ Args:
39
+ agent_id: ID of the agent
40
+ template_type: Type of template to use
41
+
42
+ Returns:
43
+ Dictionary with success status and file path
44
+ """
45
+
46
+ @abstractmethod
47
+ def read_memory(self, agent_id: Optional[str] = None) -> Dict[str, Any]:
48
+ """
49
+ Read memory content for one or all agents.
50
+
51
+ Args:
52
+ agent_id: Optional agent ID, None for all agents
53
+
54
+ Returns:
55
+ Dictionary with memory content and metadata
56
+ """
57
+
58
+ @abstractmethod
59
+ def update_memory(
60
+ self, agent_id: str, section: str, content: str
61
+ ) -> Dict[str, Any]:
62
+ """
63
+ Add learning entry to agent memory.
64
+
65
+ Args:
66
+ agent_id: ID of the agent
67
+ section: Memory section to update
68
+ content: Learning content to add
69
+
70
+ Returns:
71
+ Dictionary with success status and update details
72
+ """
73
+
74
+ @abstractmethod
75
+ def delete_memory(self, agent_id: str, confirm: bool = False) -> Dict[str, Any]:
76
+ """
77
+ Delete memory file for an agent.
78
+
79
+ Args:
80
+ agent_id: ID of the agent
81
+ confirm: Confirmation flag for deletion
82
+
83
+ Returns:
84
+ Dictionary with deletion status
85
+ """
86
+
87
+ @abstractmethod
88
+ def list_memories(self, include_stats: bool = True) -> Dict[str, Any]:
89
+ """
90
+ List all memory files with optional statistics.
91
+
92
+ Args:
93
+ include_stats: Include file statistics
94
+
95
+ Returns:
96
+ Dictionary with memory files list and stats
97
+ """
98
+
99
+ @abstractmethod
100
+ def clean_memory(
101
+ self, agent_id: Optional[str] = None, dry_run: bool = True
102
+ ) -> Dict[str, Any]:
103
+ """
104
+ Clean up memory files (remove old/unused).
105
+
106
+ Args:
107
+ agent_id: Optional specific agent to clean
108
+ dry_run: Preview changes without executing
109
+
110
+ Returns:
111
+ Dictionary with cleanup results
112
+ """
113
+
114
+ @abstractmethod
115
+ def init_project_memories(self) -> Dict[str, Any]:
116
+ """
117
+ Initialize project-specific memories task.
118
+
119
+ Returns:
120
+ Dictionary with initialization task details
121
+ """
122
+
123
+
124
+ class MemoryCRUDService(IMemoryCRUDService):
125
+ """Service for managing memory CRUD operations with robust error handling."""
126
+
127
+ def __init__(self, memory_manager: Optional[AgentMemoryManager] = None):
128
+ """
129
+ Initialize the memory CRUD service.
130
+
131
+ Args:
132
+ memory_manager: Optional memory manager instance
133
+ """
134
+ self.logger = get_logger(__name__)
135
+ self._memory_manager = memory_manager
136
+
137
+ def _get_memory_manager(self) -> AgentMemoryManager:
138
+ """Get or create memory manager instance."""
139
+ if self._memory_manager is None:
140
+ from ...core.shared.config_loader import ConfigLoader
141
+
142
+ config_loader = ConfigLoader()
143
+ config = config_loader.load_main_config()
144
+ # Use CLAUDE_MPM_USER_PWD if available
145
+ user_pwd = os.environ.get("CLAUDE_MPM_USER_PWD", os.getcwd())
146
+ current_dir = Path(user_pwd)
147
+ self._memory_manager = AgentMemoryManager(config, current_dir)
148
+ return self._memory_manager
149
+
150
+ def create_memory(
151
+ self, agent_id: str, template_type: str = "default"
152
+ ) -> Dict[str, Any]:
153
+ """
154
+ Create new memory file for an agent.
155
+
156
+ WHY: Initializes a new memory file with appropriate template structure
157
+ for the specified agent, ensuring consistent format across all memories.
158
+ """
159
+ try:
160
+ memory_manager = self._get_memory_manager()
161
+
162
+ # Check if memory already exists
163
+ existing_content = memory_manager.load_agent_memory(agent_id)
164
+ if existing_content:
165
+ return {
166
+ "success": False,
167
+ "error": f"Memory already exists for agent: {agent_id}",
168
+ "agent_id": agent_id,
169
+ "existing_file": str(
170
+ memory_manager.memories_dir / f"{agent_id}_memories.md"
171
+ ),
172
+ }
173
+
174
+ # Create memory with default template
175
+ template_content = memory_manager.template_generator.generate_template(
176
+ agent_id, template_type
177
+ )
178
+
179
+ memory_file = memory_manager.memories_dir / f"{agent_id}_memories.md"
180
+ memory_file.parent.mkdir(parents=True, exist_ok=True)
181
+ memory_file.write_text(template_content)
182
+
183
+ self.logger.info(f"Created memory file for agent: {agent_id}")
184
+
185
+ return {
186
+ "success": True,
187
+ "agent_id": agent_id,
188
+ "file_path": str(memory_file),
189
+ "template_type": template_type,
190
+ "message": f"Memory created for agent: {agent_id}",
191
+ }
192
+
193
+ except Exception as e:
194
+ self.logger.error(
195
+ f"Error creating memory for {agent_id}: {e}", exc_info=True
196
+ )
197
+ return {"success": False, "error": str(e), "agent_id": agent_id}
198
+
199
+ def read_memory(self, agent_id: Optional[str] = None) -> Dict[str, Any]:
200
+ """
201
+ Read memory content for one or all agents.
202
+
203
+ WHY: Provides access to memory content for inspection, debugging,
204
+ or integration with other tools.
205
+ """
206
+ try:
207
+ memory_manager = self._get_memory_manager()
208
+
209
+ if agent_id:
210
+ # Read single agent memory
211
+ memory_content = memory_manager.load_agent_memory(agent_id)
212
+
213
+ if not memory_content:
214
+ return {
215
+ "success": False,
216
+ "error": f"No memory found for agent: {agent_id}",
217
+ "agent_id": agent_id,
218
+ }
219
+
220
+ memory_file = memory_manager.memories_dir / f"{agent_id}_memories.md"
221
+ file_stats = None
222
+ if memory_file.exists():
223
+ stat = memory_file.stat()
224
+ file_stats = {
225
+ "size_kb": stat.st_size / 1024,
226
+ "modified": datetime.fromtimestamp(stat.st_mtime).isoformat(),
227
+ "path": str(memory_file),
228
+ }
229
+
230
+ return {
231
+ "success": True,
232
+ "agent_id": agent_id,
233
+ "content": memory_content,
234
+ "file_stats": file_stats,
235
+ }
236
+
237
+ # Read all agent memories
238
+ memory_dir = memory_manager.memories_dir
239
+ if not memory_dir.exists():
240
+ return {
241
+ "success": True,
242
+ "agents": {},
243
+ "memory_directory": str(memory_dir),
244
+ "exists": False,
245
+ }
246
+
247
+ agents = {}
248
+ for memory_file in self._get_memory_files(memory_dir):
249
+ agent_id = self._extract_agent_id(memory_file)
250
+ try:
251
+ memory_content = memory_manager.load_agent_memory(agent_id)
252
+ if memory_content:
253
+ stat = memory_file.stat()
254
+ agents[agent_id] = {
255
+ "content": memory_content,
256
+ "file_stats": {
257
+ "size_kb": stat.st_size / 1024,
258
+ "modified": datetime.fromtimestamp(
259
+ stat.st_mtime
260
+ ).isoformat(),
261
+ "path": str(memory_file),
262
+ },
263
+ }
264
+ except Exception as e:
265
+ self.logger.warning(f"Error reading memory for {agent_id}: {e}")
266
+
267
+ return {
268
+ "success": True,
269
+ "agents": agents,
270
+ "memory_directory": str(memory_dir),
271
+ "exists": True,
272
+ "agent_count": len(agents),
273
+ }
274
+
275
+ except Exception as e:
276
+ self.logger.error(f"Error reading memory: {e}", exc_info=True)
277
+ return {"success": False, "error": str(e), "agent_id": agent_id}
278
+
279
+ def update_memory(
280
+ self, agent_id: str, section: str, content: str
281
+ ) -> Dict[str, Any]:
282
+ """
283
+ Add learning entry to agent memory.
284
+
285
+ WHY: Allows manual injection of learnings for testing, correction,
286
+ or knowledge enhancement purposes.
287
+ """
288
+ try:
289
+ memory_manager = self._get_memory_manager()
290
+
291
+ # Map learning types to appropriate sections
292
+ section_map = {
293
+ "pattern": "Project Architecture",
294
+ "error": "Common Mistakes to Avoid",
295
+ "optimization": "Implementation Guidelines",
296
+ "preference": "Implementation Guidelines",
297
+ "context": "Current Technical Context",
298
+ }
299
+
300
+ section_name = section_map.get(section, section)
301
+
302
+ # Attempt to update memory
303
+ success = memory_manager.update_agent_memory(
304
+ agent_id, section_name, content
305
+ )
306
+
307
+ if success:
308
+ self.logger.info(
309
+ f"Added learning to {agent_id} memory in section: {section_name}"
310
+ )
311
+ return {
312
+ "success": True,
313
+ "agent_id": agent_id,
314
+ "section": section_name,
315
+ "content_preview": content[:100]
316
+ + ("..." if len(content) > 100 else ""),
317
+ "message": f"Learning added to {agent_id} memory",
318
+ }
319
+ return {
320
+ "success": False,
321
+ "agent_id": agent_id,
322
+ "section": section_name,
323
+ "error": "Failed to add learning - memory file may be at size limit or section may be full",
324
+ }
325
+
326
+ except Exception as e:
327
+ self.logger.error(
328
+ f"Error updating memory for {agent_id}: {e}", exc_info=True
329
+ )
330
+ return {
331
+ "success": False,
332
+ "error": str(e),
333
+ "agent_id": agent_id,
334
+ "section": section,
335
+ }
336
+
337
+ def delete_memory(self, agent_id: str, confirm: bool = False) -> Dict[str, Any]:
338
+ """
339
+ Delete memory file for an agent.
340
+
341
+ WHY: Provides controlled deletion of memory files with safety checks
342
+ to prevent accidental data loss.
343
+ """
344
+ try:
345
+ if not confirm:
346
+ return {
347
+ "success": False,
348
+ "error": "Deletion requires confirmation flag",
349
+ "agent_id": agent_id,
350
+ "hint": "Use --confirm flag to delete",
351
+ }
352
+
353
+ memory_manager = self._get_memory_manager()
354
+ memory_file = memory_manager.memories_dir / f"{agent_id}_memories.md"
355
+
356
+ if not memory_file.exists():
357
+ # Check for alternative formats
358
+ alt_files = [
359
+ memory_manager.memories_dir / f"{agent_id}_agent.md",
360
+ memory_manager.memories_dir / f"{agent_id}.md",
361
+ ]
362
+
363
+ for alt_file in alt_files:
364
+ if alt_file.exists():
365
+ memory_file = alt_file
366
+ break
367
+ else:
368
+ return {
369
+ "success": False,
370
+ "error": f"No memory file found for agent: {agent_id}",
371
+ "agent_id": agent_id,
372
+ }
373
+
374
+ # Get file size before deletion
375
+ file_size_kb = memory_file.stat().st_size / 1024
376
+
377
+ # Delete the file
378
+ memory_file.unlink()
379
+ self.logger.info(f"Deleted memory file for agent: {agent_id}")
380
+
381
+ return {
382
+ "success": True,
383
+ "agent_id": agent_id,
384
+ "deleted_file": str(memory_file),
385
+ "file_size_kb": file_size_kb,
386
+ "message": f"Memory deleted for agent: {agent_id}",
387
+ }
388
+
389
+ except Exception as e:
390
+ self.logger.error(
391
+ f"Error deleting memory for {agent_id}: {e}", exc_info=True
392
+ )
393
+ return {"success": False, "error": str(e), "agent_id": agent_id}
394
+
395
+ def list_memories(self, include_stats: bool = True) -> Dict[str, Any]:
396
+ """
397
+ List all memory files with optional statistics.
398
+
399
+ WHY: Provides overview of all memories in the system for management
400
+ and monitoring purposes.
401
+ """
402
+ try:
403
+ memory_manager = self._get_memory_manager()
404
+ memory_dir = memory_manager.memories_dir
405
+
406
+ if not memory_dir.exists():
407
+ return {
408
+ "success": True,
409
+ "memory_directory": str(memory_dir),
410
+ "exists": False,
411
+ "memories": [],
412
+ "total_size_kb": 0,
413
+ "total_files": 0,
414
+ }
415
+
416
+ memories = []
417
+ total_size = 0
418
+
419
+ for memory_file in self._get_memory_files(memory_dir):
420
+ agent_id = self._extract_agent_id(memory_file)
421
+
422
+ memory_info = {
423
+ "agent_id": agent_id,
424
+ "file": memory_file.name,
425
+ "path": str(memory_file),
426
+ }
427
+
428
+ if include_stats:
429
+ stat = memory_file.stat()
430
+ memory_info.update(
431
+ {
432
+ "size_kb": stat.st_size / 1024,
433
+ "modified": datetime.fromtimestamp(
434
+ stat.st_mtime
435
+ ).isoformat(),
436
+ "created": datetime.fromtimestamp(
437
+ stat.st_ctime
438
+ ).isoformat(),
439
+ }
440
+ )
441
+ total_size += stat.st_size
442
+
443
+ memories.append(memory_info)
444
+
445
+ return {
446
+ "success": True,
447
+ "memory_directory": str(memory_dir),
448
+ "exists": True,
449
+ "memories": sorted(memories, key=lambda x: x["agent_id"]),
450
+ "total_size_kb": total_size / 1024 if include_stats else None,
451
+ "total_files": len(memories),
452
+ }
453
+
454
+ except Exception as e:
455
+ self.logger.error(f"Error listing memories: {e}", exc_info=True)
456
+ return {"success": False, "error": str(e)}
457
+
458
+ def clean_memory(
459
+ self, agent_id: Optional[str] = None, dry_run: bool = True
460
+ ) -> Dict[str, Any]:
461
+ """
462
+ Clean up memory files (remove old/unused).
463
+
464
+ WHY: Memory files can accumulate over time. This provides controlled
465
+ cleanup to save disk space while preserving important data.
466
+
467
+ DESIGN DECISION: For Phase 1, this is a stub implementation.
468
+ Full cleanup logic will be implemented based on usage patterns.
469
+ """
470
+ try:
471
+ memory_manager = self._get_memory_manager()
472
+ memory_dir = memory_manager.memories_dir
473
+
474
+ if not memory_dir.exists():
475
+ return {
476
+ "success": True,
477
+ "message": "No memory directory found - nothing to clean",
478
+ "cleaned_files": [],
479
+ "dry_run": dry_run,
480
+ }
481
+
482
+ memory_files = list(self._get_memory_files(memory_dir))
483
+ if not memory_files:
484
+ return {
485
+ "success": True,
486
+ "message": "No memory files found - nothing to clean",
487
+ "cleaned_files": [],
488
+ "dry_run": dry_run,
489
+ }
490
+
491
+ # For Phase 1, just identify candidates for cleanup
492
+ cleanup_candidates = []
493
+
494
+ for memory_file in memory_files:
495
+ agent_id_file = self._extract_agent_id(memory_file)
496
+
497
+ # Skip if specific agent requested and doesn't match
498
+ if agent_id and agent_id_file != agent_id:
499
+ continue
500
+
501
+ stat = memory_file.stat()
502
+ age_days = (datetime.now() - datetime.fromtimestamp(stat.st_mtime)).days
503
+
504
+ # Identify files older than 30 days as candidates
505
+ if age_days > 30:
506
+ cleanup_candidates.append(
507
+ {
508
+ "agent_id": agent_id_file,
509
+ "file": str(memory_file),
510
+ "size_kb": stat.st_size / 1024,
511
+ "age_days": age_days,
512
+ "reason": "File older than 30 days with no recent access",
513
+ }
514
+ )
515
+
516
+ if dry_run:
517
+ return {
518
+ "success": True,
519
+ "message": "Cleanup preview (dry run)",
520
+ "cleanup_candidates": cleanup_candidates,
521
+ "dry_run": True,
522
+ "note": "Cleanup not yet implemented in Phase 1",
523
+ }
524
+ # Phase 1: Don't actually delete anything
525
+ return {
526
+ "success": True,
527
+ "message": "Cleanup not yet implemented in Phase 1",
528
+ "cleanup_candidates": cleanup_candidates,
529
+ "dry_run": False,
530
+ "cleaned_files": [],
531
+ "note": "Future cleanup will remove old/corrupted files",
532
+ }
533
+
534
+ except Exception as e:
535
+ self.logger.error(f"Error cleaning memory: {e}", exc_info=True)
536
+ return {"success": False, "error": str(e), "agent_id": agent_id}
537
+
538
+ def init_project_memories(self) -> Dict[str, Any]:
539
+ """
540
+ Initialize project-specific memories task.
541
+
542
+ WHY: When starting with a new project, agents need project-specific
543
+ knowledge beyond what automatic analysis provides. This creates a
544
+ task description for comprehensive project scanning.
545
+ """
546
+ try:
547
+ task_data = {
548
+ "task": "Initialize Project-Specific Memories",
549
+ "description": "Analyze project structure and create targeted memories for agents",
550
+ "instructions": [
551
+ "Scan the project structure, documentation, and source code",
552
+ "Identify key patterns, conventions, and project-specific knowledge",
553
+ "Create targeted memories for each agent type",
554
+ "Use 'claude-mpm memory add <agent> <type> \"<content>\"' commands",
555
+ ],
556
+ "focus_areas": [
557
+ "Architectural patterns and design decisions",
558
+ "Coding conventions from actual source code",
559
+ "Key modules, APIs, and integration points",
560
+ "Testing patterns and quality standards",
561
+ "Performance considerations specific to this project",
562
+ "Common pitfalls based on the codebase",
563
+ "Domain-specific terminology and concepts",
564
+ ],
565
+ "example_commands": [
566
+ 'claude-mpm memory add engineer pattern "Use dependency injection with @inject"',
567
+ 'claude-mpm memory add qa pattern "Test files follow test_<module>_<feature>.py"',
568
+ 'claude-mpm memory add research context "Project uses microservices architecture"',
569
+ ],
570
+ "analysis_targets": [
571
+ "Project structure and documentation",
572
+ "Source code for patterns and conventions",
573
+ "Testing patterns and quality standards",
574
+ "Performance considerations",
575
+ "Domain-specific terminology",
576
+ ],
577
+ }
578
+
579
+ return {
580
+ "success": True,
581
+ "task_data": task_data,
582
+ "message": "Memory initialization task created",
583
+ }
584
+
585
+ except Exception as e:
586
+ self.logger.error(f"Error creating initialization task: {e}", exc_info=True)
587
+ return {"success": False, "error": str(e)}
588
+
589
+ # Helper methods
590
+ def _get_memory_files(self, memory_dir: Path) -> List[Path]:
591
+ """Get all memory files supporting various formats."""
592
+ memory_files = []
593
+
594
+ # Support new format
595
+ memory_files.extend(memory_dir.glob("*_memories.md"))
596
+
597
+ # Support old formats for backward compatibility
598
+ memory_files.extend(memory_dir.glob("*_agent.md"))
599
+ memory_files.extend(
600
+ [
601
+ f
602
+ for f in memory_dir.glob("*.md")
603
+ if f.name != "README.md"
604
+ and not f.name.endswith("_memories.md")
605
+ and not f.name.endswith("_agent.md")
606
+ ]
607
+ )
608
+
609
+ return sorted(set(memory_files))
610
+
611
+ def _extract_agent_id(self, file_path: Path) -> str:
612
+ """Extract agent ID from various file name formats."""
613
+ if file_path.name.endswith("_memories.md"):
614
+ return file_path.stem[:-9] # Remove "_memories"
615
+ if file_path.name.endswith("_agent.md"):
616
+ return file_path.stem[:-6] # Remove "_agent"
617
+ return file_path.stem