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
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  #!/usr/bin/env python3
2
4
  """
3
5
  Agent Lifecycle Manager - ISS-0118 Integration Service
@@ -25,38 +27,37 @@ Created for ISS-0118: Agent Registry and Hierarchical Discovery System
25
27
  """
26
28
 
27
29
  import asyncio
28
- import logging
29
30
  import time
30
31
  from dataclasses import dataclass, field
31
32
  from datetime import datetime, timedelta
32
33
  from enum import Enum
33
- from pathlib import Path
34
- from typing import Dict, List, Optional, Set, Any, Tuple, Union
34
+ from typing import Any, Dict, List, Optional, Set, Tuple, Union
35
35
 
36
- from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
37
- from claude_mpm.services.agents.registry import AgentRegistry, AgentMetadata
38
- from claude_mpm.services.agents.registry.modification_tracker import (
39
- AgentModificationTracker,
40
- AgentModification,
41
- ModificationType,
42
- ModificationTier
43
- )
36
+ from claude_mpm.core.base_service import BaseService
37
+ from claude_mpm.core.unified_paths import get_path_manager
38
+ from claude_mpm.models.agent_definition import AgentDefinition, AgentType
39
+ from claude_mpm.services.agents.management import AgentManager
44
40
  from claude_mpm.services.agents.memory import (
45
41
  AgentPersistenceService,
46
- PersistenceStrategy,
42
+ PersistenceOperation,
47
43
  PersistenceRecord,
48
- PersistenceOperation
44
+ PersistenceStrategy,
49
45
  )
50
- from claude_mpm.services.agents.management import AgentManager
51
- from claude_mpm.models.agent_definition import AgentDefinition, AgentType
52
- from claude_mpm.core.base_service import BaseService
53
- from claude_mpm.core.config_paths import ConfigPaths
54
- from claude_mpm.utils.path_operations import path_ops
46
+ from claude_mpm.services.agents.registry import AgentMetadata, AgentRegistry
47
+ from claude_mpm.services.agents.registry.modification_tracker import (
48
+ AgentModification,
49
+ AgentModificationTracker,
50
+ ModificationTier,
51
+ ModificationType,
52
+ )
53
+ from claude_mpm.services.memory.cache.shared_prompt_cache import SharedPromptCache
55
54
  from claude_mpm.utils.config_manager import ConfigurationManager
55
+ from claude_mpm.utils.path_operations import path_ops
56
56
 
57
57
 
58
58
  class LifecycleOperation(Enum):
59
59
  """Agent lifecycle operations."""
60
+
60
61
  CREATE = "create"
61
62
  UPDATE = "update"
62
63
  DELETE = "delete"
@@ -68,6 +69,7 @@ class LifecycleOperation(Enum):
68
69
 
69
70
  class LifecycleState(Enum):
70
71
  """Agent lifecycle states."""
72
+
71
73
  ACTIVE = "active"
72
74
  MODIFIED = "modified"
73
75
  DELETED = "deleted"
@@ -79,7 +81,7 @@ class LifecycleState(Enum):
79
81
  @dataclass
80
82
  class AgentLifecycleRecord:
81
83
  """Complete lifecycle record for an agent."""
82
-
84
+
83
85
  agent_name: str
84
86
  current_state: LifecycleState
85
87
  tier: ModificationTier
@@ -93,12 +95,12 @@ class AgentLifecycleRecord:
93
95
  validation_status: str = "valid"
94
96
  validation_errors: List[str] = field(default_factory=list)
95
97
  metadata: Dict[str, Any] = field(default_factory=dict)
96
-
98
+
97
99
  @property
98
100
  def age_days(self) -> float:
99
101
  """Get age in days."""
100
102
  return (time.time() - self.created_at) / (24 * 3600)
101
-
103
+
102
104
  @property
103
105
  def last_modified_datetime(self) -> datetime:
104
106
  """Get last modified as datetime."""
@@ -108,7 +110,7 @@ class AgentLifecycleRecord:
108
110
  @dataclass
109
111
  class LifecycleOperationResult:
110
112
  """Result of a lifecycle operation."""
111
-
113
+
112
114
  operation: LifecycleOperation
113
115
  agent_name: str
114
116
  success: bool
@@ -124,7 +126,7 @@ class LifecycleOperationResult:
124
126
  class AgentLifecycleManager(BaseService):
125
127
  """
126
128
  Agent Lifecycle Manager - Unified agent management across hierarchy tiers.
127
-
129
+
128
130
  Features:
129
131
  - Complete agent lifecycle management (CRUD operations)
130
132
  - Integrated modification tracking and persistence
@@ -133,132 +135,117 @@ class AgentLifecycleManager(BaseService):
133
135
  - Real-time conflict detection and resolution
134
136
  - Performance monitoring and optimization
135
137
  """
136
-
138
+
137
139
  def __init__(self, config: Optional[Dict[str, Any]] = None):
138
140
  """Initialize the agent lifecycle manager."""
139
141
  super().__init__("agent_lifecycle_manager", config)
140
-
142
+
141
143
  # Configuration
142
144
  self.enable_auto_backup = self.get_config("enable_auto_backup", True)
143
145
  self.enable_auto_validation = self.get_config("enable_auto_validation", True)
144
- self.enable_cache_invalidation = self.get_config("enable_cache_invalidation", True)
146
+ self.enable_cache_invalidation = self.get_config(
147
+ "enable_cache_invalidation", True
148
+ )
145
149
  self.enable_registry_sync = self.get_config("enable_registry_sync", True)
146
150
  self.default_persistence_strategy = PersistenceStrategy(
147
- self.get_config("default_persistence_strategy", PersistenceStrategy.USER_OVERRIDE.value)
151
+ self.get_config(
152
+ "default_persistence_strategy", PersistenceStrategy.USER_OVERRIDE.value
153
+ )
148
154
  )
149
-
155
+
150
156
  # Core services
151
157
  self.shared_cache: Optional[SharedPromptCache] = None
152
158
  self.agent_registry: Optional[AgentRegistry] = None
153
159
  self.modification_tracker: Optional[AgentModificationTracker] = None
154
160
  self.persistence_service: Optional[AgentPersistenceService] = None
155
161
  self.agent_manager: Optional[AgentManager] = None
156
-
162
+
157
163
  # Lifecycle tracking
158
164
  self.agent_records: Dict[str, AgentLifecycleRecord] = {}
159
165
  self.operation_history: List[LifecycleOperationResult] = []
160
166
  self.active_operations: Dict[str, LifecycleOperation] = {}
161
-
167
+
162
168
  # Performance metrics
