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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/__init__.py +2 -2
  3. claude_mpm/__main__.py +3 -2
  4. claude_mpm/agents/__init__.py +85 -79
  5. claude_mpm/agents/agent_loader.py +464 -1003
  6. claude_mpm/agents/agent_loader_integration.py +45 -45
  7. claude_mpm/agents/agents_metadata.py +29 -30
  8. claude_mpm/agents/async_agent_loader.py +156 -138
  9. claude_mpm/agents/base_agent.json +1 -1
  10. claude_mpm/agents/base_agent_loader.py +179 -151
  11. claude_mpm/agents/frontmatter_validator.py +229 -130
  12. claude_mpm/agents/schema/agent_schema.json +1 -1
  13. claude_mpm/agents/system_agent_config.py +213 -147
  14. claude_mpm/agents/templates/__init__.py +13 -13
  15. claude_mpm/agents/templates/code_analyzer.json +2 -2
  16. claude_mpm/agents/templates/data_engineer.json +1 -1
  17. claude_mpm/agents/templates/documentation.json +23 -11
  18. claude_mpm/agents/templates/engineer.json +22 -6
  19. claude_mpm/agents/templates/memory_manager.json +1 -1
  20. claude_mpm/agents/templates/ops.json +2 -2
  21. claude_mpm/agents/templates/project_organizer.json +1 -1
  22. claude_mpm/agents/templates/qa.json +1 -1
  23. claude_mpm/agents/templates/refactoring_engineer.json +222 -0
  24. claude_mpm/agents/templates/research.json +20 -14
  25. claude_mpm/agents/templates/security.json +1 -1
  26. claude_mpm/agents/templates/ticketing.json +1 -1
  27. claude_mpm/agents/templates/version_control.json +1 -1
  28. claude_mpm/agents/templates/web_qa.json +3 -1
  29. claude_mpm/agents/templates/web_ui.json +2 -2
  30. claude_mpm/cli/__init__.py +79 -51
  31. claude_mpm/cli/__main__.py +3 -2
  32. claude_mpm/cli/commands/__init__.py +20 -20
  33. claude_mpm/cli/commands/agents.py +279 -247
  34. claude_mpm/cli/commands/aggregate.py +138 -157
  35. claude_mpm/cli/commands/cleanup.py +147 -147
  36. claude_mpm/cli/commands/config.py +93 -76
  37. claude_mpm/cli/commands/info.py +17 -16
  38. claude_mpm/cli/commands/mcp.py +140 -905
  39. claude_mpm/cli/commands/mcp_command_router.py +139 -0
  40. claude_mpm/cli/commands/mcp_config_commands.py +20 -0
  41. claude_mpm/cli/commands/mcp_install_commands.py +20 -0
  42. claude_mpm/cli/commands/mcp_server_commands.py +175 -0
  43. claude_mpm/cli/commands/mcp_tool_commands.py +34 -0
  44. claude_mpm/cli/commands/memory.py +239 -203
  45. claude_mpm/cli/commands/monitor.py +203 -81
  46. claude_mpm/cli/commands/run.py +380 -429
  47. claude_mpm/cli/commands/run_config_checker.py +160 -0
  48. claude_mpm/cli/commands/socketio_monitor.py +235 -0
  49. claude_mpm/cli/commands/tickets.py +305 -197
  50. claude_mpm/cli/parser.py +24 -1156
  51. claude_mpm/cli/parsers/__init__.py +29 -0
  52. claude_mpm/cli/parsers/agents_parser.py +136 -0
  53. claude_mpm/cli/parsers/base_parser.py +331 -0
  54. claude_mpm/cli/parsers/config_parser.py +85 -0
  55. claude_mpm/cli/parsers/mcp_parser.py +152 -0
  56. claude_mpm/cli/parsers/memory_parser.py +138 -0
  57. claude_mpm/cli/parsers/monitor_parser.py +104 -0
  58. claude_mpm/cli/parsers/run_parser.py +147 -0
  59. claude_mpm/cli/parsers/tickets_parser.py +203 -0
  60. claude_mpm/cli/ticket_cli.py +7 -3
  61. claude_mpm/cli/utils.py +55 -37
  62. claude_mpm/cli_module/__init__.py +6 -6
  63. claude_mpm/cli_module/args.py +188 -140
  64. claude_mpm/cli_module/commands.py +79 -70
  65. claude_mpm/cli_module/migration_example.py +38 -60
  66. claude_mpm/config/__init__.py +32 -25
  67. claude_mpm/config/agent_config.py +151 -119
  68. claude_mpm/config/experimental_features.py +71 -73
  69. claude_mpm/config/paths.py +94 -208
  70. claude_mpm/config/socketio_config.py +84 -73
  71. claude_mpm/constants.py +35 -18
  72. claude_mpm/core/__init__.py +9 -6
  73. claude_mpm/core/agent_name_normalizer.py +68 -71
  74. claude_mpm/core/agent_registry.py +372 -521
  75. claude_mpm/core/agent_session_manager.py +74 -63
  76. claude_mpm/core/base_service.py +116 -87
  77. claude_mpm/core/cache.py +119 -153
  78. claude_mpm/core/claude_runner.py +425 -1120
  79. claude_mpm/core/config.py +263 -168
  80. claude_mpm/core/config_aliases.py +69 -61
  81. claude_mpm/core/config_constants.py +292 -0
  82. claude_mpm/core/constants.py +57 -99
  83. claude_mpm/core/container.py +211 -178
  84. claude_mpm/core/exceptions.py +233 -89
  85. claude_mpm/core/factories.py +92 -54
  86. claude_mpm/core/framework_loader.py +378 -220
  87. claude_mpm/core/hook_manager.py +198 -83
  88. claude_mpm/core/hook_performance_config.py +136 -0
  89. claude_mpm/core/injectable_service.py +61 -55
  90. claude_mpm/core/interactive_session.py +165 -155
  91. claude_mpm/core/interfaces.py +221 -195
  92. claude_mpm/core/lazy.py +96 -96
  93. claude_mpm/core/logger.py +133 -107
  94. claude_mpm/core/logging_config.py +185 -157
  95. claude_mpm/core/minimal_framework_loader.py +20 -15
  96. claude_mpm/core/mixins.py +30 -29
  97. claude_mpm/core/oneshot_session.py +215 -181
  98. claude_mpm/core/optimized_agent_loader.py +134 -138
  99. claude_mpm/core/optimized_startup.py +159 -157
  100. claude_mpm/core/pm_hook_interceptor.py +85 -72
  101. claude_mpm/core/service_registry.py +103 -101
  102. claude_mpm/core/session_manager.py +97 -87
  103. claude_mpm/core/socketio_pool.py +212 -158
  104. claude_mpm/core/tool_access_control.py +58 -51
  105. claude_mpm/core/types.py +46 -24
  106. claude_mpm/core/typing_utils.py +166 -82
  107. claude_mpm/core/unified_agent_registry.py +721 -0
  108. claude_mpm/core/unified_config.py +550 -0
  109. claude_mpm/core/unified_paths.py +549 -0
  110. claude_mpm/dashboard/index.html +1 -1
  111. claude_mpm/dashboard/open_dashboard.py +51 -17
  112. claude_mpm/dashboard/static/css/dashboard.css +27 -8
  113. claude_mpm/dashboard/static/dist/components/agent-inference.js +2 -0
  114. claude_mpm/dashboard/static/dist/components/event-processor.js +2 -0
  115. claude_mpm/dashboard/static/dist/components/event-viewer.js +2 -0
  116. claude_mpm/dashboard/static/dist/components/export-manager.js +2 -0
  117. claude_mpm/dashboard/static/dist/components/file-tool-tracker.js +2 -0
  118. claude_mpm/dashboard/static/dist/components/hud-library-loader.js +2 -0
  119. claude_mpm/dashboard/static/dist/components/hud-manager.js +2 -0
  120. claude_mpm/dashboard/static/dist/components/hud-visualizer.js +2 -0
  121. claude_mpm/dashboard/static/dist/components/module-viewer.js +2 -0
  122. claude_mpm/dashboard/static/dist/components/session-manager.js +2 -0
  123. claude_mpm/dashboard/static/dist/components/socket-manager.js +2 -0
  124. claude_mpm/dashboard/static/dist/components/ui-state-manager.js +2 -0
  125. claude_mpm/dashboard/static/dist/components/working-directory.js +2 -0
  126. claude_mpm/dashboard/static/dist/dashboard.js +2 -0
  127. claude_mpm/dashboard/static/dist/socket-client.js +2 -0
  128. claude_mpm/dashboard/static/js/components/agent-inference.js +80 -76
  129. claude_mpm/dashboard/static/js/components/event-processor.js +71 -67
  130. claude_mpm/dashboard/static/js/components/event-viewer.js +74 -70
  131. claude_mpm/dashboard/static/js/components/export-manager.js +31 -28
  132. claude_mpm/dashboard/static/js/components/file-tool-tracker.js +106 -92
  133. claude_mpm/dashboard/static/js/components/hud-library-loader.js +11 -11
  134. claude_mpm/dashboard/static/js/components/hud-manager.js +73 -73
  135. claude_mpm/dashboard/static/js/components/hud-visualizer.js +163 -163
  136. claude_mpm/dashboard/static/js/components/module-viewer.js +305 -233
  137. claude_mpm/dashboard/static/js/components/session-manager.js +32 -29
  138. claude_mpm/dashboard/static/js/components/socket-manager.js +27 -20
  139. claude_mpm/dashboard/static/js/components/ui-state-manager.js +21 -18
  140. claude_mpm/dashboard/static/js/components/working-directory.js +74 -71
  141. claude_mpm/dashboard/static/js/dashboard.js +178 -453
  142. claude_mpm/dashboard/static/js/extension-error-handler.js +164 -0
  143. claude_mpm/dashboard/static/js/socket-client.js +120 -54
  144. claude_mpm/dashboard/templates/index.html +40 -50
  145. claude_mpm/experimental/cli_enhancements.py +60 -58
  146. claude_mpm/generators/__init__.py +1 -1
  147. claude_mpm/generators/agent_profile_generator.py +75 -65
  148. claude_mpm/hooks/__init__.py +1 -1
  149. claude_mpm/hooks/base_hook.py +33 -28
  150. claude_mpm/hooks/claude_hooks/__init__.py +1 -1
  151. claude_mpm/hooks/claude_hooks/connection_pool.py +120 -0
  152. claude_mpm/hooks/claude_hooks/event_handlers.py +743 -0
  153. claude_mpm/hooks/claude_hooks/hook_handler.py +415 -1331
  154. claude_mpm/hooks/claude_hooks/hook_wrapper.sh +4 -4
  155. claude_mpm/hooks/claude_hooks/memory_integration.py +221 -0
  156. claude_mpm/hooks/claude_hooks/response_tracking.py +348 -0
  157. claude_mpm/hooks/claude_hooks/tool_analysis.py +230 -0
  158. claude_mpm/hooks/memory_integration_hook.py +140 -100
  159. claude_mpm/hooks/tool_call_interceptor.py +89 -76
  160. claude_mpm/hooks/validation_hooks.py +57 -49
  161. claude_mpm/init.py +145 -121
  162. claude_mpm/models/__init__.py +9 -9
  163. claude_mpm/models/agent_definition.py +33 -23
  164. claude_mpm/models/agent_session.py +228 -200
  165. claude_mpm/scripts/__init__.py +1 -1
  166. claude_mpm/scripts/socketio_daemon.py +192 -75
  167. claude_mpm/scripts/socketio_server_manager.py +328 -0
  168. claude_mpm/scripts/start_activity_logging.py +25 -22
  169. claude_mpm/services/__init__.py +68 -43
  170. claude_mpm/services/agent_capabilities_service.py +271 -0
  171. claude_mpm/services/agents/__init__.py +23 -32
  172. claude_mpm/services/agents/deployment/__init__.py +3 -3
  173. claude_mpm/services/agents/deployment/agent_config_provider.py +310 -0
  174. claude_mpm/services/agents/deployment/agent_configuration_manager.py +359 -0
  175. claude_mpm/services/agents/deployment/agent_definition_factory.py +84 -0
  176. claude_mpm/services/agents/deployment/agent_deployment.py +415 -2113
  177. claude_mpm/services/agents/deployment/agent_discovery_service.py +387 -0
  178. claude_mpm/services/agents/deployment/agent_environment_manager.py +293 -0
  179. claude_mpm/services/agents/deployment/agent_filesystem_manager.py +387 -0
  180. claude_mpm/services/agents/deployment/agent_format_converter.py +453 -0
  181. claude_mpm/services/agents/deployment/agent_frontmatter_validator.py +161 -0
  182. claude_mpm/services/agents/deployment/agent_lifecycle_manager.py +345 -495
  183. claude_mpm/services/agents/deployment/agent_metrics_collector.py +279 -0
  184. claude_mpm/services/agents/deployment/agent_restore_handler.py +88 -0
  185. claude_mpm/services/agents/deployment/agent_template_builder.py +406 -0
  186. claude_mpm/services/agents/deployment/agent_validator.py +352 -0
  187. claude_mpm/services/agents/deployment/agent_version_manager.py +313 -0
  188. claude_mpm/services/agents/deployment/agent_versioning.py +6 -9
  189. claude_mpm/services/agents/deployment/agents_directory_resolver.py +79 -0
  190. claude_mpm/services/agents/deployment/async_agent_deployment.py +298 -234
  191. claude_mpm/services/agents/deployment/config/__init__.py +13 -0
  192. claude_mpm/services/agents/deployment/config/deployment_config.py +182 -0
  193. claude_mpm/services/agents/deployment/config/deployment_config_manager.py +200 -0
  194. claude_mpm/services/agents/deployment/deployment_config_loader.py +54 -0
  195. claude_mpm/services/agents/deployment/deployment_type_detector.py +124 -0
  196. claude_mpm/services/agents/deployment/facade/__init__.py +18 -0
  197. claude_mpm/services/agents/deployment/facade/async_deployment_executor.py +159 -0
  198. claude_mpm/services/agents/deployment/facade/deployment_executor.py +73 -0
  199. claude_mpm/services/agents/deployment/facade/deployment_facade.py +270 -0
  200. claude_mpm/services/agents/deployment/facade/sync_deployment_executor.py +178 -0
  201. claude_mpm/services/agents/deployment/interface_adapter.py +227 -0
  202. claude_mpm/services/agents/deployment/lifecycle_health_checker.py +85 -0
  203. claude_mpm/services/agents/deployment/lifecycle_performance_tracker.py +100 -0
  204. claude_mpm/services/agents/deployment/pipeline/__init__.py +32 -0
  205. claude_mpm/services/agents/deployment/pipeline/pipeline_builder.py +158 -0
  206. claude_mpm/services/agents/deployment/pipeline/pipeline_context.py +159 -0
  207. claude_mpm/services/agents/deployment/pipeline/pipeline_executor.py +169 -0
  208. claude_mpm/services/agents/deployment/pipeline/steps/__init__.py +19 -0
  209. claude_mpm/services/agents/deployment/pipeline/steps/agent_processing_step.py +195 -0
  210. claude_mpm/services/agents/deployment/pipeline/steps/base_step.py +119 -0
  211. claude_mpm/services/agents/deployment/pipeline/steps/configuration_step.py +79 -0
  212. claude_mpm/services/agents/deployment/pipeline/steps/target_directory_step.py +90 -0
  213. claude_mpm/services/agents/deployment/pipeline/steps/validation_step.py +100 -0
  214. claude_mpm/services/agents/deployment/processors/__init__.py +15 -0
  215. claude_mpm/services/agents/deployment/processors/agent_deployment_context.py +98 -0
  216. claude_mpm/services/agents/deployment/processors/agent_deployment_result.py +235 -0
  217. claude_mpm/services/agents/deployment/processors/agent_processor.py +258 -0
  218. claude_mpm/services/agents/deployment/refactored_agent_deployment_service.py +318 -0
  219. claude_mpm/services/agents/deployment/results/__init__.py +13 -0
  220. claude_mpm/services/agents/deployment/results/deployment_metrics.py +200 -0
  221. claude_mpm/services/agents/deployment/results/deployment_result_builder.py +249 -0
  222. claude_mpm/services/agents/deployment/strategies/__init__.py +25 -0
  223. claude_mpm/services/agents/deployment/strategies/base_strategy.py +119 -0
  224. claude_mpm/services/agents/deployment/strategies/project_strategy.py +150 -0
  225. claude_mpm/services/agents/deployment/strategies/strategy_selector.py +117 -0
  226. claude_mpm/services/agents/deployment/strategies/system_strategy.py +116 -0
  227. claude_mpm/services/agents/deployment/strategies/user_strategy.py +137 -0
  228. claude_mpm/services/agents/deployment/system_instructions_deployer.py +108 -0
  229. claude_mpm/services/agents/deployment/validation/__init__.py +19 -0
  230. claude_mpm/services/agents/deployment/validation/agent_validator.py +323 -0
  231. claude_mpm/services/agents/deployment/validation/deployment_validator.py +238 -0
  232. claude_mpm/services/agents/deployment/validation/template_validator.py +299 -0
  233. claude_mpm/services/agents/deployment/validation/validation_result.py +226 -0
  234. claude_mpm/services/agents/loading/__init__.py +2 -2
  235. claude_mpm/services/agents/loading/agent_profile_loader.py +259 -229
  236. claude_mpm/services/agents/loading/base_agent_manager.py +90 -81
  237. claude_mpm/services/agents/loading/framework_agent_loader.py +154 -129
  238. claude_mpm/services/agents/management/__init__.py +2 -2
  239. claude_mpm/services/agents/management/agent_capabilities_generator.py +72 -58
  240. claude_mpm/services/agents/management/agent_management_service.py +209 -156
  241. claude_mpm/services/agents/memory/__init__.py +9 -6
  242. claude_mpm/services/agents/memory/agent_memory_manager.py +218 -1152
  243. claude_mpm/services/agents/memory/agent_persistence_service.py +20 -16
  244. claude_mpm/services/agents/memory/analyzer.py +430 -0
  245. claude_mpm/services/agents/memory/content_manager.py +376 -0
  246. claude_mpm/services/agents/memory/template_generator.py +468 -0
  247. claude_mpm/services/agents/registry/__init__.py +7 -10
  248. claude_mpm/services/agents/registry/deployed_agent_discovery.py +122 -97
  249. claude_mpm/services/agents/registry/modification_tracker.py +351 -285
  250. claude_mpm/services/async_session_logger.py +187 -153
  251. claude_mpm/services/claude_session_logger.py +87 -72
  252. claude_mpm/services/command_handler_service.py +217 -0
  253. claude_mpm/services/communication/__init__.py +3 -2
  254. claude_mpm/services/core/__init__.py +50 -97
  255. claude_mpm/services/core/base.py +60 -53
  256. claude_mpm/services/core/interfaces/__init__.py +188 -0
  257. claude_mpm/services/core/interfaces/agent.py +351 -0
  258. claude_mpm/services/core/interfaces/communication.py +343 -0
  259. claude_mpm/services/core/interfaces/infrastructure.py +413 -0
  260. claude_mpm/services/core/interfaces/service.py +434 -0
  261. claude_mpm/services/core/interfaces.py +19 -944
  262. claude_mpm/services/event_aggregator.py +208 -170
  263. claude_mpm/services/exceptions.py +387 -308
  264. claude_mpm/services/framework_claude_md_generator/__init__.py +75 -79
  265. claude_mpm/services/framework_claude_md_generator/content_assembler.py +69 -60
  266. claude_mpm/services/framework_claude_md_generator/content_validator.py +65 -61
  267. claude_mpm/services/framework_claude_md_generator/deployment_manager.py +68 -49
  268. claude_mpm/services/framework_claude_md_generator/section_generators/__init__.py +34 -34
  269. claude_mpm/services/framework_claude_md_generator/section_generators/agents.py +25 -22
  270. claude_mpm/services/framework_claude_md_generator/section_generators/claude_pm_init.py +10 -10
  271. claude_mpm/services/framework_claude_md_generator/section_generators/core_responsibilities.py +4 -3
  272. claude_mpm/services/framework_claude_md_generator/section_generators/delegation_constraints.py +4 -3
  273. claude_mpm/services/framework_claude_md_generator/section_generators/environment_config.py +4 -3
  274. claude_mpm/services/framework_claude_md_generator/section_generators/footer.py +6 -5
  275. claude_mpm/services/framework_claude_md_generator/section_generators/header.py +8 -7
  276. claude_mpm/services/framework_claude_md_generator/section_generators/orchestration_principles.py +4 -3
  277. claude_mpm/services/framework_claude_md_generator/section_generators/role_designation.py +6 -5
  278. claude_mpm/services/framework_claude_md_generator/section_generators/subprocess_validation.py +9 -8
  279. claude_mpm/services/framework_claude_md_generator/section_generators/todo_task_tools.py +4 -3
  280. claude_mpm/services/framework_claude_md_generator/section_generators/troubleshooting.py +5 -4
  281. claude_mpm/services/framework_claude_md_generator/section_manager.py +28 -27
  282. claude_mpm/services/framework_claude_md_generator/version_manager.py +30 -28
  283. claude_mpm/services/hook_service.py +106 -114
  284. claude_mpm/services/infrastructure/__init__.py +7 -5
  285. claude_mpm/services/infrastructure/context_preservation.py +233 -199
  286. claude_mpm/services/infrastructure/daemon_manager.py +279 -0
  287. claude_mpm/services/infrastructure/logging.py +83 -76
  288. claude_mpm/services/infrastructure/monitoring.py +547 -404
  289. claude_mpm/services/mcp_gateway/__init__.py +30 -13
  290. claude_mpm/services/mcp_gateway/config/__init__.py +2 -2
  291. claude_mpm/services/mcp_gateway/config/config_loader.py +61 -56
  292. claude_mpm/services/mcp_gateway/config/config_schema.py +50 -41
  293. claude_mpm/services/mcp_gateway/config/configuration.py +82 -75
  294. claude_mpm/services/mcp_gateway/core/__init__.py +13 -20
  295. claude_mpm/services/mcp_gateway/core/base.py +80 -67
  296. claude_mpm/services/mcp_gateway/core/exceptions.py +60 -46
  297. claude_mpm/services/mcp_gateway/core/interfaces.py +87 -84
  298. claude_mpm/services/mcp_gateway/main.py +287 -137
  299. claude_mpm/services/mcp_gateway/registry/__init__.py +1 -1
  300. claude_mpm/services/mcp_gateway/registry/service_registry.py +97 -94
  301. claude_mpm/services/mcp_gateway/registry/tool_registry.py +135 -126
  302. claude_mpm/services/mcp_gateway/server/__init__.py +2 -2
  303. claude_mpm/services/mcp_gateway/server/mcp_gateway.py +105 -110
  304. claude_mpm/services/mcp_gateway/server/stdio_handler.py +105 -107
  305. claude_mpm/services/mcp_gateway/server/stdio_server.py +691 -0
  306. claude_mpm/services/mcp_gateway/tools/__init__.py +4 -2
  307. claude_mpm/services/mcp_gateway/tools/base_adapter.py +109 -119
  308. claude_mpm/services/mcp_gateway/tools/document_summarizer.py +283 -215
  309. claude_mpm/services/mcp_gateway/tools/hello_world.py +122 -120
  310. claude_mpm/services/mcp_gateway/tools/ticket_tools.py +652 -0
  311. claude_mpm/services/mcp_gateway/tools/unified_ticket_tool.py +606 -0
  312. claude_mpm/services/memory/__init__.py +2 -2
  313. claude_mpm/services/memory/builder.py +451 -362
  314. claude_mpm/services/memory/cache/__init__.py +2 -2
  315. claude_mpm/services/memory/cache/shared_prompt_cache.py +232 -194
  316. claude_mpm/services/memory/cache/simple_cache.py +107 -93
  317. claude_mpm/services/memory/indexed_memory.py +195 -193
  318. claude_mpm/services/memory/optimizer.py +267 -234
  319. claude_mpm/services/memory/router.py +571 -263
  320. claude_mpm/services/memory_hook_service.py +237 -0
  321. claude_mpm/services/port_manager.py +223 -0
  322. claude_mpm/services/project/__init__.py +3 -3
  323. claude_mpm/services/project/analyzer.py +451 -305
  324. claude_mpm/services/project/registry.py +262 -240
  325. claude_mpm/services/recovery_manager.py +287 -231
  326. claude_mpm/services/response_tracker.py +87 -67
  327. claude_mpm/services/runner_configuration_service.py +587 -0
  328. claude_mpm/services/session_management_service.py +304 -0
  329. claude_mpm/services/socketio/__init__.py +4 -4
  330. claude_mpm/services/socketio/client_proxy.py +174 -0
  331. claude_mpm/services/socketio/handlers/__init__.py +3 -3
  332. claude_mpm/services/socketio/handlers/base.py +44 -30
  333. claude_mpm/services/socketio/handlers/connection.py +145 -65
  334. claude_mpm/services/socketio/handlers/file.py +123 -108
  335. claude_mpm/services/socketio/handlers/git.py +607 -373
  336. claude_mpm/services/socketio/handlers/hook.py +170 -0
  337. claude_mpm/services/socketio/handlers/memory.py +4 -4
  338. claude_mpm/services/socketio/handlers/project.py +4 -4
  339. claude_mpm/services/socketio/handlers/registry.py +53 -38
  340. claude_mpm/services/socketio/server/__init__.py +18 -0
  341. claude_mpm/services/socketio/server/broadcaster.py +252 -0
  342. claude_mpm/services/socketio/server/core.py +399 -0
  343. claude_mpm/services/socketio/server/main.py +323 -0
  344. claude_mpm/services/socketio_client_manager.py +160 -133
  345. claude_mpm/services/socketio_server.py +36 -1885
  346. claude_mpm/services/subprocess_launcher_service.py +316 -0
  347. claude_mpm/services/system_instructions_service.py +258 -0
  348. claude_mpm/services/ticket_manager.py +19 -533
  349. claude_mpm/services/utility_service.py +285 -0
  350. claude_mpm/services/version_control/__init__.py +18 -21
  351. claude_mpm/services/version_control/branch_strategy.py +20 -10
  352. claude_mpm/services/version_control/conflict_resolution.py +37 -13
  353. claude_mpm/services/version_control/git_operations.py +52 -21
  354. claude_mpm/services/version_control/semantic_versioning.py +92 -53
  355. claude_mpm/services/version_control/version_parser.py +145 -125
  356. claude_mpm/services/version_service.py +270 -0
  357. claude_mpm/storage/__init__.py +2 -2
  358. claude_mpm/storage/state_storage.py +177 -181
  359. claude_mpm/ticket_wrapper.py +2 -2
  360. claude_mpm/utils/__init__.py +2 -2
  361. claude_mpm/utils/agent_dependency_loader.py +453 -243
  362. claude_mpm/utils/config_manager.py +157 -118
  363. claude_mpm/utils/console.py +1 -1
  364. claude_mpm/utils/dependency_cache.py +102 -107
  365. claude_mpm/utils/dependency_manager.py +52 -47
  366. claude_mpm/utils/dependency_strategies.py +131 -96
  367. claude_mpm/utils/environment_context.py +110 -102
  368. claude_mpm/utils/error_handler.py +75 -55
  369. claude_mpm/utils/file_utils.py +80 -67
  370. claude_mpm/utils/framework_detection.py +12 -11
  371. claude_mpm/utils/import_migration_example.py +12 -60
  372. claude_mpm/utils/imports.py +48 -45
  373. claude_mpm/utils/path_operations.py +100 -93
  374. claude_mpm/utils/robust_installer.py +172 -164
  375. claude_mpm/utils/session_logging.py +30 -23
  376. claude_mpm/utils/subprocess_utils.py +99 -61
  377. claude_mpm/validation/__init__.py +1 -1
  378. claude_mpm/validation/agent_validator.py +151 -111
  379. claude_mpm/validation/frontmatter_validator.py +92 -71
  380. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/METADATA +27 -1
  381. claude_mpm-4.0.3.dist-info/RECORD +402 -0
  382. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/entry_points.txt +1 -0
  383. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/licenses/LICENSE +1 -1
  384. claude_mpm/cli/commands/run_guarded.py +0 -511
  385. claude_mpm/config/memory_guardian_config.py +0 -325
  386. claude_mpm/config/memory_guardian_yaml.py +0 -335
  387. claude_mpm/core/config_paths.py +0 -150
  388. claude_mpm/core/memory_aware_runner.py +0 -353
  389. claude_mpm/dashboard/static/js/dashboard-original.js +0 -4134
  390. claude_mpm/deployment_paths.py +0 -261
  391. claude_mpm/hooks/claude_hooks/hook_handler_fixed.py +0 -454
  392. claude_mpm/models/state_models.py +0 -433
  393. claude_mpm/services/agent/__init__.py +0 -24
  394. claude_mpm/services/agent/deployment.py +0 -2548
  395. claude_mpm/services/agent/management.py +0 -598
  396. claude_mpm/services/agent/registry.py +0 -813
  397. claude_mpm/services/agents/registry/agent_registry.py +0 -813
  398. claude_mpm/services/communication/socketio.py +0 -1935
  399. claude_mpm/services/communication/websocket.py +0 -479
  400. claude_mpm/services/framework_claude_md_generator.py +0 -624
  401. claude_mpm/services/health_monitor.py +0 -893
  402. claude_mpm/services/infrastructure/graceful_degradation.py +0 -616
  403. claude_mpm/services/infrastructure/health_monitor.py +0 -775
  404. claude_mpm/services/infrastructure/memory_dashboard.py +0 -479
  405. claude_mpm/services/infrastructure/memory_guardian.py +0 -944
  406. claude_mpm/services/infrastructure/restart_protection.py +0 -642
  407. claude_mpm/services/infrastructure/state_manager.py +0 -774
  408. claude_mpm/services/mcp_gateway/manager.py +0 -334
  409. claude_mpm/services/optimized_hook_service.py +0 -542
  410. claude_mpm/services/project_analyzer.py +0 -864
  411. claude_mpm/services/project_registry.py +0 -608
  412. claude_mpm/services/standalone_socketio_server.py +0 -1300
  413. claude_mpm/services/ticket_manager_di.py +0 -318
  414. claude_mpm/services/ticketing_service_original.py +0 -510
  415. claude_mpm/utils/paths.py +0 -395
  416. claude_mpm/utils/platform_memory.py +0 -524
  417. claude_mpm-3.9.11.dist-info/RECORD +0 -306
  418. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/WHEEL +0 -0
  419. {claude_mpm-3.9.11.dist-info → claude_mpm-4.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,279 @@
1
+ from pathlib import Path
2
+
3
+ #!/usr/bin/env python3
4
+ """
5
+ Daemon Management Service for Socket.IO Server
6
+ ==============================================
7
+
8
+ Provides daemon management functionality for the Socket.IO server including
9
+ start, stop, restart, and status operations with proper process management.
10
+
11
+ This service handles:
12
+ - Process lifecycle management (start/stop/restart)
13
+ - PID file management
14
+ - Signal handling for graceful shutdown
15
+ - Conflict detection with other server instances
16
+ - Status monitoring and health checks
17
+ """
18
+
19
+ import logging
20
+ import os
21
+ import signal
22
+ import subprocess
23
+ import sys
24
+ import time
25
+ from typing import Any, Dict, Optional
26
+
27
+ try:
28
+ import psutil
29
+ except ImportError:
30
+ # Auto-install psutil if not available
31
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "psutil"])
32
+ import psutil
33
+
34
+ # from claude_mpm.core.base_service import BaseService
35
+ from claude_mpm.services.socketio.server.main import SocketIOServer
36
+
37
+ logger = logging.getLogger(__name__)
38
+
39
+
40
+ class SocketIODaemonManager:
41
+ """
42
+ Daemon management service for Socket.IO server.
43
+
44
+ Provides comprehensive daemon lifecycle management including process
45
+ monitoring, conflict detection, and graceful shutdown handling.
46
+ """
47
+
48
+ def __init__(self, host: str = "localhost", port: int = 8765):
49
+ """
50
+ Initialize the daemon manager.
51
+
52
+ Args:
53
+ host: Host to bind the server to
54
+ port: Port to bind the server to
55
+ """
56
+ # super().__init__()
57
+ self.host = host
58
+ self.port = port
59
+
60
+ # Configuration paths
61
+ self.config_dir = Path.home() / ".claude-mpm"
62
+ self.pid_file = self.config_dir / "socketio-server.pid"
63
+ self.log_file = self.config_dir / "socketio-server.log"
64
+
65
+ # Ensure directories exist
66
+ self._ensure_directories()
67
+
68
+ def _ensure_directories(self) -> None:
69
+ """Ensure required directories exist."""
70
+ self.config_dir.mkdir(parents=True, exist_ok=True)
71
+
72
+ def is_running(self) -> bool:
73
+ """
74
+ Check if the daemon server is currently running.
75
+
76
+ Returns:
77
+ True if server is running, False otherwise
78
+ """
79
+ if not self.pid_file.exists():
80
+ return False
81
+
82
+ try:
83
+ with open(self.pid_file) as f:
84
+ pid = int(f.read().strip())
85
+
86
+ # Check if process exists and is running
87
+ process = psutil.Process(pid)
88
+ return process.is_running()
89
+
90
+ except (ValueError, psutil.NoSuchProcess, psutil.AccessDenied):
91
+ # Clean up stale PID file
92
+ self.pid_file.unlink(missing_ok=True)
93
+ return False
94
+
95
+ def _check_port_conflict(self) -> Optional[Dict[str, Any]]:
96
+ """
97
+ Check for existing server on the target port.
98
+
99
+ Returns:
100
+ Server info if conflict detected, None otherwise
101
+ """
102
+ try:
103
+ import requests
104
+
105
+ response = requests.get(
106
+ f"http://{self.host}:{self.port}/health", timeout=1.0
107
+ )
108
+ if response.status_code == 200:
109
+ return response.json()
110
+ except:
111
+ pass
112
+ return None
113
+
114
+ def start(self) -> bool:
115
+ """
116
+ Start the Socket.IO server as a daemon.
117
+
118
+ Returns:
119
+ True if started successfully, False otherwise
120
+ """
121
+ if self.is_running():
122
+ logger.info("Socket.IO daemon server is already running")
123
+ return False
124
+
125
+ # Check for port conflicts
126
+ conflict_info = self._check_port_conflict()
127
+ if conflict_info and "server_id" in conflict_info:
128
+ logger.warning(
129
+ f"Port {self.port} already in use by: {conflict_info.get('server_id')}"
130
+ )
131
+ return False
132
+
133
+ try:
134
+ # Fork to create daemon process
135
+ pid = os.fork()
136
+ if pid > 0:
137
+ # Parent process - save PID and exit
138
+ with open(self.pid_file, "w") as f:
139
+ f.write(str(pid))
140
+ logger.info(f"Socket.IO server started as daemon (PID: {pid})")
141
+ return True
142
+
143
+ # Child process - become daemon
144
+ self._daemonize()
145
+ self._run_server()
146
+
147
+ except Exception as e:
148
+ logger.error(f"Failed to start daemon: {e}")
149
+ return False
150
+
151
+ def _daemonize(self) -> None:
152
+ """Convert the current process into a daemon."""
153
+ # Create new session
154
+ os.setsid()
155
+ os.umask(0)
156
+
157
+ # Redirect stdout/stderr to log file
158
+ with open(self.log_file, "a") as log:
159
+ os.dup2(log.fileno(), sys.stdout.fileno())
160
+ os.dup2(log.fileno(), sys.stderr.fileno())
161
+
162
+ def _run_server(self) -> None:
163
+ """Run the Socket.IO server in daemon mode."""
164
+ print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Starting Socket.IO server...")
165
+
166
+ # Create and configure server
167
+ server = SocketIOServer(host=self.host, port=self.port)
168
+
169
+ # Setup signal handlers
170
+ def signal_handler(signum, frame):
171
+ print(
172
+ f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] Received signal {signum}, shutting down..."
173
+ )
174
+ server.stop()
175
+ self.pid_file.unlink(missing_ok=True)
176
+ sys.exit(0)
177
+
178
+ signal.signal(signal.SIGTERM, signal_handler)
179
+ signal.signal(signal.SIGINT, signal_handler)
180
+
181
+ # Start server and keep running
182
+ server.start()
183
+
184
+ try:
185
+ while True:
186
+ time.sleep(1)
187
+ except KeyboardInterrupt:
188
+ signal_handler(signal.SIGINT, None)
189
+
190
+ def stop(self) -> bool:
191
+ """
192
+ Stop the daemon server.
193
+
194
+ Returns:
195
+ True if stopped successfully, False otherwise
196
+ """
197
+ if not self.is_running():
198
+ logger.info("Socket.IO daemon server is not running")
199
+ return False
200
+
201
+ try:
202
+ with open(self.pid_file) as f:
203
+ pid = int(f.read().strip())
204
+
205
+ logger.info(f"Stopping Socket.IO server (PID: {pid})")
206
+
207
+ # Send SIGTERM for graceful shutdown
208
+ os.kill(pid, signal.SIGTERM)
209
+
210
+ # Wait for graceful shutdown
211
+ for _ in range(10):
212
+ if not self.is_running():
213
+ logger.info("Socket.IO server stopped successfully")
214
+ self.pid_file.unlink(missing_ok=True)
215
+ return True
216
+ time.sleep(0.5)
217
+
218
+ # Force kill if still running
219
+ logger.warning("Server didn't stop gracefully, forcing shutdown")
220
+ os.kill(pid, signal.SIGKILL)
221
+ self.pid_file.unlink(missing_ok=True)
222
+ return True
223
+
224
+ except Exception as e:
225
+ logger.error(f"Error stopping server: {e}")
226
+ return False
227
+
228
+ def restart(self) -> bool:
229
+ """
230
+ Restart the daemon server.
231
+
232
+ Returns:
233
+ True if restarted successfully, False otherwise
234
+ """
235
+ logger.info("Restarting Socket.IO daemon server")
236
+ self.stop()
237
+ time.sleep(1)
238
+ return self.start()
239
+
240
+ def status(self) -> Dict[str, Any]:
241
+ """
242
+ Get detailed status information about the daemon.
243
+
244
+ Returns:
245
+ Dictionary containing status information
246
+ """
247
+ status_info = {
248
+ "running": self.is_running(),
249
+ "pid_file": str(self.pid_file),
250
+ "log_file": str(self.log_file),
251
+ "host": self.host,
252
+ "port": self.port,
253
+ "management_style": "daemon",
254
+ }
255
+
256
+ if status_info["running"]:
257
+ with open(self.pid_file) as f:
258
+ status_info["pid"] = int(f.read().strip())
259
+
260
+ # Check port accessibility
261
+ try:
262
+ import socket
263
+
264
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
265
+ result = sock.connect_ex((self.host, self.port))
266
+ sock.close()
267
+ status_info["port_accessible"] = result == 0
268
+ except:
269
+ status_info["port_accessible"] = False
270
+
271
+ # Check for conflicts
272
+ conflict_info = self._check_port_conflict()
273
+ if conflict_info and "server_id" in conflict_info:
274
+ server_id = conflict_info.get("server_id")
275
+ if server_id != "daemon-socketio":
276
+ status_info["conflict_detected"] = True
277
+ status_info["conflicting_server"] = server_id
278
+
279
+ return status_info
@@ -1,3 +1,5 @@
1
+ from pathlib import Path
2
+
1
3
  """
2
4
  Logging Service for Claude MPM Framework
3
5
  ========================================
@@ -7,62 +9,61 @@ This module provides centralized logging services and utilities.
7
9
  Part of TSK-0046: Service Layer Architecture Reorganization
8
10
  """
