claude-mpm 5.4.85__py3-none-any.whl → 5.6.76__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.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
- claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +109 -706
- 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/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- 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 +2 -2
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/executor.py +128 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/parsers/base_parser.py +84 -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/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +345 -40
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/startup_migrations.py +236 -0
- 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 +124 -0
- claude_mpm/commander/chat/repl.py +1957 -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 +868 -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 +5 -0
- claude_mpm/core/claude_runner.py +152 -0
- 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 +5 -4
- 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/output_style_manager.py +52 -12
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +10 -6
- claude_mpm/core/unified_paths.py +68 -80
- 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/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
- 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/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
- 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 +9 -9
- 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/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/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/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 +22 -15
- 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/remote_agent_discovery_service.py +3 -0
- 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/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 -2
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +261 -87
- claude_mpm/services/skills/git_skill_source_manager.py +130 -10
- claude_mpm/services/skills/selective_skill_deployer.py +142 -16
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +31 -5
- 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/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-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -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-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/{pm-teaching-mode → mpm-teaching-mode}/SKILL.md +2 -2
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm-5.6.76.dist-info/METADATA +416 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/RECORD +312 -175
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/entry_points.txt +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
- claude_mpm-5.4.85.dist-info/METADATA +0 -1023
- /claude_mpm/skills/bundled/pm/{pm-bug-reporting/pm-bug-reporting.md → mpm-bug-reporting/SKILL.md} +0 -0
- /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
"""MCP Service Registry for claude-mpm.
|
|
2
|
+
|
|
3
|
+
This module provides a registry of known MCP services with their
|
|
4
|
+
installation, configuration, and runtime requirements.
|
|
5
|
+
|
|
6
|
+
WHY: Centralizes MCP service definitions to enable enable/disable/list
|
|
7
|
+
operations with automatic configuration generation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import ClassVar
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class InstallMethod(str, Enum):
|
|
16
|
+
"""Installation method for MCP services."""
|
|
17
|
+
|
|
18
|
+
UVX = "uvx"
|
|
19
|
+
PIPX = "pipx"
|
|
20
|
+
NPX = "npx"
|
|
21
|
+
PIP = "pip"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class MCPServiceDefinition:
|
|
26
|
+
"""Definition of an MCP service with all configuration requirements.
|
|
27
|
+
|
|
28
|
+
Attributes:
|
|
29
|
+
name: Unique service identifier (e.g., "kuzu-memory")
|
|
30
|
+
package: PyPI/npm package name for installation
|
|
31
|
+
install_method: How to install (uvx, pipx, npx, pip)
|
|
32
|
+
command: Command to run the service
|
|
33
|
+
args: Default command arguments
|
|
34
|
+
required_env: Environment variables that must be set
|
|
35
|
+
optional_env: Environment variables that may be set
|
|
36
|
+
description: Human-readable description
|
|
37
|
+
env_defaults: Default values for optional env vars
|
|
38
|
+
enabled_by_default: Whether service is enabled by default
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
name: str
|
|
42
|
+
package: str
|
|
43
|
+
install_method: InstallMethod
|
|
44
|
+
command: str
|
|
45
|
+
args: list[str] = field(default_factory=list)
|
|
46
|
+
required_env: list[str] = field(default_factory=list)
|
|
47
|
+
optional_env: list[str] = field(default_factory=list)
|
|
48
|
+
description: str = ""
|
|
49
|
+
env_defaults: dict[str, str] = field(default_factory=dict)
|
|
50
|
+
enabled_by_default: bool = False
|
|
51
|
+
oauth_provider: str | None = None # "google", "microsoft", etc.
|
|
52
|
+
oauth_scopes: list[str] = field(default_factory=list) # OAuth scopes if applicable
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class MCPServiceRegistry:
|
|
56
|
+
"""Registry of known MCP services.
|
|
57
|
+
|
|
58
|
+
Provides service lookup, configuration generation, and
|
|
59
|
+
enable/disable state management.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# Registry of all known MCP services
|
|
63
|
+
SERVICES: ClassVar[dict[str, MCPServiceDefinition]] = {}
|
|
64
|
+
|
|
65
|
+
@classmethod
|
|
66
|
+
def register(cls, service: MCPServiceDefinition) -> None:
|
|
67
|
+
"""Register a service definition."""
|
|
68
|
+
cls.SERVICES[service.name] = service
|
|
69
|
+
|
|
70
|
+
@classmethod
|
|
71
|
+
def get(cls, name: str) -> MCPServiceDefinition | None:
|
|
72
|
+
"""Get a service definition by name."""
|
|
73
|
+
return cls.SERVICES.get(name)
|
|
74
|
+
|
|
75
|
+
@classmethod
|
|
76
|
+
def list_all(cls) -> list[MCPServiceDefinition]:
|
|
77
|
+
"""List all registered services."""
|
|
78
|
+
return list(cls.SERVICES.values())
|
|
79
|
+
|
|
80
|
+
@classmethod
|
|
81
|
+
def list_names(cls) -> list[str]:
|
|
82
|
+
"""List all registered service names."""
|
|
83
|
+
return list(cls.SERVICES.keys())
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def exists(cls, name: str) -> bool:
|
|
87
|
+
"""Check if a service exists in the registry."""
|
|
88
|
+
return name in cls.SERVICES
|
|
89
|
+
|
|
90
|
+
@classmethod
|
|
91
|
+
def get_default_enabled(cls) -> list[MCPServiceDefinition]:
|
|
92
|
+
"""Get services that are enabled by default."""
|
|
93
|
+
return [s for s in cls.SERVICES.values() if s.enabled_by_default]
|
|
94
|
+
|
|
95
|
+
@classmethod
|
|
96
|
+
def generate_config(
|
|
97
|
+
cls,
|
|
98
|
+
service: MCPServiceDefinition,
|
|
99
|
+
env_overrides: dict[str, str] | None = None,
|
|
100
|
+
) -> dict:
|
|
101
|
+
"""Generate MCP configuration for a service.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
service: The service definition
|
|
105
|
+
env_overrides: Environment variable overrides
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Configuration dict suitable for .mcp.json or ~/.claude.json
|
|
109
|
+
"""
|
|
110
|
+
env = {}
|
|
111
|
+
|
|
112
|
+
# Add required env vars (must be provided or have defaults)
|
|
113
|
+
for var in service.required_env:
|
|
114
|
+
if env_overrides and var in env_overrides:
|
|
115
|
+
env[var] = env_overrides[var]
|
|
116
|
+
elif var in service.env_defaults:
|
|
117
|
+
env[var] = service.env_defaults[var]
|
|
118
|
+
# If required and not provided, leave it out - caller should validate
|
|
119
|
+
|
|
120
|
+
# Add optional env vars if provided or have defaults
|
|
121
|
+
for var in service.optional_env:
|
|
122
|
+
if env_overrides and var in env_overrides:
|
|
123
|
+
env[var] = env_overrides[var]
|
|
124
|
+
elif var in service.env_defaults:
|
|
125
|
+
env[var] = service.env_defaults[var]
|
|
126
|
+
|
|
127
|
+
config: dict = {
|
|
128
|
+
"command": service.command,
|
|
129
|
+
"args": service.args.copy(),
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if env:
|
|
133
|
+
config["env"] = env
|
|
134
|
+
|
|
135
|
+
return config
|
|
136
|
+
|
|
137
|
+
@classmethod
|
|
138
|
+
def validate_env(
|
|
139
|
+
cls, service: MCPServiceDefinition, env: dict[str, str]
|
|
140
|
+
) -> tuple[bool, list[str]]:
|
|
141
|
+
"""Validate that all required env vars are provided.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
service: The service definition
|
|
145
|
+
env: Environment variables to validate
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Tuple of (is_valid, list of missing required vars)
|
|
149
|
+
"""
|
|
150
|
+
missing = []
|
|
151
|
+
for var in service.required_env:
|
|
152
|
+
if var not in env and var not in service.env_defaults:
|
|
153
|
+
missing.append(var)
|
|
154
|
+
return len(missing) == 0, missing
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
# ============================================================================
|
|
158
|
+
# Service Definitions
|
|
159
|
+
# ============================================================================
|
|
160
|
+
|
|
161
|
+
# KuzuMemory - Project memory and context management
|
|
162
|
+
KUZU_MEMORY = MCPServiceDefinition(
|
|
163
|
+
name="kuzu-memory",
|
|
164
|
+
package="kuzu-memory",
|
|
165
|
+
install_method=InstallMethod.UVX,
|
|
166
|
+
command="uvx",
|
|
167
|
+
args=["kuzu-memory"],
|
|
168
|
+
required_env=[],
|
|
169
|
+
optional_env=["KUZU_DB_PATH", "KUZU_LOG_LEVEL"],
|
|
170
|
+
description="Project memory and context management with graph database",
|
|
171
|
+
env_defaults={},
|
|
172
|
+
enabled_by_default=True,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
# MCP Ticketer - Ticket and project management
|
|
176
|
+
MCP_TICKETER = MCPServiceDefinition(
|
|
177
|
+
name="mcp-ticketer",
|
|
178
|
+
package="mcp-ticketer",
|
|
179
|
+
install_method=InstallMethod.UVX,
|
|
180
|
+
command="uvx",
|
|
181
|
+
args=["mcp-ticketer"],
|
|
182
|
+
required_env=[],
|
|
183
|
+
optional_env=["TICKETER_BACKEND", "GITHUB_TOKEN", "LINEAR_API_KEY"],
|
|
184
|
+
description="Ticket and project management integration",
|
|
185
|
+
env_defaults={},
|
|
186
|
+
enabled_by_default=True,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# MCP Vector Search - Code semantic search
|
|
190
|
+
MCP_VECTOR_SEARCH = MCPServiceDefinition(
|
|
191
|
+
name="mcp-vector-search",
|
|
192
|
+
package="mcp-vector-search",
|
|
193
|
+
install_method=InstallMethod.UVX,
|
|
194
|
+
command="uvx",
|
|
195
|
+
args=["mcp-vector-search"],
|
|
196
|
+
required_env=[],
|
|
197
|
+
optional_env=["VECTOR_SEARCH_INDEX_PATH"],
|
|
198
|
+
description="Semantic code search with vector embeddings",
|
|
199
|
+
env_defaults={},
|
|
200
|
+
enabled_by_default=True,
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
# Google Workspace MCP - Google Drive, Docs, Sheets integration
|
|
204
|
+
# Package: https://pypi.org/project/workspace-mcp/
|
|
205
|
+
GOOGLE_WORKSPACE_MCP = MCPServiceDefinition(
|
|
206
|
+
name="workspace-mcp",
|
|
207
|
+
package="workspace-mcp",
|
|
208
|
+
install_method=InstallMethod.UVX,
|
|
209
|
+
command="uvx",
|
|
210
|
+
args=["workspace-mcp", "--tool-tier", "core"],
|
|
211
|
+
required_env=["GOOGLE_OAUTH_CLIENT_ID", "GOOGLE_OAUTH_CLIENT_SECRET"],
|
|
212
|
+
optional_env=[
|
|
213
|
+
"OAUTHLIB_INSECURE_TRANSPORT",
|
|
214
|
+
"USER_GOOGLE_EMAIL",
|
|
215
|
+
"GOOGLE_PSE_API_KEY",
|
|
216
|
+
"GOOGLE_PSE_ENGINE_ID",
|
|
217
|
+
],
|
|
218
|
+
description="Google Workspace integration (Gmail, Calendar, Drive, Docs, Sheets, Slides)",
|
|
219
|
+
env_defaults={"OAUTHLIB_INSECURE_TRANSPORT": "1"},
|
|
220
|
+
enabled_by_default=False,
|
|
221
|
+
oauth_provider="google",
|
|
222
|
+
oauth_scopes=[
|
|
223
|
+
"openid",
|
|
224
|
+
"email",
|
|
225
|
+
"profile",
|
|
226
|
+
"https://www.googleapis.com/auth/gmail.modify",
|
|
227
|
+
"https://www.googleapis.com/auth/calendar",
|
|
228
|
+
"https://www.googleapis.com/auth/drive",
|
|
229
|
+
"https://www.googleapis.com/auth/documents",
|
|
230
|
+
"https://www.googleapis.com/auth/spreadsheets",
|
|
231
|
+
],
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
# MCP GitHub - GitHub repository integration (future)
|
|
235
|
+
MCP_GITHUB = MCPServiceDefinition(
|
|
236
|
+
name="mcp-github",
|
|
237
|
+
package="@modelcontextprotocol/server-github",
|
|
238
|
+
install_method=InstallMethod.NPX,
|
|
239
|
+
command="npx",
|
|
240
|
+
args=["-y", "@modelcontextprotocol/server-github"],
|
|
241
|
+
required_env=["GITHUB_PERSONAL_ACCESS_TOKEN"],
|
|
242
|
+
optional_env=[],
|
|
243
|
+
description="GitHub repository integration",
|
|
244
|
+
env_defaults={},
|
|
245
|
+
enabled_by_default=False,
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# MCP Filesystem - Local filesystem access (future)
|
|
249
|
+
MCP_FILESYSTEM = MCPServiceDefinition(
|
|
250
|
+
name="mcp-filesystem",
|
|
251
|
+
package="@modelcontextprotocol/server-filesystem",
|
|
252
|
+
install_method=InstallMethod.NPX,
|
|
253
|
+
command="npx",
|
|
254
|
+
args=["-y", "@modelcontextprotocol/server-filesystem"],
|
|
255
|
+
required_env=[],
|
|
256
|
+
optional_env=["FILESYSTEM_ROOT_PATH"],
|
|
257
|
+
description="Local filesystem access and management",
|
|
258
|
+
env_defaults={},
|
|
259
|
+
enabled_by_default=False,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
# MCP Skillset - Skills and knowledge management
|
|
263
|
+
MCP_SKILLSET = MCPServiceDefinition(
|
|
264
|
+
name="mcp-skillset",
|
|
265
|
+
package="mcp-skillset",
|
|
266
|
+
install_method=InstallMethod.UVX,
|
|
267
|
+
command="uvx",
|
|
268
|
+
args=["mcp-skillset"],
|
|
269
|
+
required_env=[],
|
|
270
|
+
optional_env=["SKILLSET_PATH", "SKILLSET_LOG_LEVEL"],
|
|
271
|
+
description="Skills and knowledge management for Claude",
|
|
272
|
+
env_defaults={},
|
|
273
|
+
enabled_by_default=True,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
# Register all services
|
|
278
|
+
def _register_builtin_services() -> None:
|
|
279
|
+
"""Register all built-in service definitions."""
|
|
280
|
+
services = [
|
|
281
|
+
KUZU_MEMORY,
|
|
282
|
+
MCP_TICKETER,
|
|
283
|
+
MCP_VECTOR_SEARCH,
|
|
284
|
+
GOOGLE_WORKSPACE_MCP,
|
|
285
|
+
MCP_GITHUB,
|
|
286
|
+
MCP_FILESYSTEM,
|
|
287
|
+
MCP_SKILLSET,
|
|
288
|
+
]
|
|
289
|
+
for service in services:
|
|
290
|
+
MCPServiceRegistry.register(service)
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
# Auto-register on module import
|
|
294
|
+
_register_builtin_services()
|
|
@@ -95,10 +95,10 @@ class DaemonManager:
|
|
|
95
95
|
def _get_default_log_file(self) -> Path:
|
|
96
96
|
"""Get default log file path with port number to support multiple daemons."""
|
|
97
97
|
project_root = Path.cwd()
|
|
98
|
-
|
|
99
|
-
|
|
98
|
+
logs_dir = project_root / ".claude-mpm" / "logs"
|
|
99
|
+
logs_dir.mkdir(parents=True, exist_ok=True)
|
|
100
100
|
# Include port in filename to support multiple daemon instances
|
|
101
|
-
return
|
|
101
|
+
return logs_dir / f"monitor-daemon-{self.port}.log"
|
|
102
102
|
|
|
103
103
|
def cleanup_port_conflicts(self, max_retries: int = 3) -> bool:
|
|
104
104
|
"""Clean up any processes using the daemon port.
|
|
@@ -649,14 +649,24 @@ class DaemonManager:
|
|
|
649
649
|
|
|
650
650
|
# Wait for the subprocess to write its PID file and bind to port
|
|
651
651
|
# The subprocess will write the PID file after it starts successfully
|
|
652
|
-
|
|
652
|
+
# Allow configuration via environment variable (default 30s to account for agent/skill sync)
|
|
653
|
+
max_wait = int(os.environ.get("CLAUDE_MPM_MONITOR_TIMEOUT", "30"))
|
|
653
654
|
start_time = time.time()
|
|
654
655
|
pid_file_found = False
|
|
655
656
|
port_bound = False
|
|
657
|
+
last_progress_log = 0.0
|
|
656
658
|
|
|
657
659
|
self.logger.debug(f"Waiting up to {max_wait}s for daemon to start...")
|
|
658
660
|
|
|
659
661
|
while time.time() - start_time < max_wait:
|
|
662
|
+
# Log progress every 5 seconds to show we're waiting
|
|
663
|
+
elapsed = time.time() - start_time
|
|
664
|
+
if elapsed - last_progress_log >= 5.0:
|
|
665
|
+
self.logger.info(
|
|
666
|
+
f"Waiting for monitor daemon... ({int(elapsed)}s elapsed, syncing agents/skills)"
|
|
667
|
+
)
|
|
668
|
+
last_progress_log = elapsed
|
|
669
|
+
|
|
660
670
|
# Check if process is still running
|
|
661
671
|
returncode = process.poll()
|
|
662
672
|
if returncode is not None:
|
|
@@ -976,6 +986,7 @@ class DaemonManager:
|
|
|
976
986
|
os.dup2(null_in.fileno(), sys.stdin.fileno())
|
|
977
987
|
|
|
978
988
|
# Redirect stdout and stderr to log file
|
|
989
|
+
# Ensure logs directory exists
|
|
979
990
|
self.log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
980
991
|
with self.log_file.open("a") as log_out:
|
|
981
992
|
os.dup2(log_out.fileno(), sys.stdout.fileno())
|
|
@@ -128,12 +128,16 @@ class DaemonLifecycle:
|
|
|
128
128
|
# Redirect stdout and stderr
|
|
129
129
|
if self.log_file:
|
|
130
130
|
# Redirect to log file
|
|
131
|
+
# Ensure logs directory exists
|
|
132
|
+
self.log_file.parent.mkdir(parents=True, exist_ok=True)
|
|
131
133
|
with self.log_file.open("a") as log_out:
|
|
132
134
|
os.dup2(log_out.fileno(), sys.stdout.fileno())
|
|
133
135
|
os.dup2(log_out.fileno(), sys.stderr.fileno())
|
|
134
136
|
else:
|
|
135
137
|
# Default to a daemon log file instead of /dev/null for errors
|
|
136
|
-
default_log =
|
|
138
|
+
default_log = (
|
|
139
|
+
Path.home() / ".claude-mpm" / "logs" / "monitor-daemon.log"
|
|
140
|
+
)
|
|
137
141
|
default_log.parent.mkdir(parents=True, exist_ok=True)
|
|
138
142
|
with default_log.open("a") as log_out:
|
|
139
143
|
os.dup2(log_out.fileno(), sys.stdout.fileno())
|
|
@@ -475,7 +479,9 @@ class DaemonLifecycle:
|
|
|
475
479
|
try:
|
|
476
480
|
# If no log file specified, create a default one
|
|
477
481
|
if not self.log_file:
|
|
478
|
-
default_log =
|
|
482
|
+
default_log = (
|
|
483
|
+
Path.home() / ".claude-mpm" / "logs" / "monitor-daemon.log"
|
|
484
|
+
)
|
|
479
485
|
default_log.parent.mkdir(parents=True, exist_ok=True)
|
|
480
486
|
self.log_file = default_log
|
|
481
487
|
|
|
@@ -368,6 +368,83 @@ class UnifiedMonitorServer:
|
|
|
368
368
|
finally:
|
|
369
369
|
await self._cleanup_async()
|
|
370
370
|
|
|
371
|
+
def _categorize_event(self, event_name: str) -> str:
|
|
372
|
+
"""Categorize event by name to determine Socket.IO event type.
|
|
373
|
+
|
|
374
|
+
Maps specific event names to their category for frontend filtering.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
event_name: The raw event name (e.g., "subagent_start", "todo_updated")
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
Category name (e.g., "hook_event", "system_event")
|
|
381
|
+
"""
|
|
382
|
+
# Hook events - agent lifecycle and todo updates
|
|
383
|
+
if event_name in ("subagent_start", "subagent_stop", "todo_updated"):
|
|
384
|
+
return "hook_event"
|
|
385
|
+
|
|
386
|
+
# Tool events - both hook-style and direct tool events
|
|
387
|
+
if event_name in (
|
|
388
|
+
"pre_tool",
|
|
389
|
+
"post_tool",
|
|
390
|
+
"tool.start",
|
|
391
|
+
"tool.end",
|
|
392
|
+
"tool_use",
|
|
393
|
+
"tool_result",
|
|
394
|
+
):
|
|
395
|
+
return "tool_event"
|
|
396
|
+
|
|
397
|
+
# Session events - session lifecycle
|
|
398
|
+
if event_name in (
|
|
399
|
+
"session.started",
|
|
400
|
+
"session.ended",
|
|
401
|
+
"session_start",
|
|
402
|
+
"session_end",
|
|
403
|
+
):
|
|
404
|
+
return "session_event"
|
|
405
|
+
|
|
406
|
+
# Response events - API response lifecycle
|
|
407
|
+
if event_name in (
|
|
408
|
+
"response.start",
|
|
409
|
+
"response.end",
|
|
410
|
+
"response_started",
|
|
411
|
+
"response_ended",
|
|
412
|
+
):
|
|
413
|
+
return "response_event"
|
|
414
|
+
|
|
415
|
+
# Agent events - agent delegation and returns
|
|
416
|
+
if event_name in (
|
|
417
|
+
"agent.delegated",
|
|
418
|
+
"agent.returned",
|
|
419
|
+
"agent_start",
|
|
420
|
+
"agent_end",
|
|
421
|
+
):
|
|
422
|
+
return "agent_event"
|
|
423
|
+
|
|
424
|
+
# File events - file operations
|
|
425
|
+
if event_name in (
|
|
426
|
+
"file.read",
|
|
427
|
+
"file.write",
|
|
428
|
+
"file.edit",
|
|
429
|
+
"file_read",
|
|
430
|
+
"file_write",
|
|
431
|
+
):
|
|
432
|
+
return "file_event"
|
|
433
|
+
|
|
434
|
+
# Claude API events
|
|
435
|
+
if event_name in ("user_prompt", "assistant_message"):
|
|
436
|
+
return "claude_event"
|
|
437
|
+
|
|
438
|
+
# System events
|
|
439
|
+
if event_name in ("system_ready", "system_shutdown"):
|
|
440
|
+
return "system_event"
|
|
441
|
+
|
|
442
|
+
# Log uncategorized events for debugging
|
|
443
|
+
self.logger.debug(f"Uncategorized event: {event_name}")
|
|
444
|
+
|
|
445
|
+
# Default to claude_event for unknown events
|
|
446
|
+
return "claude_event"
|
|
447
|
+
|
|
371
448
|
def _setup_event_handlers(self):
|
|
372
449
|
"""Setup Socket.IO event handlers."""
|
|
373
450
|
try:
|
|
@@ -474,7 +551,7 @@ class UnifiedMonitorServer:
|
|
|
474
551
|
)
|
|
475
552
|
if version_file.exists():
|
|
476
553
|
version = version_file.read_text().strip()
|
|
477
|
-
except Exception:
|
|
554
|
+
except Exception: # nosec B110
|
|
478
555
|
pass
|
|
479
556
|
|
|
480
557
|
return web.json_response(
|
|
@@ -499,10 +576,28 @@ class UnifiedMonitorServer:
|
|
|
499
576
|
event = data.get("event", "claude_event")
|
|
500
577
|
event_data = data.get("data", {})
|
|
501
578
|
|
|
502
|
-
#
|
|
579
|
+
# Extract actual event name from subtype or type within data
|
|
580
|
+
actual_event = (
|
|
581
|
+
event_data.get("subtype") or event_data.get("type") or event
|
|
582
|
+
)
|
|
583
|
+
|
|
584
|
+
# Categorize event and wrap in expected format
|
|
585
|
+
event_type = self._categorize_event(actual_event)
|
|
586
|
+
wrapped_event = {
|
|
587
|
+
"type": event_type,
|
|
588
|
+
"subtype": event,
|
|
589
|
+
"data": event_data,
|
|
590
|
+
"timestamp": event_data.get("timestamp")
|
|
591
|
+
or datetime.now(timezone.utc).isoformat() + "Z",
|
|
592
|
+
"session_id": event_data.get("session_id"),
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
# Emit to Socket.IO clients via the categorized event type
|
|
503
596
|
if self.sio:
|
|
504
|
-
await self.sio.emit(
|
|
505
|
-
self.logger.debug(
|
|
597
|
+
await self.sio.emit(event_type, wrapped_event)
|
|
598
|
+
self.logger.debug(
|
|
599
|
+
f"HTTP event forwarded to Socket.IO: {event} -> {event_type}"
|
|
600
|
+
)
|
|
506
601
|
|
|
507
602
|
return web.Response(status=204) # No content response
|
|
508
603
|
|
|
@@ -859,7 +954,7 @@ class UnifiedMonitorServer:
|
|
|
859
954
|
# Configuration endpoint for dashboard initialization
|
|
860
955
|
async def config_handler(request):
|
|
861
956
|
"""Return configuration for dashboard initialization."""
|
|
862
|
-
import subprocess
|
|
957
|
+
import subprocess # nosec B404
|
|
863
958
|
|
|
864
959
|
config = {
|
|
865
960
|
"workingDirectory": Path.cwd(),
|
|
@@ -870,7 +965,7 @@ class UnifiedMonitorServer:
|
|
|
870
965
|
|
|
871
966
|
# Try to get current git branch
|
|
872
967
|
try:
|
|
873
|
-
result = subprocess.run(
|
|
968
|
+
result = subprocess.run( # nosec B603 B607
|
|
874
969
|
["git", "branch", "--show-current"],
|
|
875
970
|
capture_output=True,
|
|
876
971
|
text=True,
|
|
@@ -880,7 +975,7 @@ class UnifiedMonitorServer:
|
|
|
880
975
|
)
|
|
881
976
|
if result.returncode == 0 and result.stdout.strip():
|
|
882
977
|
config["gitBranch"] = result.stdout.strip()
|
|
883
|
-
except Exception:
|
|
978
|
+
except Exception: # nosec B110
|
|
884
979
|
pass # Keep default "Unknown" value
|
|
885
980
|
|
|
886
981
|
return web.json_response(config)
|
|
@@ -910,7 +1005,7 @@ class UnifiedMonitorServer:
|
|
|
910
1005
|
# Git history handler
|
|
911
1006
|
async def git_history_handler(request: web.Request) -> web.Response:
|
|
912
1007
|
"""Get git history for a file."""
|
|
913
|
-
import subprocess
|
|
1008
|
+
import subprocess # nosec B404
|
|
914
1009
|
|
|
915
1010
|
try:
|
|
916
1011
|
data = await request.json()
|
|
@@ -939,7 +1034,7 @@ class UnifiedMonitorServer:
|
|
|
939
1034
|
)
|
|
940
1035
|
|
|
941
1036
|
# Get git log for file
|
|
942
|
-
result = subprocess.run(
|
|
1037
|
+
result = subprocess.run( # nosec B603 B607
|
|
943
1038
|
[
|
|
944
1039
|
"git",
|
|
945
1040
|
"log",
|
|
@@ -978,7 +1073,7 @@ class UnifiedMonitorServer:
|
|
|
978
1073
|
# Git diff handler
|
|
979
1074
|
async def git_diff_handler(request: web.Request) -> web.Response:
|
|
980
1075
|
"""Get git diff for a file with optional commit selection."""
|
|
981
|
-
import subprocess
|
|
1076
|
+
import subprocess # nosec B404
|
|
982
1077
|
|
|
983
1078
|
try:
|
|
984
1079
|
file_path = request.query.get("path", "")
|
|
@@ -1010,7 +1105,7 @@ class UnifiedMonitorServer:
|
|
|
1010
1105
|
)
|
|
1011
1106
|
|
|
1012
1107
|
# Find git repository root
|
|
1013
|
-
git_root_result = subprocess.run(
|
|
1108
|
+
git_root_result = subprocess.run( # nosec B603 B607
|
|
1014
1109
|
["git", "rev-parse", "--show-toplevel"],
|
|
1015
1110
|
check=False,
|
|
1016
1111
|
capture_output=True,
|
|
@@ -1034,7 +1129,7 @@ class UnifiedMonitorServer:
|
|
|
1034
1129
|
git_root = Path(git_root_result.stdout.strip())
|
|
1035
1130
|
|
|
1036
1131
|
# Check if file is tracked by git
|
|
1037
|
-
ls_files_result = subprocess.run(
|
|
1132
|
+
ls_files_result = subprocess.run( # nosec B603 B607
|
|
1038
1133
|
["git", "ls-files", "--error-unmatch", str(path)],
|
|
1039
1134
|
check=False,
|
|
1040
1135
|
capture_output=True,
|
|
@@ -1056,7 +1151,7 @@ class UnifiedMonitorServer:
|
|
|
1056
1151
|
)
|
|
1057
1152
|
|
|
1058
1153
|
# Get commit history for this file (last 5 commits)
|
|
1059
|
-
history_result = subprocess.run(
|
|
1154
|
+
history_result = subprocess.run( # nosec B603 B607
|
|
1060
1155
|
[
|
|
1061
1156
|
"git",
|
|
1062
1157
|
"log",
|
|
@@ -1087,7 +1182,7 @@ class UnifiedMonitorServer:
|
|
|
1087
1182
|
)
|
|
1088
1183
|
|
|
1089
1184
|
# Check for uncommitted changes
|
|
1090
|
-
uncommitted_result = subprocess.run(
|
|
1185
|
+
uncommitted_result = subprocess.run( # nosec B603 B607
|
|
1091
1186
|
["git", "diff", "HEAD", str(path)],
|
|
1092
1187
|
check=False,
|
|
1093
1188
|
capture_output=True,
|
|
@@ -1100,7 +1195,7 @@ class UnifiedMonitorServer:
|
|
|
1100
1195
|
# Get diff based on commit parameter
|
|
1101
1196
|
if commit_hash:
|
|
1102
1197
|
# Get diff for specific commit
|
|
1103
|
-
result = subprocess.run(
|
|
1198
|
+
result = subprocess.run( # nosec B603 B607
|
|
1104
1199
|
["git", "show", commit_hash, "--", str(path)],
|
|
1105
1200
|
check=False,
|
|
1106
1201
|
capture_output=True,
|
|
@@ -1469,7 +1564,7 @@ class UnifiedMonitorServer:
|
|
|
1469
1564
|
gather = asyncio.gather(*tasks_to_cancel, return_exceptions=True)
|
|
1470
1565
|
try:
|
|
1471
1566
|
loop.run_until_complete(gather)
|
|
1472
|
-
except Exception:
|
|
1567
|
+
except Exception: # nosec B110
|
|
1473
1568
|
# Some tasks might fail to cancel, that's ok
|
|
1474
1569
|
pass
|
|
1475
1570
|
|