163
169
  self.performance_metrics = {
164
- 'total_operations': 0,
165
- 'successful_operations': 0,
166
- 'failed_operations': 0,
167
- 'average_duration_ms': 0.0,
168
- 'cache_hit_rate': 0.0
170
+ "total_operations": 0,
171
+ "successful_operations": 0,
172
+ "failed_operations": 0,
173
+ "average_duration_ms": 0.0,
174
+ "cache_hit_rate": 0.0,
169
175
  }
170
-
176
+
171
177
  # Operation lock for thread safety
172
178
  self._operation_lock = asyncio.Lock()
173
-
179
+
174
180
  # Configuration manager
175
181
  self.config_mgr = ConfigurationManager(cache_enabled=True)
176
-
182
+
177
183
  self.logger.info("AgentLifecycleManager initialized")
178
-
184
+
179
185
  async def _initialize(self) -> None:
180
186
  """Initialize the lifecycle manager."""
181
187
  self.logger.info("Initializing AgentLifecycleManager...")
182
-
188
+
183
189
  # Initialize core services
184
190
  await self._initialize_core_services()
185
-
191
+
186
192
  # Load existing agent records
187
193
  await self._load_agent_records()
188
-
194
+
189
195
  # Start service integrations
190
196
  await self._setup_service_integrations()
191
-
197
+
192
198
  # Perform initial registry sync
193
199
  if self.enable_registry_sync:
194
200
  await self._sync_with_registry()
195
-
201
+
196
202
  self.logger.info("AgentLifecycleManager initialized successfully")
197
-
203
+
198
204
  async def _cleanup(self) -> None:
199
205
  """Cleanup lifecycle manager resources."""
200
206
  self.logger.info("Cleaning up AgentLifecycleManager...")
201
-
207
+
202
208
  # Save agent records
203
209
  await self._save_agent_records()
204
-
210
+
205
211
  # Stop core services if we own them
206
212
  await self._cleanup_core_services()
207
-
213
+
208
214
  self.logger.info("AgentLifecycleManager cleaned up")
209
-
215
+
210
216
  async def _health_check(self) -> Dict[str, bool]:
211
217
  """Perform lifecycle manager health checks."""
212
- checks = {}
213
-
214
- try:
215
- # Check core service availability
216
- checks["cache_service"] = self.shared_cache is not None
217
- checks["registry_service"] = self.agent_registry is not None
218
- checks["tracker_service"] = self.modification_tracker is not None
219
- checks["persistence_service"] = self.persistence_service is not None
220
-
221
- # Check operation capabilities
222
- checks["can_create_agents"] = await self._test_create_capability()
223
- checks["can_modify_agents"] = await self._test_modify_capability()
224
- checks["can_delete_agents"] = await self._test_delete_capability()
225
-
226
- # Check data integrity
227
- checks["agent_records_valid"] = len(self.agent_records) >= 0
228
- checks["operation_history_valid"] = len(self.operation_history) >= 0
229
-
230
- except Exception as e:
231
- self.logger.error(f"Lifecycle manager health check failed: {e}")
232
- checks["health_check_error"] = False
233
-
234
- return checks
235
-
218
+ from .lifecycle_health_checker import LifecycleHealthChecker
219
+
220
+ checker = LifecycleHealthChecker(self)
221
+ return await checker.perform_health_check()
222
+
236
223
  async def _initialize_core_services(self) -> None:
237
224
  """Initialize core service dependencies."""
238
225
  try:
239
226
  # Initialize SharedPromptCache
240
227
  self.shared_cache = SharedPromptCache.get_instance()
241
-
228
+
242
229
  # Initialize AgentRegistry
243
230
  self.agent_registry = AgentRegistry(cache_service=self.shared_cache)
244
-
231
+
245
232
  # Initialize AgentModificationTracker
246
233
  self.modification_tracker = AgentModificationTracker()
247
234
  await self.modification_tracker.start()
248
-
235
+
249
236
  # Initialize AgentPersistenceService
250
237
  self.persistence_service = AgentPersistenceService()
251
238
  await self.persistence_service.start()
252
-
239
+
253
240
  # Initialize AgentManager
254
241
  self.agent_manager = AgentManager()
255
-
242
+
256
243
  self.logger.info("Core services initialized successfully")
257
-
244
+
258
245
  except Exception as e:
259
246
  self.logger.error(f"Failed to initialize core services: {e}")
260
247
  raise
261
-
248
+
262
249
  async def _setup_service_integrations(self) -> None:
263
250
  """Set up integrations between services."""
264
251
  try:
@@ -267,79 +254,83 @@ class AgentLifecycleManager(BaseService):
267
254
  self.modification_tracker.register_modification_callback(
268
255
  self._handle_modification_event
269
256
  )
270
-
257
+
271
258
  self.logger.debug("Service integrations set up successfully")
272
-
259
+
273
260
  except Exception as e:
274
261
  self.logger.warning(f"Failed to setup some service integrations: {e}")
275
-
262
+
276
263
  async def _load_agent_records(self) -> None:
277
264
  """Load existing agent lifecycle records."""
278
265
  try:
279
- records_file = ConfigPaths.get_tracking_dir() / 'lifecycle_records.json'
266
+ records_file = (
267
+ get_path_manager().get_tracking_dir() / "lifecycle_records.json"
268
+ )
280
269
  if path_ops.validate_exists(records_file):
281
270
  data = self.config_mgr.load_json(records_file)
282
-
271
+
283
272
  for agent_name, record_data in data.items():
284
273
  record = AgentLifecycleRecord(**record_data)
285
274
  # Convert string enum back to enum
286
- record.current_state = LifecycleState(record_data['current_state'])
287
- record.tier = ModificationTier(record_data['tier'])
275
+ record.current_state = LifecycleState(record_data["current_state"])
276
+ record.tier = ModificationTier(record_data["tier"])
288
277
  self.agent_records[agent_name] = record
289
-
278
+
290
279
  self.logger.info(f"Loaded {len(self.agent_records)} agent records")
291
-
280
+
292
281
  except Exception as e:
293
282
  self.logger.warning(f"Failed to load agent records: {e}")
294
-
283
+
295
284
  async def _save_agent_records(self) -> None:
296
285
  """Save agent lifecycle records to disk."""
297
286
  try:
298
- records_file = ConfigPaths.get_tracking_dir() / 'lifecycle_records.json'
287
+ records_file = (
288
+ get_path_manager().get_tracking_dir() / "lifecycle_records.json"
289
+ )
299
290
  path_ops.ensure_dir(records_file.parent)
300
-
291
+
301
292
  data = {}
302
293
  for agent_name, record in self.agent_records.items():
303
294
  record_dict = record.__dict__.copy()
304
295
  # Convert enums to strings for JSON serialization
305
- record_dict['current_state'] = record.current_state.value
306
- record_dict['tier'] = record.tier.value
296
+ record_dict["current_state"] = record.current_state.value
297
+ record_dict["tier"] = record.tier.value
307
298
  data[agent_name] = record_dict
