claude-mpm 5.4.22__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/BASE_AGENT.md +164 -0
- claude_mpm/agents/BASE_ENGINEER.md +658 -0
- 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/MEMORY.md +1 -1
- claude_mpm/agents/PM_INSTRUCTIONS.md +374 -1257
- claude_mpm/agents/WORKFLOW.md +6 -253
- claude_mpm/agents/agent_loader.py +1 -1
- claude_mpm/agents/base_agent.json +31 -0
- claude_mpm/agents/frontmatter_validator.py +2 -2
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/cli/__init__.py +5 -1
- claude_mpm/cli/commands/agent_state_manager.py +10 -10
- claude_mpm/cli/commands/agents.py +11 -13
- claude_mpm/cli/commands/agents_reconcile.py +197 -0
- claude_mpm/cli/commands/auto_configure.py +4 -4
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/configure.py +621 -22
- claude_mpm/cli/commands/configure_agent_display.py +12 -0
- 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 +72 -0
- claude_mpm/cli/commands/postmortem.py +1 -1
- claude_mpm/cli/commands/profile.py +276 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +182 -32
- claude_mpm/cli/executor.py +130 -16
- claude_mpm/cli/interactive/__init__.py +10 -0
- claude_mpm/cli/interactive/agent_wizard.py +32 -52
- 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 +83 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/profile_parser.py +147 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +2 -3
- claude_mpm/cli/startup.py +690 -386
- 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 +20 -249
- claude_mpm/commands/mpm-doctor.md +16 -21
- claude_mpm/commands/mpm-help.md +12 -205
- claude_mpm/commands/mpm-init.md +88 -506
- claude_mpm/commands/mpm-monitor.md +22 -401
- claude_mpm/commands/mpm-organize.md +70 -442
- claude_mpm/commands/mpm-postmortem.md +13 -107
- claude_mpm/commands/mpm-session-resume.md +20 -363
- claude_mpm/commands/mpm-status.md +13 -69
- claude_mpm/commands/mpm-ticket-view.md +60 -495
- claude_mpm/commands/mpm-version.md +13 -107
- 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 +37 -26
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/framework/loaders/agent_loader.py +1 -1
- claude_mpm/core/framework/loaders/instruction_loader.py +52 -11
- 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 +61 -0
- 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_agent_registry.py +1 -1
- claude_mpm/core/unified_config.py +54 -8
- claude_mpm/core/unified_paths.py +95 -90
- claude_mpm/dashboard/static/svelte-build/_app/env.js +1 -0
- 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/BSNlmTZj.js +1 -0
- 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/DR8nis88.js +2 -0
- 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/NqQ1dWOy.js +1 -0
- 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.RgBboRvH.js +1 -0
- 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 -0
- claude_mpm/dashboard/static/svelte-build/favicon.svg +7 -0
- claude_mpm/dashboard/static/svelte-build/index.html +36 -0
- 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__/__init__.cpython-311.pyc +0 -0
- claude_mpm/hooks/claude_hooks/__pycache__/auto_pause_handler.cpython-311.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__/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/__pycache__/tool_analysis.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 +313 -99
- 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__/duplicate_detector.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 +67 -32
- 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/kuzu_memory_hook.py +5 -5
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +276 -0
- claude_mpm/models/git_repository.py +3 -3
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_builder.py +3 -3
- 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 +7 -7
- claude_mpm/services/agents/deployment/agent_deployment.py +29 -7
- claude_mpm/services/agents/deployment/agent_discovery_service.py +4 -2
- claude_mpm/services/agents/deployment/agent_format_converter.py +25 -13
- claude_mpm/services/agents/deployment/agent_template_builder.py +39 -19
- claude_mpm/services/agents/deployment/agents_directory_resolver.py +2 -2
- claude_mpm/services/agents/deployment/async_agent_deployment.py +31 -27
- claude_mpm/services/agents/deployment/deployment_reconciler.py +577 -0
- claude_mpm/services/agents/deployment/local_template_deployment.py +3 -1
- claude_mpm/services/agents/deployment/multi_source_deployment_service.py +169 -26
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +101 -75
- claude_mpm/services/agents/deployment/startup_reconciliation.py +138 -0
- claude_mpm/services/agents/git_source_manager.py +23 -4
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/recommender.py +5 -3
- claude_mpm/services/agents/single_tier_deployment_service.py +6 -6
- claude_mpm/services/agents/sources/git_source_sync_service.py +121 -10
- claude_mpm/services/agents/startup_sync.py +27 -4
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_check.py +2 -2
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +31 -1
- 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/git/git_operations_service.py +8 -8
- 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 +15 -3
- claude_mpm/services/monitor/server.py +571 -11
- claude_mpm/services/pm_skills_deployer.py +884 -0
- claude_mpm/services/profile_manager.py +337 -0
- claude_mpm/services/skills/git_skill_source_manager.py +281 -20
- claude_mpm/services/skills/selective_skill_deployer.py +211 -46
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +192 -70
- claude_mpm/services/socketio/dashboard_server.py +1 -0
- claude_mpm/services/socketio/event_normalizer.py +37 -6
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/core.py +262 -123
- 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 +98 -3
- claude_mpm/templates/.pre-commit-config.yaml +112 -0
- claude_mpm/utils/agent_dependency_loader.py +115 -4
- claude_mpm/utils/agent_filters.py +1 -1
- claude_mpm/utils/migration.py +4 -4
- claude_mpm/utils/robust_installer.py +86 -21
- claude_mpm-5.6.34.dist-info/METADATA +393 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/RECORD +486 -145
- claude_mpm-5.4.22.dist-info/METADATA +0 -996
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/WHEEL +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/entry_points.txt +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.22.dist-info → claude_mpm-5.6.34.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Commander CLI entry point."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import logging
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
from claude_mpm.commander.env_loader import load_env
|
|
10
|
+
from claude_mpm.commander.instance_manager import InstanceManager
|
|
11
|
+
from claude_mpm.commander.llm.openrouter_client import (
|
|
12
|
+
OpenRouterClient,
|
|
13
|
+
OpenRouterConfig,
|
|
14
|
+
)
|
|
15
|
+
from claude_mpm.commander.llm.summarizer import OutputSummarizer
|
|
16
|
+
from claude_mpm.commander.proxy.formatter import OutputFormatter
|
|
17
|
+
from claude_mpm.commander.proxy.output_handler import OutputHandler
|
|
18
|
+
from claude_mpm.commander.proxy.relay import OutputRelay
|
|
19
|
+
from claude_mpm.commander.session.manager import SessionManager
|
|
20
|
+
from claude_mpm.commander.tmux_orchestrator import TmuxOrchestrator
|
|
21
|
+
|
|
22
|
+
from .repl import CommanderREPL
|
|
23
|
+
|
|
24
|
+
# Load environment variables at module import
|
|
25
|
+
load_env()
|
|
26
|
+
|
|
27
|
+
logger = logging.getLogger(__name__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass
|
|
31
|
+
class CommanderCLIConfig:
|
|
32
|
+
"""Configuration for Commander CLI mode.
|
|
33
|
+
|
|
34
|
+
Attributes:
|
|
35
|
+
summarize_responses: Whether to use LLM to summarize instance responses
|
|
36
|
+
port: Port for internal services (reserved for future use)
|
|
37
|
+
state_dir: Directory for state persistence (optional)
|
|
38
|
+
|
|
39
|
+
Example:
|
|
40
|
+
>>> config = CommanderCLIConfig(summarize_responses=False)
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
summarize_responses: bool = True
|
|
44
|
+
port: int = 8765
|
|
45
|
+
state_dir: Optional[Path] = None
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def run_commander(
|
|
49
|
+
port: int = 8765,
|
|
50
|
+
state_dir: Optional[Path] = None,
|
|
51
|
+
config: Optional[CommanderCLIConfig] = None,
|
|
52
|
+
) -> None:
|
|
53
|
+
"""Run Commander in interactive mode.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
port: Port for internal services (unused currently).
|
|
57
|
+
state_dir: Directory for state persistence (optional).
|
|
58
|
+
config: Commander CLI configuration (optional, uses defaults if None).
|
|
59
|
+
|
|
60
|
+
Example:
|
|
61
|
+
>>> asyncio.run(run_commander())
|
|
62
|
+
# Starts interactive Commander REPL
|
|
63
|
+
>>> config = CommanderCLIConfig(summarize_responses=False)
|
|
64
|
+
>>> asyncio.run(run_commander(config=config))
|
|
65
|
+
# Starts Commander without response summarization
|
|
66
|
+
"""
|
|
67
|
+
# Use default config if not provided
|
|
68
|
+
if config is None:
|
|
69
|
+
config = CommanderCLIConfig(port=port, state_dir=state_dir)
|
|
70
|
+
|
|
71
|
+
# Setup logging
|
|
72
|
+
logging.basicConfig(
|
|
73
|
+
level=logging.INFO,
|
|
74
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
# Initialize components
|
|
78
|
+
logger.info("Initializing Commander...")
|
|
79
|
+
|
|
80
|
+
# Create tmux orchestrator
|
|
81
|
+
orchestrator = TmuxOrchestrator()
|
|
82
|
+
|
|
83
|
+
# Create instance manager
|
|
84
|
+
instance_manager = InstanceManager(orchestrator)
|
|
85
|
+
|
|
86
|
+
# Create session manager
|
|
87
|
+
session_manager = SessionManager()
|
|
88
|
+
|
|
89
|
+
# Try to initialize LLM client (optional)
|
|
90
|
+
llm_client: Optional[OpenRouterClient] = None
|
|
91
|
+
try:
|
|
92
|
+
llm_config = OpenRouterConfig()
|
|
93
|
+
llm_client = OpenRouterClient(llm_config)
|
|
94
|
+
logger.info("LLM client initialized")
|
|
95
|
+
except ValueError as e:
|
|
96
|
+
logger.warning(f"LLM client not available: {e}")
|
|
97
|
+
logger.warning("Output summarization will be disabled")
|
|
98
|
+
|
|
99
|
+
# Create output relay (optional)
|
|
100
|
+
output_relay: Optional[OutputRelay] = None
|
|
101
|
+
if llm_client:
|
|
102
|
+
try:
|
|
103
|
+
# Only create summarizer if summarize_responses is enabled
|
|
104
|
+
summarizer = None
|
|
105
|
+
if config.summarize_responses:
|
|
106
|
+
summarizer = OutputSummarizer(llm_client)
|
|
107
|
+
logger.info("Response summarization enabled")
|
|
108
|
+
else:
|
|
109
|
+
logger.info("Response summarization disabled")
|
|
110
|
+
|
|
111
|
+
handler = OutputHandler(orchestrator, summarizer)
|
|
112
|
+
formatter = OutputFormatter()
|
|
113
|
+
output_relay = OutputRelay(handler, formatter)
|
|
114
|
+
logger.info("Output relay initialized")
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.warning(f"Output relay setup failed: {e}")
|
|
117
|
+
|
|
118
|
+
# Create REPL
|
|
119
|
+
repl = CommanderREPL(
|
|
120
|
+
instance_manager=instance_manager,
|
|
121
|
+
session_manager=session_manager,
|
|
122
|
+
output_relay=output_relay,
|
|
123
|
+
llm_client=llm_client,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Run REPL
|
|
127
|
+
try:
|
|
128
|
+
await repl.run()
|
|
129
|
+
except KeyboardInterrupt:
|
|
130
|
+
logger.info("Commander interrupted by user")
|
|
131
|
+
except Exception as e:
|
|
132
|
+
logger.error(f"Commander error: {e}", exc_info=True)
|
|
133
|
+
finally:
|
|
134
|
+
# Cleanup
|
|
135
|
+
logger.info("Shutting down Commander...")
|
|
136
|
+
if output_relay:
|
|
137
|
+
await output_relay.stop_all()
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def main() -> None:
|
|
141
|
+
"""Entry point for command-line execution."""
|
|
142
|
+
asyncio.run(run_commander())
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
main()
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Built-in Commander chat commands."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from enum import Enum
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class CommandType(Enum):
|
|
9
|
+
"""Built-in command types."""
|
|
10
|
+
|
|
11
|
+
LIST = "list"
|
|
12
|
+
START = "start"
|
|
13
|
+
STOP = "stop"
|
|
14
|
+
CONNECT = "connect"
|
|
15
|
+
DISCONNECT = "disconnect"
|
|
16
|
+
STATUS = "status"
|
|
17
|
+
HELP = "help"
|
|
18
|
+
EXIT = "exit"
|
|
19
|
+
INSTANCES = "instances" # alias for list
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class Command:
|
|
24
|
+
"""Parsed command with args."""
|
|
25
|
+
|
|
26
|
+
type: CommandType
|
|
27
|
+
args: list[str]
|
|
28
|
+
raw: str
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class CommandParser:
|
|
32
|
+
"""Parses user input into commands."""
|
|
33
|
+
|
|
34
|
+
ALIASES = {
|
|
35
|
+
"ls": CommandType.LIST,
|
|
36
|
+
"instances": CommandType.LIST,
|
|
37
|
+
"quit": CommandType.EXIT,
|
|
38
|
+
"q": CommandType.EXIT,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
def parse(self, input_text: str) -> Optional[Command]:
|
|
42
|
+
"""Parse input into a Command.
|
|
43
|
+
|
|
44
|
+
Returns None if input is not a built-in command (natural language).
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
input_text: Raw user input.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Command if input is a built-in command, None otherwise.
|
|
51
|
+
|
|
52
|
+
Example:
|
|
53
|
+
>>> parser = CommandParser()
|
|
54
|
+
>>> cmd = parser.parse("list")
|
|
55
|
+
>>> cmd.type
|
|
56
|
+
<CommandType.LIST: 'list'>
|
|
57
|
+
>>> parser.parse("tell me about the code")
|
|
58
|
+
None
|
|
59
|
+
"""
|
|
60
|
+
if not input_text:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
parts = input_text.split()
|
|
64
|
+
command_str = parts[0].lower()
|
|
65
|
+
args = parts[1:] if len(parts) > 1 else []
|
|
66
|
+
|
|
67
|
+
# Check if it's an alias
|
|
68
|
+
if command_str in self.ALIASES:
|
|
69
|
+
cmd_type = self.ALIASES[command_str]
|
|
70
|
+
return Command(type=cmd_type, args=args, raw=input_text)
|
|
71
|
+
|
|
72
|
+
# Check if it's a direct command
|
|
73
|
+
try:
|
|
74
|
+
cmd_type = CommandType(command_str)
|
|
75
|
+
return Command(type=cmd_type, args=args, raw=input_text)
|
|
76
|
+
except ValueError:
|
|
77
|
+
# Not a built-in command
|
|
78
|
+
return None
|
|
79
|
+
|
|
80
|
+
def is_command(self, input_text: str) -> bool:
|
|
81
|
+
"""Check if input is a built-in command.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
input_text: Raw user input.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
True if input is a built-in command, False otherwise.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
>>> parser = CommandParser()
|
|
91
|
+
>>> parser.is_command("list")
|
|
92
|
+
True
|
|
93
|
+
>>> parser.is_command("tell me about the code")
|
|
94
|
+
False
|
|
95
|
+
"""
|
|
96
|
+
return self.parse(input_text) is not None
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"""Commander chat REPL interface."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from prompt_toolkit import PromptSession
|
|
8
|
+
from prompt_toolkit.history import FileHistory
|
|
9
|
+
|
|
10
|
+
from claude_mpm.commander.instance_manager import InstanceManager
|
|
11
|
+
from claude_mpm.commander.llm.openrouter_client import OpenRouterClient
|
|
12
|
+
from claude_mpm.commander.proxy.relay import OutputRelay
|
|
13
|
+
from claude_mpm.commander.session.manager import SessionManager
|
|
14
|
+
|
|
15
|
+
from .commands import Command, CommandParser, CommandType
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class CommanderREPL:
|
|
19
|
+
"""Interactive REPL for Commander mode."""
|
|
20
|
+
|
|
21
|
+
def __init__(
|
|
22
|
+
self,
|
|
23
|
+
instance_manager: InstanceManager,
|
|
24
|
+
session_manager: SessionManager,
|
|
25
|
+
output_relay: Optional[OutputRelay] = None,
|
|
26
|
+
llm_client: Optional[OpenRouterClient] = None,
|
|
27
|
+
):
|
|
28
|
+
"""Initialize REPL.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
instance_manager: Manages Claude instances.
|
|
32
|
+
session_manager: Manages chat session state.
|
|
33
|
+
output_relay: Optional relay for instance output.
|
|
34
|
+
llm_client: Optional OpenRouter client for chat.
|
|
35
|
+
"""
|
|
36
|
+
self.instances = instance_manager
|
|
37
|
+
self.session = session_manager
|
|
38
|
+
self.relay = output_relay
|
|
39
|
+
self.llm = llm_client
|
|
40
|
+
self.parser = CommandParser()
|
|
41
|
+
self._running = False
|
|
42
|
+
|
|
43
|
+
async def run(self) -> None:
|
|
44
|
+
"""Start the REPL loop."""
|
|
45
|
+
self._running = True
|
|
46
|
+
self._print_welcome()
|
|
47
|
+
|
|
48
|
+
# Setup history file
|
|
49
|
+
history_path = Path.home() / ".claude-mpm" / "commander_history"
|
|
50
|
+
history_path.parent.mkdir(parents=True, exist_ok=True)
|
|
51
|
+
|
|
52
|
+
prompt = PromptSession(history=FileHistory(str(history_path)))
|
|
53
|
+
|
|
54
|
+
while self._running:
|
|
55
|
+
try:
|
|
56
|
+
user_input = await asyncio.to_thread(prompt.prompt, self._get_prompt())
|
|
57
|
+
await self._handle_input(user_input.strip())
|
|
58
|
+
except KeyboardInterrupt:
|
|
59
|
+
continue
|
|
60
|
+
except EOFError:
|
|
61
|
+
break
|
|
62
|
+
|
|
63
|
+
self._print("\nGoodbye!")
|
|
64
|
+
|
|
65
|
+
async def _handle_input(self, input_text: str) -> None:
|
|
66
|
+
"""Handle user input - command or natural language.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
input_text: User input string.
|
|
70
|
+
"""
|
|
71
|
+
if not input_text:
|
|
72
|
+
return
|
|
73
|
+
|
|
74
|
+
# Check if it's a built-in command
|
|
75
|
+
command = self.parser.parse(input_text)
|
|
76
|
+
if command:
|
|
77
|
+
await self._execute_command(command)
|
|
78
|
+
else:
|
|
79
|
+
# Natural language - send to connected instance
|
|
80
|
+
await self._send_to_instance(input_text)
|
|
81
|
+
|
|
82
|
+
async def _execute_command(self, cmd: Command) -> None:
|
|
83
|
+
"""Execute a built-in command.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
cmd: Parsed command.
|
|
87
|
+
"""
|
|
88
|
+
handlers = {
|
|
89
|
+
CommandType.LIST: self._cmd_list,
|
|
90
|
+
CommandType.START: self._cmd_start,
|
|
91
|
+
CommandType.STOP: self._cmd_stop,
|
|
92
|
+
CommandType.CONNECT: self._cmd_connect,
|
|
93
|
+
CommandType.DISCONNECT: self._cmd_disconnect,
|
|
94
|
+
CommandType.STATUS: self._cmd_status,
|
|
95
|
+
CommandType.HELP: self._cmd_help,
|
|
96
|
+
CommandType.EXIT: self._cmd_exit,
|
|
97
|
+
}
|
|
98
|
+
handler = handlers.get(cmd.type)
|
|
99
|
+
if handler:
|
|
100
|
+
await handler(cmd.args)
|
|
101
|
+
|
|
102
|
+
async def _cmd_list(self, args: list[str]) -> None:
|
|
103
|
+
"""List active instances."""
|
|
104
|
+
instances = self.instances.list_instances()
|
|
105
|
+
if not instances:
|
|
106
|
+
self._print("No active instances.")
|
|
107
|
+
else:
|
|
108
|
+
self._print("Active instances:")
|
|
109
|
+
for inst in instances:
|
|
110
|
+
status = (
|
|
111
|
+
"→" if inst.name == self.session.context.connected_instance else " "
|
|
112
|
+
)
|
|
113
|
+
git_info = f" [{inst.git_branch}]" if inst.git_branch else ""
|
|
114
|
+
self._print(
|
|
115
|
+
f" {status} {inst.name} ({inst.framework}){git_info} - {inst.project_path}"
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
async def _cmd_start(self, args: list[str]) -> None:
|
|
119
|
+
"""Start a new instance: start <path> [--framework cc|mpm] [--name name]."""
|
|
120
|
+
if not args:
|
|
121
|
+
self._print("Usage: start <path> [--framework cc|mpm] [--name name]")
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
# Parse arguments
|
|
125
|
+
project_path = Path(args[0]).expanduser().resolve()
|
|
126
|
+
framework = "cc" # default
|
|
127
|
+
name = project_path.name # default
|
|
128
|
+
|
|
129
|
+
# Parse optional flags
|
|
130
|
+
i = 1
|
|
131
|
+
while i < len(args):
|
|
132
|
+
if args[i] == "--framework" and i + 1 < len(args):
|
|
133
|
+
framework = args[i + 1]
|
|
134
|
+
i += 2
|
|
135
|
+
elif args[i] == "--name" and i + 1 < len(args):
|
|
136
|
+
name = args[i + 1]
|
|
137
|
+
i += 2
|
|
138
|
+
else:
|
|
139
|
+
i += 1
|
|
140
|
+
|
|
141
|
+
# Validate path
|
|
142
|
+
if not project_path.exists():
|
|
143
|
+
self._print(f"Error: Path does not exist: {project_path}")
|
|
144
|
+
return
|
|
145
|
+
|
|
146
|
+
if not project_path.is_dir():
|
|
147
|
+
self._print(f"Error: Path is not a directory: {project_path}")
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
# Start instance
|
|
151
|
+
try:
|
|
152
|
+
instance = await self.instances.start_instance(
|
|
153
|
+
name, project_path, framework
|
|
154
|
+
)
|
|
155
|
+
self._print(f"Started instance '{name}' ({framework}) at {project_path}")
|
|
156
|
+
self._print(f"Tmux: {instance.tmux_session}:{instance.pane_target}")
|
|
157
|
+
except Exception as e:
|
|
158
|
+
self._print(f"Error starting instance: {e}")
|
|
159
|
+
|
|
160
|
+
async def _cmd_stop(self, args: list[str]) -> None:
|
|
161
|
+
"""Stop an instance: stop <name>."""
|
|
162
|
+
if not args:
|
|
163
|
+
self._print("Usage: stop <instance-name>")
|
|
164
|
+
return
|
|
165
|
+
|
|
166
|
+
name = args[0]
|
|
167
|
+
|
|
168
|
+
try:
|
|
169
|
+
await self.instances.stop_instance(name)
|
|
170
|
+
self._print(f"Stopped instance '{name}'")
|
|
171
|
+
|
|
172
|
+
# Disconnect if we were connected
|
|
173
|
+
if self.session.context.connected_instance == name:
|
|
174
|
+
self.session.disconnect()
|
|
175
|
+
except Exception as e:
|
|
176
|
+
self._print(f"Error stopping instance: {e}")
|
|
177
|
+
|
|
178
|
+
async def _cmd_connect(self, args: list[str]) -> None:
|
|
179
|
+
"""Connect to an instance: connect <name>."""
|
|
180
|
+
if not args:
|
|
181
|
+
self._print("Usage: connect <instance-name>")
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
name = args[0]
|
|
185
|
+
inst = self.instances.get_instance(name)
|
|
186
|
+
if not inst:
|
|
187
|
+
self._print(f"Instance '{name}' not found")
|
|
188
|
+
return
|
|
189
|
+
|
|
190
|
+
self.session.connect_to(name)
|
|
191
|
+
self._print(f"Connected to {name}")
|
|
192
|
+
|
|
193
|
+
async def _cmd_disconnect(self, args: list[str]) -> None:
|
|
194
|
+
"""Disconnect from current instance."""
|
|
195
|
+
if not self.session.context.is_connected:
|
|
196
|
+
self._print("Not connected to any instance")
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
name = self.session.context.connected_instance
|
|
200
|
+
self.session.disconnect()
|
|
201
|
+
self._print(f"Disconnected from {name}")
|
|
202
|
+
|
|
203
|
+
async def _cmd_status(self, args: list[str]) -> None:
|
|
204
|
+
"""Show status of current session."""
|
|
205
|
+
if self.session.context.is_connected:
|
|
206
|
+
name = self.session.context.connected_instance
|
|
207
|
+
inst = self.instances.get_instance(name)
|
|
208
|
+
if inst:
|
|
209
|
+
self._print(f"Connected to: {name}")
|
|
210
|
+
self._print(f" Framework: {inst.framework}")
|
|
211
|
+
self._print(f" Project: {inst.project_path}")
|
|
212
|
+
if inst.git_branch:
|
|
213
|
+
self._print(f" Git: {inst.git_branch} ({inst.git_status})")
|
|
214
|
+
self._print(f" Tmux: {inst.tmux_session}:{inst.pane_target}")
|
|
215
|
+
else:
|
|
216
|
+
self._print(f"Connected to: {name} (instance no longer exists)")
|
|
217
|
+
else:
|
|
218
|
+
self._print("Not connected to any instance")
|
|
219
|
+
|
|
220
|
+
self._print(f"Messages in history: {len(self.session.context.messages)}")
|
|
221
|
+
|
|
222
|
+
async def _cmd_help(self, args: list[str]) -> None:
|
|
223
|
+
"""Show help message."""
|
|
224
|
+
help_text = """
|
|
225
|
+
Commander Commands:
|
|
226
|
+
list, ls, instances List active instances
|
|
227
|
+
start <path> Start new instance at path
|
|
228
|
+
--framework <cc|mpm> Specify framework (default: cc)
|
|
229
|
+
--name <name> Specify instance name (default: dir name)
|
|
230
|
+
stop <name> Stop an instance
|
|
231
|
+
connect <name> Connect to an instance
|
|
232
|
+
disconnect Disconnect from current instance
|
|
233
|
+
status Show current session status
|
|
234
|
+
help Show this help message
|
|
235
|
+
exit, quit, q Exit Commander
|
|
236
|
+
|
|
237
|
+
Natural Language:
|
|
238
|
+
When connected to an instance, any input that is not a built-in
|
|
239
|
+
command will be sent to the connected instance as a message.
|
|
240
|
+
|
|
241
|
+
Examples:
|
|
242
|
+
start ~/myproject --framework cc --name myapp
|
|
243
|
+
connect myapp
|
|
244
|
+
Fix the authentication bug in login.py
|
|
245
|
+
disconnect
|
|
246
|
+
exit
|
|
247
|
+
"""
|
|
248
|
+
self._print(help_text)
|
|
249
|
+
|
|
250
|
+
async def _cmd_exit(self, args: list[str]) -> None:
|
|
251
|
+
"""Exit the REPL."""
|
|
252
|
+
self._running = False
|
|
253
|
+
|
|
254
|
+
async def _send_to_instance(self, message: str) -> None:
|
|
255
|
+
"""Send natural language to connected instance.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
message: User message to send.
|
|
259
|
+
"""
|
|
260
|
+
if not self.session.context.is_connected:
|
|
261
|
+
self._print("Not connected to any instance. Use 'connect <name>' first.")
|
|
262
|
+
return
|
|
263
|
+
|
|
264
|
+
name = self.session.context.connected_instance
|
|
265
|
+
inst = self.instances.get_instance(name)
|
|
266
|
+
if not inst:
|
|
267
|
+
self._print(f"Instance '{name}' no longer exists")
|
|
268
|
+
self.session.disconnect()
|
|
269
|
+
return
|
|
270
|
+
|
|
271
|
+
self._print(f"[Sending to {name}...]")
|
|
272
|
+
await self.instances.send_to_instance(name, message)
|
|
273
|
+
self.session.add_user_message(message)
|
|
274
|
+
|
|
275
|
+
# Wait for and display response
|
|
276
|
+
if self.relay:
|
|
277
|
+
try:
|
|
278
|
+
output = await self.relay.get_latest_output(
|
|
279
|
+
name, inst.pane_target, context=message
|
|
280
|
+
)
|
|
281
|
+
self._print(f"\n[Response from {name}]:\n{output}")
|
|
282
|
+
self.session.add_assistant_message(output)
|
|
283
|
+
except Exception as e:
|
|
284
|
+
self._print(f"\n[Error getting response: {e}]")
|
|
285
|
+
|
|
286
|
+
def _get_prompt(self) -> str:
|
|
287
|
+
"""Get prompt string based on connection state.
|
|
288
|
+
|
|
289
|
+
Returns:
|
|
290
|
+
Prompt string for input.
|
|
291
|
+
"""
|
|
292
|
+
if self.session.context.is_connected:
|
|
293
|
+
return f"Commander ({self.session.context.connected_instance})> "
|
|
294
|
+
return "Commander> "
|
|
295
|
+
|
|
296
|
+
def _print(self, msg: str) -> None:
|
|
297
|
+
"""Print message to console.
|
|
298
|
+
|
|
299
|
+
Args:
|
|
300
|
+
msg: Message to print.
|
|
301
|
+
"""
|
|
302
|
+
print(msg)
|
|
303
|
+
|
|
304
|
+
def _print_welcome(self) -> None:
|
|
305
|
+
"""Print welcome message."""
|
|
306
|
+
print("╔══════════════════════════════════════════╗")
|
|
307
|
+
print("║ MPM Commander - Interactive Mode ║")
|
|
308
|
+
print("╚══════════════════════════════════════════╝")
|
|
309
|
+
print("Type 'help' for commands, or natural language to chat.")
|
|
310
|
+
print()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""Daemon configuration for MPM Commander.
|
|
2
|
+
|
|
3
|
+
This module defines configuration structures for the Commander daemon,
|
|
4
|
+
including server settings, resource limits, and persistence options.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from pathlib import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class DaemonConfig:
|
|
13
|
+
"""Configuration for Commander daemon.
|
|
14
|
+
|
|
15
|
+
Attributes:
|
|
16
|
+
host: API server bind address
|
|
17
|
+
port: API server port (default: 8766 from NetworkPorts.COMMANDER_DEFAULT)
|
|
18
|
+
log_level: Logging level (DEBUG, INFO, WARNING, ERROR)
|
|
19
|
+
state_dir: Directory for state persistence
|
|
20
|
+
max_projects: Maximum concurrent projects
|
|
21
|
+
healthcheck_interval: Healthcheck interval in seconds
|
|
22
|
+
save_interval: State persistence interval in seconds
|
|
23
|
+
poll_interval: Event polling interval in seconds
|
|
24
|
+
summarize_responses: Whether to use LLM to summarize instance responses
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
>>> config = DaemonConfig(port=8766, log_level="DEBUG")
|
|
28
|
+
>>> config.state_dir
|
|
29
|
+
PosixPath('/Users/user/.claude-mpm/commander')
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
host: str = "127.0.0.1"
|
|
33
|
+
port: int = 8766 # Default commander port (from network_config.NetworkPorts.COMMANDER_DEFAULT)
|
|
34
|
+
log_level: str = "INFO"
|
|
35
|
+
state_dir: Path = Path.home() / ".claude-mpm" / "commander"
|
|
36
|
+
max_projects: int = 10
|
|
37
|
+
healthcheck_interval: int = 30
|
|
38
|
+
save_interval: int = 30
|
|
39
|
+
poll_interval: float = 2.0
|
|
40
|
+
summarize_responses: bool = True
|
|
41
|
+
|
|
42
|
+
def __post_init__(self):
|
|
43
|
+
"""Ensure state_dir is a Path object and create if needed."""
|
|
44
|
+
if isinstance(self.state_dir, str):
|
|
45
|
+
self.state_dir = Path(self.state_dir)
|
|
46
|
+
|
|
47
|
+
# Expand user home directory
|
|
48
|
+
self.state_dir = self.state_dir.expanduser()
|
|
49
|
+
|
|
50
|
+
# Create state directory if it doesn't exist
|
|
51
|
+
self.state_dir.mkdir(parents=True, exist_ok=True)
|