9
11
 
10
- from typing import Any, Dict, Optional, List
11
- from pathlib import Path
12
- import logging
13
12
  import json
13
+ import logging
14
14
  from datetime import datetime
15
+ from typing import Any, Dict, List, Optional
15
16
 
16
- from claude_mpm.services.core import SyncBaseService, IStructuredLogger
17
17
  from claude_mpm.core.logger import get_logger
18
+ from claude_mpm.services.core import IStructuredLogger, SyncBaseService
18
19
 
19
20
 
20
21
  class LoggingService(SyncBaseService, IStructuredLogger):
21
22
  """
22
23
  Centralized logging service for the Claude MPM framework.
23
-
24
+
24
25
  This service provides:
25
26
  - Structured logging with JSON output
26
27
  - Log rotation and archival
27
28
  - Performance metrics logging
28
29
  - Audit trail capabilities
29
30
  """
30
-
31
+
31
32
  def __init__(self, config: Optional[Dict[str, Any]] = None):
32
33
  """
33
34
  Initialize logging service.
34
-
35
+
35
36
  Args:
36
37
  config: Logging configuration
37
38
  """
38
39
  super().__init__("LoggingService", config)
39
- self.log_dir = Path(self.get_config('log_dir', '.claude-mpm/logs'))
40
- self.log_level = self.get_config('log_level', 'INFO')
41
- self.structured_logging = self.get_config('structured_logging', True)
40
+ self.log_dir = Path(self.get_config("log_dir", ".claude-mpm/logs"))
41
+ self.log_level = self.get_config("log_level", "INFO")
42
+ self.structured_logging = self.get_config("structured_logging", True)
42
43
  self._log_handlers = []
43
-
44
+
44
45
  def initialize(self) -> bool:
45
46
  """Initialize the logging service."""
46
47
  try:
47
48
  # Create log directory if it doesn't exist
48
49
  self.log_dir.mkdir(parents=True, exist_ok=True)
49
-
50
+
50
51
  # Set up log rotation if configured
51
- if self.get_config('enable_rotation', True):
52
+ if self.get_config("enable_rotation", True):
52
53
  self._setup_rotation()
53
-
54
+
54
55
  # Set up structured logging if enabled
55
56
  if self.structured_logging:
56
57
  self._setup_structured_logging()
57
-
58
+
58
59
  self._initialized = True
59
60
  self.log_info("Logging service initialized successfully")
60
61
  return True
61
-
62
+
62
63
  except Exception as e:
63
64
  self.log_error(f"Failed to initialize logging service: {e}")
64
65
  return False
65
-
66
+
66
67
  def shutdown(self) -> None:
67
68
  """Shutdown the logging service."""
68
69
  try:
@@ -70,133 +71,139 @@ class LoggingService(SyncBaseService, IStructuredLogger):
70
71
  for handler in self._log_handlers:
71
72
  handler.flush()
72
73
  handler.close()
73
-
74
+
74
75
  self._log_handlers.clear()
75
76
  self._shutdown = True
76
77
  self.log_info("Logging service shutdown successfully")
77
-
78
+
78
79
  except Exception as e:
79
80
  self.log_error(f"Error during logging service shutdown: {e}")
80
-
81
+
81
82
  def log(self, level: str, message: str, **context) -> None:
82
83
  """
83
84
  Log a message with context.
84
-
85
+
85
86
  Args:
86
87
  level: Log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
87
88
  message: Log message
88
89
  **context: Additional context to include
89
90
  """
90
- logger = get_logger(context.get('component', 'default'))
91
-
91
+ logger = get_logger(context.get("component", "default"))
92
+
92
93
  if self.structured_logging:
93
94
  log_entry = {
94
- 'timestamp': datetime.utcnow().isoformat(),
95
- 'level': level,
96
- 'message': message,
97
- 'context': context
95
+ "timestamp": datetime.utcnow().isoformat(),
96
+ "level": level,
97
+ "message": message,
98
+ "context": context,
98
99
  }
99
100
  message = json.dumps(log_entry)
100
-
101
+
101
102
  log_method = getattr(logger, level.lower(), logger.info)
102
103
  log_method(message)
103
-
104
+
104
105
  def log_performance(self, operation: str, duration: float, **metrics) -> None:
105
106
  """
106
107
  Log performance metrics.
107
-
108
+
108
109
  Args:
109
110
  operation: Name of the operation
110
111
  duration: Duration in seconds
111
112
  **metrics: Additional performance metrics
112
113
  """
113
- self.log('INFO', f"Performance: {operation}",
114
- operation=operation,
115
- duration_ms=duration * 1000,
116
- **metrics)
117
-
114
+ self.log(
115
+ "INFO",
116
+ f"Performance: {operation}",
117
+ operation=operation,
118
+ duration_ms=duration * 1000,
119
+ **metrics,
120
+ )
121
+
118
122
  def log_audit(self, action: str, user: str, **details) -> None:
119
123
  """
120
124
  Log an audit event.
121
-
125
+
122
126
  Args:
123
127
  action: Action performed
124
128
  user: User who performed the action
125
129
  **details: Additional audit details
126
130
  """
127
- self.log('INFO', f"Audit: {action} by {user}",
128
- audit=True,
129
- action=action,
130
- user=user,
131
- **details)
132
-
133
- def get_logs(self, level: Optional[str] = None,
134
- component: Optional[str] = None,
135
- limit: int = 100) -> List[Dict[str, Any]]:
131
+ self.log(
132
+ "INFO",
133
+ f"Audit: {action} by {user}",
134
+ audit=True,
135
+ action=action,
136
+ user=user,
137
+ **details,
138
+ )
139
+
140
+ def get_logs(
141
+ self,
142
+ level: Optional[str] = None,
143
+ component: Optional[str] = None,
144
+ limit: int = 100,
145
+ ) -> List[Dict[str, Any]]:
136
146
  """
137
147
  Retrieve recent logs.
138
-
148
+
139
149
  Args:
140
150
  level: Filter by log level
141
151
  component: Filter by component
142
152
  limit: Maximum number of logs to return
143
-
153
+
144
154
  Returns:
145
155
  List of log entries
146
156
  """
