claude-mpm 5.4.48__py3-none-any.whl → 5.6.34__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-mpm might be problematic. Click here for more details.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +66 -241
- claude_mpm/agents/CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md +413 -0
- claude_mpm/agents/CLAUDE_MPM_TEACHER_OUTPUT_STYLE.md +109 -1925
- claude_mpm/agents/PM_INSTRUCTIONS.md +119 -689
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agents.py +2 -4
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +620 -21
- claude_mpm/cli/commands/configure_agent_display.py +3 -1
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +15 -8
- claude_mpm/cli/commands/profile.py +9 -10
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +171 -17
- claude_mpm/cli/executor.py +120 -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 +76 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/profile_parser.py +0 -1
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +544 -511
- claude_mpm/cli/startup_display.py +74 -6
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +146 -0
- claude_mpm/commander/chat/commands.py +96 -0
- claude_mpm/commander/chat/repl.py +310 -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 +332 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +146 -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 +450 -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 +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 +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 +361 -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 +1 -0
- claude_mpm/core/claude_runner.py +154 -2
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +51 -3
- claude_mpm/core/interactive_session.py +12 -11
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/optimized_startup.py +3 -1
- claude_mpm/core/output_style_manager.py +66 -18
- claude_mpm/core/shared/config_loader.py +3 -1
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/1WZnGYqX.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/67pF3qNn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/6RxdMKe4.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/8cZrfX0h.js +60 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/9a6T2nm-.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B443AUzu.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/B8AwtY2H.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BF15LAsF.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BQaXIfA_.js +331 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BRcwIQNr.js +4 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uj46x2Wr.js → BSNlmTZj.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BV6nKitt.js +43 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BViJ8lZt.js +128 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BcQ-Q0FE.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Bpyvgze_.js +30 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C3rbW_a-.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C8WYN38h.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C9I8FlXH.js +61 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIQcWgO2.js +36 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIctN7YN.js +7 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CKrS_JZW.js +145 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CR6P9C4A.js +89 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRRR9MD_.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CSXtMOf0.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CT-sbxSk.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWm6DJsp.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CmKTTxBW.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CpqQ1Kzn.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Cu_Erd72.js +261 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D2nGpDRe.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9iCMida.js +267 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D9ykgMoY.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DL2Ldur1.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DPfltzjH.js +165 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{N4qtv3Hx.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DUliQN2b.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DVp1hx9R.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DXlhR01x.js +122 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/D_lyTybS.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DngoTTgh.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DqkmHtDC.js +220 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DsDh8EYs.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DypDmXgd.js +139 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Gi6I4Gst.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/IPYC-LnN.js +162 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JpevfAFt.js +68 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DjhvlsAc.js → NqQ1dWOy.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/R8CEIRAd.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Zxy7qc-l.js +64 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/qtd3IeO4.js +15 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/ulBFON_C.js +65 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/wQVh1CoA.js +10 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.Dr7t0z2J.js +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.CAGBuiOw.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DG-KkbDf.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +11 -11
- claude_mpm/dashboard-svelte/node_modules/katex/src/fonts/generate_fonts.py +58 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_tfms.py +114 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/extract_ttfs.py +122 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/format_json.py +28 -0
- claude_mpm/dashboard-svelte/node_modules/katex/src/metrics/parse_tfm.py +211 -0
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/event_handlers.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/hook_handler.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/memory_integration.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/response_tracking.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +527 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +170 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +206 -36
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager_http.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/container.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/protocols.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/state_manager.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/subagent_processor.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +310 -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 +215 -2
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/scripts/start_activity_logging.py +0 -0
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/agent_discovery_service.py +3 -1
- claude_mpm/services/agents/deployment/agent_format_converter.py +8 -6
- claude_mpm/services/agents/deployment/agent_template_builder.py +14 -4
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +4 -4
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +4 -1
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +6 -2
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/agents/sources/git_source_sync_service.py +10 -5
- claude_mpm/services/agents/startup_sync.py +5 -2
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -3
- claude_mpm/services/monitor/server.py +106 -16
- claude_mpm/services/pm_skills_deployer.py +267 -94
- claude_mpm/services/profile_manager.py +10 -4
- claude_mpm/services/skills/git_skill_source_manager.py +192 -29
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +188 -67
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/collaboration/brainstorming/SKILL.md +79 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/SKILL.md +178 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/agent-prompts.md +577 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/coordination-patterns.md +467 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/examples.md +537 -0
- claude_mpm/skills/bundled/collaboration/dispatching-parallel-agents/references/troubleshooting.md +730 -0
- claude_mpm/skills/bundled/collaboration/git-worktrees.md +317 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/SKILL.md +112 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/code-reviewer-template.md +146 -0
- claude_mpm/skills/bundled/collaboration/requesting-code-review/references/review-examples.md +412 -0
- claude_mpm/skills/bundled/collaboration/stacked-prs.md +251 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/SKILL.md +81 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/best-practices.md +362 -0
- claude_mpm/skills/bundled/collaboration/writing-plans/references/plan-structure-templates.md +312 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/SKILL.md +152 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/advanced-techniques.md +668 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/examples.md +587 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/integration.md +438 -0
- claude_mpm/skills/bundled/debugging/root-cause-tracing/references/tracing-techniques.md +391 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/CREATION-LOG.md +119 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/SKILL.md +148 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/anti-patterns.md +483 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/examples.md +452 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/troubleshooting.md +449 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/references/workflow.md +411 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-academic.md +14 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-1.md +58 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-2.md +68 -0
- claude_mpm/skills/bundled/debugging/systematic-debugging/test-pressure-3.md +69 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/SKILL.md +131 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/gate-function.md +325 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/integration-and-workflows.md +490 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/red-flags-and-failures.md +425 -0
- claude_mpm/skills/bundled/debugging/verification-before-completion/references/verification-patterns.md +499 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/INTEGRATION.md +611 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/README.md +596 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/SKILL.md +260 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/examples/nextjs-env-structure.md +315 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/frameworks.md +436 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/security.md +433 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/synchronization.md +452 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/troubleshooting.md +404 -0
- claude_mpm/skills/bundled/infrastructure/env-manager/references/validation.md +420 -0
- claude_mpm/skills/bundled/main/artifacts-builder/SKILL.md +86 -0
- claude_mpm/skills/bundled/main/internal-comms/SKILL.md +43 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/3p-updates.md +47 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/company-newsletter.md +65 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/faq-answers.md +30 -0
- claude_mpm/skills/bundled/main/internal-comms/examples/general-comms.md +16 -0
- claude_mpm/skills/bundled/main/mcp-builder/SKILL.md +160 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/design_principles.md +412 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/evaluation.md +602 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/mcp_best_practices.md +915 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/node_mcp_server.md +916 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/python_mcp_server.md +752 -0
- claude_mpm/skills/bundled/main/mcp-builder/reference/workflow.md +1237 -0
- claude_mpm/skills/bundled/main/skill-creator/SKILL.md +189 -0
- claude_mpm/skills/bundled/main/skill-creator/references/best-practices.md +500 -0
- claude_mpm/skills/bundled/main/skill-creator/references/creation-workflow.md +464 -0
- claude_mpm/skills/bundled/main/skill-creator/references/examples.md +619 -0
- claude_mpm/skills/bundled/main/skill-creator/references/progressive-disclosure.md +437 -0
- claude_mpm/skills/bundled/main/skill-creator/references/skill-structure.md +231 -0
- claude_mpm/skills/bundled/php/espocrm-development/SKILL.md +170 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/architecture.md +602 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/common-tasks.md +821 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/development-workflow.md +742 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/frontend-customization.md +726 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/hooks-and-services.md +764 -0
- claude_mpm/skills/bundled/php/espocrm-development/references/testing-debugging.md +831 -0
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-bug-reporting/SKILL.md +248 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-delegation-patterns/SKILL.md +167 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-git-file-tracking/SKILL.md +113 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-pr-workflow/SKILL.md +124 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/mpm-teaching-mode/SKILL.md +657 -0
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-ticketing-integration/SKILL.md +154 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-verification-protocols/SKILL.md +198 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/bundled/react/flexlayout-react.md +742 -0
- claude_mpm/skills/bundled/rust/desktop-applications/SKILL.md +226 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/architecture-patterns.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/native-gui-frameworks.md +901 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/platform-integration.md +775 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/state-management.md +937 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/tauri-framework.md +770 -0
- claude_mpm/skills/bundled/rust/desktop-applications/references/testing-deployment.md +961 -0
- claude_mpm/skills/bundled/security-scanning.md +112 -0
- claude_mpm/skills/bundled/tauri/tauri-async-patterns.md +495 -0
- claude_mpm/skills/bundled/tauri/tauri-build-deploy.md +599 -0
- claude_mpm/skills/bundled/tauri/tauri-command-patterns.md +535 -0
- claude_mpm/skills/bundled/tauri/tauri-error-handling.md +613 -0
- claude_mpm/skills/bundled/tauri/tauri-event-system.md +648 -0
- claude_mpm/skills/bundled/tauri/tauri-file-system.md +673 -0
- claude_mpm/skills/bundled/tauri/tauri-frontend-integration.md +767 -0
- claude_mpm/skills/bundled/tauri/tauri-performance.md +669 -0
- claude_mpm/skills/bundled/tauri/tauri-state-management.md +573 -0
- claude_mpm/skills/bundled/tauri/tauri-testing.md +384 -0
- claude_mpm/skills/bundled/tauri/tauri-window-management.md +628 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/SKILL.md +119 -0
- claude_mpm/skills/bundled/testing/condition-based-waiting/references/patterns-and-implementation.md +253 -0
- claude_mpm/skills/bundled/testing/test-driven-development/SKILL.md +145 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/anti-patterns.md +543 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/examples.md +741 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/integration.md +470 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/philosophy.md +458 -0
- claude_mpm/skills/bundled/testing/test-driven-development/references/workflow.md +639 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/SKILL.md +458 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/examples/example-inspection-report.md +411 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/assertion-quality.md +317 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/inspection-checklist.md +270 -0
- claude_mpm/skills/bundled/testing/test-quality-inspector/references/red-flags.md +436 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/SKILL.md +140 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/completeness-anti-patterns.md +572 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/core-anti-patterns.md +411 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/detection-guide.md +569 -0
- claude_mpm/skills/bundled/testing/testing-anti-patterns/references/tdd-connection.md +695 -0
- claude_mpm/skills/bundled/testing/webapp-testing/SKILL.md +184 -0
- claude_mpm/skills/bundled/testing/webapp-testing/decision-tree.md +459 -0
- claude_mpm/skills/bundled/testing/webapp-testing/playwright-patterns.md +479 -0
- claude_mpm/skills/bundled/testing/webapp-testing/reconnaissance-pattern.md +687 -0
- claude_mpm/skills/bundled/testing/webapp-testing/server-management.md +758 -0
- claude_mpm/skills/bundled/testing/webapp-testing/troubleshooting.md +868 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +29 -23
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +103 -4
- claude_mpm/utils/robust_installer.py +45 -24
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +453 -151
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.B_FtCwCQ.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.Cl_eSA4x.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BgChzWQ1.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CIXEwuWe.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CWc5urbQ.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/DMkZpdF2.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/app.DTL5mJO-.js +0 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.DzuEhzqh.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/1.DFLC8jdE.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.DPvEihJJ.js +0 -10
- claude_mpm/hooks/claude_hooks/__pycache__/installer.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/services/__pycache__/connection_manager.cpython-311.pyc +0 -0
- claude_mpm-5.4.48.dist-info/METADATA +0 -999
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.48.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
"""Manages running Claude Code/MPM instances."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from claude_mpm.commander.adapters import (
|
|
8
|
+
AdapterResponse,
|
|
9
|
+
ClaudeCodeAdapter,
|
|
10
|
+
ClaudeCodeCommunicationAdapter,
|
|
11
|
+
)
|
|
12
|
+
from claude_mpm.commander.frameworks.base import BaseFramework, InstanceInfo
|
|
13
|
+
from claude_mpm.commander.frameworks.claude_code import ClaudeCodeFramework
|
|
14
|
+
from claude_mpm.commander.frameworks.mpm import MPMFramework
|
|
15
|
+
from claude_mpm.commander.tmux_orchestrator import TmuxOrchestrator
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class InstanceNotFoundError(Exception):
|
|
21
|
+
"""Raised when an instance is not found."""
|
|
22
|
+
|
|
23
|
+
def __init__(self, name: str):
|
|
24
|
+
super().__init__(f"Instance not found: {name}")
|
|
25
|
+
self.name = name
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class FrameworkNotFoundError(Exception):
|
|
29
|
+
"""Raised when a framework is not found or not available."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, framework: str):
|
|
32
|
+
super().__init__(f"Framework not found or not available: {framework}")
|
|
33
|
+
self.framework = framework
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class InstanceAlreadyExistsError(Exception):
|
|
37
|
+
"""Raised when trying to start an instance that already exists."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, name: str):
|
|
40
|
+
super().__init__(f"Instance already exists: {name}")
|
|
41
|
+
self.name = name
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class InstanceManager:
|
|
45
|
+
"""Manages lifecycle of Claude instances.
|
|
46
|
+
|
|
47
|
+
The InstanceManager coordinates framework selection, instance startup,
|
|
48
|
+
and tracking of running instances across the TmuxOrchestrator.
|
|
49
|
+
|
|
50
|
+
Attributes:
|
|
51
|
+
orchestrator: TmuxOrchestrator for managing tmux sessions/panes
|
|
52
|
+
|
|
53
|
+
Example:
|
|
54
|
+
>>> orchestrator = TmuxOrchestrator()
|
|
55
|
+
>>> manager = InstanceManager(orchestrator)
|
|
56
|
+
>>> frameworks = manager.list_frameworks()
|
|
57
|
+
>>> print(frameworks)
|
|
58
|
+
['cc', 'mpm']
|
|
59
|
+
>>> instance = await manager.start_instance(
|
|
60
|
+
... "myapp",
|
|
61
|
+
... Path("/Users/user/myapp"),
|
|
62
|
+
... framework="cc"
|
|
63
|
+
... )
|
|
64
|
+
>>> print(instance.name, instance.framework)
|
|
65
|
+
myapp cc
|
|
66
|
+
"""
|
|
67
|
+
|
|
68
|
+
def __init__(self, orchestrator: TmuxOrchestrator):
|
|
69
|
+
"""Initialize the instance manager.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
orchestrator: TmuxOrchestrator for managing tmux sessions/panes
|
|
73
|
+
"""
|
|
74
|
+
self.orchestrator = orchestrator
|
|
75
|
+
self._instances: dict[str, InstanceInfo] = {}
|
|
76
|
+
self._frameworks = self._load_frameworks()
|
|
77
|
+
self._adapters: dict[str, ClaudeCodeCommunicationAdapter] = {}
|
|
78
|
+
|
|
79
|
+
def _load_frameworks(self) -> dict[str, BaseFramework]:
|
|
80
|
+
"""Load available frameworks.
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
Dict mapping framework name to framework instance
|
|
84
|
+
|
|
85
|
+
Example:
|
|
86
|
+
>>> manager = InstanceManager(orchestrator)
|
|
87
|
+
>>> frameworks = manager._load_frameworks()
|
|
88
|
+
>>> print(frameworks.keys())
|
|
89
|
+
dict_keys(['cc', 'mpm'])
|
|
90
|
+
"""
|
|
91
|
+
frameworks = {}
|
|
92
|
+
for framework_class in [ClaudeCodeFramework, MPMFramework]:
|
|
93
|
+
framework = framework_class()
|
|
94
|
+
if framework.is_available():
|
|
95
|
+
frameworks[framework.name] = framework
|
|
96
|
+
logger.info(
|
|
97
|
+
f"Loaded framework: {framework.name} ({framework.display_name})"
|
|
98
|
+
)
|
|
99
|
+
else:
|
|
100
|
+
logger.warning(
|
|
101
|
+
f"Framework not available: {framework.name} ({framework.display_name})"
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
return frameworks
|
|
105
|
+
|
|
106
|
+
def list_frameworks(self) -> list[str]:
|
|
107
|
+
"""List available framework names.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
List of framework names (e.g., ["cc", "mpm"])
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
>>> manager = InstanceManager(orchestrator)
|
|
114
|
+
>>> frameworks = manager.list_frameworks()
|
|
115
|
+
>>> print(frameworks)
|
|
116
|
+
['cc', 'mpm']
|
|
117
|
+
"""
|
|
118
|
+
return list(self._frameworks.keys())
|
|
119
|
+
|
|
120
|
+
async def start_instance(
|
|
121
|
+
self, name: str, project_path: Path, framework: str = "cc"
|
|
122
|
+
) -> InstanceInfo:
|
|
123
|
+
"""Start a new instance.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
name: Instance name (e.g., "myapp")
|
|
127
|
+
project_path: Path to project directory
|
|
128
|
+
framework: Framework to use ("cc" or "mpm")
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
InstanceInfo with tmux session details
|
|
132
|
+
|
|
133
|
+
Raises:
|
|
134
|
+
FrameworkNotFoundError: If framework is not available
|
|
135
|
+
InstanceAlreadyExistsError: If instance already exists
|
|
136
|
+
|
|
137
|
+
Example:
|
|
138
|
+
>>> manager = InstanceManager(orchestrator)
|
|
139
|
+
>>> instance = await manager.start_instance(
|
|
140
|
+
... "myapp",
|
|
141
|
+
... Path("/Users/user/myapp"),
|
|
142
|
+
... framework="cc"
|
|
143
|
+
... )
|
|
144
|
+
>>> print(instance.name, instance.framework)
|
|
145
|
+
myapp cc
|
|
146
|
+
"""
|
|
147
|
+
# Check if instance already exists
|
|
148
|
+
if name in self._instances:
|
|
149
|
+
raise InstanceAlreadyExistsError(name)
|
|
150
|
+
|
|
151
|
+
# Get framework
|
|
152
|
+
if framework not in self._frameworks:
|
|
153
|
+
raise FrameworkNotFoundError(framework)
|
|
154
|
+
|
|
155
|
+
framework_obj = self._frameworks[framework]
|
|
156
|
+
|
|
157
|
+
# Get git info
|
|
158
|
+
git_branch, git_status = framework_obj.get_git_info(project_path)
|
|
159
|
+
|
|
160
|
+
# Ensure tmux session exists
|
|
161
|
+
self.orchestrator.create_session()
|
|
162
|
+
|
|
163
|
+
# Create pane
|
|
164
|
+
pane_target = self.orchestrator.create_pane(name, str(project_path))
|
|
165
|
+
|
|
166
|
+
# Start framework in pane
|
|
167
|
+
startup_cmd = framework_obj.get_startup_command(project_path)
|
|
168
|
+
self.orchestrator.send_keys(pane_target, startup_cmd)
|
|
169
|
+
|
|
170
|
+
# Create communication adapter for the instance (only for Claude Code for now)
|
|
171
|
+
# Do this BEFORE creating InstanceInfo so we can set connected=True
|
|
172
|
+
has_adapter = False
|
|
173
|
+
if framework == "cc":
|
|
174
|
+
runtime_adapter = ClaudeCodeAdapter()
|
|
175
|
+
comm_adapter = ClaudeCodeCommunicationAdapter(
|
|
176
|
+
orchestrator=self.orchestrator,
|
|
177
|
+
pane_target=pane_target,
|
|
178
|
+
runtime_adapter=runtime_adapter,
|
|
179
|
+
)
|
|
180
|
+
self._adapters[name] = comm_adapter
|
|
181
|
+
has_adapter = True
|
|
182
|
+
logger.debug(f"Created communication adapter for instance '{name}'")
|
|
183
|
+
|
|
184
|
+
# Create instance info
|
|
185
|
+
instance = InstanceInfo(
|
|
186
|
+
name=name,
|
|
187
|
+
project_path=project_path,
|
|
188
|
+
framework=framework,
|
|
189
|
+
tmux_session=self.orchestrator.session_name,
|
|
190
|
+
pane_target=pane_target,
|
|
191
|
+
git_branch=git_branch,
|
|
192
|
+
git_status=git_status,
|
|
193
|
+
connected=has_adapter,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
# Track instance
|
|
197
|
+
self._instances[name] = instance
|
|
198
|
+
|
|
199
|
+
logger.info(
|
|
200
|
+
f"Started instance '{name}' with framework '{framework}' at {project_path}"
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
return instance
|
|
204
|
+
|
|
205
|
+
async def stop_instance(self, name: str) -> bool:
|
|
206
|
+
"""Stop an instance.
|
|
207
|
+
|
|
208
|
+
Args:
|
|
209
|
+
name: Instance name
|
|
210
|
+
|
|
211
|
+
Returns:
|
|
212
|
+
True if instance was stopped
|
|
213
|
+
|
|
214
|
+
Raises:
|
|
215
|
+
InstanceNotFoundError: If instance not found
|
|
216
|
+
|
|
217
|
+
Example:
|
|
218
|
+
>>> manager = InstanceManager(orchestrator)
|
|
219
|
+
>>> await manager.stop_instance("myapp")
|
|
220
|
+
True
|
|
221
|
+
"""
|
|
222
|
+
if name not in self._instances:
|
|
223
|
+
raise InstanceNotFoundError(name)
|
|
224
|
+
|
|
225
|
+
instance = self._instances[name]
|
|
226
|
+
|
|
227
|
+
# Kill tmux pane
|
|
228
|
+
self.orchestrator.kill_pane(instance.pane_target)
|
|
229
|
+
|
|
230
|
+
# Remove adapter if exists
|
|
231
|
+
if name in self._adapters:
|
|
232
|
+
del self._adapters[name]
|
|
233
|
+
instance.connected = False
|
|
234
|
+
logger.debug(f"Removed adapter for instance '{name}'")
|
|
235
|
+
|
|
236
|
+
# Remove from tracking
|
|
237
|
+
del self._instances[name]
|
|
238
|
+
|
|
239
|
+
logger.info(f"Stopped instance '{name}'")
|
|
240
|
+
|
|
241
|
+
return True
|
|
242
|
+
|
|
243
|
+
def get_instance(self, name: str) -> Optional[InstanceInfo]:
|
|
244
|
+
"""Get instance by name.
|
|
245
|
+
|
|
246
|
+
Args:
|
|
247
|
+
name: Instance name
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
InstanceInfo if found, None otherwise
|
|
251
|
+
|
|
252
|
+
Example:
|
|
253
|
+
>>> manager = InstanceManager(orchestrator)
|
|
254
|
+
>>> instance = manager.get_instance("myapp")
|
|
255
|
+
>>> if instance:
|
|
256
|
+
... print(instance.name, instance.framework)
|
|
257
|
+
myapp cc
|
|
258
|
+
"""
|
|
259
|
+
return self._instances.get(name)
|
|
260
|
+
|
|
261
|
+
def list_instances(self) -> list[InstanceInfo]:
|
|
262
|
+
"""List all running instances.
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
List of InstanceInfo for all running instances
|
|
266
|
+
|
|
267
|
+
Example:
|
|
268
|
+
>>> manager = InstanceManager(orchestrator)
|
|
269
|
+
>>> instances = manager.list_instances()
|
|
270
|
+
>>> for instance in instances:
|
|
271
|
+
... print(instance.name, instance.framework)
|
|
272
|
+
myapp cc
|
|
273
|
+
otherapp mpm
|
|
274
|
+
"""
|
|
275
|
+
return list(self._instances.values())
|
|
276
|
+
|
|
277
|
+
async def send_to_instance(
|
|
278
|
+
self, name: str, message: str, wait_for_response: bool = False
|
|
279
|
+
) -> Optional[AdapterResponse]:
|
|
280
|
+
"""Send a message/command to an instance.
|
|
281
|
+
|
|
282
|
+
Args:
|
|
283
|
+
name: Instance name
|
|
284
|
+
message: Message to send
|
|
285
|
+
wait_for_response: If True, wait for and return response
|
|
286
|
+
|
|
287
|
+
Returns:
|
|
288
|
+
AdapterResponse if wait_for_response=True, None otherwise
|
|
289
|
+
|
|
290
|
+
Raises:
|
|
291
|
+
InstanceNotFoundError: If instance not found
|
|
292
|
+
|
|
293
|
+
Example:
|
|
294
|
+
>>> manager = InstanceManager(orchestrator)
|
|
295
|
+
>>> # Send without waiting
|
|
296
|
+
>>> await manager.send_to_instance("myapp", "Fix the bug in main.py")
|
|
297
|
+
>>> # Send and wait for response
|
|
298
|
+
>>> response = await manager.send_to_instance(
|
|
299
|
+
... "myapp", "Fix the bug", wait_for_response=True
|
|
300
|
+
... )
|
|
301
|
+
>>> print(response.content)
|
|
302
|
+
"""
|
|
303
|
+
if name not in self._instances:
|
|
304
|
+
raise InstanceNotFoundError(name)
|
|
305
|
+
|
|
306
|
+
instance = self._instances[name]
|
|
307
|
+
|
|
308
|
+
# Use adapter if available
|
|
309
|
+
if name in self._adapters:
|
|
310
|
+
adapter = self._adapters[name]
|
|
311
|
+
await adapter.send(message)
|
|
312
|
+
logger.info(
|
|
313
|
+
f"Sent message via adapter to instance '{name}': {message[:50]}..."
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
if wait_for_response:
|
|
317
|
+
return await adapter.receive()
|
|
318
|
+
return None
|
|
319
|
+
|
|
320
|
+
# Fallback to direct tmux if no adapter
|
|
321
|
+
self.orchestrator.send_keys(instance.pane_target, message)
|
|
322
|
+
logger.info(f"Sent message to instance '{name}': {message[:50]}...")
|
|
323
|
+
return None
|
|
324
|
+
|
|
325
|
+
def get_adapter(self, name: str) -> Optional[ClaudeCodeCommunicationAdapter]:
|
|
326
|
+
"""Get communication adapter for an instance.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
name: Instance name
|
|
330
|
+
|
|
331
|
+
Returns:
|
|
332
|
+
ClaudeCodeCommunicationAdapter if exists, None otherwise
|
|
333
|
+
|
|
334
|
+
Example:
|
|
335
|
+
>>> manager = InstanceManager(orchestrator)
|
|
336
|
+
>>> adapter = manager.get_adapter("myapp")
|
|
337
|
+
>>> if adapter:
|
|
338
|
+
... await adapter.send("Create a new file")
|
|
339
|
+
... async for chunk in adapter.stream_response():
|
|
340
|
+
... print(chunk, end='')
|
|
341
|
+
"""
|
|
342
|
+
return self._adapters.get(name)
|
|
343
|
+
|
|
344
|
+
async def rename_instance(self, old_name: str, new_name: str) -> bool:
|
|
345
|
+
"""Rename an instance.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
old_name: Current instance name
|
|
349
|
+
new_name: New instance name
|
|
350
|
+
|
|
351
|
+
Returns:
|
|
352
|
+
True if renamed successfully
|
|
353
|
+
|
|
354
|
+
Raises:
|
|
355
|
+
InstanceNotFoundError: If old_name doesn't exist
|
|
356
|
+
InstanceAlreadyExistsError: If new_name already exists
|
|
357
|
+
|
|
358
|
+
Example:
|
|
359
|
+
>>> manager = InstanceManager(orchestrator)
|
|
360
|
+
>>> await manager.rename_instance("myapp", "myapp-v2")
|
|
361
|
+
True
|
|
362
|
+
"""
|
|
363
|
+
# Validate old_name exists
|
|
364
|
+
if old_name not in self._instances:
|
|
365
|
+
raise InstanceNotFoundError(old_name)
|
|
366
|
+
|
|
367
|
+
# Validate new_name doesn't exist
|
|
368
|
+
if new_name in self._instances:
|
|
369
|
+
raise InstanceAlreadyExistsError(new_name)
|
|
370
|
+
|
|
371
|
+
# Get instance and update name
|
|
372
|
+
instance = self._instances[old_name]
|
|
373
|
+
instance.name = new_name
|
|
374
|
+
|
|
375
|
+
# Update _instances dict (remove old key, add new)
|
|
376
|
+
del self._instances[old_name]
|
|
377
|
+
self._instances[new_name] = instance
|
|
378
|
+
|
|
379
|
+
# Update _adapters dict if exists
|
|
380
|
+
if old_name in self._adapters:
|
|
381
|
+
adapter = self._adapters[old_name]
|
|
382
|
+
del self._adapters[old_name]
|
|
383
|
+
self._adapters[new_name] = adapter
|
|
384
|
+
logger.debug(f"Moved adapter from '{old_name}' to '{new_name}'")
|
|
385
|
+
|
|
386
|
+
logger.info(f"Renamed instance from '{old_name}' to '{new_name}'")
|
|
387
|
+
|
|
388
|
+
return True
|
|
389
|
+
|
|
390
|
+
async def close_instance(self, name: str) -> bool:
|
|
391
|
+
"""Close and remove an instance.
|
|
392
|
+
|
|
393
|
+
Alias for stop_instance that provides clearer semantics for closing.
|
|
394
|
+
|
|
395
|
+
Args:
|
|
396
|
+
name: Instance name to close
|
|
397
|
+
|
|
398
|
+
Returns:
|
|
399
|
+
True if closed successfully
|
|
400
|
+
|
|
401
|
+
Raises:
|
|
402
|
+
InstanceNotFoundError: If instance not found
|
|
403
|
+
|
|
404
|
+
Example:
|
|
405
|
+
>>> manager = InstanceManager(orchestrator)
|
|
406
|
+
>>> await manager.close_instance("myapp")
|
|
407
|
+
True
|
|
408
|
+
"""
|
|
409
|
+
return await self.stop_instance(name)
|
|
410
|
+
|
|
411
|
+
async def disconnect_instance(self, name: str) -> bool:
|
|
412
|
+
"""Disconnect from an instance without closing it.
|
|
413
|
+
|
|
414
|
+
The instance keeps running but we stop communication.
|
|
415
|
+
Removes the adapter while keeping the instance tracked.
|
|
416
|
+
|
|
417
|
+
Args:
|
|
418
|
+
name: Instance name to disconnect from
|
|
419
|
+
|
|
420
|
+
Returns:
|
|
421
|
+
True if disconnected successfully
|
|
422
|
+
|
|
423
|
+
Raises:
|
|
424
|
+
InstanceNotFoundError: If instance not found
|
|
425
|
+
|
|
426
|
+
Example:
|
|
427
|
+
>>> manager = InstanceManager(orchestrator)
|
|
428
|
+
>>> await manager.disconnect_instance("myapp")
|
|
429
|
+
True
|
|
430
|
+
>>> # Instance still running, but no adapter connection
|
|
431
|
+
>>> adapter = manager.get_adapter("myapp")
|
|
432
|
+
>>> print(adapter)
|
|
433
|
+
None
|
|
434
|
+
"""
|
|
435
|
+
# Validate instance exists
|
|
436
|
+
if name not in self._instances:
|
|
437
|
+
raise InstanceNotFoundError(name)
|
|
438
|
+
|
|
439
|
+
instance = self._instances[name]
|
|
440
|
+
|
|
441
|
+
# Remove adapter if exists (but keep instance)
|
|
442
|
+
if name in self._adapters:
|
|
443
|
+
# Could add cleanup here if adapter has resources to close
|
|
444
|
+
del self._adapters[name]
|
|
445
|
+
instance.connected = False
|
|
446
|
+
logger.info(f"Disconnected from instance '{name}' (instance still running)")
|
|
447
|
+
else:
|
|
448
|
+
logger.debug(f"No adapter to disconnect for instance '{name}'")
|
|
449
|
+
|
|
450
|
+
return True
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
"""OpenRouter LLM client for Commander chat interface."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from typing import AsyncIterator
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class OpenRouterConfig:
|
|
12
|
+
"""Configuration for OpenRouter API client."""
|
|
13
|
+
|
|
14
|
+
api_key: str | None = None # Falls back to OPENROUTER_API_KEY env
|
|
15
|
+
model: str = "anthropic/claude-3.5-sonnet"
|
|
16
|
+
base_url: str = "https://openrouter.ai/api/v1"
|
|
17
|
+
max_tokens: int = 4096
|
|
18
|
+
temperature: float = 0.7
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class OpenRouterClient:
|
|
22
|
+
"""Async client for OpenRouter API."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, config: OpenRouterConfig | None = None):
|
|
25
|
+
"""Initialize client with config.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
config: OpenRouter configuration. Defaults to OpenRouterConfig().
|
|
29
|
+
|
|
30
|
+
Raises:
|
|
31
|
+
ValueError: If OPENROUTER_API_KEY is not set.
|
|
32
|
+
"""
|
|
33
|
+
self.config = config or OpenRouterConfig()
|
|
34
|
+
self._api_key = self.config.api_key or os.getenv("OPENROUTER_API_KEY")
|
|
35
|
+
if not self._api_key:
|
|
36
|
+
raise ValueError("OPENROUTER_API_KEY not set")
|
|
37
|
+
|
|
38
|
+
async def chat(self, messages: list[dict], system: str | None = None) -> str:
|
|
39
|
+
"""Send chat completion request, return response content.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
messages: List of message dicts with 'role' and 'content' keys.
|
|
43
|
+
system: Optional system prompt.
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Response content from the model.
|
|
47
|
+
|
|
48
|
+
Raises:
|
|
49
|
+
httpx.HTTPStatusError: If API request fails.
|
|
50
|
+
"""
|
|
51
|
+
async with httpx.AsyncClient() as client:
|
|
52
|
+
# Build request payload
|
|
53
|
+
payload = {
|
|
54
|
+
"model": self.config.model,
|
|
55
|
+
"messages": messages,
|
|
56
|
+
"max_tokens": self.config.max_tokens,
|
|
57
|
+
"temperature": self.config.temperature,
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if system:
|
|
61
|
+
payload["system"] = system
|
|
62
|
+
|
|
63
|
+
# Send request
|
|
64
|
+
response = await client.post(
|
|
65
|
+
f"{self.config.base_url}/chat/completions",
|
|
66
|
+
headers={
|
|
67
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
68
|
+
"Content-Type": "application/json",
|
|
69
|
+
},
|
|
70
|
+
json=payload,
|
|
71
|
+
timeout=30.0,
|
|
72
|
+
)
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
|
|
75
|
+
# Extract content from response
|
|
76
|
+
data = response.json()
|
|
77
|
+
return data["choices"][0]["message"]["content"]
|
|
78
|
+
|
|
79
|
+
async def chat_stream(
|
|
80
|
+
self, messages: list[dict], system: str | None = None
|
|
81
|
+
) -> AsyncIterator[str]:
|
|
82
|
+
"""Stream chat completion, yield chunks.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
messages: List of message dicts with 'role' and 'content' keys.
|
|
86
|
+
system: Optional system prompt.
|
|
87
|
+
|
|
88
|
+
Yields:
|
|
89
|
+
Content chunks from the streaming response.
|
|
90
|
+
|
|
91
|
+
Raises:
|
|
92
|
+
httpx.HTTPStatusError: If API request fails.
|
|
93
|
+
"""
|
|
94
|
+
async with httpx.AsyncClient() as client:
|
|
95
|
+
# Build request payload
|
|
96
|
+
payload = {
|
|
97
|
+
"model": self.config.model,
|
|
98
|
+
"messages": messages,
|
|
99
|
+
"max_tokens": self.config.max_tokens,
|
|
100
|
+
"temperature": self.config.temperature,
|
|
101
|
+
"stream": True,
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if system:
|
|
105
|
+
payload["system"] = system
|
|
106
|
+
|
|
107
|
+
# Send streaming request
|
|
108
|
+
async with client.stream(
|
|
109
|
+
"POST",
|
|
110
|
+
f"{self.config.base_url}/chat/completions",
|
|
111
|
+
headers={
|
|
112
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
113
|
+
"Content-Type": "application/json",
|
|
114
|
+
},
|
|
115
|
+
json=payload,
|
|
116
|
+
timeout=30.0,
|
|
117
|
+
) as response:
|
|
118
|
+
response.raise_for_status()
|
|
119
|
+
|
|
120
|
+
# Parse SSE stream
|
|
121
|
+
async for line in response.aiter_lines():
|
|
122
|
+
if not line.strip():
|
|
123
|
+
continue
|
|
124
|
+
|
|
125
|
+
# SSE format: "data: {json}"
|
|
126
|
+
if line.startswith("data: "):
|
|
127
|
+
data_str = line[6:] # Remove "data: " prefix
|
|
128
|
+
|
|
129
|
+
# Check for stream end
|
|
130
|
+
if data_str == "[DONE]":
|
|
131
|
+
break
|
|
132
|
+
|
|
133
|
+
# Parse JSON chunk
|
|
134
|
+
import json
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
data = json.loads(data_str)
|
|
138
|
+
delta = data["choices"][0].get("delta", {})
|
|
139
|
+
if "content" in delta:
|
|
140
|
+
yield delta["content"]
|
|
141
|
+
except (json.JSONDecodeError, KeyError, IndexError):
|
|
142
|
+
# Skip malformed chunks
|
|
143
|
+
continue
|
|
144
|
+
|
|
145
|
+
async def summarize(self, text: str, max_length: int = 500) -> str:
|
|
146
|
+
"""Summarize text to max_length characters.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
text: Text to summarize.
|
|
150
|
+
max_length: Maximum length of summary in characters.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Summarized text.
|
|
154
|
+
"""
|
|
155
|
+
messages = [
|
|
156
|
+
{
|
|
157
|
+
"role": "user",
|
|
158
|
+
"content": f"Summarize the following text in approximately {max_length} characters or less:\n\n{text}",
|
|
159
|
+
}
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
system = (
|
|
163
|
+
"You are a concise summarization assistant. "
|
|
164
|
+
"Provide clear, accurate summaries that capture the key points."
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
return await self.chat(messages, system=system)
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""Summarizes Claude Code output for user display."""
|
|
2
|
+
|
|
3
|
+
from .openrouter_client import OpenRouterClient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class OutputSummarizer:
|
|
7
|
+
"""Summarizes long output from Claude Code instances."""
|
|
8
|
+
|
|
9
|
+
def __init__(self, client: OpenRouterClient):
|
|
10
|
+
"""Initialize with OpenRouter client.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
client: OpenRouterClient instance for LLM requests.
|
|
14
|
+
"""
|
|
15
|
+
self.client = client
|
|
16
|
+
|
|
17
|
+
async def summarize(self, output: str, context: str | None = None) -> str:
|
|
18
|
+
"""Summarize Claude Code output.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
output: Raw output from Claude Code.
|
|
22
|
+
context: Optional context about what was requested.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Concise summary of the output.
|
|
26
|
+
"""
|
|
27
|
+
# Build summarization prompt
|
|
28
|
+
if context:
|
|
29
|
+
prompt = f"""Summarize the following Claude Code output.
|
|
30
|
+
|
|
31
|
+
Context: {context}
|
|
32
|
+
|
|
33
|
+
Output:
|
|
34
|
+
{output}
|
|
35
|
+
|
|
36
|
+
Provide a concise summary (2-3 sentences) that captures:
|
|
37
|
+
1. What action was taken
|
|
38
|
+
2. The key result or outcome
|
|
39
|
+
3. Any important warnings or next steps
|
|
40
|
+
|
|
41
|
+
Summary:"""
|
|
42
|
+
else:
|
|
43
|
+
prompt = f"""Summarize the following Claude Code output in 2-3 sentences.
|
|
44
|
+
|
|
45
|
+
Output:
|
|
46
|
+
{output}
|
|
47
|
+
|
|
48
|
+
Summary:"""
|
|
49
|
+
|
|
50
|
+
messages = [{"role": "user", "content": prompt}]
|
|
51
|
+
|
|
52
|
+
system = (
|
|
53
|
+
"You are a technical summarization assistant. "
|
|
54
|
+
"Provide clear, concise summaries of command output and code execution results. "
|
|
55
|
+
"Focus on actionable information and key outcomes."
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return await self.client.chat(messages, system=system)
|
|
59
|
+
|
|
60
|
+
def needs_summarization(self, output: str, threshold: int = 500) -> bool:
|
|
61
|
+
"""Check if output is long enough to warrant summarization.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
output: Output text to check.
|
|
65
|
+
threshold: Character count threshold for summarization.
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
True if output exceeds threshold, False otherwise.
|
|
69
|
+
"""
|
|
70
|
+
return len(output) > threshold
|