feat: offer backend CLI install on missing binary (entrypoints) + shared backend_available/ensure_backend helpers

- Standalone my* wrappers pass offer_install=True so a missing backend CLI
  triggers the interactive 'Install now? [y/N]' prompt (was a bare not-found).
- Add backend_available()/ensure_backend() to expose the backend registry
  (binary/env_bin/install_cmd) for xiaohe init / ensure-deps to reuse.
This commit is contained in:
Zhengshou Lai
2026-08-09 15:08:03 +08:00
parent a95c920d8a
commit c3e119e3c9
2 changed files with 30 additions and 5 deletions
+8 -5
View File
@@ -2,11 +2,14 @@
from myagents.launcher import build_cli from myagents.launcher import build_cli
claude_cli = build_cli("claude", prog_name="myclaude") # offer_install=True so a missing backend CLI (e.g. `claude`) triggers the
kimi_cli = build_cli("kimi", prog_name="mykimi") # interactive "Install now? [y/N]" prompt instead of a bare not-found error.
codex_cli = build_cli("codex", prog_name="mycodex") # Backends without an install_cmd (hermes/cursor) fall back to the manual msg.
hermes_cli = build_cli("hermes", prog_name="myhermes") claude_cli = build_cli("claude", prog_name="myclaude", offer_install=True)
cursor_cli = build_cli("cursor", prog_name="mycursor") kimi_cli = build_cli("kimi", prog_name="mykimi", offer_install=True)
codex_cli = build_cli("codex", prog_name="mycodex", offer_install=True)
hermes_cli = build_cli("hermes", prog_name="myhermes", offer_install=True)
cursor_cli = build_cli("cursor", prog_name="mycursor", offer_install=True)
def _progs(): def _progs():
+22
View File
@@ -256,6 +256,28 @@ def _offer_install(config: dict) -> str | None:
return _resolve_backend_binary(config) return _resolve_backend_binary(config)
def backend_available(backend: str) -> bool:
"""True if the backend CLI (or its env override) resolves on PATH."""
cfg = _BACKENDS.get(backend)
return bool(cfg and _resolve_backend_binary(cfg))
def ensure_backend(backend: str) -> bool:
"""Ensure a backend CLI is available, offering to install it when missing.
Reuses the interactive ``_offer_install`` (prompt on tty, install via the
backend's ``install_cmd``). Backends without an installer (e.g. hermes)
fall back to the manual not-found message. Returns True if the CLI is
available afterwards.
"""
cfg = _BACKENDS.get(backend)
if not cfg:
return False
if _resolve_backend_binary(cfg):
return True
return _offer_install(cfg) is not None
def _launch( def _launch(
backend: str, backend: str,
chat_cwd: Path, chat_cwd: Path,