308
-
299
+
309
300
  # Use save_json with custom encoder for datetime serialization
310
301
  import json
311
-
302
+
312
303
  # First convert to JSON string with custom encoder, then save
313
304
  json_str = json.dumps(data, indent=2, default=str)
314
305
  records_file.parent.mkdir(parents=True, exist_ok=True)
315
- with open(records_file, 'w', encoding='utf-8') as f:
306
+ with open(records_file, "w", encoding="utf-8") as f:
316
307
  f.write(json_str)
317
-
308
+
318
309
  self.logger.debug(f"Saved {len(self.agent_records)} agent records")
319
-
310
+
320
311
  except Exception as e:
321
312
  self.logger.error(f"Failed to save agent records: {e}")
322
-
313
+
323
314
  async def _sync_with_registry(self) -> None:
324
315
  """Synchronize with agent registry."""
325
316
  try:
326
317
  if not self.agent_registry:
327
318
  return
328
-
319
+
329
320
  # Discover all agents via registry (sync methods)
330
321
  self.agent_registry.discover_agents()
331
322
  all_agents = self.agent_registry.list_agents()
332
-
323
+
333
324
  # Update lifecycle records with registry data
334
325
  for agent_metadata in all_agents:
335
326
  if agent_metadata.name not in self.agent_records:
336
327
  # Create new lifecycle record
337
328
  tier_map = {
338
- 'project': ModificationTier.PROJECT,
339
- 'user': ModificationTier.USER,
340
- 'system': ModificationTier.SYSTEM
329
+ "project": ModificationTier.PROJECT,
330
+ "user": ModificationTier.USER,
331
+ "system": ModificationTier.SYSTEM,
341
332
  }
342
-
333
+
343
334
  record = AgentLifecycleRecord(
344
335
  agent_name=agent_metadata.name,
345
336
  current_state=LifecycleState.ACTIVE,
@@ -349,44 +340,46 @@ class AgentLifecycleManager(BaseService):
349
340
  last_modified=agent_metadata.last_modified or time.time(),
350
341
  version="1.0.0",
351
342
  metadata={
352
- 'type': agent_metadata.type,
353
- 'description': agent_metadata.description,
354
- 'capabilities': agent_metadata.capabilities,
355
- 'validated': agent_metadata.validated
356
- }
343
+ "type": agent_metadata.type,
344
+ "description": agent_metadata.description,
345
+ "capabilities": agent_metadata.capabilities,
346
+ "validated": agent_metadata.validated,
347
+ },
357
348
  )
358
-
349
+
359
350
  self.agent_records[agent_metadata.name] = record
360
-
351
+
361
352
  self.logger.info(f"Synchronized with registry: {len(all_agents)} agents")
362
-
353
+
363
354
  except Exception as e:
364
355
  self.logger.error(f"Failed to sync with registry: {e}")
365
-
366
- async def create_agent(self,
367
- agent_name: str,
368
- agent_content: str,
369
- tier: ModificationTier = ModificationTier.USER,
370
- agent_type: str = "custom",
371
- **kwargs) -> LifecycleOperationResult:
356
+
357
+ async def create_agent(
358
+ self,
359
+ agent_name: str,
360
+ agent_content: str,
361
+ tier: ModificationTier = ModificationTier.USER,
362
+ agent_type: str = "custom",
363
+ **kwargs,
364
+ ) -> LifecycleOperationResult:
372
365
  """
373
366
  Create a new agent with complete lifecycle tracking.
374
-
367
+
375
368
  Args:
376
369
  agent_name: Name of the agent to create
377
370
  agent_content: Content of the agent file
378
371
  tier: Target tier for creation
379
372
  agent_type: Type of agent (for classification)
380
373
  **kwargs: Additional metadata
381
-
374
+
382
375
  Returns:
383
376
  LifecycleOperationResult with operation details
384
377
  """
385
378
  start_time = time.time()
386
-
379
+
387
380
  async with self._operation_lock:
388
381
  self.active_operations[agent_name] = LifecycleOperation.CREATE
389
-
382
+
390
383
  try:
391
384
  # Check if agent already exists
392
385
  if agent_name in self.agent_records:
@@ -395,27 +388,33 @@ class AgentLifecycleManager(BaseService):
395
388
  agent_name=agent_name,
396
389
  success=False,
397
390
  duration_ms=(time.time() - start_time) * 1000,
398
- error_message="Agent already exists"
391
+ error_message="Agent already exists",
399
392
  )
400
-
393
+
401
394
  # Create agent definition
402
395
  agent_def = await self._create_agent_definition(
403
396
  agent_name, agent_content, tier, agent_type, **kwargs
404
397
  )
405
-
398
+
406
399
  # Determine location based on tier
407
- location = "project" if tier == ModificationTier.PROJECT else "framework"
408
-
400
+ location = (
401
+ "project" if tier == ModificationTier.PROJECT else "framework"
402
+ )
403
+
409
404
  # Create agent using AgentManager (sync call in executor)
410
405
  try:
411
406
  if self.agent_manager:
412
407
  file_path = await self._run_sync_in_executor(
413
408
  self.agent_manager.create_agent,
414
- agent_name, agent_def, location
409
+ agent_name,
410
+ agent_def,
411
+ location,
415
412
  )
416
413
  else:
417
414
  # Fallback to direct file creation if AgentManager not available
418
- file_path = await self._determine_agent_file_path(agent_name, tier)
415
+ file_path = await self._determine_agent_file_path(
416
+ agent_name, tier
417
+ )
419
418
  path_ops.ensure_dir(file_path.parent)
420
419
  path_ops.safe_write(file_path, agent_content)
421
420
  except Exception as e:
@@ -424,7 +423,7 @@ class AgentLifecycleManager(BaseService):
424
423
  file_path = await self._determine_agent_file_path(agent_name, tier)
425
424
  path_ops.ensure_dir(file_path.parent)
426
425
  path_ops.safe_write(file_path, agent_content)
427
-
426
+
428
427
  # Track modification
429
428
  modification = await self.modification_tracker.track_modification(
430
429
  agent_name=agent_name,
@@ -432,9 +431,9 @@ class AgentLifecycleManager(BaseService):
432
431
  file_path=str(file_path),
433
432
  tier=tier,
434
433
  agent_type=agent_type,
435
- **kwargs
434
+ **kwargs,
436
435
  )
437
-
436
+
438
437
  # Note: We don't use persistence_service for the actual write anymore
439
438
  # since AgentManager handles that. We create a synthetic record for compatibility.
440
439
  persistence_record = PersistenceRecord(
@@ -446,9 +445,9 @@ class AgentLifecycleManager(BaseService):
446
445
  strategy=self.default_persistence_strategy,
447
446
  success=True,
448
447
  timestamp=time.time(),
449
- file_path=str(file_path)
448
+ file_path=str(file_path),
450
449
  )