147
157
  # This would typically read from log files or a log aggregation service
148
158
  # For now, return empty list as placeholder
149
159
  return []
150
-
160
+
151
161
  def _setup_rotation(self) -> None:
152
162
  """Set up log rotation."""
153
163
  from logging.handlers import RotatingFileHandler
154
-
155
- max_bytes = self.get_config('max_bytes', 10 * 1024 * 1024) # 10MB
156
- backup_count = self.get_config('backup_count', 5)
157
-
164
+
165
+ max_bytes = self.get_config("max_bytes", 10 * 1024 * 1024) # 10MB
166
+ backup_count = self.get_config("backup_count", 5)
167
+
158
168
  handler = RotatingFileHandler(
159
- self.log_dir / 'claude_mpm.log',
169
+ self.log_dir / "claude_mpm.log",
160
170
  maxBytes=max_bytes,
161
- backupCount=backup_count
171
+ backupCount=backup_count,
162
172
  )
163
-
173
+
164
174
  formatter = logging.Formatter(
165
- '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
175
+ "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
166
176
  )
167
177
  handler.setFormatter(formatter)
168
-
178
+
169
179
  self._log_handlers.append(handler)
170
180
  logging.getLogger().addHandler(handler)
171
-
181
+
172
182
  def _setup_structured_logging(self) -> None:
