1006faa6f8
Adds a bounded, read-only health probe per CONFIGURED tool backend, run only when the user explicitly passes `--live` (real network calls): - Firecrawl: credit-usage metadata GET (auth check, no scrape spend) - FAL: models metadata GET (never a generation) - Browser: headless launch + about:blank + close (full cleanup) - MCP: initialize + tools/list per configured server (reuses the `hermes mcp test` machinery in mcp_config._probe_single_server) - TTS/STT: provider models/voices list GET (openai/groq/elevenlabs); local providers (edge/piper/faster-whisper/...) skipped Invariants: - Opt-in only: zero probes without --live (default False) - Bounded: sequential, per-probe timeout (doctor.live_probe_timeout, default 10s, config.yaml knob) - Never mutates state; unconfigured backends skip with a note - Failure isolation: every probe wrapped in a catch-all; a probe crash can never break the doctor run; failures append to the issues summary New: hermes_cli/doctor_live.py, tests/hermes_cli/test_doctor_live.py (23 tests, probes mocked at the HTTP/client seam). Wired: --live flag in subcommands/doctor.py; run_doctor calls maybe_run_live_checks after all static checks. Coordination: PR #70124 (--probe-routes) probes LLM routes; this flag probes TOOL backends — different surface, no code-region collision (the run_doctor hook here sits at the end-of-run summary, not the API Connectivity section #70124 extends). Inspired by: paradigmxyz/centaur tool-health-smoke (MIT/Apache-2.0); sibling: #70124 (LLM route probes — different surface)
45 lines
1.5 KiB
Python
45 lines
1.5 KiB
Python
"""``hermes doctor`` subcommand parser.
|
|
|
|
Extracted verbatim from ``hermes_cli/main.py:main()`` (god-file Phase 2).
|
|
Handler injected to avoid importing ``main``.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Callable
|
|
|
|
|
|
def build_doctor_parser(subparsers, *, cmd_doctor: Callable) -> None:
|
|
"""Attach the ``doctor`` subcommand to ``subparsers``."""
|
|
# =========================================================================
|
|
# doctor command
|
|
# =========================================================================
|
|
doctor_parser = subparsers.add_parser(
|
|
"doctor",
|
|
help="Check configuration and dependencies",
|
|
description="Diagnose issues with Hermes Agent setup",
|
|
)
|
|
doctor_parser.add_argument(
|
|
"--fix", action="store_true", help="Attempt to fix issues automatically"
|
|
)
|
|
doctor_parser.add_argument(
|
|
"--live",
|
|
action="store_true",
|
|
help=(
|
|
"Opt-in: run one bounded, read-only real-call health probe per "
|
|
"configured tool backend (Firecrawl/FAL/browser/MCP/TTS/STT) "
|
|
"after the static checks. Makes real network calls."
|
|
),
|
|
)
|
|
doctor_parser.add_argument(
|
|
"--ack",
|
|
metavar="ADVISORY_ID",
|
|
default=None,
|
|
help=(
|
|
"Acknowledge a security advisory by ID and exit. After ack, the "
|
|
"advisory will no longer trigger startup banners. Run `hermes "
|
|
"doctor` first to see active advisories and their IDs."
|
|
),
|
|
)
|
|
doctor_parser.set_defaults(func=cmd_doctor)
|