451
-
450
+
452
451
  # Create lifecycle record
453
452
  lifecycle_record = AgentLifecycleRecord(
454
453
  agent_name=agent_name,
@@ -460,18 +459,15 @@ class AgentLifecycleManager(BaseService):
460
459
  version="1.0.0",
461
460
  modifications=[modification.modification_id],
462
461
  persistence_operations=[persistence_record.operation_id],
463
- metadata={
464
- 'agent_type': agent_type,
465
- **kwargs
466
- }
462
+ metadata={"agent_type": agent_type, **kwargs},
467
463
  )
468
-
464
+
469
465
  self.agent_records[agent_name] = lifecycle_record
470
-
466
+
471
467
  # Invalidate cache and update registry
472
468
  cache_invalidated = await self._invalidate_agent_cache(agent_name)
473
469
  registry_updated = await self._update_registry(agent_name)
474
-
470
+
475
471
  # Create result
476
472
  result = LifecycleOperationResult(
477
473
  operation=LifecycleOperation.CREATE,
@@ -482,59 +478,60 @@ class AgentLifecycleManager(BaseService):
482
478
  persistence_id=persistence_record.operation_id,
483
479
  cache_invalidated=cache_invalidated,
484
480
  registry_updated=registry_updated,
485
- metadata={'file_path': str(file_path)}
481
+ metadata={"file_path": str(file_path)},
486
482
  )
487
-
483
+
488
484
  if not persistence_record.success:
489
485
  result.error_message = persistence_record.error_message
490
486
  lifecycle_record.current_state = LifecycleState.CONFLICTED
491
-
487
+
492
488
  # Update performance metrics
493
489
  await self._update_performance_metrics(result)
494
-
490
+
495
491
  self.operation_history.append(result)
496
- self.logger.info(f"Created agent '{agent_name}' in {result.duration_ms:.1f}ms")
497
-
492
+ self.logger.info(
493
+ f"Created agent '{agent_name}' in {result.duration_ms:.1f}ms"
494
+ )
495
+
498
496
  return result
499
-
497
+
500
498
  except Exception as e:
501
499
  result = LifecycleOperationResult(
502
500
  operation=LifecycleOperation.CREATE,
503
501
  agent_name=agent_name,
504
502
  success=False,
505
503
  duration_ms=(time.time() - start_time) * 1000,
506
- error_message=str(e)
504
+ error_message=str(e),
507
505
  )
508
-
506
+
509
507
  self.operation_history.append(result)
510
508
  await self._update_performance_metrics(result)
511
-
509
+
512
510
  self.logger.error(f"Failed to create agent '{agent_name}': {e}")
513
511
  return result
514
-
512
+
515
513
  finally:
516
514
  self.active_operations.pop(agent_name, None)
517
-
518
- async def update_agent(self,
519
- agent_name: str,
520
- agent_content: str,
521
- **kwargs) -> LifecycleOperationResult:
515
+
516
+ async def update_agent(
517
+ self, agent_name: str, agent_content: str, **kwargs
518
+ ) -> LifecycleOperationResult:
522
519
  """
523
520
  Update an existing agent with lifecycle tracking.
524
-
521
+
525
522
  Args:
526
523
  agent_name: Name of the agent to update
527
524
  agent_content: New content for the agent
528
525
  **kwargs: Additional metadata
529
-
526
+
530
527
  Returns:
531
528
  LifecycleOperationResult with operation details
532
529
  """
533
530
  start_time = time.time()
534
-
531
+
535
532
  async with self._operation_lock:
536
533
  self.active_operations[agent_name] = LifecycleOperation.UPDATE
537
-
534
+
538
535
  try:
539
536
  # Check if agent exists
540
537
  if agent_name not in self.agent_records:
@@ -543,11 +540,11 @@ class AgentLifecycleManager(BaseService):
543
540
  agent_name=agent_name,
544
541
  success=False,
545
542
  duration_ms=(time.time() - start_time) * 1000,
546
- error_message="Agent not found"
543
+ error_message="Agent not found",
547
544
  )
548
-
545
+
549
546
  record = self.agent_records[agent_name]
550
-
547
+
551
548
  # Update agent using AgentManager
552
549
  try:
553
550
  if self.agent_manager:
@@ -555,25 +552,31 @@ class AgentLifecycleManager(BaseService):
555
552
  current_def = await self._run_sync_in_executor(
556
553
  self.agent_manager.read_agent, agent_name
557
554
  )
558
-
555
+
559
556
  if current_def:
560
557
  # Update raw content
561
558
  current_def.raw_content = agent_content
562
-
559
+
563
560
  # Apply any metadata updates from kwargs
564
- if 'model_preference' in kwargs:
565
- current_def.metadata.model_preference = kwargs['model_preference']
566
- if 'tags' in kwargs:
567
- current_def.metadata.tags = kwargs['tags']
568
- if 'specializations' in kwargs:
569
- current_def.metadata.specializations = kwargs['specializations']
570
-
561
+ if "model_preference" in kwargs:
562
+ current_def.metadata.model_preference = kwargs[
563
+ "model_preference"
564
+ ]
565
+ if "tags" in kwargs:
566
+ current_def.metadata.tags = kwargs["tags"]
567
+ if "specializations" in kwargs:
568
+ current_def.metadata.specializations = kwargs[
569
+ "specializations"
570
+ ]
571
+
571
572
  # Update via AgentManager
572
573
  updated_def = await self._run_sync_in_executor(
573
574
  self.agent_manager.update_agent,
574
- agent_name, {"raw_content": agent_content}, True
575
+ agent_name,
576
+ {"raw_content": agent_content},
577
+ True,
575
578
  )
576
-
579
+
577
580
  if not updated_def:
578
581
  raise Exception("AgentManager update failed")
579
582
  else:
@@ -589,16 +592,16 @@ class AgentLifecycleManager(BaseService):
589
592
  file_path = Path(record.file_path)
590
593
  if path_ops.validate_exists(file_path):
591
594
  path_ops.safe_write(file_path, agent_content)
592
-
595
+
593
596
  # Track modification
594
597
  modification = await self.modification_tracker.track_modification(
595
598
  agent_name=agent_name,
596
599
  modification_type=ModificationType.MODIFY,
597
600
  file_path=record.file_path,
598
601
  tier=record.tier,
599
- **kwargs
602
+ **kwargs,
600
603
  )
601
-
604
+
602
605
  # Create synthetic persistence record for compatibility
603
606
  persistence_record = PersistenceRecord(
604
607
  operation_id=f"update_{agent_name}_{time.time()}",
@@ -609,24 +612,24 @@ class AgentLifecycleManager(BaseService):
609
612
  strategy=self.default_persistence_strategy,
610
613
  success=True,
611
614
  timestamp=time.time(),
612
- file_path=record.file_path
615
+ file_path=record.file_path,
613
616
  )
