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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (411) 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 +155 -0
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +90 -49
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +21 -18
  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 +143 -762
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1150
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +217 -0
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +36 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +571 -0
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +40 -23
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +14 -21
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +97 -93
  298. claude_mpm/services/mcp_gateway/main.py +307 -127
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +100 -101
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +4 -4
  303. claude_mpm/services/mcp_gateway/server/{mcp_server.py → mcp_gateway.py} +149 -153
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +110 -121
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +20 -534
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +9 -0
  358. claude_mpm/storage/state_storage.py +552 -0
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +51 -2
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/config/memory_guardian_config.py +0 -325
  385. claude_mpm/core/config_paths.py +0 -150
  386. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  387. claude_mpm/deployment_paths.py +0 -261
  388. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  389. claude_mpm/models/state_models.py +0 -433
  390. claude_mpm/services/agent/__init__.py +0 -24
  391. claude_mpm/services/agent/deployment.py +0 -2548
  392. claude_mpm/services/agent/management.py +0 -598
  393. claude_mpm/services/agent/registry.py +0 -813
  394. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  395. claude_mpm/services/communication/socketio.py +0 -1935
  396. claude_mpm/services/communication/websocket.py +0 -479
  397. claude_mpm/services/framework_claude_md_generator.py +0 -624
  398. claude_mpm/services/health_monitor.py +0 -893
  399. claude_mpm/services/infrastructure/memory_guardian.py +0 -770
  400. claude_mpm/services/mcp_gateway/server/mcp_server_simple.py +0 -444
  401. claude_mpm/services/optimized_hook_service.py +0 -542
  402. claude_mpm/services/project_analyzer.py +0 -864
  403. claude_mpm/services/project_registry.py +0 -608
  404. claude_mpm/services/standalone_socketio_server.py +0 -1300
  405. claude_mpm/services/ticket_manager_di.py +0 -318
  406. claude_mpm/services/ticketing_service_original.py +0 -510
  407. claude_mpm/utils/paths.py +0 -395
  408. claude_mpm/utils/platform_memory.py +0 -524
  409. claude_mpm-3.9.9.dist-info/RECORD +0 -293
  410. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  411. {claude_mpm-3.9.9.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
claude_mpm/core/config.py CHANGED
@@ -5,16 +5,17 @@ Handles loading configuration from files, environment variables,
5
5
  and default values with proper validation and type conversion.
6
6
  """
7
7
 
8
+ import json
9
+ import logging
8
10
  import os
9
11
  from pathlib import Path
10
- from typing import Any, Dict, Optional, Union, List, Tuple
11
- import logging
12
+ from typing import Any, Dict, List, Optional, Tuple, Union
13
+
12
14
  import yaml
13
- import json
14
15
 
15
16
  from ..utils.config_manager import ConfigurationManager
16
- from .config_paths import ConfigPaths
17
- from .exceptions import ConfigurationError
17
+ from .exceptions import ConfigurationError, FileOperationError
18
+ from .unified_paths import get_path_manager
18
19
 
19
20
  logger = logging.getLogger(__name__)
20
21
 
@@ -54,7 +55,7 @@ class Config:
54
55
 
55
56
  # Track where configuration was loaded from
56
57
  self._loaded_from = None
57
-
58
+
58
59
  # Load from file if provided
59
60
  if config_file:
60
61
  self.load_file(config_file)
@@ -81,7 +82,7 @@ class Config:
81
82
 
82
83
  def load_file(self, file_path: Union[str, Path]) -> None:
83
84
  """Load configuration from file with enhanced error handling.
84
-
85
+
85
86
  WHY: Configuration loading failures can cause silent issues. We need
86
87
  to provide clear, actionable error messages to help users fix problems.
87
88
  """
@@ -89,7 +90,9 @@ class Config:
89
90
 
90
91
  if not file_path.exists():
91
92
  logger.warning(f"Configuration file not found: {file_path}")
92
- logger.info(f"TIP: Create a configuration file with: mkdir -p {file_path.parent} && touch {file_path}")
93
+ logger.info(
94
+ f"TIP: Create a configuration file with: mkdir -p {file_path.parent} && touch {file_path}"
95
+ )
93
96
  return
94
97
 
95
98
  try:
@@ -98,46 +101,71 @@ class Config:
98
101
  logger.error(f"Configuration file is not readable: {file_path}")
99
102
  logger.info(f"TIP: Fix permissions with: chmod 644 {file_path}")
100
103
  return
101
-
104
+
102
105
  # Check file size (warn if too large)
103
106
  file_size = file_path.stat().st_size
104
107
  if file_size > 1024 * 1024: # 1MB
105
- logger.warning(f"Configuration file is large ({file_size} bytes): {file_path}")
106
-
108
+ logger.warning(
109
+ f"Configuration file is large ({file_size} bytes): {file_path}"
110
+ )
111
+
107
112
  # Try to load the configuration
108
113
  file_config = self._config_mgr.load_auto(file_path)
109
114
  if file_config:
110
115
  self._config = self._config_mgr.merge_configs(self._config, file_config)
111
116
  logger.info(f"✓ Successfully loaded configuration from {file_path}")
112
-
117
+
113
118
  # Log important configuration values for debugging
114
119
  if logger.isEnabledFor(logging.DEBUG):
115
- response_logging = file_config.get('response_logging', {})
120
+ response_logging = file_config.get("response_logging", {})
116
121
  if response_logging:
117
- logger.debug(f"Response logging enabled: {response_logging.get('enabled', False)}")
118
- logger.debug(f"Response logging format: {response_logging.get('format', 'json')}")
122
+ logger.debug(
123
+ f"Response logging enabled: {response_logging.get('enabled', False)}"
124
+ )
125
+ logger.debug(
126
+ f"Response logging format: {response_logging.get('format', 'json')}"
127
+ )
119
128
 
120
129
  except yaml.YAMLError as e:
121
130
  logger.error(f"YAML syntax error in {file_path}: {e}")
122
- if hasattr(e, 'problem_mark'):
131
+ if hasattr(e, "problem_mark"):
123
132
  mark = e.problem_mark
124
133
  logger.error(f"Error at line {mark.line + 1}, column {mark.column + 1}")
125
- logger.info("TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py")
126
- logger.info("TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' " + str(file_path))
134
+ logger.info(
135
+ "TIP: Validate your YAML at https://www.yamllint.com/ or run: python scripts/validate_configuration.py"
136
+ )
137
+ logger.info(
138
+ "TIP: Common issue - YAML requires spaces, not tabs. Fix with: sed -i '' 's/\t/ /g' "
139
+ + str(file_path)
140
+ )
127
141
  # Store error for later retrieval
128
- self._config['_load_error'] = str(e)
129
-
142
+ self._config["_load_error"] = str(e)
143
+
130
144
  except json.JSONDecodeError as e:
131
145
  logger.error(f"JSON syntax error in {file_path}: {e}")
132
146
  logger.error(f"Error at line {e.lineno}, column {e.colno}")
133
147
  logger.info("TIP: Validate your JSON at https://jsonlint.com/")
134
- self._config['_load_error'] = str(e)
135
-
148
+ self._config["_load_error"] = str(e)
149
+
150
+ except (OSError, IOError, PermissionError) as e:
151
+ raise FileOperationError(
152
+ f"Failed to read configuration file: {e}",
153
+ context={
154
+ "file_path": str(file_path),
155
+ "operation": "read",
156
+ "error_type": type(e).__name__,
157
+ },
158
+ )
136
159
  except Exception as e:
137
- logger.error(f"Failed to load configuration from {file_path}: {e}")
138
- logger.info("TIP: Check file permissions and format (YAML/JSON)")
139
- logger.info("TIP: Run validation with: python scripts/validate_configuration.py")
140
- self._config['_load_error'] = str(e)
160
+ # Catch any remaining unexpected errors and wrap them as configuration errors
161
+ raise ConfigurationError(
162
+ f"Unexpected error loading configuration from {file_path}: {e}",
163
+ context={
164
+ "file_path": str(file_path),
165
+ "error_type": type(e).__name__,
166
+ "original_error": str(e),
167
+ },
168
+ )
141
169
 
142
170
  def _load_env_vars(self) -> None:
143
171
  """Load configuration from environment variables."""
@@ -241,7 +269,7 @@ class Config:
241
269
  "file_descriptors": 1000,
242
270
  "max_clients": 1000,
243
271
  "max_error_rate": 0.1,
244
- "network_timeout": 2.0
272
+ "network_timeout": 2.0,
245
273
  },
246
274
  # Automatic recovery configuration
247
275
  "recovery": {
@@ -252,14 +280,14 @@ class Config:
252
280
  "circuit_breaker": {
253
281
  "failure_threshold": 5,
254
282
  "timeout_seconds": 300,
255
- "success_threshold": 3
283
+ "success_threshold": 3,
256
284
  },
257
285
  "strategy": {
258
286
  "warning_threshold": 2,
259
287
  "critical_threshold": 1,
260
288
  "failure_window_seconds": 300,
261
- "min_recovery_interval": 60
262
- }
289
+ "min_recovery_interval": 60,
290
+ },
263
291
  },
264
292
  # Service management
265
293
  "graceful_shutdown_timeout": 30,
@@ -294,18 +322,26 @@ class Config:
294
322
  "memory_usage_log_interval": 300, # Log memory usage every 5 minutes
295
323
  "max_memory_usage_mb": 2048, # Warn if memory usage exceeds 2GB
296
324
  "cleanup_on_startup": False, # Don't auto-cleanup on startup
297
- "compress_archives": True # Compress archived files
325
+ "compress_archives": True, # Compress archived files
298
326
  },
299
327
  # Evaluation system - Phase 2 Mirascope integration
300
328
  "enable_evaluation": True,
301
- "evaluation_storage_path": str(ConfigPaths.get_user_config_dir() / "training"),
329
+ "evaluation_storage_path": str(
330
+ get_path_manager().get_user_config_dir() / "training"
331
+ ),
302
332
  "correction_capture_enabled": True,
303
333
  "correction_storage_rotation_days": 30,
304
334
  "evaluation_logging_enabled": True,
305
335
  "auto_prompt_improvement": False, # Disabled by default for Phase 1
306
336
  # Mirascope evaluation settings
307
337
  "evaluation_provider": "auto", # auto, openai, anthropic
308
- "evaluation_criteria": ["correctness", "relevance", "completeness", "clarity", "helpfulness"],
338
+ "evaluation_criteria": [
339
+ "correctness",
340
+ "relevance",
341
+ "completeness",
342
+ "clarity",
343
+ "helpfulness",
344
+ ],
309
345
  "evaluation_caching_enabled": True,
310
346
  "evaluation_cache_ttl_hours": 24,
311
347
  "evaluation_cache_max_size": 1000,
@@ -337,23 +373,23 @@ class Config:
337
373
  "correction_compression_enabled": True,
338
374
  # Agent Memory System configuration
339
375
  "memory": {
340
- "enabled": True, # Master switch for memory system
341
- "auto_learning": True, # Automatic learning extraction (changed default to True)
376
+ "enabled": True, # Master switch for memory system
377
+ "auto_learning": True, # Automatic learning extraction (changed default to True)
342
378
  "limits": {
343
- "default_size_kb": 80, # Default file size limit (80KB ~20k tokens)
344
- "max_sections": 10, # Maximum sections per file
345
- "max_items_per_section": 15, # Maximum items per section
346
- "max_line_length": 120 # Maximum line length
379
+ "default_size_kb": 80, # Default file size limit (80KB ~20k tokens)
380
+ "max_sections": 10, # Maximum sections per file
381
+ "max_items_per_section": 15, # Maximum items per section
382
+ "max_line_length": 120, # Maximum line length
347
383
  },
348
384
  "agent_overrides": {
349
- "research": { # Research agent override
350
- "size_kb": 120, # Can have larger memory (120KB ~30k tokens)
351
- "auto_learning": True # Enable auto learning
385
+ "research": { # Research agent override
386
+ "size_kb": 120, # Can have larger memory (120KB ~30k tokens)
387
+ "auto_learning": True, # Enable auto learning
352
388
  },
353
- "qa": { # QA agent override
354
- "auto_learning": True # Enable auto learning
355
- }
356
- }
389
+ "qa": {
390
+ "auto_learning": True
391
+ }, # QA agent override # Enable auto learning
392
+ },
357
393
  },
358
394
  # Socket.IO server health and recovery configuration
359
395
  "socketio_server": {
@@ -370,8 +406,8 @@ class Config:
370
406
  "memory_mb": 500,
371
407
  "file_descriptors": 1000,
372
408
  "max_clients": 1000,
373
- "max_error_rate": 0.1
374
- }
409
+ "max_error_rate": 0.1,
410
+ },
375
411
  },
376
412
  "recovery": {
377
413
  "enabled": True,
@@ -380,35 +416,35 @@ class Config:
380
416
  "circuit_breaker": {
381
417
  "failure_threshold": 5,
382
418
  "timeout_seconds": 300,
383
- "success_threshold": 3
419
+ "success_threshold": 3,
384
420
  },
385
421
  "strategy": {
386
422
  "warning_threshold": 2,
387
423
  "critical_threshold": 1,
388
424
  "failure_window_seconds": 300,
389
- "min_recovery_interval": 60
425
+ "min_recovery_interval": 60,
390
426
  },
391
427
  "actions": {
392
428
  "log_warning": True,
393
429
  "clear_connections": True,
394
430
  "restart_service": True,
395
- "emergency_stop": True
396
- }
397
- }
431
+ "emergency_stop": True,
432
+ },
433
+ },
398
434
  },
399
435
  # Agent deployment configuration
400
436
  "agent_deployment": {
401
- "excluded_agents": [], # List of agent IDs to exclude from deployment
402
- "exclude_dependencies": False, # Whether to exclude agent dependencies too
403
- "case_sensitive": False # Whether agent name matching is case-sensitive
404
- }
437
+ "excluded_agents": [], # List of agent IDs to exclude from deployment
438
+ "exclude_dependencies": False, # Whether to exclude agent dependencies too
439
+ "case_sensitive": False, # Whether agent name matching is case-sensitive
440
+ },
405
441
  }
406
442
 
407
443
  # Apply defaults for missing keys
408
444
  for key, default_value in defaults.items():
409
445
  if key not in self._config:
410
446
  self._config[key] = default_value
411
-
447
+
412
448
  # Validate health and recovery configuration
413
449
  self._validate_health_recovery_config()
414
450
 
@@ -458,14 +494,36 @@ class Config:
458
494
  else:
459
495
  raise ConfigurationError(
460
496
  f"Unsupported configuration format: {format}",
461
- context={"format": format, "supported_formats": ["json", "yaml", "yml"]}
497
+ context={
498
+ "format": format,
499
+ "supported_formats": ["json", "yaml", "yml"],
500
+ },
462
501
  )
463
502
 
464
503
  logger.info(f"Configuration saved to {file_path}")
465
504
 
505
+ except (OSError, IOError, PermissionError) as e:
506
+ raise FileOperationError(
507
+ f"Failed to write configuration file: {e}",
508
+ context={
509
+ "file_path": str(file_path),
510
+ "operation": "write",
511
+ "format": format,
512
+ "error_type": type(e).__name__,
513
+ },
514
+ )
466
515
  except Exception as e:
467
- logger.error(f"Failed to save configuration to {file_path}: {e}")
468
- raise
516
+ # Re-raise ConfigurationError as-is, wrap others
517
+ if isinstance(e, ConfigurationError):
518
+ raise
519
+ raise ConfigurationError(
520
+ f"Unexpected error saving configuration: {e}",
521
+ context={
522
+ "file_path": str(file_path),
523
+ "format": format,
524
+ "error_type": type(e).__name__,
525
+ },
526
+ )
469
527
 
470
528
  def validate(self, schema: Dict[str, Any]) -> bool:
471
529
  """
@@ -494,7 +552,10 @@ class Config:
494
552
  return True
495
553
 
496
554
  except Exception as e:
497
- logger.error(f"Configuration validation error: {e}")
555
+ # Validation errors should be logged but not raise exceptions
556
+ # since this method returns a boolean result
557
+ logger.error(f"Unexpected error during configuration validation: {e}")
558
+ logger.debug(f"Validation error details: {type(e).__name__}: {e}")
498
559
  return False
499
560
 
500
561
  def __getitem__(self, key: str) -> Any:
@@ -513,182 +574,216 @@ class Config:
513
574
  """Validate health monitoring and recovery configuration."""
514
575
  try:
515
576
  # Validate health thresholds
516
- thresholds = self.get('health_thresholds', {})
517
- if thresholds.get('cpu_percent', 0) < 0 or thresholds.get('cpu_percent', 0) > 100:
518
- logger.warning("CPU threshold should be between 0-100, using default 80")
519
- self.set('health_thresholds.cpu_percent', 80.0)
520
-
521
- if thresholds.get('memory_mb', 0) <= 0:
522
- logger.warning("Memory threshold should be positive, using default 500MB")
523
- self.set('health_thresholds.memory_mb', 500)
524
-
525
- if thresholds.get('max_error_rate', 0) < 0 or thresholds.get('max_error_rate', 0) > 1:
526
- logger.warning("Error rate threshold should be between 0-1, using default 0.1")
527
- self.set('health_thresholds.max_error_rate', 0.1)
528
-
577
+ thresholds = self.get("health_thresholds", {})
578
+ if (
579
+ thresholds.get("cpu_percent", 0) < 0
580
+ or thresholds.get("cpu_percent", 0) > 100
581
+ ):
582
+ logger.warning(
583
+ "CPU threshold should be between 0-100, using default 80"
584
+ )
585
+ self.set("health_thresholds.cpu_percent", 80.0)
586
+
587
+ if thresholds.get("memory_mb", 0) <= 0:
588
+ logger.warning(
589
+ "Memory threshold should be positive, using default 500MB"
590
+ )
591
+ self.set("health_thresholds.memory_mb", 500)
592
+
593
+ if (
594
+ thresholds.get("max_error_rate", 0) < 0
595
+ or thresholds.get("max_error_rate", 0) > 1
596
+ ):
597
+ logger.warning(
598
+ "Error rate threshold should be between 0-1, using default 0.1"
599
+ )
600
+ self.set("health_thresholds.max_error_rate", 0.1)
601
+
529
602
  # Validate recovery configuration
530
- recovery_config = self.get('recovery', {})
531
- if recovery_config.get('max_recovery_attempts', 0) <= 0:
532
- logger.warning("Max recovery attempts should be positive, using default 5")
533
- self.set('recovery.max_recovery_attempts', 5)
534
-
603
+ recovery_config = self.get("recovery", {})
604
+ if recovery_config.get("max_recovery_attempts", 0) <= 0:
605
+ logger.warning(
606
+ "Max recovery attempts should be positive, using default 5"
607
+ )
608
+ self.set("recovery.max_recovery_attempts", 5)
609
+
535
610
  # Validate circuit breaker configuration
536
- cb_config = recovery_config.get('circuit_breaker', {})
537
- if cb_config.get('failure_threshold', 0) <= 0:
538
- logger.warning("Circuit breaker failure threshold should be positive, using default 5")
539
- self.set('recovery.circuit_breaker.failure_threshold', 5)
540
-
541
- if cb_config.get('timeout_seconds', 0) <= 0:
542
- logger.warning("Circuit breaker timeout should be positive, using default 300")
543
- self.set('recovery.circuit_breaker.timeout_seconds', 300)
544
-
611
+ cb_config = recovery_config.get("circuit_breaker", {})
612
+ if cb_config.get("failure_threshold", 0) <= 0:
613
+ logger.warning(
614
+ "Circuit breaker failure threshold should be positive, using default 5"
615
+ )
616
+ self.set("recovery.circuit_breaker.failure_threshold", 5)
617
+
618
+ if cb_config.get("timeout_seconds", 0) <= 0:
619
+ logger.warning(
620
+ "Circuit breaker timeout should be positive, using default 300"
621
+ )
622
+ self.set("recovery.circuit_breaker.timeout_seconds", 300)
623
+
545
624
  except Exception as e:
546
625
  logger.error(f"Error validating health/recovery configuration: {e}")
547
-
626
+
548
627
  def get_health_monitoring_config(self) -> Dict[str, Any]:
549
628
  """Get health monitoring configuration with defaults."""
550
629
  base_config = {
551
- 'enabled': self.get('enable_health_monitoring', True),
552
- 'check_interval': self.get('health_check_interval', 30),
553
- 'history_size': self.get('health_history_size', 100),
554
- 'aggregation_window': self.get('health_aggregation_window', 300),
555
- 'thresholds': self.get('health_thresholds', {
556
- 'cpu_percent': 80.0,
557
- 'memory_mb': 500,
558
- 'file_descriptors': 1000,
559
- 'max_clients': 1000,
560
- 'max_error_rate': 0.1,
561
- 'network_timeout': 2.0
562
- })
630
+ "enabled": self.get("enable_health_monitoring", True),
631
+ "check_interval": self.get("health_check_interval", 30),
632
+ "history_size": self.get("health_history_size", 100),
633
+ "aggregation_window": self.get("health_aggregation_window", 300),
634
+ "thresholds": self.get(
635
+ "health_thresholds",
636
+ {
637
+ "cpu_percent": 80.0,
638
+ "memory_mb": 500,
639
+ "file_descriptors": 1000,
640
+ "max_clients": 1000,
641
+ "max_error_rate": 0.1,
642
+ "network_timeout": 2.0,
643
+ },
644
+ ),
563
645
  }
564
-
646
+
565
647
  # Merge with socketio-specific config if available
566
- socketio_config = self.get('socketio_server.health_monitoring', {})
648
+ socketio_config = self.get("socketio_server.health_monitoring", {})
567
649
  if socketio_config:
568
650
  base_config.update(socketio_config)
569
-
651
+
570
652
  return base_config
571
-
653
+
572
654
  def get_recovery_config(self) -> Dict[str, Any]:
573
655
  """Get recovery configuration with defaults."""
574
- base_config = self.get('recovery', {
575
- 'enabled': True,
576
- 'check_interval': 60,
577
- 'max_recovery_attempts': 5,
578
- 'recovery_timeout': 30,
579
- 'circuit_breaker': {
580
- 'failure_threshold': 5,
581
- 'timeout_seconds': 300,
582
- 'success_threshold': 3
656
+ base_config = self.get(
657
+ "recovery",
658
+ {
659
+ "enabled": True,
660
+ "check_interval": 60,
661
+ "max_recovery_attempts": 5,
662
+ "recovery_timeout": 30,
663
+ "circuit_breaker": {
664
+ "failure_threshold": 5,
665
+ "timeout_seconds": 300,
666
+ "success_threshold": 3,
667
+ },
668
+ "strategy": {
669
+ "warning_threshold": 2,
670
+ "critical_threshold": 1,
671
+ "failure_window_seconds": 300,
672
+ "min_recovery_interval": 60,
673
+ },
583
674
  },
584
- 'strategy': {
585
- 'warning_threshold': 2,
586
- 'critical_threshold': 1,
587
- 'failure_window_seconds': 300,
588
- 'min_recovery_interval': 60
589
- }
590
- })
591
-
675
+ )
676
+
592
677
  # Merge with socketio-specific config if available
593
- socketio_config = self.get('socketio_server.recovery', {})
678
+ socketio_config = self.get("socketio_server.recovery", {})
594
679
  if socketio_config:
595
680
  base_config = self._config_mgr.merge_configs(base_config, socketio_config)
596
-
681
+
597
682
  return base_config
598
683
 
599
684
  def validate_configuration(self) -> Tuple[bool, List[str], List[str]]:
600
685
  """Validate the loaded configuration programmatically.
601
-
686
+
602
687
  WHY: Provide a programmatic way to validate configuration that can be
603
688
  used by other components to check configuration health.
604
-
689
+
605
690
  Returns:
606
691
  Tuple of (is_valid, errors, warnings)
607
692
  """
608
693
  errors = []
609
694
  warnings = []
610
-
695
+
611
696
  # Check if there was a load error
612
- if '_load_error' in self._config:
697
+ if "_load_error" in self._config:
613
698
  errors.append(f"Configuration load error: {self._config['_load_error']}")
614
-
699
+
615
700
  # Validate response_logging configuration
616
- response_logging = self.get('response_logging', {})
701
+ response_logging = self.get("response_logging", {})
617
702
  if response_logging:
618
703
  # Check enabled field
619
- if 'enabled' in response_logging and not isinstance(response_logging['enabled'], bool):
704
+ if "enabled" in response_logging and not isinstance(
705
+ response_logging["enabled"], bool
706
+ ):
620
707
  errors.append(
621
708
  f"response_logging.enabled must be boolean, got {type(response_logging['enabled']).__name__}"
622
709
  )
623
-
710
+
624
711
  # Check format field
625
- if 'format' in response_logging:
626
- valid_formats = ['json', 'syslog', 'journald']
627
- if response_logging['format'] not in valid_formats:
712
+ if "format" in response_logging:
713
+ valid_formats = ["json", "syslog", "journald"]
714
+ if response_logging["format"] not in valid_formats:
628
715
  errors.append(
629
716
  f"response_logging.format must be one of {valid_formats}, "
630
717
  f"got '{response_logging['format']}'"
631
718
  )
632
-
719
+
633
720
  # Check session_directory
634
- if 'session_directory' in response_logging:
635
- session_dir = Path(response_logging['session_directory'])
721
+ if "session_directory" in response_logging:
722
+ session_dir = Path(response_logging["session_directory"])
636
723
  if session_dir.is_absolute() and not session_dir.parent.exists():
637
724
  warnings.append(
638
725
  f"Parent directory for session_directory does not exist: {session_dir.parent}"
639
726
  )
640
-
727
+
641
728
  # Validate memory configuration
642
- memory_config = self.get('memory', {})
729
+ memory_config = self.get("memory", {})
643
730
  if memory_config:
644
- if 'enabled' in memory_config and not isinstance(memory_config['enabled'], bool):
731
+ if "enabled" in memory_config and not isinstance(
732
+ memory_config["enabled"], bool
733
+ ):
645
734
  errors.append(f"memory.enabled must be boolean")
646
-
735
+
647
736
  # Check limits
648
- limits = memory_config.get('limits', {})
649
- for field in ['default_size_kb', 'max_sections', 'max_items_per_section']:
737
+ limits = memory_config.get("limits", {})
738
+ for field in ["default_size_kb", "max_sections", "max_items_per_section"]:
650
739
  if field in limits:
651
740
  value = limits[field]
652
741
  if not isinstance(value, int) or value <= 0:
653
- errors.append(f"memory.limits.{field} must be positive integer, got {value}")
654
-
742
+ errors.append(
743
+ f"memory.limits.{field} must be positive integer, got {value}"
744
+ )
745
+
655
746
  # Validate health thresholds
656
- health_thresholds = self.get('health_thresholds', {})
747
+ health_thresholds = self.get("health_thresholds", {})
657
748
  if health_thresholds:
658
- cpu = health_thresholds.get('cpu_percent')
659
- if cpu is not None and (not isinstance(cpu, (int, float)) or cpu < 0 or cpu > 100):
749
+ cpu = health_thresholds.get("cpu_percent")
750
+ if cpu is not None and (
751
+ not isinstance(cpu, (int, float)) or cpu < 0 or cpu > 100
752
+ ):
660
753
  errors.append(f"health_thresholds.cpu_percent must be 0-100, got {cpu}")
661
-
662
- mem = health_thresholds.get('memory_mb')
754
+
755
+ mem = health_thresholds.get("memory_mb")
663
756
  if mem is not None and (not isinstance(mem, (int, float)) or mem <= 0):
664
- errors.append(f"health_thresholds.memory_mb must be positive, got {mem}")
665
-
757
+ errors.append(
758
+ f"health_thresholds.memory_mb must be positive, got {mem}"
759
+ )
760
+
666
761
  is_valid = len(errors) == 0
667
762
  return is_valid, errors, warnings
668
-
763
+
669
764
  def get_configuration_status(self) -> Dict[str, Any]:
670
765
  """Get detailed configuration status for debugging.
671
-
766
+
672
767
  WHY: Provide a comprehensive view of configuration state for
673
768
  troubleshooting and health checks.
674
-
769
+
675
770
  Returns:
676
771
  Dictionary with configuration status information
677
772
  """
678
773
  is_valid, errors, warnings = self.validate_configuration()
679
-
774
+
680
775
  status = {
681
- 'valid': is_valid,
682
- 'errors': errors,
683
- 'warnings': warnings,
684
- 'loaded_from': getattr(self, '_loaded_from', 'defaults'),
685
- 'key_count': len(self._config),
686
- 'has_response_logging': 'response_logging' in self._config,
687
- 'has_memory_config': 'memory' in self._config,
688
- 'response_logging_enabled': self.get('response_logging.enabled', False),
689
- 'memory_enabled': self.get('memory.enabled', False)
776
+ "valid": is_valid,
777
+ "errors": errors,
778
+ "warnings": warnings,
779
+ "loaded_from": getattr(self, "_loaded_from", "defaults"),
780
+ "key_count": len(self._config),
781
+ "has_response_logging": "response_logging" in self._config,
782
+ "has_memory_config": "memory" in self._config,
783
+ "response_logging_enabled": self.get("response_logging.enabled", False),
784
+ "memory_enabled": self.get("memory.enabled", False),
690
785
  }
691
-
786
+
692
787
  return status
693
788
 
694
789
  def __repr__(self) -> str: