claude-mpm 3.9.11__py3-none-any.whl → 4.0.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,721 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Unified Agent Registry System for Claude MPM
4
+ ============================================
5
+
6
+ This module consolidates all agent registry functionality from the duplicate modules:
7
+ - core/agent_registry.py (AgentRegistryAdapter and legacy functions)
8
+ - services/agents/registry/agent_registry.py (Full-featured AgentRegistry)
9
+ - agents/core/agent_registry.py (Core AgentRegistry with memory integration)
10
+
11
+ Design Principles:
12
+ - Single source of truth for agent discovery and management
13
+ - Consistent API across all agent operations
14
+ - Hierarchical tier system (PROJECT > USER > SYSTEM)
15
+ - Memory-aware agent creation
16
+ - Efficient caching with smart invalidation
17
+ - Comprehensive metadata management
18
+ - Backward compatibility during migration
19
+
20
+ Architecture:
21
+ - UnifiedAgentRegistry: Main registry class
22
+ - AgentMetadata: Standardized agent metadata model
23
+ - AgentTier: Hierarchical precedence system
24
+ - AgentType: Agent classification system
25
+ - Discovery engine with tier-based precedence
26
+ """
27
+
28
+ import json
29
+ import logging
30
+ import time
31
+ from dataclasses import asdict, dataclass
32
+ from datetime import datetime
33
+ from enum import Enum
34
+ from pathlib import Path
35
+ from typing import Any, Dict, List, Optional, Set, Union
36
+
37
+ from .unified_paths import get_path_manager
38
+
39
+ logger = logging.getLogger(__name__)
40
+
41
+
42
+ class AgentTier(Enum):
43
+ """Agent tier hierarchy for precedence resolution."""
44
+
45
+ PROJECT = "project" # Highest precedence
46
+ USER = "user" # Medium precedence
47
+ SYSTEM = "system" # Lowest precedence
48
+
49
+
50
+ class AgentType(Enum):
51
+ """Agent type classification."""
52
+
53
+ CORE = "core" # Core framework agents
54
+ SPECIALIZED = "specialized" # Specialized domain agents
55
+ USER_DEFINED = "user_defined" # User-created agents
56
+ PROJECT = "project" # Project-specific agents
57
+ MEMORY_AWARE = "memory_aware" # Memory-enhanced agents
58
+
59
+
60
+ class AgentFormat(Enum):
61
+ """Supported agent file formats."""
62
+
63
+ MARKDOWN = "markdown"
64
+ JSON = "json"
65
+ YAML = "yaml"
66
+
67
+
68
+ @dataclass
69
+ class AgentMetadata:
70
+ """Standardized agent metadata model."""
71
+
72
+ name: str
73
+ agent_type: AgentType
74
+ tier: AgentTier
75
+ path: str
76
+ format: AgentFormat
77
+ last_modified: float
78
+ description: str = ""
79
+ specializations: List[str] = None
80
+ memory_files: List[str] = None
81
+ dependencies: List[str] = None
82
+ version: str = "1.0.0"
83
+ author: str = ""
84
+ tags: List[str] = None
85
+
86
+ def __post_init__(self):
87
+ """Initialize default values for mutable fields."""
88
+ if self.specializations is None:
89
+ self.specializations = []
90
+ if self.memory_files is None:
91
+ self.memory_files = []
92
+ if self.dependencies is None:
93
+ self.dependencies = []
94
+ if self.tags is None:
95
+ self.tags = []
96
+
97
+ def to_dict(self) -> Dict[str, Any]:
98
+ """Convert to dictionary representation."""
99
+ data = asdict(self)
100
+ data["agent_type"] = self.agent_type.value
101
+ data["tier"] = self.tier.value
102
+ data["format"] = self.format.value
103
+ return data
104
+
105
+ @classmethod
106
+ def from_dict(cls, data: Dict[str, Any]) -> "AgentMetadata":
107
+ """Create from dictionary representation."""
108
+ data["agent_type"] = AgentType(data["agent_type"])
109
+ data["tier"] = AgentTier(data["tier"])
110
+ data["format"] = AgentFormat(data["format"])
111
+ return cls(**data)
112
+
113
+
114
+ class UnifiedAgentRegistry:
115
+ """
116
+ Unified agent registry system that consolidates all agent-related functionality.
117
+
118
+ This class provides a single, authoritative interface for all agent operations
119
+ in Claude MPM, replacing the multiple duplicate agent registry modules.
120
+ """
121
+
122
+ def __init__(self, cache_enabled: bool = True, cache_ttl: int = 3600):
123
+ """Initialize the unified agent registry."""
124
+ self.path_manager = get_path_manager()
125
+
126
+ # Registry storage
127
+ self.registry: Dict[str, AgentMetadata] = {}
128
+ self.discovery_paths: List[Path] = []
129
+ self.discovered_files: Set[Path] = set()
130
+
131
+ # Cache configuration
132
+ self.cache_enabled = cache_enabled
133
+ self.cache_ttl = cache_ttl
134
+ self.cache_prefix = "unified_agent_registry"
135
+
136
+ # Discovery configuration
137
+ self.file_extensions = {".md", ".json", ".yaml", ".yml"}
138
+ self.ignore_patterns = {"__pycache__", ".git", "node_modules", ".pytest_cache"}
139
+
140
+ # Statistics
141
+ self.discovery_stats = {
142
+ "last_discovery": None,
143
+ "total_discovered": 0,
144
+ "cache_hits": 0,
145
+ "cache_misses": 0,
146
+ "discovery_duration": 0.0,
147
+ }
148
+
149
+ # Setup discovery paths
150
+ self._setup_discovery_paths()
151
+
152
+ logger.info(
153
+ f"UnifiedAgentRegistry initialized with cache={'enabled' if cache_enabled else 'disabled'}"
154
+ )
155
+
156
+ def _setup_discovery_paths(self) -> None:
157
+ """Setup standard discovery paths for agent files."""
158
+ # Project-level agents (highest priority)
159
+ project_path = self.path_manager.get_project_agents_dir()
160
+ if project_path.exists():
161
+ self.discovery_paths.append(project_path)
162
+
163
+ # User-level agents
164
+ user_path = self.path_manager.get_user_agents_dir()
165
+ if user_path.exists():
166
+ self.discovery_paths.append(user_path)
167
+
168
+ # System-level agents
169
+ system_path = self.path_manager.get_system_agents_dir()
170
+ if system_path.exists():
171
+ self.discovery_paths.append(system_path)
172
+
173
+ # Templates directory
174
+ templates_path = self.path_manager.get_templates_dir()
175
+ if templates_path.exists():
176
+ self.discovery_paths.append(templates_path)
177
+
178
+ logger.debug(
179
+ f"Discovery paths configured: {[str(p) for p in self.discovery_paths]}"
180
+ )
181
+
182
+ def discover_agents(self, force_refresh: bool = False) -> Dict[str, AgentMetadata]:
183
+ """
184
+ Discover all agents from configured paths with tier precedence.
185
+
186
+ Args:
187
+ force_refresh: Force re-discovery even if cache is valid
188
+
189
+ Returns:
190
+ Dictionary mapping agent names to their metadata
191
+ """
192
+ start_time = time.time()
193
+
194
+ # Check cache first (if enabled and not forcing refresh)
195
+ if self.cache_enabled and not force_refresh and self._is_cache_valid():
196
+ self.discovery_stats["cache_hits"] += 1
197
+ logger.debug("Using cached agent registry")
198
+ return self.registry
199
+
200
+ self.discovery_stats["cache_misses"] += 1
201
+
202
+ # Clear existing registry and discovered files
203
+ self.registry.clear()
204
+ self.discovered_files.clear()
205
+
206
+ # Discover agents from all paths
207
+ for discovery_path in self.discovery_paths:
208
+ tier = self._determine_tier(discovery_path)
209
+ self._discover_path(discovery_path, tier)
210
+
211
+ # Handle tier precedence
212
+ self._apply_tier_precedence()
213
+
214
+ # Discover and integrate memory files
215
+ self._discover_memory_integration()
216
+
217
+ # Cache the results
218
+ if self.cache_enabled:
219
+ self._cache_registry()
220
+
221
+ # Update statistics
222
+ self.discovery_stats["last_discovery"] = time.time()
223
+ self.discovery_stats["total_discovered"] = len(self.registry)
224
+ self.discovery_stats["discovery_duration"] = time.time() - start_time
225
+
226
+ logger.info(
227
+ f"Discovered {len(self.registry)} agents in {self.discovery_stats['discovery_duration']:.2f}s"
228
+ )
229
+
230
+ return self.registry
231
+
232
+ def _discover_path(self, path: Path, tier: AgentTier) -> None:
233
+ """Discover agents in a specific path."""
234
+ if not path.exists():
235
+ return
236
+
237
+ for file_path in path.rglob("*"):
238
+ # Skip directories and ignored patterns
239
+ if file_path.is_dir():
240
+ continue
241
+
242
+ if any(pattern in str(file_path) for pattern in self.ignore_patterns):
243
+ continue
244
+
245
+ # Check file extension
246
+ if file_path.suffix not in self.file_extensions:
247
+ continue
248
+
249
+ # Extract agent name
250
+ agent_name = self._extract_agent_name(file_path)
251
+ if not agent_name:
252
+ continue
253
+
254
+ # Create agent metadata
255
+ try:
256
+ metadata = self._create_agent_metadata(file_path, agent_name, tier)
257
+ if metadata:
258
+ self.registry[agent_name] = metadata
259
+ self.discovered_files.add(file_path)
260
+ logger.debug(
261
+ f"Discovered agent: {agent_name} ({tier.value}) at {file_path}"
262
+ )
263
+ except Exception as e:
264
+ logger.warning(f"Failed to process agent file {file_path}: {e}")
265
+
266
+ def _extract_agent_name(self, file_path: Path) -> Optional[str]:
267
+ """Extract agent name from file path."""
268
+ # Remove extension and use filename as agent name
269
+ name = file_path.stem
270
+
271
+ # Skip certain files
272
+ skip_files = {"README", "INSTRUCTIONS", "template", "example"}
273
+ if name.upper() in skip_files:
274
+ return None
275
+
276
+ # Normalize name
277
+ return name.lower().replace("-", "_").replace(" ", "_")
278
+
279
+ def _create_agent_metadata(
280
+ self, file_path: Path, agent_name: str, tier: AgentTier
281
+ ) -> Optional[AgentMetadata]:
282
+ """Create agent metadata from file."""
283
+ try:
284
+ # Determine format
285
+ format_map = {
286
+ ".md": AgentFormat.MARKDOWN,
287
+ ".json": AgentFormat.JSON,
288
+ ".yaml": AgentFormat.YAML,
289
+ ".yml": AgentFormat.YAML,
290
+ }
291
+ agent_format = format_map.get(file_path.suffix, AgentFormat.MARKDOWN)
292
+
293
+ # Determine agent type
294
+ agent_type = self._determine_agent_type(file_path, tier)
295
+
296
+ # Extract metadata from file content
297
+ description, specializations = self._extract_file_metadata(
298
+ file_path, agent_format
299
+ )
300
+
301
+ return AgentMetadata(
302
+ name=agent_name,
303
+ agent_type=agent_type,
304
+ tier=tier,
305
+ path=str(file_path),
306
+ format=agent_format,
307
+ last_modified=file_path.stat().st_mtime,
308
+ description=description,
309
+ specializations=specializations,
310
+ )
311
+
312
+ except Exception as e:
313
+ logger.error(f"Failed to create metadata for {file_path}: {e}")
314
+ return None
315
+
316
+ def _determine_tier(self, path: Path) -> AgentTier:
317
+ """Determine agent tier based on path."""
318
+ path_str = str(path)
319
+
320
+ if (
321
+ "project" in path_str
322
+ or str(self.path_manager.get_project_agents_dir()) in path_str
323
+ ):
324
+ return AgentTier.PROJECT
325
+ elif (
326
+ "user" in path_str
327
+ or str(self.path_manager.get_user_agents_dir()) in path_str
328
+ ):
329
+ return AgentTier.USER
330
+ else:
331
+ return AgentTier.SYSTEM
332
+
333
+ def _determine_agent_type(self, file_path: Path, tier: AgentTier) -> AgentType:
334
+ """Determine agent type based on file path and tier."""
335
+ path_str = str(file_path).lower()
336
+
337
+ # Project-specific agents
338
+ if tier == AgentTier.PROJECT:
339
+ return AgentType.PROJECT
340
+
341
+ # User-defined agents
342
+ if tier == AgentTier.USER:
343
+ return AgentType.USER_DEFINED
344
+
345
+ # Core framework agents
346
+ if "templates" in path_str or "core" in path_str:
347
+ return AgentType.CORE
348
+
349
+ # Specialized agents
350
+ return AgentType.SPECIALIZED
351
+
352
+ def _extract_file_metadata(
353
+ self, file_path: Path, agent_format: AgentFormat
354
+ ) -> tuple[str, List[str]]:
355
+ """Extract description and specializations from agent file."""
356
+ try:
357
+ content = file_path.read_text(encoding="utf-8")
358
+
359
+ if agent_format == AgentFormat.JSON:
360
+ data = json.loads(content)
361
+ description = data.get("description", "")
362
+ specializations = data.get("specializations", [])
363
+ elif agent_format in [AgentFormat.YAML, AgentFormat.YAML]:
364
+ try:
365
+ import yaml
366
+
367
+ data = yaml.safe_load(content)
368
+ description = data.get("description", "")
369
+ specializations = data.get("specializations", [])
370
+ except ImportError:
371
+ # Fallback if yaml not available
372
+ description = ""
373
+ specializations = []
374
+ else: # Markdown
375
+ # Extract from frontmatter or content
376
+ description = self._extract_markdown_description(content)
377
+ specializations = self._extract_markdown_specializations(content)
378
+
379
+ return description, specializations
380
+
381
+ except Exception as e:
382
+ logger.warning(f"Failed to extract metadata from {file_path}: {e}")
383
+ return "", []
384
+
385
+ def _extract_markdown_description(self, content: str) -> str:
386
+ """Extract description from markdown content."""
387
+ lines = content.split("\n")
388
+
389
+ # Look for frontmatter
390
+ if lines and lines[0].strip() == "---":
391
+ in_frontmatter = True
392
+ for i, line in enumerate(lines[1:], 1):
393
+ if line.strip() == "---":
394
+ break
395
+ if line.startswith("description:"):
396
+ return line.split(":", 1)[1].strip().strip("\"'")
397
+
398
+ # Look for first paragraph
399
+ for line in lines:
400
+ line = line.strip()
401
+ if line and not line.startswith("#") and not line.startswith("---"):
402
+ return line
403
+
404
+ return ""
405
+
406
+ def _extract_markdown_specializations(self, content: str) -> List[str]:
407
+ """Extract specializations from markdown content."""
408
+ specializations = []
409
+
410
+ # Look for frontmatter
411
+ lines = content.split("\n")
412
+ if lines and lines[0].strip() == "---":
413
+ in_frontmatter = True
414
+ for i, line in enumerate(lines[1:], 1):
415
+ if line.strip() == "---":
416
+ break
417
+ if line.startswith("specializations:"):
418
+ # Parse YAML list
419
+ spec_content = line.split(":", 1)[1].strip()
420
+ if spec_content.startswith("[") and spec_content.endswith("]"):
421
+ # JSON-style list
422
+ try:
423
+ specializations = json.loads(spec_content)
424
+ except:
425
+ pass
426
+
427
+ return specializations
428
+
429
+ def _apply_tier_precedence(self) -> None:
430
+ """Apply tier precedence rules to resolve conflicts."""
431
+ # Group agents by name
432
+ agent_groups = {}
433
+ for name, metadata in self.registry.items():
434
+ if name not in agent_groups:
435
+ agent_groups[name] = []
436
+ agent_groups[name].append(metadata)
437
+
438
+ # Resolve conflicts using tier precedence
439
+ resolved_registry = {}
440
+ tier_order = [AgentTier.PROJECT, AgentTier.USER, AgentTier.SYSTEM]
441
+
442
+ for name, agents in agent_groups.items():
443
+ if len(agents) == 1:
444
+ resolved_registry[name] = agents[0]
445
+ else:
446
+ # Find highest precedence agent
447
+ for tier in tier_order:
448
+ for agent in agents:
449
+ if agent.tier == tier:
450
+ resolved_registry[name] = agent
451
+ logger.debug(
452
+ f"Resolved conflict for {name}: using {tier.value} tier"
453
+ )
454
+ break
455
+ if name in resolved_registry:
456
+ break
457
+
458
+ self.registry = resolved_registry
459
+
460
+ def _discover_memory_integration(self) -> None:
461
+ """Discover and integrate memory files with agents."""
462
+ memories_dir = self.path_manager.get_memories_dir("project")
463
+ if not memories_dir.exists():
464
+ return
465
+
466
+ for memory_file in memories_dir.glob("*.md"):
467
+ memory_name = memory_file.stem
468
+
469
+ # Find matching agent
470
+ for agent_name, metadata in self.registry.items():
471
+ if agent_name == memory_name or memory_name in agent_name:
472
+ metadata.memory_files.append(str(memory_file))
473
+ metadata.agent_type = AgentType.MEMORY_AWARE
474
+ logger.debug(
475
+ f"Integrated memory file {memory_file} with agent {agent_name}"
476
+ )
477
+
478
+ def _is_cache_valid(self) -> bool:
479
+ """Check if the current cache is still valid."""
480
+ if not self.discovery_stats["last_discovery"]:
481
+ return False
482
+
483
+ # Check if cache has expired
484
+ cache_age = time.time() - self.discovery_stats["last_discovery"]
485
+ if cache_age > self.cache_ttl:
486
+ return False
487
+
488
+ # Check if any discovered files have been modified
489
+ for file_path in self.discovered_files:
490
+ if file_path.exists():
491
+ if file_path.stat().st_mtime > self.discovery_stats["last_discovery"]:
492
+ return False
493
+ else:
494
+ # File was deleted
495
+ return False
496
+
497
+ return True
498
+
499
+ def _cache_registry(self) -> None:
500
+ """Cache the current registry state."""
501
+ # For now, we just store in memory
502
+ # In a full implementation, this could write to disk
503
+ pass
504
+
505
+ # ========================================================================
506
+ # Public API Methods
507
+ # ========================================================================
508
+
509
+ def get_agent(self, name: str) -> Optional[AgentMetadata]:
510
+ """Get agent metadata by name."""
511
+ if not self.registry:
512
+ self.discover_agents()
513
+
514
+ return self.registry.get(name)
515
+
516
+ def list_agents(
517
+ self,
518
+ tier: Optional[AgentTier] = None,
519
+ agent_type: Optional[AgentType] = None,
520
+ tags: Optional[List[str]] = None,
521
+ ) -> List[AgentMetadata]:
522
+ """List agents with optional filtering."""
523
+ if not self.registry:
524
+ self.discover_agents()
525
+
526
+ agents = list(self.registry.values())
527
+
528
+ # Apply filters
529
+ if tier:
530
+ agents = [a for a in agents if a.tier == tier]
531
+
532
+ if agent_type:
533
+ agents = [a for a in agents if a.agent_type == agent_type]
534
+
535
+ if tags:
536
+ agents = [a for a in agents if any(tag in a.tags for tag in tags)]
537
+
538
+ return sorted(agents, key=lambda a: (a.tier.value, a.name))
539
+
540
+ def get_agent_names(self) -> List[str]:
541
+ """Get list of all agent names."""
542
+ if not self.registry:
543
+ self.discover_agents()
544
+
545
+ return sorted(self.registry.keys())
546
+
547
+ def get_core_agents(self) -> List[AgentMetadata]:
548
+ """Get all core framework agents."""
549
+ return self.list_agents(agent_type=AgentType.CORE)
550
+
551
+ def get_specialized_agents(self) -> List[AgentMetadata]:
552
+ """Get all specialized agents."""
553
+ return self.list_agents(agent_type=AgentType.SPECIALIZED)
554
+
555
+ def get_project_agents(self) -> List[AgentMetadata]:
556
+ """Get all project-specific agents."""
557
+ return self.list_agents(tier=AgentTier.PROJECT)
558
+
559
+ def get_memory_aware_agents(self) -> List[AgentMetadata]:
560
+ """Get all memory-aware agents."""
561
+ return self.list_agents(agent_type=AgentType.MEMORY_AWARE)
562
+
563
+ def add_discovery_path(self, path: Union[str, Path]) -> None:
564
+ """Add a new path for agent discovery."""
565
+ path = Path(path)
566
+ if path.exists() and path not in self.discovery_paths:
567
+ self.discovery_paths.append(path)
568
+ logger.info(f"Added discovery path: {path}")
569
+ # Force re-discovery with new path
570
+ self.discover_agents(force_refresh=True)
571
+
572
+ def invalidate_cache(self) -> None:
573
+ """Invalidate the current cache."""
574
+ self.discovery_stats["last_discovery"] = None
575
+ logger.debug("Agent registry cache invalidated")
576
+
577
+ def get_registry_stats(self) -> Dict[str, Any]:
578
+ """Get registry statistics."""
579
+ return {
580
+ **self.discovery_stats,
581
+ "total_agents": len(self.registry),
582
+ "discovery_paths": [str(p) for p in self.discovery_paths],
583
+ "cache_enabled": self.cache_enabled,
584
+ }
585
+
586
+ def export_registry(self, output_path: Union[str, Path]) -> None:
587
+ """Export registry to JSON file."""
588
+ output_path = Path(output_path)
589
+
590
+ export_data = {
591
+ "metadata": {
592
+ "export_time": datetime.now().isoformat(),
593
+ "total_agents": len(self.registry),
594
+ "discovery_paths": [str(p) for p in self.discovery_paths],
595
+ },
596
+ "agents": {
597
+ name: metadata.to_dict() for name, metadata in self.registry.items()
598
+ },
599
+ }
600
+
601
+ with open(output_path, "w") as f:
602
+ json.dump(export_data, f, indent=2)
603
+
604
+ logger.info(f"Exported {len(self.registry)} agents to {output_path}")
605
+
606
+ def import_registry(self, input_path: Union[str, Path]) -> None:
607
+ """Import registry from JSON file."""
608
+ input_path = Path(input_path)
609
+
610
+ with open(input_path, "r") as f:
611
+ data = json.load(f)
612
+
613
+ # Clear current registry
614
+ self.registry.clear()
615
+
616
+ # Import agents
617
+ for name, agent_data in data.get("agents", {}).items():
618
+ self.registry[name] = AgentMetadata.from_dict(agent_data)
619
+
620
+ logger.info(f"Imported {len(self.registry)} agents from {input_path}")
621
+
622
+
623
+ # ============================================================================
624
+ # Singleton Instance and Convenience Functions
625
+ # ============================================================================
626
+
627
+ # Global singleton instance
628
+ _agent_registry: Optional[UnifiedAgentRegistry] = None
629
+
630
+
631
+ def get_agent_registry() -> UnifiedAgentRegistry:
632
+ """Get the global UnifiedAgentRegistry instance."""
633
+ global _agent_registry
634
+ if _agent_registry is None:
635
+ _agent_registry = UnifiedAgentRegistry()
636
+ return _agent_registry
637
+
638
+
639
+ # Convenience functions for backward compatibility
640
+ def discover_agents() -> Dict[str, AgentMetadata]:
641
+ """Discover all agents."""
642
+ return get_agent_registry().discover_agents()
643
+
644
+
645
+ def list_agents(
646
+ tier: Optional[AgentTier] = None, agent_type: Optional[AgentType] = None
647
+ ) -> List[AgentMetadata]:
648
+ """List agents with optional filtering."""
649
+ return get_agent_registry().list_agents(tier=tier, agent_type=agent_type)
650
+
651
+
652
+ def get_agent(name: str) -> Optional[AgentMetadata]:
653
+ """Get agent metadata by name."""
654
+ return get_agent_registry().get_agent(name)
655
+
656
+
657
+ def get_core_agents() -> List[AgentMetadata]:
658
+ """Get all core framework agents."""
659
+ return get_agent_registry().get_core_agents()
660
+
661
+
662
+ def get_specialized_agents() -> List[AgentMetadata]:
663
+ """Get all specialized agents."""
664
+ return get_agent_registry().get_specialized_agents()
665
+
666
+
667
+ def get_project_agents() -> List[AgentMetadata]:
668
+ """Get all project-specific agents."""
669
+ return get_agent_registry().get_project_agents()
670
+
671
+
672
+ def get_agent_names() -> List[str]:
673
+ """Get list of all agent names."""
674
+ return get_agent_registry().get_agent_names()
675
+
676
+
677
+ def get_registry_stats() -> Dict[str, Any]:
678
+ """Get registry statistics."""
679
+ return get_agent_registry().get_registry_stats()
680
+
681
+
682
+ # Legacy function names for backward compatibility
683
+ def listAgents() -> List[str]:
684
+ """Legacy function: Get list of agent names."""
685
+ return get_agent_names()
686
+
687
+
688
+ def discover_agents_sync() -> Dict[str, AgentMetadata]:
689
+ """Legacy function: Synchronous agent discovery."""
690
+ return discover_agents()
691
+
692
+
693
+ def list_agents_all() -> List[AgentMetadata]:
694
+ """Legacy function: List all agents."""
695
+ return list_agents()
696
+
697
+
698
+ # ============================================================================
699
+ # Export All Public Symbols
700
+ # ============================================================================
701
+
702
+ __all__ = [
703
+ "UnifiedAgentRegistry",
704
+ "AgentMetadata",
705
+ "AgentTier",
706
+ "AgentType",
707
+ "AgentFormat",
708
+ "get_agent_registry",
709
+ "discover_agents",
710
+ "list_agents",
711
+ "get_agent",
712
+ "get_core_agents",
713
+ "get_specialized_agents",
714
+ "get_project_agents",
715
+ "get_agent_names",
716
+ "get_registry_stats",
717
+ # Legacy compatibility
718
+ "listAgents",
719
+ "discover_agents_sync",
720
+ "list_agents_all",
721
+ ]