614
-
617
+
615
618
  # Update lifecycle record
616
619
  record.current_state = LifecycleState.MODIFIED
617
620
  record.last_modified = time.time()
618
621
  record.modifications.append(modification.modification_id)
619
622
  record.persistence_operations.append(persistence_record.operation_id)
620
-
623
+
621
624
  # Increment version
622
- current_version = record.version.split('.')
625
+ current_version = record.version.split(".")
623
626
  current_version[-1] = str(int(current_version[-1]) + 1)
624
- record.version = '.'.join(current_version)
625
-
627
+ record.version = ".".join(current_version)
628
+
626
629
  # Invalidate cache and update registry
627
630
  cache_invalidated = await self._invalidate_agent_cache(agent_name)
628
631
  registry_updated = await self._update_registry(agent_name)
629
-
632
+
630
633
  # Create result
631
634
  result = LifecycleOperationResult(
632
635
  operation=LifecycleOperation.UPDATE,
@@ -637,55 +640,57 @@ class AgentLifecycleManager(BaseService):
637
640
  persistence_id=persistence_record.operation_id,
638
641
  cache_invalidated=cache_invalidated,
639
642
  registry_updated=registry_updated,
640
- metadata={'new_version': record.version}
643
+ metadata={"new_version": record.version},
641
644
  )
642
-
645
+
643
646
  if not persistence_record.success:
644
647
  result.error_message = persistence_record.error_message
645
648
  record.current_state = LifecycleState.CONFLICTED
646
-
649
+
647
650
  # Update performance metrics
648
651
  await self._update_performance_metrics(result)
649
-
652
+
650
653
  self.operation_history.append(result)
651
- self.logger.info(f"Updated agent '{agent_name}' to version {record.version} in {result.duration_ms:.1f}ms")
652
-
654
+ self.logger.info(
655
+ f"Updated agent '{agent_name}' to version {record.version} in {result.duration_ms:.1f}ms"
656
+ )
657
+
653
658
  return result
654
-
659
+
655
660
  except Exception as e:
656
661
  result = LifecycleOperationResult(
657
662
  operation=LifecycleOperation.UPDATE,
658
663
  agent_name=agent_name,
659
664
  success=False,
660
665
  duration_ms=(time.time() - start_time) * 1000,
661
- error_message=str(e)
666
+ error_message=str(e),
662
667
  )
663
-
668
+
664
669
  self.operation_history.append(result)
665
670
  await self._update_performance_metrics(result)
666
-
671
+
667
672
  self.logger.error(f"Failed to update agent '{agent_name}': {e}")
668
673
  return result
669
-
674
+
670
675
  finally:
671
676
  self.active_operations.pop(agent_name, None)
672
-
677
+
673
678
  async def delete_agent(self, agent_name: str, **kwargs) -> LifecycleOperationResult:
674
679
  """
675
680
  Delete an agent with lifecycle tracking.
676
-
681
+
677
682
  Args:
678
683
  agent_name: Name of the agent to delete
679
684
  **kwargs: Additional metadata
680
-
685
+
681
686
  Returns:
682
687
  LifecycleOperationResult with operation details
683
688
  """
684
689
  start_time = time.time()
685
-
690
+
686
691
  async with self._operation_lock:
687
692
  self.active_operations[agent_name] = LifecycleOperation.DELETE
688
-
693
+
689
694
  try:
690
695
  # Check if agent exists
691
696
  if agent_name not in self.agent_records:
@@ -694,16 +699,16 @@ class AgentLifecycleManager(BaseService):
694
699
  agent_name=agent_name,
695
700
  success=False,
696
701
  duration_ms=(time.time() - start_time) * 1000,
697
- error_message="Agent not found"
702
+ error_message="Agent not found",
698
703
  )
699
-
704
+
700
705
  record = self.agent_records[agent_name]
701
-
706
+
702
707
  # Create backup before deletion
703
708
  backup_path = None
704
709
  if self.enable_auto_backup:
705
710
  backup_path = await self._create_deletion_backup(agent_name, record)
706
-
711
+
707
712
  # Track modification
708
713
  modification = await self.modification_tracker.track_modification(
709
714
  agent_name=agent_name,
@@ -711,9 +716,9 @@ class AgentLifecycleManager(BaseService):
711
716
  file_path=record.file_path,
712
717
  tier=record.tier,
713
718
  backup_path=backup_path,
714
- **kwargs
719
+ **kwargs,
715
720
  )
716
-
721
+
717
722
  # Delete agent using AgentManager
718
723
  deletion_success = False
719
724
  try:
@@ -736,18 +741,18 @@ class AgentLifecycleManager(BaseService):
736
741
  if path_ops.validate_exists(file_path):
737
742
  path_ops.safe_delete(file_path)
738
743
  deletion_success = True
739
-
744
+
740
745
  # Update lifecycle record
741
746
  record.current_state = LifecycleState.DELETED
742
747
  record.last_modified = time.time()
743
748
  record.modifications.append(modification.modification_id)
744
749
  if backup_path:
745
750
  record.backup_paths.append(backup_path)
746
-
751
+
747
752
  # Invalidate cache and update registry
748
753
  cache_invalidated = await self._invalidate_agent_cache(agent_name)
749
754
  registry_updated = await self._update_registry(agent_name)
750
-
755
+
751
756
  # Create result
752
757
  result = LifecycleOperationResult(
753
758
  operation=LifecycleOperation.DELETE,
@@ -757,414 +762,259 @@ class AgentLifecycleManager(BaseService):
757
762
  modification_id=modification.modification_id,
758
763
  cache_invalidated=cache_invalidated,
759
764
  registry_updated=registry_updated,
760
- metadata={'backup_path': backup_path}
765
+ metadata={"backup_path": backup_path},
761
766
  )
762
-
767
+
763
768
  # Update performance metrics
764
769
  await self._update_performance_metrics(result)
765
-
770
+
766
771
  self.operation_history.append(result)
767
- self.logger.info(f"Deleted agent '{agent_name}' in {result.duration_ms:.1f}ms")
768
-
772
+ self.logger.info(
773
+ f"Deleted agent '{agent_name}' in {result.duration_ms:.1f}ms"
774
+ )
775
+
769
776
  return result
770
-
777
+
771
778
  except Exception as e:
772
779
  result = LifecycleOperationResult(
773
780
  operation=LifecycleOperation.DELETE,
774
781
  agent_name=agent_name,
775
782
  success=False,
776
783
  duration_ms=(time.time() - start_time) * 1000,
777
- error_message=str(e)
784
+ error_message=str(e),
778
785
  )
