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,616 +0,0 @@
1
- """Graceful degradation service for Memory Guardian system.
2
-
3
- Implements fallback strategies when monitoring components fail, ensuring
4
- the system continues to function even with reduced capabilities.
5
- """
6
-
7
- import asyncio
8
- import logging
9
- import os
10
- import subprocess
11
- import time
12
- from dataclasses import dataclass
13
- from datetime import datetime
14
- from enum import Enum
15
- from pathlib import Path
16
- from typing import Dict, List, Optional, Any, Callable, Set
17
-
18
- from claude_mpm.services.core.base import BaseService
19
-
20
-
21
- class DegradationLevel(Enum):
22
- """System degradation levels."""
23
- NORMAL = "normal" # Full functionality
24
- MINOR = "minor" # Some features disabled
25
- MODERATE = "moderate" # Running with reduced capabilities
26
- SEVERE = "severe" # Minimal functionality
27
- EMERGENCY = "emergency" # Emergency mode only
28
-
29
-
30
- class FeatureState(Enum):
31
- """Feature availability state."""
32
- AVAILABLE = "available"
33
- DEGRADED = "degraded"
34
- UNAVAILABLE = "unavailable"
35
-
36
-
37
- @dataclass
38
- class Feature:
39
- """System feature definition."""
40
- name: str
41
- state: FeatureState
42
- fallback_mode: Optional[str]
43
- reason: Optional[str]
44
- degraded_at: Optional[float]
45
-
46
- def to_dict(self) -> Dict[str, Any]:
47
- """Convert to dictionary."""
48
- return {
49
- 'name': self.name,
50
- 'state': self.state.value,
51
- 'fallback_mode': self.fallback_mode,
52
- 'reason': self.reason,
53
- 'degraded_at': self.degraded_at,
54
- 'degraded_at_iso': datetime.fromtimestamp(self.degraded_at).isoformat() if self.degraded_at else None
55
- }
56
-
57
-
58
- @dataclass
59
- class DegradationStatus:
60
- """System degradation status."""
61
- level: DegradationLevel
62
- features: List[Feature]
63
- active_fallbacks: List[str]
64
- notifications: List[str]
65
- timestamp: float
66
-
67
- @property
68
- def available_features(self) -> int:
69
- """Count of available features."""
70
- return sum(1 for f in self.features if f.state == FeatureState.AVAILABLE)
71
-
72
- @property
73
- def degraded_features(self) -> int:
74
- """Count of degraded features."""
75
- return sum(1 for f in self.features if f.state == FeatureState.DEGRADED)
76
-
77
- @property
78
- def unavailable_features(self) -> int:
79
- """Count of unavailable features."""
80
- return sum(1 for f in self.features if f.state == FeatureState.UNAVAILABLE)
81
-
82
- def to_dict(self) -> Dict[str, Any]:
83
- """Convert to dictionary."""
84
- return {
85
- 'level': self.level.value,
86
- 'available_features': self.available_features,
87
- 'degraded_features': self.degraded_features,
88
- 'unavailable_features': self.unavailable_features,
89
- 'features': [f.to_dict() for f in self.features],
90
- 'active_fallbacks': self.active_fallbacks,
91
- 'notifications': self.notifications,
92
- 'timestamp': self.timestamp,
93
- 'timestamp_iso': datetime.fromtimestamp(self.timestamp).isoformat()
94
- }
95
-
96
-
97
- class GracefulDegradation(BaseService):
98
- """Service for managing graceful degradation of system features."""
99
-
100
- def __init__(
101
- self,
102
- enable_notifications: bool = True,
103
- log_degradation_events: bool = True,
104
- state_file: Optional[Path] = None
105
- ):
106
- """Initialize graceful degradation service.
107
-
108
- Args:
109
- enable_notifications: Whether to show user notifications
110
- log_degradation_events: Whether to log degradation events
111
- state_file: Optional file for persisting degradation state
112
- """
113
- super().__init__("GracefulDegradation")
114
-
115
- # Configuration
116
- self.enable_notifications = enable_notifications
117
- self.log_degradation_events = log_degradation_events
118
- self.state_file = state_file
119
-
120
- # Feature registry
121
- self.features: Dict[str, Feature] = {}
122
- self.fallback_handlers: Dict[str, Callable] = {}
123
- self.recovery_handlers: Dict[str, Callable] = {}
124
-
125
- # State tracking
126
- self.degradation_level = DegradationLevel.NORMAL
127
- self.active_fallbacks: Set[str] = set()
128
- self.pending_notifications: List[str] = []
129
- self.degradation_history: List[DegradationStatus] = []
130
-
131
- # Initialize core features
132
- self._initialize_core_features()
133
-
134
- self.log_info("Graceful degradation service initialized")
135
-
136
- async def initialize(self) -> bool:
137
- """Initialize the graceful degradation service.
138
-
139
- Returns:
140
- True if initialization successful
141
- """
142
- try:
143
- self.log_info("Initializing graceful degradation service")
144
-
145
- # Check system capabilities
146
- await self._check_system_capabilities()
147
-
148
- # Start notification handler
149
- if self.enable_notifications:
150
- asyncio.create_task(self._notification_handler())
151
-
152
- self._initialized = True
153
- self.log_info("Graceful degradation service initialized successfully")
154
- return True
155
-
156
- except Exception as e:
157
- self.log_error(f"Failed to initialize graceful degradation: {e}")
158
- return False
159
-
160
- async def shutdown(self) -> None:
161
- """Shutdown the graceful degradation service."""
162
- try:
163
- self.log_info("Shutting down graceful degradation service")
164
-
165
- # Save state if configured
166
- if self.state_file:
167
- self._save_state()
168
-
169
- self._shutdown = True
170
- self.log_info("Graceful degradation service shutdown complete")
171
-
172
- except Exception as e:
173
- self.log_error(f"Error during graceful degradation shutdown: {e}")
174
-
175
- def register_feature(
176
- self,
177
- name: str,
178
- fallback_handler: Optional[Callable] = None,
179
- recovery_handler: Optional[Callable] = None
180
- ) -> None:
181
- """Register a system feature with optional fallback/recovery handlers.
182
-
183
- Args:
184
- name: Feature name
185
- fallback_handler: Handler to call when feature degrades
186
- recovery_handler: Handler to call when feature recovers
187
- """
188
- self.features[name] = Feature(
189
- name=name,
190
- state=FeatureState.AVAILABLE,
191
- fallback_mode=None,
192
- reason=None,
193
- degraded_at=None
194
- )
195
-
196
- if fallback_handler:
197
- self.fallback_handlers[name] = fallback_handler
198
-
199
- if recovery_handler:
200
- self.recovery_handlers[name] = recovery_handler
201
-
202
- self.log_debug(f"Registered feature: {name}")
203
-
204
- async def degrade_feature(
205
- self,
206
- feature_name: str,
207
- reason: str,
208
- fallback_mode: Optional[str] = None
209
- ) -> bool:
210
- """Degrade a system feature to fallback mode.
211
-
212
- Args:
213
- feature_name: Name of feature to degrade
214
- reason: Reason for degradation
215
- fallback_mode: Optional description of fallback mode
216
-
217
- Returns:
218
- True if degradation successful
219
- """
220
- if feature_name not in self.features:
221
- self.log_warning(f"Unknown feature: {feature_name}")
222
- return False
223
-
224
- feature = self.features[feature_name]
225
-
226
- if feature.state == FeatureState.UNAVAILABLE:
227
- self.log_debug(f"Feature {feature_name} already unavailable")
228
- return True
229
-
230
- # Update feature state
231
- old_state = feature.state
232
- feature.state = FeatureState.DEGRADED
233
- feature.fallback_mode = fallback_mode or "basic mode"
234
- feature.reason = reason
235
- feature.degraded_at = time.time()
236
-
237
- # Log degradation
238
- if self.log_degradation_events:
239
- self.log_warning(
240
- f"Feature degraded: {feature_name} - {reason} "
241
- f"(fallback: {feature.fallback_mode})"
242
- )
243
-
244
- # Add notification
245
- self._add_notification(
246
- f"System feature '{feature_name}' running in {feature.fallback_mode} due to: {reason}"
247
- )
248
-
249
- # Execute fallback handler if available
250
- if feature_name in self.fallback_handlers:
251
- try:
252
- await self.fallback_handlers[feature_name](reason)
253
- except Exception as e:
254
- self.log_error(f"Fallback handler failed for {feature_name}: {e}")
255
-
256
- # Add to active fallbacks
257
- self.active_fallbacks.add(feature_name)
258
-
259
- # Update degradation level
260
- self._update_degradation_level()
261
-
262
- # Record status
263
- self._record_status()
264
-
265
- return True
266
-
267
- async def disable_feature(
268
- self,
269
- feature_name: str,
270
- reason: str
271
- ) -> bool:
272
- """Completely disable a system feature.
273
-
274
- Args:
275
- feature_name: Name of feature to disable
276
- reason: Reason for disabling
277
-
278
- Returns:
279
- True if disable successful
280
- """
281
- if feature_name not in self.features:
282
- self.log_warning(f"Unknown feature: {feature_name}")
283
- return False
284
-
285
- feature = self.features[feature_name]
286
-
287
- if feature.state == FeatureState.UNAVAILABLE:
288
- self.log_debug(f"Feature {feature_name} already disabled")
289
- return True
290
-
291
- # Update feature state
292
- feature.state = FeatureState.UNAVAILABLE
293
- feature.fallback_mode = None
294
- feature.reason = reason
295
- feature.degraded_at = time.time()
296
-
297
- # Log disable
298
- if self.log_degradation_events:
299
- self.log_error(f"Feature disabled: {feature_name} - {reason}")
300
-
301
- # Add notification
302
- self._add_notification(
303
- f"System feature '{feature_name}' has been disabled: {reason}"
304
- )
305
-
306
- # Remove from active fallbacks if present
307
- self.active_fallbacks.discard(feature_name)
308
-
309
- # Update degradation level
310
- self._update_degradation_level()
311
-
312
- # Record status
313
- self._record_status()
314
-
315
- return True
316
-
317
- async def recover_feature(self, feature_name: str) -> bool:
318
- """Recover a degraded feature to normal operation.
319
-
320
- Args:
321
- feature_name: Name of feature to recover
322
-
323
- Returns:
324
- True if recovery successful
325
- """
326
- if feature_name not in self.features:
327
- self.log_warning(f"Unknown feature: {feature_name}")
328
- return False
329
-
330
- feature = self.features[feature_name]
331
-
332
- if feature.state == FeatureState.AVAILABLE:
333
- self.log_debug(f"Feature {feature_name} already available")
334
- return True
335
-
336
- # Update feature state
337
- old_state = feature.state
338
- feature.state = FeatureState.AVAILABLE
339
- feature.fallback_mode = None
340
- feature.reason = None
341
- feature.degraded_at = None
342
-
343
- # Log recovery
344
- self.log_info(f"Feature recovered: {feature_name}")
345
-
346
- # Add notification
347
- self._add_notification(
348
- f"System feature '{feature_name}' has been restored to normal operation"
349
- )
350
-
351
- # Execute recovery handler if available
352
- if feature_name in self.recovery_handlers:
353
- try:
354
- await self.recovery_handlers[feature_name]()
355
- except Exception as e:
356
- self.log_error(f"Recovery handler failed for {feature_name}: {e}")
357
-
358
- # Remove from active fallbacks
359
- self.active_fallbacks.discard(feature_name)
360
-
361
- # Update degradation level
362
- self._update_degradation_level()
363
-
364
- # Record status
365
- self._record_status()
366
-
367
- return True
368
-
369
- def get_status(self) -> DegradationStatus:
370
- """Get current degradation status.
371
-
372
- Returns:
373
- DegradationStatus object
374
- """
375
- return DegradationStatus(
376
- level=self.degradation_level,
377
- features=list(self.features.values()),
378
- active_fallbacks=list(self.active_fallbacks),
379
- notifications=list(self.pending_notifications),
380
- timestamp=time.time()
381
- )
382
-
383
- def get_feature_state(self, feature_name: str) -> Optional[FeatureState]:
384
- """Get the state of a specific feature.
385
-
386
- Args:
387
- feature_name: Name of feature
388
-
389
- Returns:
390
- FeatureState or None if feature not found
391
- """
392
- feature = self.features.get(feature_name)
393
- return feature.state if feature else None
394
-
395
- def is_degraded(self) -> bool:
396
- """Check if system is running in degraded mode.
397
-
398
- Returns:
399
- True if any features are degraded
400
- """
401
- return self.degradation_level != DegradationLevel.NORMAL
402
-
403
- async def fallback_to_basic_monitoring(self) -> bool:
404
- """Fallback to basic memory monitoring without psutil.
405
-
406
- Returns:
407
- True if fallback successful
408
- """
409
- self.log_info("Falling back to basic memory monitoring")
410
-
411
- # Degrade memory monitoring feature
412
- await self.degrade_feature(
413
- "memory_monitoring",
414
- "psutil unavailable",
415
- "basic OS commands"
416
- )
417
-
418
- # Use platform-specific commands as fallback
419
- if os.name == 'posix':
420
- # Unix-like systems
421
- self._add_notification(
422
- "Using basic memory monitoring via 'ps' command. "
423
- "Install psutil for full functionality."
424
- )
425
- elif os.name == 'nt':
426
- # Windows
427
- self._add_notification(
428
- "Using basic memory monitoring via 'wmic' command. "
429
- "Install psutil for full functionality."
430
- )
431
-
432
- return True
433
-
434
- async def fallback_to_manual_checks(self) -> bool:
435
- """Fallback to manual memory checks when automated monitoring fails.
436
-
437
- Returns:
438
- True if fallback successful
439
- """
440
- self.log_info("Falling back to manual memory checks")
441
-
442
- # Degrade automated monitoring
443
- await self.degrade_feature(
444
- "automated_monitoring",
445
- "monitoring service failure",
446
- "manual periodic checks"
447
- )
448
-
449
- self._add_notification(
450
- "Automated memory monitoring disabled. "
451
- "Manual checks will be performed periodically."
452
- )
453
-
454
- return True
455
-
456
- async def continue_without_state(self) -> bool:
457
- """Continue operation without state preservation.
458
-
459
- Returns:
460
- True if fallback successful
461
- """
462
- self.log_info("Continuing without state preservation")
463
-
464
- # Disable state preservation
465
- await self.disable_feature(
466
- "state_preservation",
467
- "storage failure"
468
- )
469
-
470
- self._add_notification(
471
- "State preservation disabled due to storage issues. "
472
- "System state will not persist across restarts."
473
- )
474
-
475
- return True
476
-
477
- def _initialize_core_features(self) -> None:
478
- """Initialize core system features."""
479
- core_features = [
480
- "memory_monitoring",
481
- "automated_monitoring",
482
- "state_preservation",
483
- "restart_protection",
484
- "health_monitoring",
485
- "process_management",
486
- "notification_system",
487
- "logging_system"
488
- ]
489
-
490
- for feature in core_features:
491
- self.register_feature(feature)
492
-
493
- async def _check_system_capabilities(self) -> None:
494
- """Check and degrade features based on system capabilities."""
495
- # Check for psutil
496
- try:
497
- import psutil
498
- except ImportError:
499
- await self.fallback_to_basic_monitoring()
500
-
501
- # Check for network connectivity
502
- try:
503
- import socket
504
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
505
- sock.settimeout(2)
506
- result = sock.connect_ex(('8.8.8.8', 53))
507
- sock.close()
508
- if result != 0:
509
- await self.degrade_feature(
510
- "health_monitoring",
511
- "no network connectivity",
512
- "local checks only"
513
- )
514
- except:
515
- await self.degrade_feature(
516
- "health_monitoring",
517
- "network check failed",
518
- "local checks only"
519
- )
520
-
521
- # Check for storage access
522
- if self.state_file:
523
- try:
524
- self.state_file.parent.mkdir(parents=True, exist_ok=True)
525
- test_file = self.state_file.parent / '.test'
526
- test_file.write_text('test')
527
- test_file.unlink()
528
- except:
529
- await self.continue_without_state()
530
-
531
- def _update_degradation_level(self) -> None:
532
- """Update overall degradation level based on feature states."""
533
- total_features = len(self.features)
534
- if total_features == 0:
535
- self.degradation_level = DegradationLevel.NORMAL
536
- return
537
-
538
- unavailable_count = sum(1 for f in self.features.values() if f.state == FeatureState.UNAVAILABLE)
539
- degraded_count = sum(1 for f in self.features.values() if f.state == FeatureState.DEGRADED)
540
-
541
- unavailable_ratio = unavailable_count / total_features
542
- degraded_ratio = degraded_count / total_features
543
-
544
- if unavailable_ratio >= 0.5:
545
- self.degradation_level = DegradationLevel.EMERGENCY
546
- elif unavailable_ratio >= 0.25:
547
- self.degradation_level = DegradationLevel.SEVERE
548
- elif degraded_ratio >= 0.5:
549
- self.degradation_level = DegradationLevel.MODERATE
550
- elif degraded_ratio >= 0.25:
551
- self.degradation_level = DegradationLevel.MINOR
552
- else:
553
- self.degradation_level = DegradationLevel.NORMAL
554
-
555
- def _add_notification(self, message: str) -> None:
556
- """Add a notification for the user.
557
-
558
- Args:
559
- message: Notification message
560
- """
561
- if self.enable_notifications:
562
- self.pending_notifications.append(message)
563
- self.log_info(f"Notification: {message}")
564
-
565
- def _record_status(self) -> None:
566
- """Record current degradation status."""
567
- status = self.get_status()
568
- self.degradation_history.append(status)
569
-
570
- # Trim history
571
- if len(self.degradation_history) > 100:
572
- self.degradation_history = self.degradation_history[-100:]
573
-
574
- async def _notification_handler(self) -> None:
575
- """Background task to handle user notifications."""
576
- while not self._shutdown:
577
- try:
578
- if self.pending_notifications:
579
- # Process pending notifications
580
- notifications = list(self.pending_notifications)
581
- self.pending_notifications.clear()
582
-
583
- for notification in notifications:
584
- # In a real implementation, this would show system notifications
585
- # For now, just log them
586
- self.log_info(f"USER NOTIFICATION: {notification}")
587
-
588
- await asyncio.sleep(5) # Check every 5 seconds
589
-
590
- except Exception as e:
591
- self.log_error(f"Error in notification handler: {e}")
592
- await asyncio.sleep(5)
593
-
594
- def _save_state(self) -> None:
595
- """Save degradation state to file."""
596
- if not self.state_file:
597
- return
598
-
599
- try:
600
- import json
601
-
602
- state = {
603
- 'degradation_level': self.degradation_level.value,
604
- 'features': [f.to_dict() for f in self.features.values()],
605
- 'active_fallbacks': list(self.active_fallbacks),
606
- 'history': [s.to_dict() for s in self.degradation_history[-10:]]
607
- }
608
-
609
- self.state_file.parent.mkdir(parents=True, exist_ok=True)
610
- with open(self.state_file, 'w') as f:
611
- json.dump(state, f, indent=2)
612
-
613
- self.log_debug(f"Saved degradation state to {self.state_file}")
614
-
615
- except Exception as e:
616
- self.log_error(f"Failed to save degradation state: {e}")