claude-mpm 5.4.71__py3-none-any.whl → 5.6.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/PM_INSTRUCTIONS.md +101 -703
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- 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 +46 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +2 -2
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skills.py +166 -14
- claude_mpm/cli/executor.py +119 -16
- 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 +71 -1
- claude_mpm/cli/parsers/commander_parser.py +83 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/startup.py +183 -348
- claude_mpm/cli/startup_display.py +72 -5
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +72 -0
- claude_mpm/commander/adapters/__init__.py +31 -0
- claude_mpm/commander/adapters/base.py +191 -0
- claude_mpm/commander/adapters/claude_code.py +361 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +105 -0
- claude_mpm/commander/api/errors.py +112 -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 +215 -0
- claude_mpm/commander/api/routes/work.py +260 -0
- claude_mpm/commander/api/schemas.py +182 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +107 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -0
- claude_mpm/commander/config.py +49 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/daemon.py +398 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +143 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +62 -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 +337 -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/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +121 -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 +309 -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 +404 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +316 -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 +361 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +189 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +219 -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/constants.py +1 -0
- claude_mpm/core/claude_runner.py +2 -2
- claude_mpm/core/config.py +5 -0
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +7 -7
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +35 -11
- claude_mpm/core/output_style_manager.py +27 -9
- 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/{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 +486 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +254 -11
- claude_mpm/hooks/claude_hooks/hook_handler.py +106 -89
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +75 -8
- claude_mpm/hooks/claude_hooks/memory_integration.py +22 -11
- claude_mpm/hooks/claude_hooks/response_tracking.py +3 -1
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +20 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +14 -77
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +30 -6
- claude_mpm/hooks/session_resume_hook.py +85 -1
- claude_mpm/init.py +1 -1
- claude_mpm/scripts/claude-hook-handler.sh +39 -12
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -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/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/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/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -2
- claude_mpm/services/monitor/server.py +106 -16
- claude_mpm/services/pm_skills_deployer.py +259 -87
- claude_mpm/services/skills/git_skill_source_manager.py +56 -3
- claude_mpm/services/skills/selective_skill_deployer.py +114 -26
- claude_mpm/services/skills/skill_discovery_service.py +57 -3
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- 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-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-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/skill_manager.py +4 -4
- claude_mpm/utils/agent_dependency_loader.py +4 -2
- claude_mpm/utils/robust_installer.py +10 -6
- claude_mpm-5.6.3.dist-info/METADATA +391 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/RECORD +261 -179
- 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/hooks/claude_hooks/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/__init__.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/correlation_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/tool_analysis.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-312.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__/connection_manager_http.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/duplicate_detector.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-312.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-312.pyc +0 -0
- claude_mpm-5.4.71.dist-info/METADATA +0 -1005
- /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.71.dist-info → claude_mpm-5.6.3.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.71.dist-info → claude_mpm-5.6.3.dist-info}/top_level.txt +0 -0
claude_mpm/core/logging_utils.py
CHANGED
|
@@ -103,21 +103,45 @@ class LoggerFactory:
|
|
|
103
103
|
|
|
104
104
|
# Set up root logger
|
|
105
105
|
root_logger = logging.getLogger()
|
|
106
|
-
|
|
106
|
+
|
|
107
|
+
# CRITICAL FIX: Respect existing root logger suppression
|
|
108
|
+
# If root logger is already set to CRITICAL+1 (suppressed by startup.py),
|
|
109
|
+
# don't override it. This prevents logging from appearing during startup
|
|
110
|
+
# before the CLI's setup_logging() runs.
|
|
111
|
+
current_level = root_logger.level
|
|
112
|
+
desired_level = LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
|
|
113
|
+
|
|
114
|
+
# Only set level if current is unset (0) or lower than desired
|
|
115
|
+
# CRITICAL+1 is 51, so this check preserves suppression
|
|
116
|
+
should_configure_logging = current_level == 0 or (
|
|
117
|
+
current_level < desired_level and current_level <= logging.CRITICAL
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if should_configure_logging:
|
|
121
|
+
root_logger.setLevel(desired_level)
|
|
122
|
+
# else: root logger is suppressed (CRITICAL+1), keep it suppressed
|
|
107
123
|
|
|
108
124
|
# Remove existing handlers
|
|
109
125
|
root_logger.handlers = []
|
|
110
126
|
|
|
111
|
-
#
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
# CRITICAL FIX: Don't add handlers if logging is suppressed
|
|
128
|
+
# If root logger is at CRITICAL+1 (startup suppression), don't add any handlers
|
|
129
|
+
# This prevents early imports from logging before CLI setup_logging() runs
|
|
130
|
+
if should_configure_logging:
|
|
131
|
+
# Console handler - MUST use stderr to avoid corrupting hook JSON output
|
|
132
|
+
# WHY stderr: Hook handlers output JSON to stdout. Logging to stdout
|
|
133
|
+
# corrupts this JSON and causes "hook error" messages from Claude Code.
|
|
134
|
+
console_handler = logging.StreamHandler(sys.stderr)
|
|
135
|
+
console_handler.setLevel(
|
|
136
|
+
LoggingConfig.LEVELS.get(cls._log_level, logging.INFO)
|
|
137
|
+
)
|
|
138
|
+
console_formatter = logging.Formatter(
|
|
139
|
+
log_format or LoggingConfig.DEFAULT_FORMAT,
|
|
140
|
+
date_format or LoggingConfig.DATE_FORMAT,
|
|
141
|
+
)
|
|
142
|
+
console_handler.setFormatter(console_formatter)
|
|
143
|
+
root_logger.addHandler(console_handler)
|
|
144
|
+
cls._handlers["console"] = console_handler
|
|
121
145
|
|
|
122
146
|
# File handler (optional)
|
|
123
147
|
if log_to_file and cls._log_dir:
|
|
@@ -13,7 +13,7 @@ Users can change it if they want, and the system will respect their choice.
|
|
|
13
13
|
|
|
14
14
|
import json
|
|
15
15
|
import re
|
|
16
|
-
import subprocess
|
|
16
|
+
import subprocess # nosec B404
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import Any, Dict, Literal, Optional, TypedDict, cast
|
|
19
19
|
|
|
@@ -27,7 +27,9 @@ _CACHED_CLAUDE_VERSION: Optional[str] = None
|
|
|
27
27
|
_VERSION_DETECTED: bool = False
|
|
28
28
|
|
|
29
29
|
# Output style types
|
|
30
|
-
OutputStyleType = Literal[
|
|
30
|
+
OutputStyleType = Literal[
|
|
31
|
+
"professional", "teaching", "research", "founders"
|
|
32
|
+
] # "founders" is deprecated, use "research"
|
|
31
33
|
|
|
32
34
|
|
|
33
35
|
class StyleConfig(TypedDict):
|
|
@@ -41,9 +43,10 @@ class StyleConfig(TypedDict):
|
|
|
41
43
|
class OutputStyleManager:
|
|
42
44
|
"""Manages output style deployment and version-based handling.
|
|
43
45
|
|
|
44
|
-
Supports
|
|
46
|
+
Supports three output styles:
|
|
45
47
|
- professional: Default Claude MPM style (claude-mpm.md)
|
|
46
48
|
- teaching: Adaptive teaching mode (claude-mpm-teacher.md)
|
|
49
|
+
- research: Codebase research mode for founders, PMs, and developers (claude-mpm-research.md)
|
|
47
50
|
"""
|
|
48
51
|
|
|
49
52
|
def __init__(self) -> None:
|
|
@@ -62,14 +65,29 @@ class OutputStyleManager:
|
|
|
62
65
|
/ "agents"
|
|
63
66
|
/ "CLAUDE_MPM_OUTPUT_STYLE.md",
|
|
64
67
|
target=self.output_style_dir / "claude-mpm.md",
|
|
65
|
-
name="
|
|
68
|
+
name="Claude MPM",
|
|
66
69
|
),
|
|
67
70
|
"teaching": StyleConfig(
|
|
68
71
|
source=Path(__file__).parent.parent
|
|
69
72
|
/ "agents"
|
|
70
73
|
/ "CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md",
|
|
71
74
|
target=self.output_style_dir / "claude-mpm-teacher.md",
|
|
72
|
-
name="
|
|
75
|
+
name="Claude MPM Teacher",
|
|
76
|
+
),
|
|
77
|
+
"research": StyleConfig(
|
|
78
|
+
source=Path(__file__).parent.parent
|
|
79
|
+
/ "agents"
|
|
80
|
+
/ "CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md",
|
|
81
|
+
target=self.output_style_dir / "claude-mpm-research.md",
|
|
82
|
+
name="Claude MPM Research",
|
|
83
|
+
),
|
|
84
|
+
# Backward compatibility alias (deprecated)
|
|
85
|
+
"founders": StyleConfig(
|
|
86
|
+
source=Path(__file__).parent.parent
|
|
87
|
+
/ "agents"
|
|
88
|
+
/ "CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md",
|
|
89
|
+
target=self.output_style_dir / "claude-mpm-research.md",
|
|
90
|
+
name="Claude MPM Research",
|
|
73
91
|
),
|
|
74
92
|
}
|
|
75
93
|
|
|
@@ -93,7 +111,7 @@ class OutputStyleManager:
|
|
|
93
111
|
|
|
94
112
|
try:
|
|
95
113
|
# Run claude --version command
|
|
96
|
-
result = subprocess.run(
|
|
114
|
+
result = subprocess.run( # nosec B603 B607
|
|
97
115
|
["claude", "--version"],
|
|
98
116
|
capture_output=True,
|
|
99
117
|
text=True,
|
|
@@ -300,12 +318,12 @@ class OutputStyleManager:
|
|
|
300
318
|
self.logger.error(f"Failed to deploy {style} style: {e}")
|
|
301
319
|
return False
|
|
302
320
|
|
|
303
|
-
def _activate_output_style(self, style_name: str = "
|
|
321
|
+
def _activate_output_style(self, style_name: str = "Claude MPM") -> bool:
|
|
304
322
|
"""
|
|
305
323
|
Update Claude Code settings to activate a specific output style.
|
|
306
324
|
|
|
307
325
|
Args:
|
|
308
|
-
style_name: Name of the style to activate (e.g., "
|
|
326
|
+
style_name: Name of the style to activate (e.g., "Claude MPM", "Claude MPM Teacher")
|
|
309
327
|
|
|
310
328
|
Returns:
|
|
311
329
|
True if activated successfully, False otherwise
|
|
@@ -443,7 +461,7 @@ class OutputStyleManager:
|
|
|
443
461
|
|
|
444
462
|
# Activate the default style if requested
|
|
445
463
|
if activate_default and results.get("professional", False):
|
|
446
|
-
self._activate_output_style("
|
|
464
|
+
self._activate_output_style("Claude MPM")
|
|
447
465
|
|
|
448
466
|
return results
|
|
449
467
|
|
|
@@ -16,7 +16,7 @@ Design Principles:
|
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
from typing import Any, Dict, List, Optional, Union
|
|
18
18
|
|
|
19
|
-
from pydantic import BaseModel, Field,
|
|
19
|
+
from pydantic import BaseModel, Field, field_validator
|
|
20
20
|
from pydantic_settings import BaseSettings
|
|
21
21
|
|
|
22
22
|
from .exceptions import ConfigurationError
|
|
@@ -54,8 +54,9 @@ class LoggingConfig(BaseModel):
|
|
|
54
54
|
default=True, description="Enable console logging"
|
|
55
55
|
)
|
|
56
56
|
|
|
57
|
-
@
|
|
58
|
-
|
|
57
|
+
@field_validator("level")
|
|
58
|
+
@classmethod
|
|
59
|
+
def validate_log_level(cls, v):
|
|
59
60
|
valid_levels = ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
60
61
|
if v.upper() not in valid_levels:
|
|
61
62
|
raise ValueError(f"Invalid log level. Must be one of: {valid_levels}")
|
|
@@ -65,8 +66,36 @@ class LoggingConfig(BaseModel):
|
|
|
65
66
|
class AgentConfig(BaseModel):
|
|
66
67
|
"""Agent system configuration."""
|
|
67
68
|
|
|
69
|
+
# Explicit deployment lists (simplified model)
|
|
70
|
+
enabled: List[str] = Field(
|
|
71
|
+
default_factory=list,
|
|
72
|
+
description="Explicit list of agent IDs to deploy (empty = use auto_discover)",
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
# Required agents that are always deployed
|
|
76
|
+
# Standard 7 core agents for essential PM workflow functionality
|
|
77
|
+
# These are auto-deployed when no agents are specified in configuration
|
|
78
|
+
required: List[str] = Field(
|
|
79
|
+
default_factory=lambda: [
|
|
80
|
+
"engineer", # General-purpose implementation
|
|
81
|
+
"research", # Codebase exploration and analysis
|
|
82
|
+
"qa", # Testing and quality assurance
|
|
83
|
+
"web-qa", # Browser-based testing specialist
|
|
84
|
+
"documentation", # Documentation generation
|
|
85
|
+
"ops", # Basic deployment operations
|
|
86
|
+
"ticketing", # Ticket tracking (essential for PM workflow)
|
|
87
|
+
],
|
|
88
|
+
description="Agents that are always deployed (standard 7 core agents)",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
include_universal: bool = Field(
|
|
92
|
+
default=True,
|
|
93
|
+
description="Auto-include all agents with 'universal' toolchain/category",
|
|
94
|
+
)
|
|
95
|
+
|
|
68
96
|
auto_discover: bool = Field(
|
|
69
|
-
default=
|
|
97
|
+
default=False,
|
|
98
|
+
description="Enable automatic agent discovery (deprecated, use enabled list)",
|
|
70
99
|
)
|
|
71
100
|
precedence: List[str] = Field(
|
|
72
101
|
default=["project", "user", "system"], description="Agent precedence order"
|
|
@@ -239,6 +268,21 @@ class DocumentationConfig(BaseModel):
|
|
|
239
268
|
)
|
|
240
269
|
|
|
241
270
|
|
|
271
|
+
class SkillConfig(BaseModel):
|
|
272
|
+
"""Skill system configuration."""
|
|
273
|
+
|
|
274
|
+
# Explicit deployment lists (simplified model)
|
|
275
|
+
enabled: List[str] = Field(
|
|
276
|
+
default_factory=list,
|
|
277
|
+
description="Explicit list of skill IDs to deploy (includes agent dependencies)",
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
auto_detect_dependencies: bool = Field(
|
|
281
|
+
default=True,
|
|
282
|
+
description="Automatically include skills required by enabled agents",
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
|
|
242
286
|
class UnifiedConfig(BaseSettings):
|
|
243
287
|
"""
|
|
244
288
|
Unified configuration model for Claude MPM.
|
|
@@ -258,6 +302,7 @@ class UnifiedConfig(BaseSettings):
|
|
|
258
302
|
network: NetworkConfig = Field(default_factory=NetworkConfig)
|
|
259
303
|
logging: LoggingConfig = Field(default_factory=LoggingConfig)
|
|
260
304
|
agents: AgentConfig = Field(default_factory=AgentConfig)
|
|
305
|
+
skills: SkillConfig = Field(default_factory=SkillConfig)
|
|
261
306
|
memory: MemoryConfig = Field(default_factory=MemoryConfig)
|
|
262
307
|
security: SecurityConfig = Field(default_factory=SecurityConfig)
|
|
263
308
|
performance: PerformanceConfig = Field(default_factory=PerformanceConfig)
|
|
@@ -287,8 +332,9 @@ class UnifiedConfig(BaseSettings):
|
|
|
287
332
|
validate_assignment = True
|
|
288
333
|
extra = "allow" # Allow extra fields for backward compatibility
|
|
289
334
|
|
|
290
|
-
@
|
|
291
|
-
|
|
335
|
+
@field_validator("environment")
|
|
336
|
+
@classmethod
|
|
337
|
+
def validate_environment(cls, v):
|
|
292
338
|
valid_envs = ["development", "testing", "production"]
|
|
293
339
|
if v not in valid_envs:
|
|
294
340
|
raise ValueError(f"Invalid environment. Must be one of: {valid_envs}")
|
|
@@ -554,12 +600,12 @@ class ConfigurationService:
|
|
|
554
600
|
import yaml
|
|
555
601
|
|
|
556
602
|
with file_path.open("w") as f:
|
|
557
|
-
yaml.dump(self._config.
|
|
603
|
+
yaml.dump(self._config.model_dump(), f, default_flow_style=False)
|
|
558
604
|
elif format.lower() == "json":
|
|
559
605
|
import json
|
|
560
606
|
|
|
561
607
|
with file_path.open("w") as f:
|
|
562
|
-
json.dump(self._config.
|
|
608
|
+
json.dump(self._config.model_dump(), f, indent=2)
|
|
563
609
|
else:
|
|
564
610
|
raise ConfigurationError(f"Unsupported export format: {format}")
|
|
565
611
|
|
claude_mpm/core/unified_paths.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
1
|
"""
|
|
3
2
|
Unified Path Management System for Claude MPM
|
|
4
3
|
==============================================
|
|
@@ -36,6 +35,24 @@ from claude_mpm.core.logging_utils import get_logger
|
|
|
36
35
|
logger = get_logger(__name__)
|
|
37
36
|
|
|
38
37
|
|
|
38
|
+
def _safe_cwd() -> Path:
|
|
39
|
+
"""Safely get the current working directory.
|
|
40
|
+
|
|
41
|
+
If the current directory no longer exists (deleted/moved), fall back to home directory.
|
|
42
|
+
This prevents FileNotFoundError when Path.cwd() is called from a deleted directory.
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Path: Current working directory, or home directory if cwd doesn't exist
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
return Path.cwd()
|
|
49
|
+
except (FileNotFoundError, OSError) as e:
|
|
50
|
+
logger.debug(
|
|
51
|
+
f"Current directory doesn't exist ({e}), falling back to home directory"
|
|
52
|
+
)
|
|
53
|
+
return Path.home()
|
|
54
|
+
|
|
55
|
+
|
|
39
56
|
class PathType(Enum):
|
|
40
57
|
"""Enumeration of different path types for categorization."""
|
|
41
58
|
|
|
@@ -59,6 +76,7 @@ class DeploymentContext(Enum):
|
|
|
59
76
|
EDITABLE_INSTALL = "editable_install"
|
|
60
77
|
PIP_INSTALL = "pip_install"
|
|
61
78
|
PIPX_INSTALL = "pipx_install"
|
|
79
|
+
UV_TOOLS = "uv_tools"
|
|
62
80
|
SYSTEM_PACKAGE = "system_package"
|
|
63
81
|
|
|
64
82
|
|
|
@@ -95,7 +113,7 @@ class PathContext:
|
|
|
95
113
|
|
|
96
114
|
# Additional check: If we're running from within a claude-mpm development directory
|
|
97
115
|
# This handles the case where pipx claude-mpm is invoked from within the dev directory
|
|
98
|
-
cwd =
|
|
116
|
+
cwd = _safe_cwd()
|
|
99
117
|
current = cwd
|
|
100
118
|
for _ in range(5): # Check up to 5 levels up from current directory
|
|
101
119
|
if (current / "pyproject.toml").exists() and (
|
|
@@ -114,7 +132,7 @@ class PathContext:
|
|
|
114
132
|
# Verify this is a development setup by checking for key files
|
|
115
133
|
if (current / "scripts" / "claude-mpm").exists():
|
|
116
134
|
return True
|
|
117
|
-
except Exception:
|
|
135
|
+
except Exception: # nosec B110
|
|
118
136
|
pass
|
|
119
137
|
if current == current.parent:
|
|
120
138
|
break
|
|
@@ -140,7 +158,7 @@ class PathContext:
|
|
|
140
158
|
f"Found editable install via .pth file: {pth_file}"
|
|
141
159
|
)
|
|
142
160
|
return True
|
|
143
|
-
except Exception:
|
|
161
|
+
except Exception: # nosec B112
|
|
144
162
|
continue
|
|
145
163
|
|
|
146
164
|
# Check for egg-link files
|
|
@@ -156,7 +174,7 @@ class PathContext:
|
|
|
156
174
|
f"Found editable install via egg-link: {egg_link}"
|
|
157
175
|
)
|
|
158
176
|
return True
|
|
159
|
-
except Exception:
|
|
177
|
+
except Exception: # nosec B112
|
|
160
178
|
continue
|
|
161
179
|
except ImportError:
|
|
162
180
|
pass
|
|
@@ -173,113 +191,100 @@ class PathContext:
|
|
|
173
191
|
|
|
174
192
|
Priority order:
|
|
175
193
|
1. Environment variable override (CLAUDE_MPM_DEV_MODE)
|
|
176
|
-
2.
|
|
177
|
-
3.
|
|
178
|
-
|
|
194
|
+
2. Package installation path (uv tools, pipx, site-packages, editable)
|
|
195
|
+
3. Current working directory (opt-in with CLAUDE_MPM_PREFER_LOCAL_SOURCE)
|
|
196
|
+
|
|
197
|
+
This ensures installed packages use their installation paths rather than
|
|
198
|
+
accidentally picking up development paths from CWD.
|
|
179
199
|
"""
|
|
180
|
-
#
|
|
200
|
+
# 1. Explicit environment variable override
|
|
181
201
|
if os.environ.get("CLAUDE_MPM_DEV_MODE", "").lower() in ("1", "true", "yes"):
|
|
182
202
|
logger.debug(
|
|
183
203
|
"Development mode forced via CLAUDE_MPM_DEV_MODE environment variable"
|
|
184
204
|
)
|
|
185
205
|
return DeploymentContext.DEVELOPMENT
|
|
186
206
|
|
|
187
|
-
# Check
|
|
188
|
-
# This handles the case where pipx claude-mpm is run from within the dev directory
|
|
189
|
-
cwd = Path.cwd()
|
|
190
|
-
current = cwd
|
|
191
|
-
for _ in range(5): # Check up to 5 levels up from current directory
|
|
192
|
-
if (current / "pyproject.toml").exists() and (
|
|
193
|
-
current / "src" / "claude_mpm"
|
|
194
|
-
).exists():
|
|
195
|
-
# Check if this is the claude-mpm project
|
|
196
|
-
try:
|
|
197
|
-
pyproject_content = (current / "pyproject.toml").read_text()
|
|
198
|
-
if (
|
|
199
|
-
'name = "claude-mpm"' in pyproject_content
|
|
200
|
-
or '"claude-mpm"' in pyproject_content
|
|
201
|
-
):
|
|
202
|
-
logger.debug(
|
|
203
|
-
f"Detected claude-mpm development directory at {current}"
|
|
204
|
-
)
|
|
205
|
-
logger.debug(
|
|
206
|
-
"Using development mode for local source preference"
|
|
207
|
-
)
|
|
208
|
-
return DeploymentContext.DEVELOPMENT
|
|
209
|
-
except Exception:
|
|
210
|
-
pass
|
|
211
|
-
if current == current.parent:
|
|
212
|
-
break
|
|
213
|
-
current = current.parent
|
|
214
|
-
|
|
207
|
+
# 2. Check where the actual package is installed
|
|
215
208
|
try:
|
|
216
209
|
import claude_mpm
|
|
217
210
|
|
|
218
211
|
module_path = Path(claude_mpm.__file__).parent
|
|
212
|
+
package_str = str(module_path)
|
|
219
213
|
|
|
220
|
-
#
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
# Check if we should use development paths
|
|
225
|
-
# This could be because we're in a src/ directory or running from dev directory
|
|
226
|
-
if module_path.parent.name == "src":
|
|
227
|
-
return DeploymentContext.DEVELOPMENT
|
|
228
|
-
if "pipx" in str(module_path):
|
|
229
|
-
# Running via pipx but from within a development directory
|
|
230
|
-
# Use development mode to prefer local source over pipx installation
|
|
231
|
-
cwd = Path.cwd()
|
|
232
|
-
current = cwd
|
|
233
|
-
for _ in range(5):
|
|
234
|
-
if (current / "src" / "claude_mpm").exists() and (
|
|
235
|
-
current / "pyproject.toml"
|
|
236
|
-
).exists():
|
|
237
|
-
logger.debug(
|
|
238
|
-
"Running pipx from development directory, using development mode"
|
|
239
|
-
)
|
|
240
|
-
return DeploymentContext.DEVELOPMENT
|
|
241
|
-
if current == current.parent:
|
|
242
|
-
break
|
|
243
|
-
current = current.parent
|
|
244
|
-
return DeploymentContext.EDITABLE_INSTALL
|
|
245
|
-
return DeploymentContext.EDITABLE_INSTALL
|
|
214
|
+
# UV tools installation (~/.local/share/uv/tools/)
|
|
215
|
+
if "/.local/share/uv/tools/" in package_str:
|
|
216
|
+
logger.debug(f"Detected uv tools installation at {module_path}")
|
|
217
|
+
return DeploymentContext.UV_TOOLS
|
|
246
218
|
|
|
247
|
-
#
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
)
|
|
219
|
+
# pipx installation (~/.local/pipx/venvs/)
|
|
220
|
+
if "/.local/pipx/venvs/" in package_str or "/pipx/" in package_str:
|
|
221
|
+
logger.debug(f"Detected pipx installation at {module_path}")
|
|
222
|
+
return DeploymentContext.PIPX_INSTALL
|
|
223
|
+
|
|
224
|
+
# site-packages (pip install) - but not editable
|
|
225
|
+
if "/site-packages/" in package_str and "/src/" not in package_str:
|
|
226
|
+
logger.debug(f"Detected pip installation at {module_path}")
|
|
227
|
+
return DeploymentContext.PIP_INSTALL
|
|
228
|
+
|
|
229
|
+
# Editable install (pip install -e) - module in src/
|
|
230
|
+
if module_path.parent.name == "src":
|
|
231
|
+
# Check if this is truly an editable install
|
|
232
|
+
if PathContext._is_editable_install():
|
|
233
|
+
logger.debug(f"Detected editable installation at {module_path}")
|
|
234
|
+
return DeploymentContext.EDITABLE_INSTALL
|
|
235
|
+
# Module in src/ but not editable - development mode
|
|
253
236
|
logger.debug(
|
|
254
237
|
f"Detected development mode via directory structure at {module_path}"
|
|
255
238
|
)
|
|
256
239
|
return DeploymentContext.DEVELOPMENT
|
|
257
240
|
|
|
258
|
-
#
|
|
259
|
-
if "
|
|
260
|
-
logger.debug(f"Detected pipx installation at {module_path}")
|
|
261
|
-
return DeploymentContext.PIPX_INSTALL
|
|
262
|
-
|
|
263
|
-
# Check for system package
|
|
264
|
-
if "dist-packages" in str(module_path):
|
|
241
|
+
# dist-packages (system package manager)
|
|
242
|
+
if "dist-packages" in package_str:
|
|
265
243
|
logger.debug(f"Detected system package installation at {module_path}")
|
|
266
244
|
return DeploymentContext.SYSTEM_PACKAGE
|
|
267
245
|
|
|
268
|
-
#
|
|
269
|
-
if "site-packages" in str(module_path):
|
|
270
|
-
# Already checked for editable above, so this is a regular pip install
|
|
271
|
-
logger.debug(f"Detected pip installation at {module_path}")
|
|
272
|
-
return DeploymentContext.PIP_INSTALL
|
|
273
|
-
|
|
274
|
-
# Default to pip install
|
|
246
|
+
# Default to pip install for any other installation
|
|
275
247
|
logger.debug(f"Defaulting to pip installation for {module_path}")
|
|
276
248
|
return DeploymentContext.PIP_INSTALL
|
|
277
249
|
|
|
278
250
|
except ImportError:
|
|
279
251
|
logger.debug(
|
|
280
|
-
"ImportError during
|
|
252
|
+
"ImportError during module path detection, checking CWD as fallback"
|
|
281
253
|
)
|
|
282
|
-
|
|
254
|
+
|
|
255
|
+
# 3. CWD-based detection (OPT-IN ONLY for explicit development work)
|
|
256
|
+
# Only use CWD if explicitly requested or no package installation found
|
|
257
|
+
if os.environ.get("CLAUDE_MPM_PREFER_LOCAL_SOURCE", "").lower() in (
|
|
258
|
+
"1",
|
|
259
|
+
"true",
|
|
260
|
+
"yes",
|
|
261
|
+
):
|
|
262
|
+
cwd = _safe_cwd()
|
|
263
|
+
current = cwd
|
|
264
|
+
for _ in range(5): # Check up to 5 levels up from current directory
|
|
265
|
+
if (current / "pyproject.toml").exists() and (
|
|
266
|
+
current / "src" / "claude_mpm"
|
|
267
|
+
).exists():
|
|
268
|
+
# Check if this is the claude-mpm project
|
|
269
|
+
try:
|
|
270
|
+
pyproject_content = (current / "pyproject.toml").read_text()
|
|
271
|
+
if (
|
|
272
|
+
'name = "claude-mpm"' in pyproject_content
|
|
273
|
+
or '"claude-mpm"' in pyproject_content
|
|
274
|
+
):
|
|
275
|
+
logger.debug(
|
|
276
|
+
f"CLAUDE_MPM_PREFER_LOCAL_SOURCE: Using development directory at {current}"
|
|
277
|
+
)
|
|
278
|
+
return DeploymentContext.DEVELOPMENT
|
|
279
|
+
except Exception: # nosec B110
|
|
280
|
+
pass
|
|
281
|
+
if current == current.parent:
|
|
282
|
+
break
|
|
283
|
+
current = current.parent
|
|
284
|
+
|
|
285
|
+
# Final fallback: assume development mode
|
|
286
|
+
logger.debug("No installation detected, defaulting to development mode")
|
|
287
|
+
return DeploymentContext.DEVELOPMENT
|
|
283
288
|
|
|
284
289
|
|
|
285
290
|
class UnifiedPathManager:
|
|
@@ -346,7 +351,7 @@ class UnifiedPathManager:
|
|
|
346
351
|
):
|
|
347
352
|
# For development mode, first check if we're running from within a dev directory
|
|
348
353
|
# This handles the case where pipx is invoked from a development directory
|
|
349
|
-
cwd =
|
|
354
|
+
cwd = _safe_cwd()
|
|
350
355
|
current = cwd
|
|
351
356
|
for _ in range(5):
|
|
352
357
|
if (current / "src" / "claude_mpm").exists() and (
|
|
@@ -360,7 +365,7 @@ class UnifiedPathManager:
|
|
|
360
365
|
f"Found framework root via cwd at {current}"
|
|
361
366
|
)
|
|
362
367
|
return current
|
|
363
|
-
except Exception:
|
|
368
|
+
except Exception: # nosec B110
|
|
364
369
|
pass
|
|
365
370
|
if current == current.parent:
|
|
366
371
|
break
|
|
@@ -403,7 +408,7 @@ class UnifiedPathManager:
|
|
|
403
408
|
@lru_cache(maxsize=1)
|
|
404
409
|
def project_root(self) -> Path:
|
|
405
410
|
"""Get the current project root directory."""
|
|
406
|
-
current =
|
|
411
|
+
current = _safe_cwd()
|
|
407
412
|
while current != current.parent:
|
|
408
413
|
for marker in self._project_markers:
|
|
409
414
|
if (current / marker).exists():
|
|
@@ -413,7 +418,7 @@ class UnifiedPathManager:
|
|
|
413
418
|
|
|
414
419
|
# Fallback to current directory
|
|
415
420
|
logger.warning("Could not find project root, using current directory")
|
|
416
|
-
return
|
|
421
|
+
return _safe_cwd()
|
|
417
422
|
|
|
418
423
|
@property
|
|
419
424
|
def package_root(self) -> Path:
|
|
@@ -562,7 +567,7 @@ class UnifiedPathManager:
|
|
|
562
567
|
self, filename: str, start_path: Optional[Path] = None
|
|
563
568
|
) -> Optional[Path]:
|
|
564
569
|
"""Search for a file by traversing up the directory tree."""
|
|
565
|
-
current = start_path or
|
|
570
|
+
current = start_path or _safe_cwd()
|
|
566
571
|
|
|
567
572
|
while current != current.parent:
|
|
568
573
|
candidate = current / filename
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji";font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.\!container{width:100%!important}.container{width:100%}@media(min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media(min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media(min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media(min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media(min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0;right:0;bottom:0;left:0}.bottom-4{bottom:1rem}.left-4{left:1rem}.right-2{right:.5rem}.right-4{right:1rem}.top-0{top:0}.top-2{top:.5rem}.top-4{top:1rem}.z-50{z-index:50}.mx-auto{margin-left:auto;margin-right:auto}.-ml-1{margin-left:-.25rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-6{margin-bottom:1.5rem}.ml-1{margin-left:.25rem}.ml-2{margin-left:.5rem}.ml-4{margin-left:1rem}.ml-auto{margin-left:auto}.mr-1{margin-right:.25rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.table{display:table}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-full{height:100%}.h-screen{height:100vh}.max-h-\[calc\(100vh-280px\)\]{max-height:calc(100vh - 280px)}.min-h-0{min-height:0px}.min-h-\[400px\]{min-height:400px}.min-h-screen{min-height:100vh}.w-1\/3{width:33.333333%}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-64{width:16rem}.w-full{width:100%}.min-w-0{min-width:0px}.max-w-xs{max-width:20rem}.flex-1{flex:1 1 0%}.flex-shrink{flex-shrink:1}.flex-shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.rotate-90{--tw-rotate: 90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.cursor-pointer{cursor:pointer}.resize{resize:both}.grid-cols-\[110px_120px_160px_120px_100px\]{grid-template-columns:110px 120px 160px 120px 100px}.grid-cols-\[140px_1fr_80px_100px\]{grid-template-columns:140px 1fr 80px 100px}.grid-cols-\[50px_1fr_100px_120px_auto\]{grid-template-columns:50px 1fr 100px 120px auto}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0{gap:0px}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-2\.5>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.625rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.625rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.space-y-4>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1rem * var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(1.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem * var(--tw-space-y-reverse))}.divide-y>:not([hidden])~:not([hidden]){--tw-divide-y-reverse: 0;border-top-width:calc(1px * calc(1 - var(--tw-divide-y-reverse)));border-bottom-width:calc(1px * var(--tw-divide-y-reverse))}.divide-slate-200>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(226 232 240 / var(--tw-divide-opacity, 1))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.break-all{word-break:break-all}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l-4{border-left-width:4px}.border-r{border-right-width:1px}.border-amber-200{--tw-border-opacity: 1;border-color:rgb(253 230 138 / var(--tw-border-opacity, 1))}.border-amber-400{--tw-border-opacity: 1;border-color:rgb(251 191 36 / var(--tw-border-opacity, 1))}.border-amber-500\/30{border-color:#f59e0b4d}.border-blue-200{--tw-border-opacity: 1;border-color:rgb(191 219 254 / var(--tw-border-opacity, 1))}.border-blue-500\/20{border-color:#3b82f633}.border-blue-500\/30{border-color:#3b82f64d}.border-green-500\/20{border-color:#22c55e33}.border-green-500\/30{border-color:#22c55e4d}.border-purple-200{--tw-border-opacity: 1;border-color:rgb(233 213 255 / var(--tw-border-opacity, 1))}.border-purple-500\/20{border-color:#a855f733}.border-purple-500\/30{border-color:#a855f74d}.border-red-500\/20{border-color:#ef444433}.border-slate-200{--tw-border-opacity: 1;border-color:rgb(226 232 240 / var(--tw-border-opacity, 1))}.border-slate-300{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.border-slate-500{--tw-border-opacity: 1;border-color:rgb(100 116 139 / var(--tw-border-opacity, 1))}.border-slate-500\/20{border-color:#64748b33}.border-slate-500\/30{border-color:#64748b4d}.border-slate-600{--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity, 1))}.border-slate-700{--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.border-violet-400{--tw-border-opacity: 1;border-color:rgb(167 139 250 / var(--tw-border-opacity, 1))}.border-l-cyan-500{--tw-border-opacity: 1;border-left-color:rgb(6 182 212 / var(--tw-border-opacity, 1))}.border-l-transparent{border-left-color:transparent}.bg-amber-100{--tw-bg-opacity: 1;background-color:rgb(254 243 199 / var(--tw-bg-opacity, 1))}.bg-amber-200{--tw-bg-opacity: 1;background-color:rgb(253 230 138 / var(--tw-bg-opacity, 1))}.bg-amber-50{--tw-bg-opacity: 1;background-color:rgb(255 251 235 / var(--tw-bg-opacity, 1))}.bg-amber-500{--tw-bg-opacity: 1;background-color:rgb(245 158 11 / var(--tw-bg-opacity, 1))}.bg-amber-500\/20{background-color:#f59e0b33}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity, 1))}.bg-blue-50{--tw-bg-opacity: 1;background-color:rgb(239 246 255 / var(--tw-bg-opacity, 1))}.bg-blue-500\/20{background-color:#3b82f633}.bg-blue-500\/5{background-color:#3b82f60d}.bg-cyan-50{--tw-bg-opacity: 1;background-color:rgb(236 254 255 / var(--tw-bg-opacity, 1))}.bg-cyan-500{--tw-bg-opacity: 1;background-color:rgb(6 182 212 / var(--tw-bg-opacity, 1))}.bg-green-100{--tw-bg-opacity: 1;background-color:rgb(220 252 231 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/20{background-color:#22c55e33}.bg-green-500\/5{background-color:#22c55e0d}.bg-purple-50{--tw-bg-opacity: 1;background-color:rgb(250 245 255 / var(--tw-bg-opacity, 1))}.bg-purple-500\/20{background-color:#a855f733}.bg-purple-500\/5{background-color:#a855f70d}.bg-red-100{--tw-bg-opacity: 1;background-color:rgb(254 226 226 / var(--tw-bg-opacity, 1))}.bg-red-50{--tw-bg-opacity: 1;background-color:rgb(254 242 242 / var(--tw-bg-opacity, 1))}.bg-red-500{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.bg-red-500\/5{background-color:#ef44440d}.bg-slate-100{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.bg-slate-200{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.bg-slate-50{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.bg-slate-500\/20{background-color:#64748b33}.bg-slate-500\/5{background-color:#64748b0d}.bg-slate-600{--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity, 1))}.bg-slate-800\/90{background-color:#1e293be6}.bg-slate-800\/95{background-color:#1e293bf2}.bg-slate-900{--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.bg-violet-500{--tw-bg-opacity: 1;background-color:rgb(139 92 246 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-12{padding-top:3rem;padding-bottom:3rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-4{padding-top:1rem;padding-bottom:1rem}.pb-2{padding-bottom:.5rem}.pr-2{padding-right:.5rem}.pt-2{padding-top:.5rem}.text-left{text-align:left}.text-center{text-align:center}.text-right{text-align:right}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.capitalize{text-transform:capitalize}.italic{font-style:italic}.leading-none{line-height:1}.text-amber-300{--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.text-amber-500{--tw-text-opacity: 1;color:rgb(245 158 11 / var(--tw-text-opacity, 1))}.text-amber-600{--tw-text-opacity: 1;color:rgb(217 119 6 / var(--tw-text-opacity, 1))}.text-amber-700{--tw-text-opacity: 1;color:rgb(180 83 9 / var(--tw-text-opacity, 1))}.text-blue-300{--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity, 1))}.text-cyan-400{--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.text-cyan-600{--tw-text-opacity: 1;color:rgb(8 145 178 / var(--tw-text-opacity, 1))}.text-green-300{--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.text-green-400{--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-green-700{--tw-text-opacity: 1;color:rgb(21 128 61 / var(--tw-text-opacity, 1))}.text-green-800{--tw-text-opacity: 1;color:rgb(22 101 52 / var(--tw-text-opacity, 1))}.text-purple-400{--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.text-purple-600{--tw-text-opacity: 1;color:rgb(147 51 234 / var(--tw-text-opacity, 1))}.text-red-400{--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-red-800{--tw-text-opacity: 1;color:rgb(153 27 27 / var(--tw-text-opacity, 1))}.text-red-900{--tw-text-opacity: 1;color:rgb(127 29 29 / var(--tw-text-opacity, 1))}.text-slate-100{--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.text-slate-300{--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.text-slate-400{--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.text-slate-500{--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.text-slate-600{--tw-text-opacity: 1;color:rgb(71 85 105 / var(--tw-text-opacity, 1))}.text-slate-700{--tw-text-opacity: 1;color:rgb(51 65 85 / var(--tw-text-opacity, 1))}.text-slate-800{--tw-text-opacity: 1;color:rgb(30 41 59 / var(--tw-text-opacity, 1))}.text-slate-900{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.underline{text-decoration-line:underline}.placeholder-slate-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.placeholder-slate-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(148 163 184 / var(--tw-placeholder-opacity, 1))}.opacity-50{opacity:.5}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-cyan-300{--tw-ring-opacity: 1;--tw-ring-color: rgb(103 232 249 / var(--tw-ring-opacity, 1))}.drop-shadow{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-transform{transition-property:transform;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;--color-bg-primary: #ffffff;--color-bg-secondary: #f8fafc;--color-bg-code: #f1f5f9;--color-text-primary: #0f172a;--color-text-secondary: #475569;--color-text-tertiary: #64748b;--color-border: #e2e8f0;--color-primary: #0891b2}.dark{--color-bg-primary: #0f172a;--color-bg-secondary: #1e293b;--color-bg-code: #334155;--color-text-primary: #f1f5f9;--color-text-secondary: #cbd5e1;--color-text-tertiary: #94a3b8;--color-border: #334155;--color-primary: #06b6d4}body{margin:0;padding:0;background-color:#0f172a;color:#e2e8f0}.hover\:border-slate-300:hover{--tw-border-opacity: 1;border-color:rgb(203 213 225 / var(--tw-border-opacity, 1))}.hover\:bg-blue-500\/10:hover{background-color:#3b82f61a}.hover\:bg-green-500\/10:hover{background-color:#22c55e1a}.hover\:bg-purple-500\/10:hover{background-color:#a855f71a}.hover\:bg-red-500\/10:hover{background-color:#ef44441a}.hover\:bg-slate-100:hover{--tw-bg-opacity: 1;background-color:rgb(241 245 249 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-200:hover{--tw-bg-opacity: 1;background-color:rgb(226 232 240 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-300:hover{--tw-bg-opacity: 1;background-color:rgb(203 213 225 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-50:hover{--tw-bg-opacity: 1;background-color:rgb(248 250 252 / var(--tw-bg-opacity, 1))}.hover\:bg-slate-500\/10:hover{background-color:#64748b1a}.hover\:bg-slate-700:hover{--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.hover\:text-slate-900:hover{--tw-text-opacity: 1;color:rgb(15 23 42 / var(--tw-text-opacity, 1))}.hover\:underline:hover{text-decoration-line:underline}.focus\:border-transparent:focus{border-color:transparent}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.focus\:ring-2:focus{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.focus\:ring-cyan-500:focus{--tw-ring-opacity: 1;--tw-ring-color: rgb(6 182 212 / var(--tw-ring-opacity, 1))}.dark\:divide-slate-700:is(.dark *)>:not([hidden])~:not([hidden]){--tw-divide-opacity: 1;border-color:rgb(51 65 85 / var(--tw-divide-opacity, 1))}.dark\:border-amber-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(146 64 14 / var(--tw-border-opacity, 1))}.dark\:border-blue-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(30 64 175 / var(--tw-border-opacity, 1))}.dark\:border-purple-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(107 33 168 / var(--tw-border-opacity, 1))}.dark\:border-slate-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity, 1))}.dark\:border-slate-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(51 65 85 / var(--tw-border-opacity, 1))}.dark\:border-l-cyan-400:is(.dark *){--tw-border-opacity: 1;border-left-color:rgb(34 211 238 / var(--tw-border-opacity, 1))}.dark\:bg-amber-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(180 83 9 / var(--tw-bg-opacity, 1))}.dark\:bg-amber-900\/20:is(.dark *){background-color:#78350f33}.dark\:bg-amber-900\/30:is(.dark *){background-color:#78350f4d}.dark\:bg-black\/30:is(.dark *){background-color:#0000004d}.dark\:bg-blue-900\/20:is(.dark *){background-color:#1e3a8a33}.dark\:bg-blue-900\/30:is(.dark *){background-color:#1e3a8a4d}.dark\:bg-cyan-500\/20:is(.dark *){background-color:#06b6d433}.dark\:bg-green-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(20 83 45 / var(--tw-bg-opacity, 1))}.dark\:bg-green-900\/30:is(.dark *){background-color:#14532d4d}.dark\:bg-purple-900\/20:is(.dark *){background-color:#581c8733}.dark\:bg-red-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(127 29 29 / var(--tw-bg-opacity, 1))}.dark\:bg-red-900\/20:is(.dark *){background-color:#7f1d1d33}.dark\:bg-slate-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:bg-slate-800\/20:is(.dark *){background-color:#1e293b33}.dark\:bg-slate-800\/40:is(.dark *){background-color:#1e293b66}.dark\:bg-slate-800\/50:is(.dark *){background-color:#1e293b80}.dark\:bg-slate-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 23 42 / var(--tw-bg-opacity, 1))}.dark\:text-amber-300:is(.dark *){--tw-text-opacity: 1;color:rgb(252 211 77 / var(--tw-text-opacity, 1))}.dark\:text-amber-400:is(.dark *){--tw-text-opacity: 1;color:rgb(251 191 36 / var(--tw-text-opacity, 1))}.dark\:text-blue-300:is(.dark *){--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.dark\:text-blue-400:is(.dark *){--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.dark\:text-cyan-400:is(.dark *){--tw-text-opacity: 1;color:rgb(34 211 238 / var(--tw-text-opacity, 1))}.dark\:text-green-200:is(.dark *){--tw-text-opacity: 1;color:rgb(187 247 208 / var(--tw-text-opacity, 1))}.dark\:text-green-300:is(.dark *){--tw-text-opacity: 1;color:rgb(134 239 172 / var(--tw-text-opacity, 1))}.dark\:text-green-400:is(.dark *){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-purple-400:is(.dark *){--tw-text-opacity: 1;color:rgb(192 132 252 / var(--tw-text-opacity, 1))}.dark\:text-red-100:is(.dark *){--tw-text-opacity: 1;color:rgb(254 226 226 / var(--tw-text-opacity, 1))}.dark\:text-red-200:is(.dark *){--tw-text-opacity: 1;color:rgb(254 202 202 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-slate-100:is(.dark *){--tw-text-opacity: 1;color:rgb(241 245 249 / var(--tw-text-opacity, 1))}.dark\:text-slate-200:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}.dark\:text-slate-300:is(.dark *){--tw-text-opacity: 1;color:rgb(203 213 225 / var(--tw-text-opacity, 1))}.dark\:text-slate-400:is(.dark *){--tw-text-opacity: 1;color:rgb(148 163 184 / var(--tw-text-opacity, 1))}.dark\:text-slate-500:is(.dark *){--tw-text-opacity: 1;color:rgb(100 116 139 / var(--tw-text-opacity, 1))}.dark\:text-white:is(.dark *){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.dark\:text-yellow-400:is(.dark *){--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-slate-500:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(100 116 139 / var(--tw-placeholder-opacity, 1))}.dark\:ring-cyan-500\/30:is(.dark *){--tw-ring-color: rgb(6 182 212 / .3)}.dark\:hover\:border-slate-600:hover:is(.dark *){--tw-border-opacity: 1;border-color:rgb(71 85 105 / var(--tw-border-opacity, 1))}.dark\:hover\:bg-slate-600:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(71 85 105 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(51 65 85 / var(--tw-bg-opacity, 1))}.dark\:hover\:bg-slate-700\/30:hover:is(.dark *){background-color:#3341554d}.dark\:hover\:bg-slate-700\/50:hover:is(.dark *){background-color:#33415580}.dark\:hover\:bg-slate-800:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(30 41 59 / var(--tw-bg-opacity, 1))}.dark\:hover\:text-slate-200:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(226 232 240 / var(--tw-text-opacity, 1))}
|