779
-
786
+
780
787
  self.operation_history.append(result)
781
788
  await self._update_performance_metrics(result)
782
-
789
+
783
790
  self.logger.error(f"Failed to delete agent '{agent_name}': {e}")
784
791
  return result
785
-
792
+
786
793
  finally:
787
794
  self.active_operations.pop(agent_name, None)
788
-
789
- async def _determine_agent_file_path(self, agent_name: str, tier: ModificationTier) -> Path:
795
+
796
+ async def _determine_agent_file_path(
797
+ self, agent_name: str, tier: ModificationTier
798
+ ) -> Path:
790
799
  """Determine appropriate file path for agent."""
791
800
  if tier == ModificationTier.USER:
792
- base_path = ConfigPaths.get_user_agents_dir()
801
+ base_path = get_path_manager().get_user_agents_dir()
793
802
  elif tier == ModificationTier.PROJECT:
794
- base_path = ConfigPaths.get_project_agents_dir()
803
+ base_path = get_path_manager().get_project_agents_dir()
795
804
  else: # SYSTEM
796
- base_path = Path.cwd() / 'claude_pm' / 'agents'
797
-
805
+ base_path = Path.cwd() / "claude_pm" / "agents"
806
+
798
807
  path_ops.ensure_dir(base_path)
799
808
  return base_path / f"{agent_name}_agent.py"
800
-
801
- async def _create_deletion_backup(self, agent_name: str, record: AgentLifecycleRecord) -> Optional[str]:
809
+
810
+ async def _create_deletion_backup(
811
+ self, agent_name: str, record: AgentLifecycleRecord
812
+ ) -> Optional[str]:
802
813
  """Create backup before agent deletion."""
803
814
  try:
804
815
  source_path = Path(record.file_path)
805
816
  if not path_ops.validate_exists(source_path):
806
817
  return None
807
-
808
- backup_dir = ConfigPaths.get_tracking_dir() / 'backups'
818
+
819
+ backup_dir = get_path_manager().get_tracking_dir() / "backups"
809
820
  path_ops.ensure_dir(backup_dir)
810
-
811
- timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
821
+
822
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
812
823
  backup_filename = f"{agent_name}_deleted_{timestamp}{source_path.suffix}"
813
824
  backup_path = backup_dir / backup_filename
814
-
825
+
815
826
  path_ops.safe_copy(source_path, backup_path)
816
827
  return str(backup_path)
817
-
828
+
818
829
  except Exception as e:
819
- self.logger.warning(f"Failed to create deletion backup for {agent_name}: {e}")
830
+ self.logger.warning(
831
+ f"Failed to create deletion backup for {agent_name}: {e}"
832
+ )
820
833
  return None
821
-
834
+
822
835
  async def _invalidate_agent_cache(self, agent_name: str) -> bool:
823
836
  """Invalidate cache entries for agent."""
824
837
  if not self.enable_cache_invalidation or not self.shared_cache:
825
838
  return False
826
-
839
+
827
840
  try:
828
841
  patterns = [
829
842
  f"agent_profile:{agent_name}:*",
830
843
  f"task_prompt:{agent_name}:*",
831
844
  f"agent_registry_discovery",
832
- f"agent_profile_enhanced:{agent_name}:*"
845
+ f"agent_profile_enhanced:{agent_name}:*",
833
846
  ]
834
-
847
+
835
848
  for pattern in patterns:
836
849
  await asyncio.get_event_loop().run_in_executor(
837
- None,
838
- lambda p=pattern: self.shared_cache.invalidate(p)
850
+ None, lambda p=pattern: self.shared_cache.invalidate(p)
839
851
  )
840
-
852
+
841
853
  return True
842
-
854
+
843
855
  except Exception as e:
844
856
  self.logger.warning(f"Failed to invalidate cache for {agent_name}: {e}")
845
857
  return False
846
-
858
+
847
859
  async def _update_registry(self, agent_name: str) -> bool:
848
860
  """Update agent registry after modification."""
849
861
  if not self.enable_registry_sync or not self.agent_registry:
850
862
  return False
851
-
863
+
852
864
  try:
853
865
  # Refresh registry (discover_agents is synchronous)
854
866
  self.agent_registry.discover_agents()
855
867
  return True
856
-
868
+
857
869
  except Exception as e:
858
870
  self.logger.warning(f"Failed to update registry for {agent_name}: {e}")
859
871
  return False
860
-
861
- async def _update_performance_metrics(self, result: LifecycleOperationResult) -> None:
862
- """Update performance metrics with operation result.
863
-
864
- METRICS COLLECTION:
865
- This method demonstrates a simple ETL pipeline for operational metrics:
866
-
867
- 1. EXTRACT: Pull raw data from operation results
868
- - Success/failure status
869
- - Operation duration
870
- - Cache invalidation events
871
- - Operation type and agent tier
872
-
873
- 2. TRANSFORM: Calculate derived metrics
874
- - Success rates and failure percentages
875
- - Rolling averages for performance
876
- - Operation distribution by type
877
- - Performance by agent tier
878
-
879
- 3. LOAD: Store in metrics structure
880
- - In-memory storage for real-time access
881
- - Could be extended to push to:
882
- * Time-series databases (Prometheus, InfluxDB)
883
- * AI observability platforms (Datadog, New Relic)
884
- * Custom analytics pipelines
885
-
886
- OPTIMIZATION OPPORTUNITIES:
887
- - Add percentile calculations (p50, p95, p99)
888
- - Track operation queuing times
889
- - Monitor resource usage per operation
890
- - Implement sliding window metrics
891
- """
892
- self.performance_metrics['total_operations'] += 1
893
-
894
- if result.success:
895
- self.performance_metrics['successful_operations'] += 1
896
- else:
897
- self.performance_metrics['failed_operations'] += 1
898
-
899
- # Update average duration using incremental calculation
900
- # This avoids storing all durations in memory
901
- total_ops = self.performance_metrics['total_operations']
902
- current_avg = self.performance_metrics['average_duration_ms']
903
- new_avg = ((current_avg * (total_ops - 1)) + result.duration_ms) / total_ops
904
- self.performance_metrics['average_duration_ms'] = new_avg
905
-
906
- # METRICS: Track operation type distribution
907
- # This helps identify which operations are most common
908
- op_type = result.operation.value
909
- if 'operation_distribution' not in self.performance_metrics:
910
- self.performance_metrics['operation_distribution'] = {}
911
- self.performance_metrics['operation_distribution'][op_type] = \
912
- self.performance_metrics['operation_distribution'].get(op_type, 0) + 1
913
-
914
- # METRICS: Track performance by agent tier
915
- # Useful for identifying tier-specific performance issues
916
- if hasattr(result, 'tier') and result.tier:
917
- if 'tier_performance' not in self.performance_metrics:
918
- self.performance_metrics['tier_performance'] = {}
919
- tier_name = result.tier.value if hasattr(result.tier, 'value') else str(result.tier)
920
- if tier_name not in self.performance_metrics['tier_performance']:
921
- self.performance_metrics['tier_performance'][tier_name] = {
922
- 'count': 0,
923
- 'total_duration_ms': 0,
924
- 'average_duration_ms': 0
925
- }
926
- tier_metrics = self.performance_metrics['tier_performance'][tier_name]
927
- tier_metrics['count'] += 1
928
- tier_metrics['total_duration_ms'] += result.duration_ms
929
- tier_metrics['average_duration_ms'] = \
930
- tier_metrics['total_duration_ms'] / tier_metrics['count']
931
-
932
- # Update cache hit rate if cache was involved
933
- if result.cache_invalidated:
934
- # Track cache invalidation frequency
935
- if 'cache_invalidations' not in self.performance_metrics:
936
- self.performance_metrics['cache_invalidations'] = 0
937
- self.performance_metrics['cache_invalidations'] += 1
938
-
872
+
873
+ async def _update_performance_metrics(
874
+ self, result: LifecycleOperationResult
875
+ ) -> None:
876
+ """Update performance metrics with operation result."""
877
+ from .lifecycle_performance_tracker import LifecyclePerformanceTracker
878
+
879
+ tracker = LifecyclePerformanceTracker(self.performance_metrics)
880
+ tracker.update_metrics(result)
881
+
939
882
  async def _handle_modification_event(self, modification: AgentModification) -> None:
