claude-mpm 5.4.41__py3-none-any.whl → 5.6.72__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.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +161 -298
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/auth/__init__.py +35 -0
- claude_mpm/auth/callback_server.py +328 -0
- claude_mpm/auth/models.py +104 -0
- claude_mpm/auth/oauth_manager.py +266 -0
- claude_mpm/auth/providers/__init__.py +12 -0
- claude_mpm/auth/providers/base.py +165 -0
- claude_mpm/auth/providers/google.py +261 -0
- claude_mpm/auth/token_storage.py +252 -0
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/mcp.py +29 -17
- claude_mpm/cli/commands/mcp_command_router.py +39 -0
- claude_mpm/cli/commands/mcp_service_commands.py +304 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +15 -8
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/profile.py +9 -10
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +129 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +30 -50
- claude_mpm/cli/interactive/questionary_styles.py +65 -0
- claude_mpm/cli/interactive/skill_selector.py +481 -0
- claude_mpm/cli/parsers/base_parser.py +89 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/mcp_parser.py +79 -0
- claude_mpm/cli/parsers/oauth_parser.py +165 -0
- claude_mpm/cli/parsers/profile_parser.py +0 -1
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +662 -524
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +149 -0
- claude_mpm/commander/chat/commands.py +122 -0
- claude_mpm/commander/chat/repl.py +1821 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +392 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +233 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +57 -0
- claude_mpm/commander/git/__init__.py +5 -0
- claude_mpm/commander/git/worktree_manager.py +212 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +865 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +127 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +403 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +362 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +6 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +53 -4
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +3 -1
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +11 -11
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +291 -59
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +326 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +224 -4
- claude_mpm/mcp/__init__.py +9 -0
- claude_mpm/mcp/google_workspace_server.py +610 -0
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +37 -17
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +36 -8
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +50 -26
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +21 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/agents/sources/git_source_sync_service.py +116 -5
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/mcp_config_manager.py +99 -19
- claude_mpm/services/mcp_service_registry.py +294 -0
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -3
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +302 -94
- claude_mpm/services/profile_manager.py +10 -4
- claude_mpm/services/skills/git_skill_source_manager.py +192 -29
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +29 -23
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.6.72.dist-info/METADATA +416 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/RECORD +477 -159
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/entry_points.txt +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm-5.4.41.dist-info/METADATA +0 -998
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.41.dist-info → claude_mpm-5.6.72.dist-info}/top_level.txt +0 -0
|
@@ -8,13 +8,21 @@ with their original requests.
|
|
|
8
8
|
import json
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
-
import sys
|
|
12
11
|
from datetime import datetime, timezone
|
|
13
12
|
from pathlib import Path
|
|
14
13
|
from typing import Any, Optional
|
|
15
14
|
|
|
15
|
+
# Try to import _log from hook_handler, fall back to no-op
|
|
16
|
+
try:
|
|
17
|
+
from claude_mpm.hooks.claude_hooks.hook_handler import _log
|
|
18
|
+
except ImportError:
|
|
19
|
+
|
|
20
|
+
def _log(msg: str) -> None:
|
|
21
|
+
pass # Silent fallback
|
|
22
|
+
|
|
23
|
+
|
|
16
24
|
# Debug mode
|
|
17
|
-
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "
|
|
25
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
18
26
|
|
|
19
27
|
# Response tracking integration
|
|
20
28
|
# NOTE: ResponseTracker import moved to _initialize_response_tracking() for lazy loading
|
|
@@ -80,10 +88,7 @@ class ResponseTrackingManager:
|
|
|
80
88
|
|
|
81
89
|
if not (response_tracking_enabled or response_logging_enabled):
|
|
82
90
|
if DEBUG:
|
|
83
|
-
|
|
84
|
-
"Response tracking disabled - skipping initialization",
|
|
85
|
-
file=sys.stderr,
|
|
86
|
-
)
|
|
91
|
+
_log("Response tracking disabled - skipping initialization")
|
|
87
92
|
return
|
|
88
93
|
|
|
89
94
|
# Initialize response tracker with config
|
|
@@ -101,15 +106,11 @@ class ResponseTrackingManager:
|
|
|
101
106
|
if self.track_all_interactions
|
|
102
107
|
else "Task delegations only"
|
|
103
108
|
)
|
|
104
|
-
|
|
105
|
-
f"✅ Response tracking initialized (mode: {mode})", file=sys.stderr
|
|
106
|
-
)
|
|
109
|
+
_log(f"✅ Response tracking initialized (mode: {mode})")
|
|
107
110
|
|
|
108
111
|
except Exception as e:
|
|
109
112
|
if DEBUG:
|
|
110
|
-
|
|
111
|
-
f"❌ Failed to initialize response tracking: {e}", file=sys.stderr
|
|
112
|
-
)
|
|
113
|
+
_log(f"❌ Failed to initialize response tracking: {e}")
|
|
113
114
|
# Don't fail the entire handler - response tracking is optional
|
|
114
115
|
|
|
115
116
|
def track_agent_response(
|
|
@@ -130,12 +131,11 @@ class ResponseTrackingManager:
|
|
|
130
131
|
|
|
131
132
|
try:
|
|
132
133
|
# Get the original request data stored during pre-tool
|
|
133
|
-
request_info = delegation_requests.get(session_id)
|
|
134
|
+
request_info = delegation_requests.get(session_id) # nosec B113 - False positive: dict.get(), not requests library
|
|
134
135
|
if not request_info:
|
|
135
136
|
if DEBUG:
|
|
136
|
-
|
|
137
|
-
f"No request data found for session {session_id}, skipping response tracking"
|
|
138
|
-
file=sys.stderr,
|
|
137
|
+
_log(
|
|
138
|
+
f"No request data found for session {session_id}, skipping response tracking"
|
|
139
139
|
)
|
|
140
140
|
return
|
|
141
141
|
|
|
@@ -163,15 +163,11 @@ class ResponseTrackingManager:
|
|
|
163
163
|
if json_match:
|
|
164
164
|
structured_response = json.loads(json_match.group(1))
|
|
165
165
|
if DEBUG:
|
|
166
|
-
|
|
167
|
-
f"Extracted structured response from {agent_type} agent",
|
|
168
|
-
file=sys.stderr,
|
|
169
|
-
)
|
|
166
|
+
_log(f"Extracted structured response from {agent_type} agent")
|
|
170
167
|
except (json.JSONDecodeError, AttributeError) as e:
|
|
171
168
|
if DEBUG:
|
|
172
|
-
|
|
173
|
-
f"No structured JSON response found in {agent_type} agent output: {e}"
|
|
174
|
-
file=sys.stderr,
|
|
169
|
+
_log(
|
|
170
|
+
f"No structured JSON response found in {agent_type} agent output: {e}"
|
|
175
171
|
)
|
|
176
172
|
|
|
177
173
|
# Get the original request (prompt + description)
|
|
@@ -220,9 +216,8 @@ class ResponseTrackingManager:
|
|
|
220
216
|
if structured_response.get("MEMORIES"):
|
|
221
217
|
if DEBUG:
|
|
222
218
|
memories_count = len(structured_response["MEMORIES"])
|
|
223
|
-
|
|
224
|
-
f"Agent {agent_type} returned MEMORIES field with {memories_count} items"
|
|
225
|
-
file=sys.stderr,
|
|
219
|
+
_log(
|
|
220
|
+
f"Agent {agent_type} returned MEMORIES field with {memories_count} items"
|
|
226
221
|
)
|
|
227
222
|
|
|
228
223
|
# Check if task was completed for logging purposes
|
|
@@ -232,9 +227,7 @@ class ResponseTrackingManager:
|
|
|
232
227
|
# Log files modified for debugging
|
|
233
228
|
if DEBUG and structured_response.get("files_modified"):
|
|
234
229
|
files = [f["file"] for f in structured_response["files_modified"]]
|
|
235
|
-
|
|
236
|
-
f"Agent {agent_type} modified files: {files}", file=sys.stderr
|
|
237
|
-
)
|
|
230
|
+
_log(f"Agent {agent_type} modified files: {files}")
|
|
238
231
|
|
|
239
232
|
# Track the response
|
|
240
233
|
file_path = self.response_tracker.track_response(
|
|
@@ -246,14 +239,12 @@ class ResponseTrackingManager:
|
|
|
246
239
|
)
|
|
247
240
|
|
|
248
241
|
if file_path and DEBUG:
|
|
249
|
-
|
|
250
|
-
f"✅ Tracked response for {agent_type} agent in session {session_id}: {file_path.name}"
|
|
251
|
-
file=sys.stderr,
|
|
242
|
+
_log(
|
|
243
|
+
f"✅ Tracked response for {agent_type} agent in session {session_id}: {file_path.name}"
|
|
252
244
|
)
|
|
253
245
|
elif DEBUG and not file_path:
|
|
254
|
-
|
|
255
|
-
f"Response tracking returned None for {agent_type} agent (might be excluded or disabled)"
|
|
256
|
-
file=sys.stderr,
|
|
246
|
+
_log(
|
|
247
|
+
f"Response tracking returned None for {agent_type} agent (might be excluded or disabled)"
|
|
257
248
|
)
|
|
258
249
|
|
|
259
250
|
# Clean up the request data after successful tracking
|
|
@@ -261,7 +252,7 @@ class ResponseTrackingManager:
|
|
|
261
252
|
|
|
262
253
|
except Exception as e:
|
|
263
254
|
if DEBUG:
|
|
264
|
-
|
|
255
|
+
_log(f"❌ Failed to track agent response: {e}")
|
|
265
256
|
# Don't fail the hook processing - response tracking is optional
|
|
266
257
|
|
|
267
258
|
def track_stop_response(
|
|
@@ -286,11 +277,10 @@ class ResponseTrackingManager:
|
|
|
286
277
|
prompt_data = pending_prompts.get(session_id)
|
|
287
278
|
|
|
288
279
|
if DEBUG:
|
|
289
|
-
|
|
290
|
-
f" - output present: {bool(output)} (length: {len(str(output)) if output else 0})"
|
|
291
|
-
file=sys.stderr,
|
|
280
|
+
_log(
|
|
281
|
+
f" - output present: {bool(output)} (length: {len(str(output)) if output else 0})"
|
|
292
282
|
)
|
|
293
|
-
|
|
283
|
+
_log(f" - prompt_data present: {bool(prompt_data)}")
|
|
294
284
|
|
|
295
285
|
if output and prompt_data:
|
|
296
286
|
# Add prompt timestamp to metadata
|
|
@@ -300,12 +290,11 @@ class ResponseTrackingManager:
|
|
|
300
290
|
if "stop_reason" in event:
|
|
301
291
|
metadata["stop_reason"] = event["stop_reason"]
|
|
302
292
|
if DEBUG:
|
|
303
|
-
|
|
304
|
-
f" - Captured stop_reason: {event['stop_reason']}",
|
|
305
|
-
file=sys.stderr,
|
|
306
|
-
)
|
|
293
|
+
_log(f" - Captured stop_reason: {event['stop_reason']}")
|
|
307
294
|
|
|
308
295
|
# Capture Claude API usage data if available
|
|
296
|
+
# NOTE: Usage data is already captured in metadata by handle_stop_fast()
|
|
297
|
+
# which also handles auto-pause triggering (even when response tracking disabled)
|
|
309
298
|
if "usage" in event:
|
|
310
299
|
usage_data = event["usage"]
|
|
311
300
|
metadata["usage"] = {
|
|
@@ -322,10 +311,7 @@ class ResponseTrackingManager:
|
|
|
322
311
|
total_tokens = usage_data.get(
|
|
323
312
|
"input_tokens", 0
|
|
324
313
|
) + usage_data.get("output_tokens", 0)
|
|
325
|
-
|
|
326
|
-
f" - Captured usage: {total_tokens} total tokens",
|
|
327
|
-
file=sys.stderr,
|
|
328
|
-
)
|
|
314
|
+
_log(f" - Captured usage: {total_tokens} total tokens")
|
|
329
315
|
|
|
330
316
|
# Track the main Claude response
|
|
331
317
|
file_path = self.response_tracker.track_response(
|
|
@@ -337,14 +323,14 @@ class ResponseTrackingManager:
|
|
|
337
323
|
)
|
|
338
324
|
|
|
339
325
|
if file_path and DEBUG:
|
|
340
|
-
|
|
326
|
+
_log(f" - Response tracked to: {file_path}")
|
|
341
327
|
|
|
342
328
|
# Clean up pending prompt
|
|
343
329
|
del pending_prompts[session_id]
|
|
344
330
|
|
|
345
331
|
except Exception as e:
|
|
346
332
|
if DEBUG:
|
|
347
|
-
|
|
333
|
+
_log(f"Error tracking stop response: {e}")
|
|
348
334
|
|
|
349
335
|
def track_assistant_response(self, event: dict, pending_prompts: dict):
|
|
350
336
|
"""Handle assistant response events for comprehensive response tracking."""
|
|
@@ -359,9 +345,8 @@ class ResponseTrackingManager:
|
|
|
359
345
|
prompt_data = pending_prompts.get(session_id)
|
|
360
346
|
if not prompt_data:
|
|
361
347
|
if DEBUG:
|
|
362
|
-
|
|
363
|
-
f"No stored prompt for session {session_id[:8]}..., skipping response tracking"
|
|
364
|
-
file=sys.stderr,
|
|
348
|
+
_log(
|
|
349
|
+
f"No stored prompt for session {session_id[:8]}..., skipping response tracking"
|
|
365
350
|
)
|
|
366
351
|
return
|
|
367
352
|
|
|
@@ -375,9 +360,8 @@ class ResponseTrackingManager:
|
|
|
375
360
|
|
|
376
361
|
if not response_content:
|
|
377
362
|
if DEBUG:
|
|
378
|
-
|
|
379
|
-
f"No response content in event for session {session_id[:8]}..."
|
|
380
|
-
file=sys.stderr,
|
|
363
|
+
_log(
|
|
364
|
+
f"No response content in event for session {session_id[:8]}..."
|
|
381
365
|
)
|
|
382
366
|
return
|
|
383
367
|
|
|
@@ -399,9 +383,8 @@ class ResponseTrackingManager:
|
|
|
399
383
|
)
|
|
400
384
|
|
|
401
385
|
if file_path and DEBUG:
|
|
402
|
-
|
|
403
|
-
f"✅ Tracked Claude response for session {session_id[:8]}...: {file_path.name}"
|
|
404
|
-
file=sys.stderr,
|
|
386
|
+
_log(
|
|
387
|
+
f"✅ Tracked Claude response for session {session_id[:8]}...: {file_path.name}"
|
|
405
388
|
)
|
|
406
389
|
|
|
407
390
|
# Clean up the stored prompt
|
|
@@ -409,4 +392,4 @@ class ResponseTrackingManager:
|
|
|
409
392
|
|
|
410
393
|
except Exception as e:
|
|
411
394
|
if DEBUG:
|
|
412
|
-
|
|
395
|
+
_log(f"❌ Failed to track assistant response: {e}")
|
|
@@ -3,13 +3,34 @@
|
|
|
3
3
|
# Use HTTP-based connection manager for stable dashboard communication
|
|
4
4
|
# from .connection_manager import ConnectionManagerService # Old SocketIO-based
|
|
5
5
|
from .connection_manager_http import ConnectionManagerService # New HTTP-based
|
|
6
|
+
from .container import HookServiceContainer, get_container
|
|
6
7
|
from .duplicate_detector import DuplicateEventDetector
|
|
8
|
+
from .protocols import (
|
|
9
|
+
IAutoPauseHandler,
|
|
10
|
+
IConnectionManager,
|
|
11
|
+
IDuplicateDetector,
|
|
12
|
+
IEventHandlers,
|
|
13
|
+
IMemoryHookManager,
|
|
14
|
+
IResponseTrackingManager,
|
|
15
|
+
IStateManager,
|
|
16
|
+
ISubagentProcessor,
|
|
17
|
+
)
|
|
7
18
|
from .state_manager import StateManagerService
|
|
8
19
|
from .subagent_processor import SubagentResponseProcessor
|
|
9
20
|
|
|
10
21
|
__all__ = [
|
|
11
22
|
"ConnectionManagerService",
|
|
12
23
|
"DuplicateEventDetector",
|
|
24
|
+
"HookServiceContainer",
|
|
25
|
+
"IAutoPauseHandler",
|
|
26
|
+
"IConnectionManager",
|
|
27
|
+
"IDuplicateDetector",
|
|
28
|
+
"IEventHandlers",
|
|
29
|
+
"IMemoryHookManager",
|
|
30
|
+
"IResponseTrackingManager",
|
|
31
|
+
"IStateManager",
|
|
32
|
+
"ISubagentProcessor",
|
|
13
33
|
"StateManagerService",
|
|
14
34
|
"SubagentResponseProcessor",
|
|
35
|
+
"get_container",
|
|
15
36
|
]
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -20,8 +20,17 @@ import os
|
|
|
20
20
|
import sys
|
|
21
21
|
from datetime import datetime, timezone
|
|
22
22
|
|
|
23
|
-
#
|
|
24
|
-
|
|
23
|
+
# Try to import _log from hook_handler, fall back to no-op
|
|
24
|
+
try:
|
|
25
|
+
from claude_mpm.hooks.claude_hooks.hook_handler import _log
|
|
26
|
+
except ImportError:
|
|
27
|
+
|
|
28
|
+
def _log(msg: str) -> None:
|
|
29
|
+
pass # Silent fallback
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Debug mode - disabled by default to prevent logging overhead in production
|
|
33
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
25
34
|
|
|
26
35
|
# Import extracted modules with fallback for direct execution
|
|
27
36
|
try:
|
|
@@ -94,13 +103,10 @@ class ConnectionManagerService:
|
|
|
94
103
|
try:
|
|
95
104
|
self.connection_pool = get_connection_pool()
|
|
96
105
|
if DEBUG:
|
|
97
|
-
|
|
106
|
+
_log("✅ Modern SocketIO connection pool initialized")
|
|
98
107
|
except Exception as e:
|
|
99
108
|
if DEBUG:
|
|
100
|
-
|
|
101
|
-
f"⚠️ Failed to initialize SocketIO connection pool: {e}",
|
|
102
|
-
file=sys.stderr,
|
|
103
|
-
)
|
|
109
|
+
_log(f"⚠️ Failed to initialize SocketIO connection pool: {e}")
|
|
104
110
|
self.connection_pool = None
|
|
105
111
|
|
|
106
112
|
def emit_event(self, namespace: str, event: str, data: dict):
|
|
@@ -134,6 +140,23 @@ class ConnectionManagerService:
|
|
|
134
140
|
# Otherwise use "hook" as the type
|
|
135
141
|
if event == "hook_execution":
|
|
136
142
|
hook_type = data.get("hook_type", "unknown")
|
|
143
|
+
|
|
144
|
+
# BUGFIX: Validate hook_type is meaningful (not generic/invalid values)
|
|
145
|
+
# Problem: Dashboard shows "hook hook" instead of "PreToolUse", "UserPromptSubmit", etc.
|
|
146
|
+
# Root cause: hook_type defaults to "hook" or "unknown", providing no useful information
|
|
147
|
+
# Solution: Fallback to hook_name, then to descriptive "hook_execution_untyped"
|
|
148
|
+
if hook_type in ("hook", "unknown", "", None):
|
|
149
|
+
# Try fallback to hook_name field (set by _emit_hook_execution_event)
|
|
150
|
+
hook_type = data.get("hook_name", "unknown_hook")
|
|
151
|
+
|
|
152
|
+
# Final fallback if still generic - use descriptive name
|
|
153
|
+
if hook_type in ("hook", "unknown", "", None):
|
|
154
|
+
hook_type = "hook_execution_untyped"
|
|
155
|
+
|
|
156
|
+
# Debug log when we detect invalid hook_type for troubleshooting
|
|
157
|
+
if DEBUG:
|
|
158
|
+
_log(f"⚠️ Invalid hook_type detected, using fallback: {hook_type}")
|
|
159
|
+
|
|
137
160
|
event_type = hook_type
|
|
138
161
|
else:
|
|
139
162
|
event_type = "hook"
|
|
@@ -157,16 +180,12 @@ class ConnectionManagerService:
|
|
|
157
180
|
if DEBUG and event in ["subagent_stop", "pre_tool"]:
|
|
158
181
|
if event == "subagent_stop":
|
|
159
182
|
agent_type = data.get("agent_type", "unknown")
|
|
160
|
-
|
|
161
|
-
f"Hook handler: Publishing SubagentStop for agent '{agent_type}'",
|
|
162
|
-
file=sys.stderr,
|
|
163
|
-
)
|
|
183
|
+
_log(f"Hook handler: Publishing SubagentStop for agent '{agent_type}'")
|
|
164
184
|
elif event == "pre_tool" and data.get("tool_name") == "Task":
|
|
165
185
|
delegation = data.get("delegation_details", {})
|
|
166
186
|
agent_type = delegation.get("agent_type", "unknown")
|
|
167
|
-
|
|
168
|
-
f"Hook handler: Publishing Task delegation to agent '{agent_type}'"
|
|
169
|
-
file=sys.stderr,
|
|
187
|
+
_log(
|
|
188
|
+
f"Hook handler: Publishing Task delegation to agent '{agent_type}'"
|
|
170
189
|
)
|
|
171
190
|
|
|
172
191
|
# Emit through direct Socket.IO connection pool (primary path)
|
|
@@ -176,11 +195,11 @@ class ConnectionManagerService:
|
|
|
176
195
|
# Emit to Socket.IO server directly
|
|
177
196
|
self.connection_pool.emit("mpm_event", claude_event_data)
|
|
178
197
|
if DEBUG:
|
|
179
|
-
|
|
198
|
+
_log(f"✅ Emitted via connection pool: {event}")
|
|
180
199
|
return # Success - no need for fallback
|
|
181
200
|
except Exception as e:
|
|
182
201
|
if DEBUG:
|
|
183
|
-
|
|
202
|
+
_log(f"⚠️ Failed to emit via connection pool: {e}")
|
|
184
203
|
|
|
185
204
|
# HTTP fallback for cross-process communication (when direct calls fail)
|
|
186
205
|
# This replaces EventBus for reliability without the complexity
|
|
@@ -201,22 +220,18 @@ class ConnectionManagerService:
|
|
|
201
220
|
|
|
202
221
|
if response.status_code in [200, 204]:
|
|
203
222
|
if DEBUG:
|
|
204
|
-
|
|
223
|
+
_log("✅ HTTP fallback successful")
|
|
205
224
|
elif DEBUG:
|
|
206
|
-
|
|
207
|
-
f"⚠️ HTTP fallback failed: {response.status_code}",
|
|
208
|
-
file=sys.stderr,
|
|
209
|
-
)
|
|
225
|
+
_log(f"⚠️ HTTP fallback failed: {response.status_code}")
|
|
210
226
|
|
|
211
227
|
except Exception as e:
|
|
212
228
|
if DEBUG:
|
|
213
|
-
|
|
229
|
+
_log(f"⚠️ HTTP fallback error: {e}")
|
|
214
230
|
|
|
215
231
|
# Warn if no emission method is available
|
|
216
232
|
if not self.connection_pool and DEBUG:
|
|
217
|
-
|
|
218
|
-
f"⚠️ No event emission method available for: {claude_event_data.get('event', 'unknown')}"
|
|
219
|
-
file=sys.stderr,
|
|
233
|
+
_log(
|
|
234
|
+
f"⚠️ No event emission method available for: {claude_event_data.get('event', 'unknown')}"
|
|
220
235
|
)
|
|
221
236
|
|
|
222
237
|
def cleanup(self):
|
|
@@ -225,5 +240,5 @@ class ConnectionManagerService:
|
|
|
225
240
|
if self.connection_pool:
|
|
226
241
|
try:
|
|
227
242
|
self.connection_pool.cleanup()
|
|
228
|
-
except Exception:
|
|
243
|
+
except Exception: # nosec B110
|
|
229
244
|
pass # Ignore cleanup errors during destruction
|
|
@@ -7,16 +7,29 @@ This service manages:
|
|
|
7
7
|
DESIGN DECISION: Use stateless HTTP POST instead of persistent SocketIO
|
|
8
8
|
connections because hook handlers are ephemeral processes (< 1 second lifetime).
|
|
9
9
|
This eliminates disconnection issues and matches the process lifecycle.
|
|
10
|
+
|
|
11
|
+
DESIGN DECISION: Synchronous HTTP POST only (no async)
|
|
12
|
+
Hook handlers are too short-lived (~25ms lifecycle) to benefit from async.
|
|
13
|
+
Using asyncio.run() creates event loops that close before HTTP operations complete,
|
|
14
|
+
causing "Event loop is closed" errors. Synchronous HTTP POST in a thread pool
|
|
15
|
+
is simpler and more reliable for ephemeral processes.
|
|
10
16
|
"""
|
|
11
17
|
|
|
12
|
-
import asyncio
|
|
13
18
|
import os
|
|
14
|
-
import sys
|
|
15
19
|
from concurrent.futures import ThreadPoolExecutor
|
|
16
20
|
from datetime import datetime, timezone
|
|
17
21
|
|
|
18
|
-
#
|
|
19
|
-
|
|
22
|
+
# Try to import _log from hook_handler, fall back to no-op
|
|
23
|
+
try:
|
|
24
|
+
from claude_mpm.hooks.claude_hooks.hook_handler import _log
|
|
25
|
+
except ImportError:
|
|
26
|
+
|
|
27
|
+
def _log(msg: str) -> None:
|
|
28
|
+
pass # Silent fallback
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
# Debug mode - disabled by default to prevent logging overhead in production
|
|
32
|
+
DEBUG = os.environ.get("CLAUDE_MPM_HOOK_DEBUG", "false").lower() == "true"
|
|
20
33
|
|
|
21
34
|
# Import requests for HTTP POST communication
|
|
22
35
|
try:
|
|
@@ -27,9 +40,6 @@ except ImportError:
|
|
|
27
40
|
REQUESTS_AVAILABLE = False
|
|
28
41
|
requests = None
|
|
29
42
|
|
|
30
|
-
# Import high-performance event emitter - lazy loaded in _async_emit()
|
|
31
|
-
# to reduce hook handler initialization time by ~85% (792ms -> minimal)
|
|
32
|
-
|
|
33
43
|
# Import EventNormalizer for consistent event formatting
|
|
34
44
|
try:
|
|
35
45
|
from claude_mpm.services.socketio.event_normalizer import EventNormalizer
|
|
@@ -55,10 +65,6 @@ except ImportError:
|
|
|
55
65
|
)
|
|
56
66
|
|
|
57
67
|
|
|
58
|
-
# EventBus removed - using direct HTTP POST only
|
|
59
|
-
# This eliminates duplicate events and simplifies the architecture
|
|
60
|
-
|
|
61
|
-
|
|
62
68
|
class ConnectionManagerService:
|
|
63
69
|
"""Manages connections for the Claude hook handler using HTTP POST."""
|
|
64
70
|
|
|
@@ -72,35 +78,26 @@ class ConnectionManagerService:
|
|
|
72
78
|
self.server_port = int(os.environ.get("CLAUDE_MPM_SERVER_PORT", "8765"))
|
|
73
79
|
self.http_endpoint = f"http://{self.server_host}:{self.server_port}/api/events"
|
|
74
80
|
|
|
75
|
-
# EventBus removed - using direct HTTP POST only
|
|
76
|
-
|
|
77
|
-
# For backward compatibility with tests
|
|
78
|
-
self.connection_pool = None # No longer used
|
|
79
|
-
|
|
80
|
-
# Track async emit tasks to prevent garbage collection
|
|
81
|
-
self._emit_tasks: set = set()
|
|
82
|
-
|
|
83
81
|
# Thread pool for non-blocking HTTP requests
|
|
84
82
|
# WHY: Prevents HTTP POST from blocking hook processing (2s timeout → 0ms blocking)
|
|
85
|
-
# max_workers=2: Sufficient for low-frequency
|
|
83
|
+
# max_workers=2: Sufficient for low-frequency hook events
|
|
86
84
|
self._http_executor = ThreadPoolExecutor(
|
|
87
85
|
max_workers=2, thread_name_prefix="http-emit"
|
|
88
86
|
)
|
|
89
87
|
|
|
90
88
|
if DEBUG:
|
|
91
|
-
|
|
92
|
-
f"✅ HTTP connection manager initialized - endpoint: {self.http_endpoint}"
|
|
93
|
-
file=sys.stderr,
|
|
89
|
+
_log(
|
|
90
|
+
f"✅ HTTP connection manager initialized - endpoint: {self.http_endpoint}"
|
|
94
91
|
)
|
|
95
92
|
|
|
96
93
|
def emit_event(self, namespace: str, event: str, data: dict):
|
|
97
|
-
"""Emit event using
|
|
94
|
+
"""Emit event using HTTP POST.
|
|
98
95
|
|
|
99
|
-
WHY
|
|
100
|
-
-
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
96
|
+
WHY HTTP POST only:
|
|
97
|
+
- Hook handlers are ephemeral (~25ms lifecycle)
|
|
98
|
+
- Async emission causes "Event loop is closed" errors
|
|
99
|
+
- HTTP POST in thread pool is simpler and more reliable
|
|
100
|
+
- Completes in 20-50ms, which is acceptable for hook handlers
|
|
104
101
|
"""
|
|
105
102
|
# Create event data for normalization
|
|
106
103
|
raw_event = {
|
|
@@ -120,74 +117,17 @@ class ConnectionManagerService:
|
|
|
120
117
|
if DEBUG and event in ["subagent_stop", "pre_tool"]:
|
|
121
118
|
if event == "subagent_stop":
|
|
122
119
|
agent_type = data.get("agent_type", "unknown")
|
|
123
|
-
|
|
124
|
-
f"Hook handler: Publishing SubagentStop for agent '{agent_type}'",
|
|
125
|
-
file=sys.stderr,
|
|
126
|
-
)
|
|
120
|
+
_log(f"Hook handler: Publishing SubagentStop for agent '{agent_type}'")
|
|
127
121
|
elif event == "pre_tool" and data.get("tool_name") == "Task":
|
|
128
122
|
delegation = data.get("delegation_details", {})
|
|
129
123
|
agent_type = delegation.get("agent_type", "unknown")
|
|
130
|
-
|
|
131
|
-
f"Hook handler: Publishing Task delegation to agent '{agent_type}'"
|
|
132
|
-
file=sys.stderr,
|
|
124
|
+
_log(
|
|
125
|
+
f"Hook handler: Publishing Task delegation to agent '{agent_type}'"
|
|
133
126
|
)
|
|
134
127
|
|
|
135
|
-
#
|
|
136
|
-
success = self._try_async_emit(namespace, event, claude_event_data)
|
|
137
|
-
if success:
|
|
138
|
-
return
|
|
139
|
-
|
|
140
|
-
# Fallback to HTTP POST for cross-process communication
|
|
128
|
+
# Emit via HTTP POST (non-blocking, runs in thread pool)
|
|
141
129
|
self._try_http_emit(namespace, event, claude_event_data)
|
|
142
130
|
|
|
143
|
-
def _try_async_emit(self, namespace: str, event: str, data: dict) -> bool:
|
|
144
|
-
"""Try to emit event using high-performance async emitter."""
|
|
145
|
-
try:
|
|
146
|
-
# Run async emission in the current event loop or create one
|
|
147
|
-
loop = None
|
|
148
|
-
try:
|
|
149
|
-
loop = asyncio.get_running_loop()
|
|
150
|
-
except RuntimeError:
|
|
151
|
-
# No running loop, create a new one
|
|
152
|
-
pass
|
|
153
|
-
|
|
154
|
-
if loop:
|
|
155
|
-
# We're in an async context, create a task with tracking
|
|
156
|
-
task = loop.create_task(self._async_emit(namespace, event, data))
|
|
157
|
-
self._emit_tasks.add(task)
|
|
158
|
-
task.add_done_callback(self._emit_tasks.discard)
|
|
159
|
-
# Don't wait for completion to maintain low latency
|
|
160
|
-
if DEBUG:
|
|
161
|
-
print(f"✅ Async emit scheduled: {event}", file=sys.stderr)
|
|
162
|
-
return True
|
|
163
|
-
# No event loop, run synchronously
|
|
164
|
-
success = asyncio.run(self._async_emit(namespace, event, data))
|
|
165
|
-
if DEBUG and success:
|
|
166
|
-
print(f"✅ Async emit successful: {event}", file=sys.stderr)
|
|
167
|
-
return success
|
|
168
|
-
|
|
169
|
-
except Exception as e:
|
|
170
|
-
if DEBUG:
|
|
171
|
-
print(f"⚠️ Async emit failed: {e}", file=sys.stderr)
|
|
172
|
-
return False
|
|
173
|
-
|
|
174
|
-
async def _async_emit(self, namespace: str, event: str, data: dict) -> bool:
|
|
175
|
-
"""Async helper for event emission."""
|
|
176
|
-
try:
|
|
177
|
-
# Lazy load event emitter to reduce initialization overhead
|
|
178
|
-
from claude_mpm.services.monitor.event_emitter import get_event_emitter
|
|
179
|
-
|
|
180
|
-
emitter = await get_event_emitter()
|
|
181
|
-
return await emitter.emit_event(namespace, "claude_event", data)
|
|
182
|
-
except ImportError:
|
|
183
|
-
if DEBUG:
|
|
184
|
-
print("⚠️ Event emitter not available", file=sys.stderr)
|
|
185
|
-
return False
|
|
186
|
-
except Exception as e:
|
|
187
|
-
if DEBUG:
|
|
188
|
-
print(f"⚠️ Async emitter error: {e}", file=sys.stderr)
|
|
189
|
-
return False
|
|
190
|
-
|
|
191
131
|
def _try_http_emit(self, namespace: str, event: str, data: dict):
|
|
192
132
|
"""Try to emit event using HTTP POST fallback (non-blocking).
|
|
193
133
|
|
|
@@ -196,10 +136,7 @@ class ConnectionManagerService:
|
|
|
196
136
|
"""
|
|
197
137
|
if not REQUESTS_AVAILABLE:
|
|
198
138
|
if DEBUG:
|
|
199
|
-
|
|
200
|
-
"⚠️ requests module not available - cannot emit via HTTP",
|
|
201
|
-
file=sys.stderr,
|
|
202
|
-
)
|
|
139
|
+
_log("⚠️ requests module not available - cannot emit via HTTP")
|
|
203
140
|
return
|
|
204
141
|
|
|
205
142
|
# Submit to thread pool - don't wait for result (fire-and-forget)
|
|
@@ -225,25 +162,21 @@ class ConnectionManagerService:
|
|
|
225
162
|
|
|
226
163
|
if response.status_code in [200, 204]:
|
|
227
164
|
if DEBUG:
|
|
228
|
-
|
|
165
|
+
_log(f"✅ HTTP POST successful: {event}")
|
|
229
166
|
elif DEBUG:
|
|
230
|
-
|
|
231
|
-
f"⚠️ HTTP POST failed with status {response.status_code}: {event}",
|
|
232
|
-
file=sys.stderr,
|
|
233
|
-
)
|
|
167
|
+
_log(f"⚠️ HTTP POST failed with status {response.status_code}: {event}")
|
|
234
168
|
|
|
235
169
|
except requests.exceptions.Timeout:
|
|
236
170
|
if DEBUG:
|
|
237
|
-
|
|
171
|
+
_log(f"⚠️ HTTP POST timeout for: {event}")
|
|
238
172
|
except requests.exceptions.ConnectionError:
|
|
239
173
|
if DEBUG:
|
|
240
|
-
|
|
241
|
-
f"⚠️ HTTP POST connection failed for: {event} (server not running?)"
|
|
242
|
-
file=sys.stderr,
|
|
174
|
+
_log(
|
|
175
|
+
f"⚠️ HTTP POST connection failed for: {event} (server not running?)"
|
|
243
176
|
)
|
|
244
177
|
except Exception as e:
|
|
245
178
|
if DEBUG:
|
|
246
|
-
|
|
179
|
+
_log(f"⚠️ HTTP POST error for {event}: {e}")
|
|
247
180
|
|
|
248
181
|
def cleanup(self):
|
|
249
182
|
"""Cleanup connections on service destruction."""
|
|
@@ -251,4 +184,4 @@ class ConnectionManagerService:
|
|
|
251
184
|
if hasattr(self, "_http_executor"):
|
|
252
185
|
self._http_executor.shutdown(wait=False)
|
|
253
186
|
if DEBUG:
|
|
254
|
-
|
|
187
|
+
_log("✅ HTTP executor shutdown")
|