claude-mpm 5.4.85__py3-none-any.whl → 5.6.76__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_mpm/VERSION +1 -1
- claude_mpm/agents/CLAUDE_MPM_OUTPUT_STYLE.md +8 -5
- claude_mpm/agents/{CLAUDE_MPM_FOUNDERS_OUTPUT_STYLE.md → CLAUDE_MPM_RESEARCH_OUTPUT_STYLE.md} +14 -6
- claude_mpm/agents/PM_INSTRUCTIONS.md +109 -706
- claude_mpm/agents/WORKFLOW.md +2 -0
- claude_mpm/agents/templates/circuit-breakers.md +26 -17
- claude_mpm/auth/__init__.py +35 -0
- claude_mpm/auth/callback_server.py +328 -0
- claude_mpm/auth/models.py +104 -0
- claude_mpm/auth/oauth_manager.py +266 -0
- claude_mpm/auth/providers/__init__.py +12 -0
- claude_mpm/auth/providers/base.py +165 -0
- claude_mpm/auth/providers/google.py +261 -0
- claude_mpm/auth/token_storage.py +252 -0
- claude_mpm/cli/commands/autotodos.py +566 -0
- claude_mpm/cli/commands/commander.py +216 -0
- claude_mpm/cli/commands/hook_errors.py +60 -60
- claude_mpm/cli/commands/mcp.py +29 -17
- claude_mpm/cli/commands/mcp_command_router.py +39 -0
- claude_mpm/cli/commands/mcp_service_commands.py +304 -0
- claude_mpm/cli/commands/monitor.py +2 -2
- claude_mpm/cli/commands/mpm_init/core.py +2 -2
- claude_mpm/cli/commands/oauth.py +481 -0
- claude_mpm/cli/commands/run.py +35 -3
- claude_mpm/cli/commands/skill_source.py +51 -2
- claude_mpm/cli/commands/skills.py +5 -3
- claude_mpm/cli/executor.py +128 -16
- claude_mpm/cli/helpers.py +1 -1
- claude_mpm/cli/parsers/base_parser.py +84 -1
- claude_mpm/cli/parsers/commander_parser.py +116 -0
- claude_mpm/cli/parsers/mcp_parser.py +79 -0
- claude_mpm/cli/parsers/oauth_parser.py +165 -0
- claude_mpm/cli/parsers/run_parser.py +10 -0
- claude_mpm/cli/parsers/skill_source_parser.py +4 -0
- claude_mpm/cli/parsers/skills_parser.py +5 -0
- claude_mpm/cli/startup.py +345 -40
- claude_mpm/cli/startup_display.py +76 -7
- claude_mpm/cli/startup_logging.py +2 -2
- claude_mpm/cli/startup_migrations.py +236 -0
- claude_mpm/cli/utils.py +7 -3
- claude_mpm/commander/__init__.py +78 -0
- claude_mpm/commander/adapters/__init__.py +60 -0
- claude_mpm/commander/adapters/auggie.py +260 -0
- claude_mpm/commander/adapters/base.py +288 -0
- claude_mpm/commander/adapters/claude_code.py +392 -0
- claude_mpm/commander/adapters/codex.py +237 -0
- claude_mpm/commander/adapters/communication.py +366 -0
- claude_mpm/commander/adapters/example_usage.py +310 -0
- claude_mpm/commander/adapters/mpm.py +389 -0
- claude_mpm/commander/adapters/registry.py +204 -0
- claude_mpm/commander/api/__init__.py +16 -0
- claude_mpm/commander/api/app.py +121 -0
- claude_mpm/commander/api/errors.py +133 -0
- claude_mpm/commander/api/routes/__init__.py +8 -0
- claude_mpm/commander/api/routes/events.py +184 -0
- claude_mpm/commander/api/routes/inbox.py +171 -0
- claude_mpm/commander/api/routes/messages.py +148 -0
- claude_mpm/commander/api/routes/projects.py +271 -0
- claude_mpm/commander/api/routes/sessions.py +226 -0
- claude_mpm/commander/api/routes/work.py +296 -0
- claude_mpm/commander/api/schemas.py +186 -0
- claude_mpm/commander/chat/__init__.py +7 -0
- claude_mpm/commander/chat/cli.py +149 -0
- claude_mpm/commander/chat/commands.py +124 -0
- claude_mpm/commander/chat/repl.py +1957 -0
- claude_mpm/commander/config.py +51 -0
- claude_mpm/commander/config_loader.py +115 -0
- claude_mpm/commander/core/__init__.py +10 -0
- claude_mpm/commander/core/block_manager.py +325 -0
- claude_mpm/commander/core/response_manager.py +323 -0
- claude_mpm/commander/daemon.py +603 -0
- claude_mpm/commander/env_loader.py +59 -0
- claude_mpm/commander/events/__init__.py +26 -0
- claude_mpm/commander/events/manager.py +392 -0
- claude_mpm/commander/frameworks/__init__.py +12 -0
- claude_mpm/commander/frameworks/base.py +233 -0
- claude_mpm/commander/frameworks/claude_code.py +58 -0
- claude_mpm/commander/frameworks/mpm.py +57 -0
- claude_mpm/commander/git/__init__.py +5 -0
- claude_mpm/commander/git/worktree_manager.py +212 -0
- claude_mpm/commander/inbox/__init__.py +16 -0
- claude_mpm/commander/inbox/dedup.py +128 -0
- claude_mpm/commander/inbox/inbox.py +224 -0
- claude_mpm/commander/inbox/models.py +70 -0
- claude_mpm/commander/instance_manager.py +868 -0
- claude_mpm/commander/llm/__init__.py +6 -0
- claude_mpm/commander/llm/openrouter_client.py +167 -0
- claude_mpm/commander/llm/summarizer.py +70 -0
- claude_mpm/commander/memory/__init__.py +45 -0
- claude_mpm/commander/memory/compression.py +347 -0
- claude_mpm/commander/memory/embeddings.py +230 -0
- claude_mpm/commander/memory/entities.py +310 -0
- claude_mpm/commander/memory/example_usage.py +290 -0
- claude_mpm/commander/memory/integration.py +325 -0
- claude_mpm/commander/memory/search.py +381 -0
- claude_mpm/commander/memory/store.py +657 -0
- claude_mpm/commander/models/__init__.py +18 -0
- claude_mpm/commander/models/events.py +127 -0
- claude_mpm/commander/models/project.py +162 -0
- claude_mpm/commander/models/work.py +214 -0
- claude_mpm/commander/parsing/__init__.py +20 -0
- claude_mpm/commander/parsing/extractor.py +132 -0
- claude_mpm/commander/parsing/output_parser.py +270 -0
- claude_mpm/commander/parsing/patterns.py +100 -0
- claude_mpm/commander/persistence/__init__.py +11 -0
- claude_mpm/commander/persistence/event_store.py +274 -0
- claude_mpm/commander/persistence/state_store.py +403 -0
- claude_mpm/commander/persistence/work_store.py +164 -0
- claude_mpm/commander/polling/__init__.py +13 -0
- claude_mpm/commander/polling/event_detector.py +104 -0
- claude_mpm/commander/polling/output_buffer.py +49 -0
- claude_mpm/commander/polling/output_poller.py +153 -0
- claude_mpm/commander/project_session.py +268 -0
- claude_mpm/commander/proxy/__init__.py +12 -0
- claude_mpm/commander/proxy/formatter.py +89 -0
- claude_mpm/commander/proxy/output_handler.py +191 -0
- claude_mpm/commander/proxy/relay.py +155 -0
- claude_mpm/commander/registry.py +410 -0
- claude_mpm/commander/runtime/__init__.py +10 -0
- claude_mpm/commander/runtime/executor.py +191 -0
- claude_mpm/commander/runtime/monitor.py +346 -0
- claude_mpm/commander/session/__init__.py +6 -0
- claude_mpm/commander/session/context.py +81 -0
- claude_mpm/commander/session/manager.py +59 -0
- claude_mpm/commander/tmux_orchestrator.py +362 -0
- claude_mpm/commander/web/__init__.py +1 -0
- claude_mpm/commander/work/__init__.py +30 -0
- claude_mpm/commander/work/executor.py +207 -0
- claude_mpm/commander/work/queue.py +405 -0
- claude_mpm/commander/workflow/__init__.py +27 -0
- claude_mpm/commander/workflow/event_handler.py +241 -0
- claude_mpm/commander/workflow/notifier.py +146 -0
- claude_mpm/commands/mpm-config.md +8 -0
- claude_mpm/commands/mpm-doctor.md +8 -0
- claude_mpm/commands/mpm-help.md +8 -0
- claude_mpm/commands/mpm-init.md +8 -0
- claude_mpm/commands/mpm-monitor.md +8 -0
- claude_mpm/commands/mpm-organize.md +8 -0
- claude_mpm/commands/mpm-postmortem.md +8 -0
- claude_mpm/commands/mpm-session-resume.md +9 -1
- claude_mpm/commands/mpm-status.md +8 -0
- claude_mpm/commands/mpm-ticket-view.md +8 -0
- claude_mpm/commands/mpm-version.md +8 -0
- claude_mpm/commands/mpm.md +8 -0
- claude_mpm/config/agent_presets.py +8 -7
- claude_mpm/config/skill_sources.py +16 -0
- claude_mpm/constants.py +5 -0
- claude_mpm/core/claude_runner.py +152 -0
- claude_mpm/core/config.py +35 -22
- claude_mpm/core/config_constants.py +74 -9
- claude_mpm/core/constants.py +56 -12
- claude_mpm/core/hook_manager.py +53 -4
- claude_mpm/core/interactive_session.py +5 -4
- claude_mpm/core/logger.py +26 -9
- claude_mpm/core/logging_utils.py +39 -13
- claude_mpm/core/network_config.py +148 -0
- claude_mpm/core/oneshot_session.py +7 -6
- claude_mpm/core/output_style_manager.py +52 -12
- claude_mpm/core/socketio_pool.py +47 -15
- claude_mpm/core/unified_config.py +10 -6
- claude_mpm/core/unified_paths.py +68 -80
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.C33zOoyM.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.CW1J-YuA.css +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cs_tUR18.js → 1WZnGYqX.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CDuw-vjf.js → 67pF3qNn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bTOqqlTd.js → 6RxdMKe4.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DwBR2MJi.js → 8cZrfX0h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{ZGh7QtNv.js → 9a6T2nm-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D9lljYKQ.js → B443AUzu.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{RJiighC3.js → B8AwtY2H.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{uuIeMWc-.js → BF15LAsF.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{D3k0OPJN.js → BRcwIQNr.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CyWMqx4W.js → BV6nKitt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CiIAseT4.js → BViJ8lZt.js} +5 -5
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CBBdVcY8.js → BcQ-Q0FE.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BovzEFCE.js → Bpyvgze_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BzTRqg-z.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/C0Fr8dve.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{eNVUfhuA.js → C3rbW_a-.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{GYwsonyD.js → C8WYN38h.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BIF9m_hv.js → C9I8FlXH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B0uc0UOD.js → CIQcWgO2.js} +3 -3
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Be7GpZd6.js → CIctN7YN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Bh0LDWpI.js → CKrS_JZW.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DUrLdbGD.js → CR6P9C4A.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7xVLGWV.js → CRRR9MD_.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/CRcR2DqT.js +334 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dhb8PKl3.js → CSXtMOf0.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BPYeabCQ.js → CT-sbxSk.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{sQeU3Y1z.js → CWm6DJsp.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CnA0NrzZ.js → CpqQ1Kzn.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4B-KCzX.js → D2nGpDRe.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DGkLK5U1.js → D9iCMida.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{BofRWZRR.js → D9ykgMoY.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DmxopI1J.js → DL2Ldur1.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C30mlcqg.js → DPfltzjH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Vzk33B_K.js → DR8nis88.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DI7hHRFL.js → DUliQN2b.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C4JcI4KD.js → DXlhR01x.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{bT1r9zLR.js → D_lyTybS.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DZX00Y4g.js → DngoTTgh.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzZX-COe.js → DqkmHtDC.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{B7RN905-.js → DsDh8EYs.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DLVjFsZ3.js → DypDmXgd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{iEWssX7S.js → IPYC-LnN.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/JTLiF7dt.js +24 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DaimHw_p.js → JpevfAFt.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{DY1XQ8fi.js → R8CEIRAd.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Dle-35c7.js → Zxy7qc-l.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/q9Hm6zAU.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{C_Usid8X.js → qtd3IeO4.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{CzeYkLYB.js → ulBFON_C.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/{Cfqx1Qun.js → wQVh1CoA.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/{app.D6-I5TpK.js → app.Dr7t0z2J.js} +2 -2
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.BGhZHUS3.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{0.m1gL8KXf.js → 0.RgBboRvH.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/{1.CgNOuw-d.js → 1.DG-KkbDf.js} +1 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.D_jnf-x6.js +1 -0
- claude_mpm/dashboard/static/svelte-build/_app/version.json +1 -1
- claude_mpm/dashboard/static/svelte-build/index.html +9 -9
- claude_mpm/experimental/cli_enhancements.py +2 -1
- claude_mpm/hooks/claude_hooks/INTEGRATION_EXAMPLE.md +243 -0
- claude_mpm/hooks/claude_hooks/README_AUTO_PAUSE.md +403 -0
- claude_mpm/hooks/claude_hooks/auto_pause_handler.py +485 -0
- claude_mpm/hooks/claude_hooks/event_handlers.py +466 -136
- claude_mpm/hooks/claude_hooks/hook_handler.py +204 -104
- claude_mpm/hooks/claude_hooks/hook_wrapper.sh +6 -11
- claude_mpm/hooks/claude_hooks/installer.py +291 -59
- claude_mpm/hooks/claude_hooks/memory_integration.py +52 -32
- claude_mpm/hooks/claude_hooks/response_tracking.py +43 -60
- claude_mpm/hooks/claude_hooks/services/__init__.py +21 -0
- claude_mpm/hooks/claude_hooks/services/connection_manager.py +41 -26
- claude_mpm/hooks/claude_hooks/services/connection_manager_http.py +38 -105
- claude_mpm/hooks/claude_hooks/services/container.py +326 -0
- claude_mpm/hooks/claude_hooks/services/protocols.py +328 -0
- claude_mpm/hooks/claude_hooks/services/state_manager.py +25 -38
- claude_mpm/hooks/claude_hooks/services/subagent_processor.py +75 -77
- claude_mpm/hooks/session_resume_hook.py +89 -1
- claude_mpm/hooks/templates/pre_tool_use_simple.py +6 -6
- claude_mpm/hooks/templates/pre_tool_use_template.py +16 -8
- claude_mpm/init.py +22 -15
- claude_mpm/mcp/__init__.py +9 -0
- claude_mpm/mcp/google_workspace_server.py +610 -0
- claude_mpm/scripts/claude-hook-handler.sh +46 -19
- claude_mpm/services/agents/agent_recommendation_service.py +8 -8
- claude_mpm/services/agents/agent_selection_service.py +2 -2
- claude_mpm/services/agents/cache_git_manager.py +1 -1
- claude_mpm/services/agents/deployment/remote_agent_discovery_service.py +3 -0
- claude_mpm/services/agents/loading/framework_agent_loader.py +75 -2
- claude_mpm/services/agents/single_tier_deployment_service.py +4 -4
- claude_mpm/services/cli/__init__.py +3 -0
- claude_mpm/services/cli/incremental_pause_manager.py +561 -0
- claude_mpm/services/cli/session_resume_helper.py +10 -2
- claude_mpm/services/command_deployment_service.py +44 -26
- claude_mpm/services/delegation_detector.py +175 -0
- claude_mpm/services/diagnostics/checks/agent_sources_check.py +30 -0
- claude_mpm/services/diagnostics/checks/configuration_check.py +24 -0
- claude_mpm/services/diagnostics/checks/installation_check.py +22 -0
- claude_mpm/services/diagnostics/checks/mcp_services_check.py +23 -0
- claude_mpm/services/diagnostics/doctor_reporter.py +31 -1
- claude_mpm/services/diagnostics/models.py +14 -1
- claude_mpm/services/event_log.py +325 -0
- claude_mpm/services/hook_installer_service.py +77 -8
- claude_mpm/services/infrastructure/__init__.py +4 -0
- claude_mpm/services/infrastructure/context_usage_tracker.py +291 -0
- claude_mpm/services/infrastructure/resume_log_generator.py +24 -5
- claude_mpm/services/mcp_config_manager.py +99 -19
- claude_mpm/services/mcp_service_registry.py +294 -0
- claude_mpm/services/monitor/daemon_manager.py +15 -4
- claude_mpm/services/monitor/management/lifecycle.py +8 -2
- claude_mpm/services/monitor/server.py +111 -16
- claude_mpm/services/pm_skills_deployer.py +261 -87
- claude_mpm/services/skills/git_skill_source_manager.py +130 -10
- claude_mpm/services/skills/selective_skill_deployer.py +142 -16
- claude_mpm/services/skills/skill_discovery_service.py +74 -4
- claude_mpm/services/skills_deployer.py +31 -5
- claude_mpm/services/socketio/handlers/hook.py +14 -7
- claude_mpm/services/socketio/server/main.py +12 -4
- claude_mpm/skills/__init__.py +2 -1
- claude_mpm/skills/bundled/pm/mpm/SKILL.md +38 -0
- claude_mpm/skills/bundled/pm/mpm-agent-update-workflow/SKILL.md +75 -0
- claude_mpm/skills/bundled/pm/mpm-circuit-breaker-enforcement/SKILL.md +476 -0
- claude_mpm/skills/bundled/pm/mpm-config/SKILL.md +29 -0
- claude_mpm/skills/bundled/pm/mpm-doctor/SKILL.md +53 -0
- claude_mpm/skills/bundled/pm/mpm-help/SKILL.md +35 -0
- claude_mpm/skills/bundled/pm/mpm-init/SKILL.md +125 -0
- claude_mpm/skills/bundled/pm/mpm-monitor/SKILL.md +32 -0
- claude_mpm/skills/bundled/pm/mpm-organize/SKILL.md +121 -0
- claude_mpm/skills/bundled/pm/mpm-postmortem/SKILL.md +22 -0
- claude_mpm/skills/bundled/pm/mpm-session-management/SKILL.md +312 -0
- claude_mpm/skills/bundled/pm/mpm-session-pause/SKILL.md +170 -0
- claude_mpm/skills/bundled/pm/mpm-session-resume/SKILL.md +31 -0
- claude_mpm/skills/bundled/pm/mpm-status/SKILL.md +37 -0
- claude_mpm/skills/bundled/pm/{pm-teaching-mode → mpm-teaching-mode}/SKILL.md +2 -2
- claude_mpm/skills/bundled/pm/mpm-ticket-view/SKILL.md +110 -0
- claude_mpm/skills/bundled/pm/mpm-tool-usage-guide/SKILL.md +386 -0
- claude_mpm/skills/bundled/pm/mpm-version/SKILL.md +21 -0
- claude_mpm/skills/registry.py +295 -90
- claude_mpm/skills/skill_manager.py +4 -4
- claude_mpm-5.6.76.dist-info/METADATA +416 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/RECORD +312 -175
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/WHEEL +1 -1
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/entry_points.txt +2 -0
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/0.DWzvg0-y.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/assets/2.ThTw9_ym.css +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/4TdZjIqw.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/5shd3_w0.js +0 -24
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/BKjSRqUr.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Da0KfYnO.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/chunks/Dfy6j1xT.js +0 -323
- claude_mpm/dashboard/static/svelte-build/_app/immutable/entry/start.NWzMBYRp.js +0 -1
- claude_mpm/dashboard/static/svelte-build/_app/immutable/nodes/2.C0GcWctS.js +0 -1
- claude_mpm-5.4.85.dist-info/METADATA +0 -1023
- /claude_mpm/skills/bundled/pm/{pm-bug-reporting/pm-bug-reporting.md → mpm-bug-reporting/SKILL.md} +0 -0
- /claude_mpm/skills/bundled/pm/{pm-delegation-patterns → mpm-delegation-patterns}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-git-file-tracking → mpm-git-file-tracking}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-pr-workflow → mpm-pr-workflow}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-ticketing-integration → mpm-ticketing-integration}/SKILL.md +0 -0
- /claude_mpm/skills/bundled/pm/{pm-verification-protocols → mpm-verification-protocols}/SKILL.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/licenses/LICENSE-FAQ.md +0 -0
- {claude_mpm-5.4.85.dist-info → claude_mpm-5.6.76.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"""Communication adapters for managing async I/O with AI coding assistants.
|
|
2
|
+
|
|
3
|
+
This module provides the async communication layer that sits between
|
|
4
|
+
InstanceManager and TmuxOrchestrator, using RuntimeAdapter for parsing.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import logging
|
|
9
|
+
from abc import ABC, abstractmethod
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import TYPE_CHECKING, AsyncIterator, Optional
|
|
13
|
+
|
|
14
|
+
from claude_mpm.commander.tmux_orchestrator import TmuxOrchestrator
|
|
15
|
+
|
|
16
|
+
from .base import RuntimeAdapter
|
|
17
|
+
|
|
18
|
+
if TYPE_CHECKING:
|
|
19
|
+
from .base import ParsedResponse
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class AdapterState(Enum):
|
|
25
|
+
"""States that a communication adapter can be in."""
|
|
26
|
+
|
|
27
|
+
IDLE = "idle" # Ready for input
|
|
28
|
+
PROCESSING = "processing" # Working on request
|
|
29
|
+
WAITING = "waiting" # Waiting for user input (e.g., permission)
|
|
30
|
+
ERROR = "error" # Error state
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass
|
|
34
|
+
class AdapterResponse:
|
|
35
|
+
"""Response from a communication adapter.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
content: The response content
|
|
39
|
+
state: Current adapter state
|
|
40
|
+
tool_uses: List of tools used in response
|
|
41
|
+
files_modified: List of files edited
|
|
42
|
+
is_complete: True if response is complete (prompt returned)
|
|
43
|
+
|
|
44
|
+
Example:
|
|
45
|
+
>>> response = AdapterResponse(
|
|
46
|
+
... content="File created: test.py",
|
|
47
|
+
... state=AdapterState.IDLE,
|
|
48
|
+
... tool_uses=["Write"],
|
|
49
|
+
... files_modified=["test.py"],
|
|
50
|
+
... is_complete=True
|
|
51
|
+
... )
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
content: str
|
|
55
|
+
state: AdapterState
|
|
56
|
+
tool_uses: Optional[list[str]] = None
|
|
57
|
+
files_modified: Optional[list[str]] = None
|
|
58
|
+
is_complete: bool = False
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class BaseCommunicationAdapter(ABC):
|
|
62
|
+
"""Abstract base class for communication adapters.
|
|
63
|
+
|
|
64
|
+
A communication adapter manages the async I/O with an AI coding assistant
|
|
65
|
+
via TmuxOrchestrator, maintaining state and handling streaming responses.
|
|
66
|
+
|
|
67
|
+
Example:
|
|
68
|
+
>>> orchestrator = TmuxOrchestrator()
|
|
69
|
+
>>> adapter = ClaudeCodeCommunicationAdapter(orchestrator, "%0")
|
|
70
|
+
>>> await adapter.send("Fix the bug in main.py")
|
|
71
|
+
>>> response = await adapter.receive()
|
|
72
|
+
>>> print(response.content)
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
@abstractmethod
|
|
76
|
+
async def send(self, message: str) -> None:
|
|
77
|
+
"""Send a message to the assistant.
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
message: The message to send
|
|
81
|
+
|
|
82
|
+
Example:
|
|
83
|
+
>>> await adapter.send("Fix the bug in main.py")
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
@abstractmethod
|
|
87
|
+
async def receive(self, timeout: float = 30.0) -> AdapterResponse:
|
|
88
|
+
"""Wait for and return response.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
timeout: Maximum time to wait for response
|
|
92
|
+
|
|
93
|
+
Returns:
|
|
94
|
+
AdapterResponse with parsed content and state
|
|
95
|
+
|
|
96
|
+
Example:
|
|
97
|
+
>>> response = await adapter.receive(timeout=60.0)
|
|
98
|
+
>>> print(response.content)
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
@abstractmethod
|
|
102
|
+
async def interrupt(self) -> bool:
|
|
103
|
+
"""Send interrupt signal (Ctrl+C).
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
True if interrupt was successful
|
|
107
|
+
|
|
108
|
+
Example:
|
|
109
|
+
>>> success = await adapter.interrupt()
|
|
110
|
+
"""
|
|
111
|
+
|
|
112
|
+
@abstractmethod
|
|
113
|
+
def is_ready(self) -> bool:
|
|
114
|
+
"""Check if adapter is ready for input.
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
True if adapter is in IDLE state
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
>>> if adapter.is_ready():
|
|
121
|
+
... await adapter.send("Next task")
|
|
122
|
+
"""
|
|
123
|
+
|
|
124
|
+
@abstractmethod
|
|
125
|
+
async def stream_response(self) -> AsyncIterator[str]:
|
|
126
|
+
"""Stream response chunks as they arrive.
|
|
127
|
+
|
|
128
|
+
Yields:
|
|
129
|
+
Response chunks as they become available
|
|
130
|
+
|
|
131
|
+
Example:
|
|
132
|
+
>>> async for chunk in adapter.stream_response():
|
|
133
|
+
... print(chunk, end='')
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class ClaudeCodeCommunicationAdapter(BaseCommunicationAdapter):
|
|
138
|
+
"""Communication adapter for Claude Code CLI.
|
|
139
|
+
|
|
140
|
+
This adapter manages async I/O with Claude Code via TmuxOrchestrator,
|
|
141
|
+
using ClaudeCodeAdapter (RuntimeAdapter) for output parsing.
|
|
142
|
+
|
|
143
|
+
Attributes:
|
|
144
|
+
orchestrator: TmuxOrchestrator for tmux operations
|
|
145
|
+
pane_target: Tmux pane target (e.g., "%0")
|
|
146
|
+
poll_interval: Polling interval for output capture (seconds)
|
|
147
|
+
|
|
148
|
+
Example:
|
|
149
|
+
>>> orchestrator = TmuxOrchestrator()
|
|
150
|
+
>>> adapter = ClaudeCodeCommunicationAdapter(orchestrator, "%0")
|
|
151
|
+
>>> await adapter.send("Create a new Python file")
|
|
152
|
+
>>> response = await adapter.receive()
|
|
153
|
+
>>> print(response.files_modified)
|
|
154
|
+
['new_file.py']
|
|
155
|
+
"""
|
|
156
|
+
|
|
157
|
+
def __init__(
|
|
158
|
+
self,
|
|
159
|
+
orchestrator: TmuxOrchestrator,
|
|
160
|
+
pane_target: str,
|
|
161
|
+
runtime_adapter: RuntimeAdapter,
|
|
162
|
+
poll_interval: float = 0.2,
|
|
163
|
+
):
|
|
164
|
+
"""Initialize the communication adapter.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
orchestrator: TmuxOrchestrator for tmux operations
|
|
168
|
+
pane_target: Tmux pane target (e.g., "%0")
|
|
169
|
+
runtime_adapter: RuntimeAdapter for parsing output
|
|
170
|
+
poll_interval: Polling interval for output capture (seconds)
|
|
171
|
+
"""
|
|
172
|
+
self.orchestrator = orchestrator
|
|
173
|
+
self.pane_target = pane_target
|
|
174
|
+
self.runtime_adapter = runtime_adapter
|
|
175
|
+
self.poll_interval = poll_interval
|
|
176
|
+
self._state = AdapterState.IDLE
|
|
177
|
+
self._last_output = ""
|
|
178
|
+
self._output_buffer = ""
|
|
179
|
+
|
|
180
|
+
async def send(self, message: str) -> None:
|
|
181
|
+
"""Send message to Claude Code.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
message: The message to send
|
|
185
|
+
|
|
186
|
+
Example:
|
|
187
|
+
>>> await adapter.send("Fix the bug in main.py")
|
|
188
|
+
"""
|
|
189
|
+
logger.debug(f"Sending message to {self.pane_target}: {message[:50]}...")
|
|
190
|
+
self._state = AdapterState.PROCESSING
|
|
191
|
+
self._output_buffer = ""
|
|
192
|
+
|
|
193
|
+
# Format message using RuntimeAdapter
|
|
194
|
+
formatted = self.runtime_adapter.format_input(message)
|
|
195
|
+
|
|
196
|
+
# Send via tmux
|
|
197
|
+
self.orchestrator.send_keys(self.pane_target, formatted, enter=True)
|
|
198
|
+
|
|
199
|
+
async def receive(self, timeout: float = 30.0) -> AdapterResponse:
|
|
200
|
+
"""Wait for complete response from Claude Code.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
timeout: Maximum time to wait for response
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
AdapterResponse with parsed content and state
|
|
207
|
+
|
|
208
|
+
Example:
|
|
209
|
+
>>> response = await adapter.receive(timeout=60.0)
|
|
210
|
+
>>> if response.is_complete:
|
|
211
|
+
... print("Task complete!")
|
|
212
|
+
"""
|
|
213
|
+
start = asyncio.get_event_loop().time()
|
|
214
|
+
|
|
215
|
+
while asyncio.get_event_loop().time() - start < timeout:
|
|
216
|
+
# Capture output from tmux pane
|
|
217
|
+
output = self.orchestrator.capture_output(self.pane_target, lines=100)
|
|
218
|
+
|
|
219
|
+
# Get only new output
|
|
220
|
+
new_output = self._get_new_output(output)
|
|
221
|
+
if new_output:
|
|
222
|
+
self._output_buffer += new_output
|
|
223
|
+
|
|
224
|
+
# Parse response using RuntimeAdapter
|
|
225
|
+
parsed = self.runtime_adapter.parse_response(output)
|
|
226
|
+
|
|
227
|
+
# Check if error occurred (prioritize error state)
|
|
228
|
+
if parsed.is_error:
|
|
229
|
+
self._state = AdapterState.ERROR
|
|
230
|
+
logger.warning(f"Error detected: {parsed.error_message}")
|
|
231
|
+
return self._build_response(parsed, is_complete=True)
|
|
232
|
+
|
|
233
|
+
# Check if waiting for user input (question)
|
|
234
|
+
if parsed.is_question:
|
|
235
|
+
self._state = AdapterState.WAITING
|
|
236
|
+
logger.debug(f"Question detected: {parsed.question_text}")
|
|
237
|
+
return self._build_response(parsed, is_complete=False)
|
|
238
|
+
|
|
239
|
+
# Check if response is complete (idle state)
|
|
240
|
+
if parsed.is_complete:
|
|
241
|
+
self._state = AdapterState.IDLE
|
|
242
|
+
logger.debug("Response complete (idle detected)")
|
|
243
|
+
return self._build_response(parsed, is_complete=True)
|
|
244
|
+
|
|
245
|
+
# Continue polling
|
|
246
|
+
await asyncio.sleep(self.poll_interval)
|
|
247
|
+
|
|
248
|
+
# Timeout - return partial response
|
|
249
|
+
logger.warning(f"Timeout after {timeout}s")
|
|
250
|
+
parsed = self.runtime_adapter.parse_response(self._output_buffer)
|
|
251
|
+
return self._build_response(parsed, is_complete=False)
|
|
252
|
+
|
|
253
|
+
async def interrupt(self) -> bool:
|
|
254
|
+
"""Send Ctrl+C to interrupt Claude Code.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
True if interrupt was successful
|
|
258
|
+
|
|
259
|
+
Example:
|
|
260
|
+
>>> success = await adapter.interrupt()
|
|
261
|
+
>>> if success:
|
|
262
|
+
... print("Interrupted successfully")
|
|
263
|
+
"""
|
|
264
|
+
try:
|
|
265
|
+
logger.info(f"Sending interrupt to {self.pane_target}")
|
|
266
|
+
self.orchestrator.send_keys(self.pane_target, "C-c", enter=False)
|
|
267
|
+
self._state = AdapterState.IDLE
|
|
268
|
+
return True
|
|
269
|
+
except Exception as e:
|
|
270
|
+
logger.error(f"Failed to interrupt: {e}")
|
|
271
|
+
return False
|
|
272
|
+
|
|
273
|
+
def is_ready(self) -> bool:
|
|
274
|
+
"""Check if adapter is ready for input.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
True if adapter is in IDLE state
|
|
278
|
+
|
|
279
|
+
Example:
|
|
280
|
+
>>> if adapter.is_ready():
|
|
281
|
+
... await adapter.send("Next task")
|
|
282
|
+
"""
|
|
283
|
+
return self._state == AdapterState.IDLE
|
|
284
|
+
|
|
285
|
+
async def stream_response(self) -> AsyncIterator[str]:
|
|
286
|
+
"""Stream response chunks from Claude Code.
|
|
287
|
+
|
|
288
|
+
Yields:
|
|
289
|
+
Response chunks as they become available
|
|
290
|
+
|
|
291
|
+
Example:
|
|
292
|
+
>>> async for chunk in adapter.stream_response():
|
|
293
|
+
... print(chunk, end='', flush=True)
|
|
294
|
+
"""
|
|
295
|
+
last_len = 0
|
|
296
|
+
|
|
297
|
+
while self._state == AdapterState.PROCESSING:
|
|
298
|
+
# Capture current output
|
|
299
|
+
output = self.orchestrator.capture_output(self.pane_target, lines=100)
|
|
300
|
+
|
|
301
|
+
# Get new output since last check and add to buffer
|
|
302
|
+
new_output = self._get_new_output(output)
|
|
303
|
+
if new_output:
|
|
304
|
+
self._output_buffer += new_output
|
|
305
|
+
|
|
306
|
+
# Yield new chunk if buffer grew
|
|
307
|
+
if len(self._output_buffer) > last_len:
|
|
308
|
+
chunk = self._output_buffer[last_len:]
|
|
309
|
+
last_len = len(self._output_buffer)
|
|
310
|
+
yield chunk
|
|
311
|
+
|
|
312
|
+
# Check if complete using RuntimeAdapter
|
|
313
|
+
parsed = self.runtime_adapter.parse_response(output)
|
|
314
|
+
if parsed.is_complete:
|
|
315
|
+
self._state = AdapterState.IDLE
|
|
316
|
+
logger.debug("Streaming complete (idle detected)")
|
|
317
|
+
break
|
|
318
|
+
|
|
319
|
+
await asyncio.sleep(self.poll_interval)
|
|
320
|
+
|
|
321
|
+
def _get_new_output(self, current: str) -> str:
|
|
322
|
+
"""Get only new output since last capture.
|
|
323
|
+
|
|
324
|
+
Args:
|
|
325
|
+
current: Current output from tmux pane
|
|
326
|
+
|
|
327
|
+
Returns:
|
|
328
|
+
New output that hasn't been seen before
|
|
329
|
+
"""
|
|
330
|
+
if current == self._last_output:
|
|
331
|
+
return ""
|
|
332
|
+
|
|
333
|
+
# Find where new content starts
|
|
334
|
+
if self._last_output and current.startswith(self._last_output):
|
|
335
|
+
new = current[len(self._last_output) :]
|
|
336
|
+
else:
|
|
337
|
+
new = current
|
|
338
|
+
|
|
339
|
+
self._last_output = current
|
|
340
|
+
return new
|
|
341
|
+
|
|
342
|
+
def _build_response(
|
|
343
|
+
self,
|
|
344
|
+
parsed: "ParsedResponse",
|
|
345
|
+
is_complete: bool,
|
|
346
|
+
) -> AdapterResponse:
|
|
347
|
+
"""Build AdapterResponse from ParsedResponse.
|
|
348
|
+
|
|
349
|
+
Args:
|
|
350
|
+
parsed: ParsedResponse from RuntimeAdapter
|
|
351
|
+
is_complete: Whether response is complete
|
|
352
|
+
|
|
353
|
+
Returns:
|
|
354
|
+
AdapterResponse with metadata
|
|
355
|
+
"""
|
|
356
|
+
# TODO: Extract tool uses and files modified from content
|
|
357
|
+
# This would require additional parsing patterns in RuntimeAdapter
|
|
358
|
+
# For now, return basic response
|
|
359
|
+
|
|
360
|
+
return AdapterResponse(
|
|
361
|
+
content=parsed.content,
|
|
362
|
+
state=self._state,
|
|
363
|
+
tool_uses=None, # Future: extract from content
|
|
364
|
+
files_modified=None, # Future: extract from content
|
|
365
|
+
is_complete=is_complete,
|
|
366
|
+
)
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"""Example usage of multi-runtime adapter architecture.
|
|
2
|
+
|
|
3
|
+
This module demonstrates how to use the adapter registry and
|
|
4
|
+
individual adapters for different AI coding runtimes.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
from typing import Optional
|
|
9
|
+
|
|
10
|
+
from claude_mpm.commander.adapters import (
|
|
11
|
+
AdapterRegistry,
|
|
12
|
+
AuggieAdapter,
|
|
13
|
+
ClaudeCodeAdapter,
|
|
14
|
+
CodexAdapter,
|
|
15
|
+
MPMAdapter,
|
|
16
|
+
RuntimeAdapter,
|
|
17
|
+
RuntimeCapability,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# Configure logging
|
|
21
|
+
logging.basicConfig(
|
|
22
|
+
level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
|
|
23
|
+
)
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def example_registry_usage() -> None:
|
|
28
|
+
"""Demonstrate adapter registry usage."""
|
|
29
|
+
print("\n" + "=" * 60)
|
|
30
|
+
print("ADAPTER REGISTRY USAGE")
|
|
31
|
+
print("=" * 60 + "\n")
|
|
32
|
+
|
|
33
|
+
# List all registered adapters
|
|
34
|
+
registered = AdapterRegistry.list_registered()
|
|
35
|
+
print(f"Registered adapters: {registered}")
|
|
36
|
+
|
|
37
|
+
# Detect available runtimes on system
|
|
38
|
+
available = AdapterRegistry.detect_available()
|
|
39
|
+
print(f"Available runtimes: {available}")
|
|
40
|
+
|
|
41
|
+
# Get default adapter (best available)
|
|
42
|
+
default_adapter = AdapterRegistry.get_default()
|
|
43
|
+
if default_adapter:
|
|
44
|
+
print(f"\nDefault adapter: {default_adapter.name}")
|
|
45
|
+
print(f"Capabilities: {default_adapter.capabilities}")
|
|
46
|
+
else:
|
|
47
|
+
print("\nNo adapters available on this system")
|
|
48
|
+
|
|
49
|
+
# Get specific adapter
|
|
50
|
+
mpm_adapter = AdapterRegistry.get("mpm")
|
|
51
|
+
if mpm_adapter:
|
|
52
|
+
print(f"\nMPM adapter available: {mpm_adapter.name}")
|
|
53
|
+
else:
|
|
54
|
+
print("\nMPM adapter not available")
|
|
55
|
+
|
|
56
|
+
# Check if specific runtime is available
|
|
57
|
+
if AdapterRegistry.is_available("claude-code"):
|
|
58
|
+
print("\nClaude Code is available")
|
|
59
|
+
else:
|
|
60
|
+
print("\nClaude Code is NOT available")
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def example_adapter_capabilities() -> None:
|
|
64
|
+
"""Demonstrate checking adapter capabilities."""
|
|
65
|
+
print("\n" + "=" * 60)
|
|
66
|
+
print("ADAPTER CAPABILITIES")
|
|
67
|
+
print("=" * 60 + "\n")
|
|
68
|
+
|
|
69
|
+
adapters = [
|
|
70
|
+
ClaudeCodeAdapter(),
|
|
71
|
+
AuggieAdapter(),
|
|
72
|
+
CodexAdapter(),
|
|
73
|
+
MPMAdapter(),
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
for adapter in adapters:
|
|
77
|
+
print(f"\n{adapter.name.upper()} Adapter:")
|
|
78
|
+
print(
|
|
79
|
+
f" Command: {adapter.runtime_info.command if adapter.runtime_info else 'N/A'}"
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Check for specific capabilities
|
|
83
|
+
info = adapter.runtime_info
|
|
84
|
+
if info:
|
|
85
|
+
print(f" Supports agents: {info.supports_agents}")
|
|
86
|
+
print(f" Instruction file: {info.instruction_file or 'None'}")
|
|
87
|
+
|
|
88
|
+
# Check for advanced features
|
|
89
|
+
if RuntimeCapability.AGENT_DELEGATION in info.capabilities:
|
|
90
|
+
print(" ✓ Agent delegation supported")
|
|
91
|
+
else:
|
|
92
|
+
print(" ✗ Agent delegation NOT supported")
|
|
93
|
+
|
|
94
|
+
if RuntimeCapability.HOOKS in info.capabilities:
|
|
95
|
+
print(" ✓ Lifecycle hooks supported")
|
|
96
|
+
else:
|
|
97
|
+
print(" ✗ Lifecycle hooks NOT supported")
|
|
98
|
+
|
|
99
|
+
if RuntimeCapability.MCP_TOOLS in info.capabilities:
|
|
100
|
+
print(" ✓ MCP tools supported")
|
|
101
|
+
else:
|
|
102
|
+
print(" ✗ MCP tools NOT supported")
|
|
103
|
+
|
|
104
|
+
if RuntimeCapability.SKILLS in info.capabilities:
|
|
105
|
+
print(" ✓ Skills supported")
|
|
106
|
+
else:
|
|
107
|
+
print(" ✗ Skills NOT supported")
|
|
108
|
+
|
|
109
|
+
if RuntimeCapability.MONITOR in info.capabilities:
|
|
110
|
+
print(" ✓ Real-time monitoring supported")
|
|
111
|
+
else:
|
|
112
|
+
print(" ✗ Real-time monitoring NOT supported")
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def example_build_commands() -> None:
|
|
116
|
+
"""Demonstrate building launch commands."""
|
|
117
|
+
print("\n" + "=" * 60)
|
|
118
|
+
print("BUILD LAUNCH COMMANDS")
|
|
119
|
+
print("=" * 60 + "\n")
|
|
120
|
+
|
|
121
|
+
project_path = "/home/user/my-project"
|
|
122
|
+
agent_prompt = "You are a Python expert specializing in FastAPI and async code."
|
|
123
|
+
|
|
124
|
+
adapters = [
|
|
125
|
+
ClaudeCodeAdapter(),
|
|
126
|
+
AuggieAdapter(),
|
|
127
|
+
CodexAdapter(),
|
|
128
|
+
MPMAdapter(),
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
for adapter in adapters:
|
|
132
|
+
print(f"\n{adapter.name.upper()}:")
|
|
133
|
+
|
|
134
|
+
# Basic launch command
|
|
135
|
+
cmd = adapter.build_launch_command(project_path)
|
|
136
|
+
print(f" Basic: {cmd}")
|
|
137
|
+
|
|
138
|
+
# With agent prompt
|
|
139
|
+
cmd_with_prompt = adapter.build_launch_command(project_path, agent_prompt)
|
|
140
|
+
print(f" With prompt: {cmd_with_prompt}")
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def example_inject_instructions() -> None:
|
|
144
|
+
"""Demonstrate injecting custom instructions."""
|
|
145
|
+
print("\n" + "=" * 60)
|
|
146
|
+
print("INJECT CUSTOM INSTRUCTIONS")
|
|
147
|
+
print("=" * 60 + "\n")
|
|
148
|
+
|
|
149
|
+
instructions = """You are a senior Python engineer.
|
|
150
|
+
Follow PEP 8 strictly.
|
|
151
|
+
Write comprehensive tests for all code.
|
|
152
|
+
Use type hints everywhere."""
|
|
153
|
+
|
|
154
|
+
adapters = [
|
|
155
|
+
ClaudeCodeAdapter(),
|
|
156
|
+
AuggieAdapter(),
|
|
157
|
+
CodexAdapter(),
|
|
158
|
+
MPMAdapter(),
|
|
159
|
+
]
|
|
160
|
+
|
|
161
|
+
for adapter in adapters:
|
|
162
|
+
print(f"\n{adapter.name.upper()}:")
|
|
163
|
+
|
|
164
|
+
cmd = adapter.inject_instructions(instructions)
|
|
165
|
+
if cmd:
|
|
166
|
+
print(f" Command: {cmd}")
|
|
167
|
+
else:
|
|
168
|
+
print(" Not supported")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def example_inject_agent_context() -> None:
|
|
172
|
+
"""Demonstrate injecting agent context."""
|
|
173
|
+
print("\n" + "=" * 60)
|
|
174
|
+
print("INJECT AGENT CONTEXT")
|
|
175
|
+
print("=" * 60 + "\n")
|
|
176
|
+
|
|
177
|
+
agent_id = "eng-001"
|
|
178
|
+
context = {
|
|
179
|
+
"role": "Engineer",
|
|
180
|
+
"specialty": "Backend Python",
|
|
181
|
+
"task": "Implement API endpoints",
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
adapters = [
|
|
185
|
+
ClaudeCodeAdapter(),
|
|
186
|
+
AuggieAdapter(),
|
|
187
|
+
CodexAdapter(),
|
|
188
|
+
MPMAdapter(),
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
for adapter in adapters:
|
|
192
|
+
print(f"\n{adapter.name.upper()}:")
|
|
193
|
+
|
|
194
|
+
cmd = adapter.inject_agent_context(agent_id, context)
|
|
195
|
+
if cmd:
|
|
196
|
+
print(f" Command: {cmd[:100]}...")
|
|
197
|
+
else:
|
|
198
|
+
print(" Not supported")
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def example_parse_response() -> None:
|
|
202
|
+
"""Demonstrate parsing runtime output."""
|
|
203
|
+
print("\n" + "=" * 60)
|
|
204
|
+
print("PARSE RUNTIME OUTPUT")
|
|
205
|
+
print("=" * 60 + "\n")
|
|
206
|
+
|
|
207
|
+
# Simulate different output scenarios
|
|
208
|
+
outputs = {
|
|
209
|
+
"idle": "File created successfully.\n> ",
|
|
210
|
+
"error": "Error: File not found: config.py\n> ",
|
|
211
|
+
"question": "Should I proceed with the changes? (y/n)?",
|
|
212
|
+
"processing": "Processing your request...",
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
adapter = ClaudeCodeAdapter()
|
|
216
|
+
|
|
217
|
+
for scenario, output in outputs.items():
|
|
218
|
+
print(f"\n{scenario.upper()}:")
|
|
219
|
+
parsed = adapter.parse_response(output)
|
|
220
|
+
print(f" Content: {parsed.content[:50]}...")
|
|
221
|
+
print(f" Is complete: {parsed.is_complete}")
|
|
222
|
+
print(f" Is error: {parsed.is_error}")
|
|
223
|
+
print(f" Is question: {parsed.is_question}")
|
|
224
|
+
if parsed.error_message:
|
|
225
|
+
print(f" Error message: {parsed.error_message}")
|
|
226
|
+
if parsed.question_text:
|
|
227
|
+
print(f" Question: {parsed.question_text}")
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
def example_runtime_selection() -> None:
|
|
231
|
+
"""Demonstrate selecting runtime based on requirements."""
|
|
232
|
+
print("\n" + "=" * 60)
|
|
233
|
+
print("RUNTIME SELECTION LOGIC")
|
|
234
|
+
print("=" * 60 + "\n")
|
|
235
|
+
|
|
236
|
+
def select_runtime(
|
|
237
|
+
needs_agents: bool = False, needs_mcp: bool = False
|
|
238
|
+
) -> Optional[RuntimeAdapter]:
|
|
239
|
+
"""Select appropriate runtime based on requirements."""
|
|
240
|
+
# Get all available adapters
|
|
241
|
+
available = AdapterRegistry.detect_available()
|
|
242
|
+
|
|
243
|
+
# Filter by requirements
|
|
244
|
+
for name in available:
|
|
245
|
+
adapter = AdapterRegistry.get(name)
|
|
246
|
+
if not adapter or not adapter.runtime_info:
|
|
247
|
+
continue
|
|
248
|
+
|
|
249
|
+
info = adapter.runtime_info
|
|
250
|
+
|
|
251
|
+
# Check agent requirement
|
|
252
|
+
if needs_agents and not info.supports_agents:
|
|
253
|
+
continue
|
|
254
|
+
|
|
255
|
+
# Check MCP requirement
|
|
256
|
+
if needs_mcp and RuntimeCapability.MCP_TOOLS not in info.capabilities:
|
|
257
|
+
continue
|
|
258
|
+
|
|
259
|
+
# Found suitable runtime
|
|
260
|
+
return adapter
|
|
261
|
+
|
|
262
|
+
return None
|
|
263
|
+
|
|
264
|
+
# Example 1: Need agent delegation
|
|
265
|
+
print("Requirement: Agent delegation")
|
|
266
|
+
adapter = select_runtime(needs_agents=True)
|
|
267
|
+
if adapter:
|
|
268
|
+
print(f" Selected: {adapter.name}")
|
|
269
|
+
else:
|
|
270
|
+
print(" No suitable runtime found")
|
|
271
|
+
|
|
272
|
+
# Example 2: Need MCP tools
|
|
273
|
+
print("\nRequirement: MCP tools")
|
|
274
|
+
adapter = select_runtime(needs_mcp=True)
|
|
275
|
+
if adapter:
|
|
276
|
+
print(f" Selected: {adapter.name}")
|
|
277
|
+
else:
|
|
278
|
+
print(" No suitable runtime found")
|
|
279
|
+
|
|
280
|
+
# Example 3: Need both
|
|
281
|
+
print("\nRequirement: Agent delegation + MCP tools")
|
|
282
|
+
adapter = select_runtime(needs_agents=True, needs_mcp=True)
|
|
283
|
+
if adapter:
|
|
284
|
+
print(f" Selected: {adapter.name}")
|
|
285
|
+
else:
|
|
286
|
+
print(" No suitable runtime found")
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
def main() -> None:
|
|
290
|
+
"""Run all examples."""
|
|
291
|
+
print("\n" + "#" * 60)
|
|
292
|
+
print("# MULTI-RUNTIME ADAPTER ARCHITECTURE EXAMPLES")
|
|
293
|
+
print("#" * 60)
|
|
294
|
+
|
|
295
|
+
# Run all examples
|
|
296
|
+
example_registry_usage()
|
|
297
|
+
example_adapter_capabilities()
|
|
298
|
+
example_build_commands()
|
|
299
|
+
example_inject_instructions()
|
|
300
|
+
example_inject_agent_context()
|
|
301
|
+
example_parse_response()
|
|
302
|
+
example_runtime_selection()
|
|
303
|
+
|
|
304
|
+
print("\n" + "#" * 60)
|
|
305
|
+
print("# EXAMPLES COMPLETE")
|
|
306
|
+
print("#" * 60 + "\n")
|
|
307
|
+
|
|
308
|
+
|
|
309
|
+
if __name__ == "__main__":
|
|
310
|
+
main()
|