940
883
  """Handle modification events from tracker."""
941
884
  try:
942
885
  agent_name = modification.agent_name
943
-
886
+
944
887
  # Update lifecycle record if exists
945
888
  if agent_name in self.agent_records:
946
889
  record = self.agent_records[agent_name]
947
890
  record.last_modified = modification.timestamp
948
891
  record.modifications.append(modification.modification_id)
949
-
892
+
950
893
  # Update state based on modification type
951
894
  if modification.modification_type == ModificationType.DELETE:
952
895
  record.current_state = LifecycleState.DELETED
953
- elif modification.modification_type in [ModificationType.CREATE, ModificationType.MODIFY]:
896
+ elif modification.modification_type in [
897
+ ModificationType.CREATE,
898
+ ModificationType.MODIFY,
899
+ ]:
954
900
  record.current_state = LifecycleState.MODIFIED
955
-
956
- self.logger.debug(f"Updated lifecycle record for {agent_name} due to {modification.modification_type.value}")
957
-
901
+
902
+ self.logger.debug(
903
+ f"Updated lifecycle record for {agent_name} due to {modification.modification_type.value}"
904
+ )
905
+
958
906
  except Exception as e:
959
907
  self.logger.error(f"Error handling modification event: {e}")
960
-
961
- async def _test_create_capability(self) -> bool:
962
- """Test agent creation capability."""
963
- try:
964
- # This would test if we can create agents in the configured tiers
965
- return (self.modification_tracker is not None and
966
- self.persistence_service is not None)
967
- except Exception:
968
- return False
969
-
970
- async def _test_modify_capability(self) -> bool:
971
- """Test agent modification capability."""
972
- try:
973
- # This would test if we can modify existing agents
974
- return (self.modification_tracker is not None and
975
- self.persistence_service is not None)
976
- except Exception:
977
- return False
978
-
979
- async def _test_delete_capability(self) -> bool:
980
- """Test agent deletion capability."""
981
- try:
982
- # This would test if we can delete agents
983
- return self.modification_tracker is not None
984
- except Exception:
985
- return False
986
-
908
+
909
+ # Test capability methods moved to LifecycleHealthChecker
910
+
987
911
  async def _cleanup_core_services(self) -> None:
988
912
  """Cleanup core services if we manage their lifecycle."""
989
913
  try:
990
914
  if self.modification_tracker:
991
915
  await self.modification_tracker.stop()
992
-
916
+
993
917
  if self.persistence_service:
994
918
  await self.persistence_service.stop()
995
-
919
+
996
920
  except Exception as e:
997
921
  self.logger.error(f"Error cleaning up core services: {e}")
998
-
922
+
999
923
  # Public API Methods
1000
-
924
+
1001
925
  async def get_agent_status(self, agent_name: str) -> Optional[AgentLifecycleRecord]:
1002
926
  """Get current status of an agent."""
1003
927
  return self.agent_records.get(agent_name)
1004
-
1005
- async def list_agents(self, state_filter: Optional[LifecycleState] = None) -> List[AgentLifecycleRecord]:
928
+
929
+ async def list_agents(
930
+ self, state_filter: Optional[LifecycleState] = None
931
+ ) -> List[AgentLifecycleRecord]:
1006
932
  """List agents with optional state filtering."""
1007
933
  agents = list(self.agent_records.values())
1008
-
934
+
1009
935
  if state_filter:
1010
936
  agents = [agent for agent in agents if agent.current_state == state_filter]
1011
-
937
+
1012
938
  return sorted(agents, key=lambda x: x.last_modified, reverse=True)
1013
-
1014
- async def get_operation_history(self, agent_name: Optional[str] = None, limit: int = 100) -> List[LifecycleOperationResult]:
939
+
940
+ async def get_operation_history(
941
+ self, agent_name: Optional[str] = None, limit: int = 100
942
+ ) -> List[LifecycleOperationResult]:
1015
943
  """Get operation history with optional filtering."""
1016
944
  history = self.operation_history
1017
-
945
+
1018
946
  if agent_name:
1019
947
  history = [op for op in history if op.agent_name == agent_name]
1020
-
948
+
1021
949
  return sorted(history, key=lambda x: x.duration_ms, reverse=True)[:limit]
1022
-
950
+
1023
951
  async def get_lifecycle_stats(self) -> Dict[str, Any]:
1024
952
  """Get comprehensive lifecycle statistics."""
1025
953
  stats = {
1026
- 'total_agents': len(self.agent_records),
1027
- 'active_operations': len(self.active_operations),
1028
- 'performance_metrics': self.performance_metrics.copy()
954
+ "total_agents": len(self.agent_records),
955
+ "active_operations": len(self.active_operations),
956
+ "performance_metrics": self.performance_metrics.copy(),
1029
957
  }
1030
-
958
+
1031
959
  # State distribution
1032
960
  state_counts = {}
1033
961
  for record in self.agent_records.values():
1034
- state_counts[record.current_state.value] = state_counts.get(record.current_state.value, 0) + 1
1035
-
1036
- stats['agents_by_state'] = state_counts
1037
-
962
+ state_counts[record.current_state.value] = (
963
+ state_counts.get(record.current_state.value, 0) + 1
964
+ )
965
+
966
+ stats["agents_by_state"] = state_counts
967
+
1038
968
  # Tier distribution