173
183
  """Set up structured JSON logging."""
174
184
  import logging.config
175
-
185
+
176
186
  config = {
177
- 'version': 1,
178
- 'disable_existing_loggers': False,
179
- 'formatters': {
180
- 'json': {
181
- 'class': 'pythonjsonlogger.jsonlogger.JsonFormatter',
182
- 'format': '%(asctime)s %(name)s %(levelname)s %(message)s'
187
+ "version": 1,
188
+ "disable_existing_loggers": False,
189
+ "formatters": {
190
+ "json": {
191
+ "class": "pythonjsonlogger.jsonlogger.JsonFormatter",
192
+ "format": "%(asctime)s %(name)s %(levelname)s %(message)s",
183
193
  }
184
194
  },
185
- 'handlers': {
186
- 'json_file': {
187
- 'class': 'logging.FileHandler',
188
- 'filename': str(self.log_dir / 'structured.json'),
189
- 'formatter': 'json'
195
+ "handlers": {
196
+ "json_file": {
197
+ "class": "logging.FileHandler",
198
+ "filename": str(self.log_dir / "structured.json"),
199
+ "formatter": "json",
190
200
  }
191
201
  },
192
- 'root': {
193
- 'handlers': ['json_file'],
194
- 'level': self.log_level
195
- }
202
+ "root": {"handlers": ["json_file"], "level": self.log_level},
196
203
  }
197
-
204
+
198
205
  try:
199
206
  logging.config.dictConfig(config)
200
207
  except ImportError:
201
208
  # If pythonjsonlogger is not available, fall back to regular logging
202
- self.log_warning("pythonjsonlogger not available, using standard logging")
209
+ self.log_warning("pythonjsonlogger not available, using standard logging")