claude-mpm 3.9.11__py3-none-any.whl → 4.0.4__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 (434) 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 +2 -2
  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 +330 -86
  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 +363 -220
  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 +124 -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/built/components/agent-inference.js +2 -0
  113. claude_mpm/dashboard/static/built/components/event-processor.js +2 -0
  114. claude_mpm/dashboard/static/built/components/event-viewer.js +2 -0
  115. claude_mpm/dashboard/static/built/components/export-manager.js +2 -0
  116. claude_mpm/dashboard/static/built/components/file-tool-tracker.js +2 -0
  117. claude_mpm/dashboard/static/built/components/hud-library-loader.js +2 -0
  118. claude_mpm/dashboard/static/built/components/hud-manager.js +2 -0
  119. claude_mpm/dashboard/static/built/components/hud-visualizer.js +2 -0
  120. claude_mpm/dashboard/static/built/components/module-viewer.js +2 -0
  121. claude_mpm/dashboard/static/built/components/session-manager.js +2 -0
  122. claude_mpm/dashboard/static/built/components/socket-manager.js +2 -0
  123. claude_mpm/dashboard/static/built/components/ui-state-manager.js +2 -0
  124. claude_mpm/dashboard/static/built/components/working-directory.js +2 -0
  125. claude_mpm/dashboard/static/built/dashboard.js +2 -0
  126. claude_mpm/dashboard/static/built/socket-client.js +2 -0
  127. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  128. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  129. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  130. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  131. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  132. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  133. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  134. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  135. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  136. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  137. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  138. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  139. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  140. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  141. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  142. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  143. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  144. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  145. claude_mpm/dashboard/static/js/components/event-viewer.js +93 -72
  146. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  147. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +110 -96
  148. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  149. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  150. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  151. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  152. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  153. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  154. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  155. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  156. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  157. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  158. claude_mpm/dashboard/static/js/socket-client.js +133 -53
  159. claude_mpm/dashboard/templates/index.html +40 -50
  160. claude_mpm/experimental/cli_enhancements.py +60 -58
  161. claude_mpm/generators/__init__.py +1 -1
  162. claude_mpm/generators/agent_profile_generator.py +75 -65
  163. claude_mpm/hooks/__init__.py +1 -1
  164. claude_mpm/hooks/base_hook.py +33 -28
  165. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  166. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  167. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  168. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  169. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  170. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  171. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  172. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  173. claude_mpm/hooks/memory_integration_hook.py +140 -100
  174. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  175. claude_mpm/hooks/validation_hooks.py +57 -49
  176. claude_mpm/init.py +145 -121
  177. claude_mpm/models/__init__.py +9 -9
  178. claude_mpm/models/agent_definition.py +33 -23
  179. claude_mpm/models/agent_session.py +228 -200
  180. claude_mpm/scripts/__init__.py +1 -1
  181. claude_mpm/scripts/socketio_daemon.py +192 -75
  182. claude_mpm/scripts/socketio_server_manager.py +328 -0
  183. claude_mpm/scripts/start_activity_logging.py +25 -22
  184. claude_mpm/services/__init__.py +68 -43
  185. claude_mpm/services/agent_capabilities_service.py +271 -0
  186. claude_mpm/services/agents/__init__.py +23 -32
  187. claude_mpm/services/agents/deployment/__init__.py +3 -3
  188. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  189. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  190. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  191. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  192. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  193. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  194. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  195. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  196. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  197. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  198. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  199. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  200. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  201. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  202. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  203. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  204. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  205. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  206. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  207. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  208. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  209. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  210. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  211. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  212. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  213. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  214. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  215. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  216. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  217. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  218. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  219. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  220. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  221. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  222. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  223. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  224. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  225. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  226. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  227. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  228. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  229. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  230. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  231. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  232. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  233. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  234. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  235. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  236. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  237. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  238. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  239. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  240. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  241. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  242. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  243. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  244. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  245. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  246. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  247. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  248. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  249. claude_mpm/services/agents/loading/__init__.py +2 -2
  250. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  251. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  252. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  253. claude_mpm/services/agents/management/__init__.py +2 -2
  254. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  255. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  256. claude_mpm/services/agents/memory/__init__.py +9 -6
  257. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  258. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  259. claude_mpm/services/agents/memory/analyzer.py +430 -0
  260. claude_mpm/services/agents/memory/content_manager.py +376 -0
  261. claude_mpm/services/agents/memory/template_generator.py +468 -0
  262. claude_mpm/services/agents/registry/__init__.py +7 -10
  263. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  264. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  265. claude_mpm/services/async_session_logger.py +187 -153
  266. claude_mpm/services/claude_session_logger.py +87 -72
  267. claude_mpm/services/command_handler_service.py +217 -0
  268. claude_mpm/services/communication/__init__.py +3 -2
  269. claude_mpm/services/core/__init__.py +50 -97
  270. claude_mpm/services/core/base.py +60 -53
  271. claude_mpm/services/core/interfaces/__init__.py +188 -0
  272. claude_mpm/services/core/interfaces/agent.py +351 -0
  273. claude_mpm/services/core/interfaces/communication.py +343 -0
  274. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  275. claude_mpm/services/core/interfaces/service.py +434 -0
  276. claude_mpm/services/core/interfaces.py +19 -944
  277. claude_mpm/services/event_aggregator.py +208 -170
  278. claude_mpm/services/exceptions.py +387 -308
  279. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  280. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  281. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  282. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  283. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  284. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  285. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  286. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  287. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  288. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  289. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  290. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  291. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  292. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  293. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  294. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  295. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  296. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  297. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  298. claude_mpm/services/hook_service.py +106 -114
  299. claude_mpm/services/infrastructure/__init__.py +7 -5
  300. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  301. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  302. claude_mpm/services/infrastructure/logging.py +83 -76
  303. claude_mpm/services/infrastructure/monitoring.py +547 -404
  304. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  305. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  306. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  307. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  308. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  309. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  310. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  311. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  312. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  313. claude_mpm/services/mcp_gateway/main.py +287 -137
  314. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  315. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  316. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  317. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  318. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  319. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  320. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  321. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  322. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  323. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  324. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  325. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  326. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  327. claude_mpm/services/memory/__init__.py +2 -2
  328. claude_mpm/services/memory/builder.py +451 -362
  329. claude_mpm/services/memory/cache/__init__.py +2 -2
  330. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  331. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  332. claude_mpm/services/memory/indexed_memory.py +195 -193
  333. claude_mpm/services/memory/optimizer.py +267 -234
  334. claude_mpm/services/memory/router.py +571 -263
  335. claude_mpm/services/memory_hook_service.py +237 -0
  336. claude_mpm/services/port_manager.py +575 -0
  337. claude_mpm/services/project/__init__.py +3 -3
  338. claude_mpm/services/project/analyzer.py +451 -305
  339. claude_mpm/services/project/registry.py +262 -240
  340. claude_mpm/services/recovery_manager.py +287 -231
  341. claude_mpm/services/response_tracker.py +87 -67
  342. claude_mpm/services/runner_configuration_service.py +587 -0
  343. claude_mpm/services/session_management_service.py +304 -0
  344. claude_mpm/services/socketio/__init__.py +4 -4
  345. claude_mpm/services/socketio/client_proxy.py +174 -0
  346. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  347. claude_mpm/services/socketio/handlers/base.py +44 -30
  348. claude_mpm/services/socketio/handlers/connection.py +166 -64
  349. claude_mpm/services/socketio/handlers/file.py +123 -108
  350. claude_mpm/services/socketio/handlers/git.py +607 -373
  351. claude_mpm/services/socketio/handlers/hook.py +185 -0
  352. claude_mpm/services/socketio/handlers/memory.py +4 -4
  353. claude_mpm/services/socketio/handlers/project.py +4 -4
  354. claude_mpm/services/socketio/handlers/registry.py +53 -38
  355. claude_mpm/services/socketio/server/__init__.py +18 -0
  356. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  357. claude_mpm/services/socketio/server/core.py +399 -0
  358. claude_mpm/services/socketio/server/main.py +323 -0
  359. claude_mpm/services/socketio_client_manager.py +160 -133
  360. claude_mpm/services/socketio_server.py +36 -1885
  361. claude_mpm/services/subprocess_launcher_service.py +316 -0
  362. claude_mpm/services/system_instructions_service.py +258 -0
  363. claude_mpm/services/ticket_manager.py +19 -533
  364. claude_mpm/services/utility_service.py +285 -0
  365. claude_mpm/services/version_control/__init__.py +18 -21
  366. claude_mpm/services/version_control/branch_strategy.py +20 -10
  367. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  368. claude_mpm/services/version_control/git_operations.py +52 -21
  369. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  370. claude_mpm/services/version_control/version_parser.py +145 -125
  371. claude_mpm/services/version_service.py +270 -0
  372. claude_mpm/storage/__init__.py +2 -2
  373. claude_mpm/storage/state_storage.py +177 -181
  374. claude_mpm/ticket_wrapper.py +2 -2
  375. claude_mpm/utils/__init__.py +2 -2
  376. claude_mpm/utils/agent_dependency_loader.py +453 -243
  377. claude_mpm/utils/config_manager.py +157 -118
  378. claude_mpm/utils/console.py +1 -1
  379. claude_mpm/utils/dependency_cache.py +102 -107
  380. claude_mpm/utils/dependency_manager.py +52 -47
  381. claude_mpm/utils/dependency_strategies.py +131 -96
  382. claude_mpm/utils/environment_context.py +110 -102
  383. claude_mpm/utils/error_handler.py +75 -55
  384. claude_mpm/utils/file_utils.py +80 -67
  385. claude_mpm/utils/framework_detection.py +12 -11
  386. claude_mpm/utils/import_migration_example.py +12 -60
  387. claude_mpm/utils/imports.py +48 -45
  388. claude_mpm/utils/path_operations.py +100 -93
  389. claude_mpm/utils/robust_installer.py +172 -164
  390. claude_mpm/utils/session_logging.py +30 -23
  391. claude_mpm/utils/subprocess_utils.py +99 -61
  392. claude_mpm/validation/__init__.py +1 -1
  393. claude_mpm/validation/agent_validator.py +151 -111
  394. claude_mpm/validation/frontmatter_validator.py +92 -71
  395. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/METADATA +90 -22
  396. claude_mpm-4.0.4.dist-info/RECORD +417 -0
  397. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/entry_points.txt +1 -0
  398. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/licenses/LICENSE +1 -1
  399. claude_mpm/cli/commands/run_guarded.py +0 -511
  400. claude_mpm/config/memory_guardian_config.py +0 -325
  401. claude_mpm/config/memory_guardian_yaml.py +0 -335
  402. claude_mpm/core/config_paths.py +0 -150
  403. claude_mpm/core/memory_aware_runner.py +0 -353
  404. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  405. claude_mpm/deployment_paths.py +0 -261
  406. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  407. claude_mpm/models/state_models.py +0 -433
  408. claude_mpm/services/agent/__init__.py +0 -24
  409. claude_mpm/services/agent/deployment.py +0 -2548
  410. claude_mpm/services/agent/management.py +0 -598
  411. claude_mpm/services/agent/registry.py +0 -813
  412. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  413. claude_mpm/services/communication/socketio.py +0 -1935
  414. claude_mpm/services/communication/websocket.py +0 -479
  415. claude_mpm/services/framework_claude_md_generator.py +0 -624
  416. claude_mpm/services/health_monitor.py +0 -893
  417. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  418. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  419. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  420. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  421. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  422. claude_mpm/services/infrastructure/state_manager.py +0 -774
  423. claude_mpm/services/mcp_gateway/manager.py +0 -334
  424. claude_mpm/services/optimized_hook_service.py +0 -542
  425. claude_mpm/services/project_analyzer.py +0 -864
  426. claude_mpm/services/project_registry.py +0 -608
  427. claude_mpm/services/standalone_socketio_server.py +0 -1300
  428. claude_mpm/services/ticket_manager_di.py +0 -318
  429. claude_mpm/services/ticketing_service_original.py +0 -510
  430. claude_mpm/utils/paths.py +0 -395
  431. claude_mpm/utils/platform_memory.py +0 -524
  432. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  433. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.dist-info}/WHEEL +0 -0
  434. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.4.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
+ ]