"""Slash-command handlers for the interactive CLI (``HermesCLI`` inherits ``CLICommandsMixin``). cli.py-internal symbols (``_cprint``/``_ACCENT``/``save_config_value``…) are imported LAZILY inside the helpers/handlers via ``from cli import ...`` — cli.py imports this module (cycle otherwise). """ from __future__ import annotations import argparse import atexit import importlib import io import json import os import shlex import subprocess import sys import tempfile import threading import time import uuid from contextlib import redirect_stdout, suppress from io import StringIO from datetime import datetime from urllib.parse import urlparse from rich import box as rich_box from rich.markup import escape as _escape from rich.panel import Panel from hermes_constants import display_hermes_home, is_termux as _is_termux_environment from agent.turn_context import extract_api_content_sidecar from hermes_cli.browser_connect import ( DEFAULT_BROWSER_CDP_URL, discover_local_cdp_url, find_free_debug_port, is_browser_debug_ready, launch_chrome_debug, local_port_in_use, manual_chrome_debug_command) # Output helpers. Slash-command text is user-visible: every literal below is load-bearing. def _cp(*lines: str) -> None: """``_cprint`` each line (lazy import: cli.py imports this module).""" from cli import _cprint for line in lines: _cprint(line) def _pr(*lines: str) -> None: """print() each line.""" for line in lines: print(line) def _save(key: str, value) -> bool: """cli.save_config_value, resolved lazily (cli.py imports this module).""" from cli import save_config_value return save_config_value(key, value) def _dim(text: str) -> str: """Wrap ``text`` in the dim ANSI escape.""" from cli import _DIM, _RST return f"{_DIM}{text}{_RST}" def _dim_line(text: str) -> str: """Two-space indented dim line (the standard slash-command hint shape).""" return " " + _dim(text) def _accent(text: str) -> str: """Wrap ``text`` in the skin accent ANSI escape.""" from cli import _ACCENT, _RST return f"{_ACCENT}{text}{_RST}" def _accent_line(text: str) -> str: """Two-space indented accent line (the standard slash-command headline shape).""" return f" {_accent(text)}" def _probe(module: str, name: str, default, *args): """``.(*args)`` or ``default`` when the import or the call fails (optional subsystems: browser backends, async delegations, wake word, ...).""" try: return getattr(importlib.import_module(module), name)(*args) except Exception: return default class _TTYBuf(StringIO): """StringIO that claims to be a TTY so ``hermes_cli.colors.color()`` still emits ANSI escapes.""" def isatty(self) -> bool: return True _FAILED = object() def _attempt(label: str, errors, fn, *args, **kwargs): """``fn(*args, **kwargs)``, or ``_FAILED`` after printing ``