refactor(hermes_cli): inline _try_poll, hoist datetime import, share _kv/_detail and _header/_lines

This commit is contained in:
Teknium
2026-09-03 00:11:01 -07:00
parent 439ceb51ed
commit 0c26446e15
6 changed files with 17 additions and 31 deletions

View File

@@ -204,10 +204,8 @@ def _print_cmd_rows(rows):
def _print_section_header(title):
print(_setup.color("─" * 60, _setup.Colors.DIM))
print()
print(_setup.color(title, _setup.Colors.CYAN, _setup.Colors.BOLD))
print()
print(_setup.color("─" * 60, _setup.Colors.DIM), end="\n\n")
print(_setup.color(title, _setup.Colors.CYAN, _setup.Colors.BOLD), end="\n\n")
def _print_setup_summary(config: dict, hermes_home):
@@ -251,8 +249,7 @@ def _print_setup_summary(config: dict, hermes_home):
for line in _DONE_BANNER:
print(_setup.color(line, _setup.Colors.GREEN))
print()
print(_setup.color(f"📁 All your files are in {_dhh()}/:", _setup.Colors.CYAN, _setup.Colors.BOLD))
print()
print(_setup.color(f"📁 All your files are in {_dhh()}/:", _setup.Colors.CYAN, _setup.Colors.BOLD), end="\n\n")
for label, value in (("Settings:", f" {_setup.get_config_path()}"), ("API Keys:", f" {_setup.get_env_path()}"),
("Data:", f" {hermes_home}/cron/, sessions/, logs/")):
print(f" {_setup.color(label, _setup.Colors.YELLOW)}{value}")
@@ -262,9 +259,7 @@ def _print_setup_summary(config: dict, hermes_home):
_print_cmd_rows(_EDIT_WIZARD_ROWS)
print()
_print_cmd_rows(_EDIT_CONFIG_ROWS)
print(" Set a specific value")
print()
print(" Or edit the files directly:")
print(" Set a specific value\n\n Or edit the files directly:")
for path in (_setup.get_config_path(), _setup.get_env_path()):
print(f" {_setup.color(f'nano {path}', _setup.Colors.DIM)}")
print()

View File

@@ -270,8 +270,7 @@ def _setup_backend_plugin(config: dict, backend: str) -> None:
_BUILTIN_TERMINAL_BACKENDS = [
("local", "Local - run directly on this machine (default)"),
("docker", "Docker - isolated container with configurable resources"),
("modal", "Modal - serverless cloud sandbox"),
("ssh", "SSH - run on a remote machine"),
("modal", "Modal - serverless cloud sandbox"), ("ssh", "SSH - run on a remote machine"),
("daytona", "Daytona - persistent cloud development environment"),
("vercel_sandbox", "Vercel Sandbox - cloud microVM with snapshot filesystem persistence")]
_TERMINAL_BACKEND_SETUP = {

View File

@@ -132,9 +132,7 @@ def _prompt_validated(
# --- Wizard
def _header(title: str) -> None:
print("─" * 50)
print(title)
print("─" * 50)
_lines("─" * 50, title, "─" * 50)
def _lines(*lines: str) -> None:

View File

@@ -40,12 +40,12 @@ def _row(name: str, ok: bool, text: str, width: int = 12, sep: str = " ") -> No
def _detail(label: str, value) -> None:
"""Print an indented ``label: value`` detail line under a status row."""
print(f" {label:<12}{value}")
_kv(label, value, " ", 12)
def _kv(label: str, value) -> None:
def _kv(label: str, value, indent: str = " ", width: int = 14) -> None:
"""Print a `` Label: value`` line (label padded to the 14-col status layout)."""
print(f" {label:<14}{value}")
print(f"{indent}{label:<{width}}{value}")
def _kv_flag(label: str, ok, on: str, off: str) -> None:

View File

@@ -2,6 +2,8 @@
Origin helpers (``_row``, ``_first_env_value``, ...) are resolved through the ``hermes_cli.status``
module object so tests that monkeypatch that module keep working."""
from datetime import datetime, timezone
from hermes_cli.auth import AuthError
from hermes_cli.nous_account import (
format_nous_portal_entitlement_message, get_nous_portal_account_info)
@@ -14,7 +16,6 @@ def _format_iso_timestamp(value) -> str:
text = value.strip() if isinstance(value, str) else ""
if not text:
return "(unknown)"
from datetime import datetime, timezone
try:
parsed = datetime.fromisoformat(text[:-1] + "+00:00" if text.endswith("Z") else text)
except Exception:
@@ -25,7 +26,6 @@ def _format_iso_timestamp(value) -> str:
def _qwen_expiry(expires_at_ms) -> str:
from datetime import datetime, timezone
return datetime.fromtimestamp(int(expires_at_ms) / 1000, tz=timezone.utc).isoformat()

View File

@@ -84,8 +84,7 @@ def print_qr_code(url: str, *, include_link: bool = True) -> None:
def create_pairing(
api_url: str | None = None, bot_name: str = DEFAULT_BOT_NAME, timeout: float = 10.0
) -> TelegramPairing | None:
"""POST a pairing; returns deep link, QR payload, public id and the secret poll token (used
only as a bearer credential while polling)."""
"""POST a pairing; the returned poll token is only used as a bearer credential while polling."""
try:
resp = httpx.post(f"{_api_url(api_url)}/v1/telegram/pairings", json={"bot_name": bot_name}, timeout=timeout)
if resp.status_code not in (200, 201):
@@ -122,14 +121,6 @@ def poll_pairing_result_once(
_parse_owner_user_id(data.get("owner_user_id")))
def _try_poll(api_url: str | None, pairing: TelegramPairing) -> TelegramBotSetupResult | None:
"""One poll attempt; transport/JSON errors count as 'not ready yet'."""
try:
return poll_pairing_result_once(api_url, pairing)
except (httpx.HTTPError, ValueError):
return None
def poll_for_setup_result(
api_url: str | None, pairing: TelegramPairing, timeout: float = DEFAULT_POLL_TIMEOUT,
interval: float = POLL_INTERVAL, on_tick=None) -> Optional[TelegramBotSetupResult]:
@@ -140,8 +131,11 @@ def poll_for_setup_result(
while time.monotonic() < deadline:
if on_tick:
on_tick(time.monotonic() - start)
if result := _try_poll(api_url, pairing):
return result
try: # transport/JSON errors count as 'not ready yet'
if result := poll_pairing_result_once(api_url, pairing):
return result
except (httpx.HTTPError, ValueError):
pass
time.sleep(interval)
return None