diff --git a/hermes_cli/main.py b/hermes_cli/main.py index fa10749012f..75fb6ecd658 100644 --- a/hermes_cli/main.py +++ b/hermes_cli/main.py @@ -61,12 +61,76 @@ try: except ModuleNotFoundError: pass +import os +import sys + + +def _is_termux_startup_environment_fast() -> bool: + """Tiny Termux check for pre-import startup shortcuts.""" + prefix = os.environ.get("PREFIX", "") + return bool( + os.environ.get("TERMUX_VERSION") + or "com.termux/files/usr" in prefix + or prefix.startswith("/data/data/com.termux/") + ) + + +def _is_termux_fast_version_argv(argv: list[str]) -> bool: + return argv in (["--version"], ["-V"], ["version"]) + + +def _read_openai_version_fast() -> str | None: + """Read OpenAI SDK version without importing ``importlib.metadata``.""" + for base in sys.path: + if not base: + base = os.getcwd() + version_file = os.path.join(base, "openai", "_version.py") + try: + with open(version_file, encoding="utf-8") as handle: + for line in handle: + stripped = line.strip() + if not stripped.startswith("__version__"): + continue + _key, _sep, value = stripped.partition("=") + value = value.split("#", 1)[0].strip().strip("\"'") + return value or None + except OSError: + continue + return None + + +def _print_fast_version_info() -> None: + from hermes_cli import __release_date__, __version__ + + project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir)) + print(f"Hermes Agent v{__version__} ({__release_date__})") + print(f"Project: {project_root}") + print(f"Python: {sys.version.split()[0]}") + + openai_version = _read_openai_version_fast() + print(f"OpenAI SDK: {openai_version}" if openai_version else "OpenAI SDK: Not installed") + + +def _try_termux_ultrafast_version() -> bool: + """Handle ``hermes --version`` before config/logging imports on Termux.""" + if os.environ.get("HERMES_TERMUX_DISABLE_FAST_CLI") == "1": + return False + if not _is_termux_startup_environment_fast(): + return False + if not _is_termux_fast_version_argv(sys.argv[1:]): + return False + + _print_fast_version_info() + return True + + +if _try_termux_ultrafast_version(): + raise SystemExit(0) + import argparse import json -import os import shutil import subprocess -import sys from pathlib import Path from typing import Optional @@ -10742,10 +10806,6 @@ def _set_chat_arg_defaults(args) -> None: setattr(args, attr, default) -def _is_termux_fast_version_argv(argv: list[str]) -> bool: - return argv in (["--version"], ["-V"], ["version"]) - - def _try_termux_fast_cli_launch() -> bool: """Run obvious Termux non-TUI chat/oneshot/version paths on a light parser.""" if not _is_termux_startup_environment(): diff --git a/tests/hermes_cli/test_tui_resume_flow.py b/tests/hermes_cli/test_tui_resume_flow.py index 7e6ccc05927..7645188437b 100644 --- a/tests/hermes_cli/test_tui_resume_flow.py +++ b/tests/hermes_cli/test_tui_resume_flow.py @@ -364,6 +364,34 @@ def test_termux_fast_cli_launch_version_skips_update_check(monkeypatch, main_mod assert captured == [False] +def test_termux_ultrafast_version_runs_before_heavy_startup( + monkeypatch, capsys, main_mod +): + monkeypatch.setenv("TERMUX_VERSION", "1") + monkeypatch.delenv("HERMES_TERMUX_DISABLE_FAST_CLI", raising=False) + monkeypatch.setattr(sys, "argv", ["hermes", "--version"]) + + assert main_mod._try_termux_ultrafast_version() is True + + out = capsys.readouterr().out + assert "Hermes Agent v" in out + assert "Project:" in out + assert "Python:" in out + assert "OpenAI SDK:" in out + + +def test_read_openai_version_fast(monkeypatch, tmp_path, main_mod): + package_dir = tmp_path / "openai" + package_dir.mkdir() + (package_dir / "_version.py").write_text( + '__version__ = "9.8.7" # x-release-please-version\n', + encoding="utf-8", + ) + monkeypatch.setattr(sys, "path", [str(tmp_path)]) + + assert main_mod._read_openai_version_fast() == "9.8.7" + + def test_termux_fast_cli_launch_skips_help(monkeypatch, main_mod): monkeypatch.setenv("TERMUX_VERSION", "1") monkeypatch.delenv("HERMES_TUI", raising=False)