1039
969
  tier_counts = {}
1040
970
  for record in self.agent_records.values():
1041
971
  tier_counts[record.tier.value] = tier_counts.get(record.tier.value, 0) + 1
1042
-
1043
- stats['agents_by_tier'] = tier_counts
1044
-
972
+
973
+ stats["agents_by_tier"] = tier_counts
974
+
1045
975
  # Recent activity
1046
976
  recent_ops = [
1047
- op for op in self.operation_history
977
+ op
978
+ for op in self.operation_history
1048
979
  if (time.time() - (op.duration_ms / 1000)) < 3600 # Last hour
1049
980
  ]
1050
- stats['recent_operations'] = len(recent_ops)
1051
-
981
+ stats["recent_operations"] = len(recent_ops)
982
+
1052
983
  return stats
1053
-
1054
- async def _create_agent_definition(self, agent_name: str, agent_content: str,
1055
- tier: ModificationTier, agent_type: str, **kwargs) -> AgentDefinition:
1056
- """
1057
- Create an AgentDefinition from lifecycle parameters.
1058
-
1059
- WHY: This method bridges the gap between the lifecycle manager's parameters
1060
- and the AgentManager's expected AgentDefinition model.
1061
-
1062
- DESIGN DECISION: Creating a minimal AgentDefinition here because:
1063
- - The full markdown parsing happens in AgentManager
1064
- - We only need to provide the essential metadata
1065
- - This keeps the lifecycle manager focused on orchestration
1066
- """
1067
- # Map tier to AgentType
1068
- type_map = {
1069
- ModificationTier.USER: AgentType.CUSTOM,
1070
- ModificationTier.PROJECT: AgentType.PROJECT,
1071
- ModificationTier.SYSTEM: AgentType.SYSTEM
1072
- }
1073
-
1074
- # Create metadata
1075
- from claude_mpm.models.agent_definition import AgentMetadata, AgentPermissions
1076
- metadata = AgentMetadata(
1077
- type=type_map.get(tier, AgentType.CUSTOM),
1078
- model_preference=kwargs.get('model_preference', 'claude-3-sonnet'),
1079
- version="1.0.0",
1080
- author=kwargs.get('author', 'claude-mpm'),
1081
- tags=kwargs.get('tags', []),
1082
- specializations=kwargs.get('specializations', [])
1083
- )
1084
-
1085
- # Create minimal definition
1086
- definition = AgentDefinition(
1087
- name=agent_name,
1088
- title=agent_name.replace('-', ' ').title(),
1089
- file_path="", # Will be set by AgentManager
1090
- metadata=metadata,
1091
- primary_role=kwargs.get('primary_role', f"{agent_name} agent"),
1092
- when_to_use={"select": [], "do_not_select": []},
1093
- capabilities=[],
1094
- authority=AgentPermissions(),
1095
- workflows=[],
1096
- escalation_triggers=[],
1097
- kpis=[],
1098
- dependencies=[],
1099
- tools_commands="",
1100
- raw_content=agent_content
984
+
985
+ async def _create_agent_definition(
986
+ self,
987
+ agent_name: str,
988
+ agent_content: str,
989
+ tier: ModificationTier,
990
+ agent_type: str,
991
+ **kwargs,
992
+ ) -> AgentDefinition:
993
+ """Create an AgentDefinition from lifecycle parameters."""
994
+ from .agent_definition_factory import AgentDefinitionFactory
995
+
996
+ factory = AgentDefinitionFactory()
997
+ return factory.create_agent_definition(
998
+ agent_name, agent_content, tier, agent_type, **kwargs
1101
999
  )
1102
-
1103
- return definition
1104
-
1000
+
1105
1001
  async def _run_sync_in_executor(self, func, *args, **kwargs):
1106
1002
  """
1107
1003
  Run a synchronous function in an executor to avoid blocking.
1108
-
1004
+
1109
1005
  WHY: AgentManager has synchronous methods but AgentLifecycleManager is async.
1110
1006
  This allows us to call sync methods without blocking the event loop.
1111
-
1007
+
1112
1008
  PERFORMANCE: Uses the default executor which manages a thread pool efficiently.
1113
1009
  """
1114
1010
  loop = asyncio.get_event_loop()
1115
1011
  return await loop.run_in_executor(None, func, *args, **kwargs)
1116
-
1117
- async def restore_agent(self, agent_name: str, backup_path: Optional[str] = None) -> LifecycleOperationResult:
1012
+
1013
+ async def restore_agent(
1014
+ self, agent_name: str, backup_path: Optional[str] = None
1015
+ ) -> LifecycleOperationResult:
1118
1016
  """Restore agent from backup."""
1119
- start_time = time.time()
1120
-
1121
- try:
1122
- record = self.agent_records.get(agent_name)
1123
- if not record:
1124
- return LifecycleOperationResult(
1125
- operation=LifecycleOperation.RESTORE,
1126
- agent_name=agent_name,
1127
- success=False,
1128
- duration_ms=(time.time() - start_time) * 1000,
1129
- error_message="Agent record not found"
1130
- )
1131
-
1132
- # Use latest backup if not specified
1133
- if not backup_path and record.backup_paths:
1134
- backup_path = record.backup_paths[-1]
1135
-
1136
- if not backup_path or not path_ops.validate_exists(backup_path):
1137
- return LifecycleOperationResult(
1138
- operation=LifecycleOperation.RESTORE,
1139
- agent_name=agent_name,
1140
- success=False,
1141
- duration_ms=(time.time() - start_time) * 1000,
1142
- error_message="No valid backup found"
1143
- )
1144
-
1145
- # Read backup content
1146
- backup_content = path_ops.safe_read(backup_path)
1147
- if not backup_content:
1148
- return LifecycleOperationResult(
1149
- operation=LifecycleOperation.RESTORE,
1150
- agent_name=agent_name,
1151
- success=False,
1152
- duration_ms=(time.time() - start_time) * 1000,
1153
- error_message="Failed to read backup content"
1154
- )
1155
-
1156
- # Restore via update operation
1157
- return await self.update_agent(
1158
- agent_name=agent_name,
1159
- agent_content=backup_content,
1160
- restored_from=backup_path
1161
- )
1162
-
1163
- except Exception as e:
1164
- return LifecycleOperationResult(
1165
- operation=LifecycleOperation.RESTORE,
1166
- agent_name=agent_name,
1167
- success=False,
1168
- duration_ms=(time.time() - start_time) * 1000,
1169
- error_message=str(e)
1170
- )
1017
+ from .agent_restore_handler import AgentRestoreHandler
1018
+
1019
+ handler = AgentRestoreHandler(self)
1020
+ return await handler.restore_agent(agent_name, backup_path)