Merge upstream b1f003e186 while preserving PM runtime ownership and
Python 3.14 worker startup, Windows signing, and macOS wait recovery.
Keep retired runtime modules deleted. Port upstream updater preflight
checks into the checkout strategy and preserve live build logging.
Carry checkpoint filename handling and process recovery into the current
module layout. Regenerate locks and adapt incoming platform test markers.
Focused Python and JavaScript tests, desktop and root-test typechecks,
conflict-path lint checks, lock validation, and retired-import checks pass.
The full test suite and packaged release builds were not run.
46 lines
1.9 KiB
Python
46 lines
1.9 KiB
Python
"""Hermes CLI - Unified command-line interface for Hermes Agent."""
|
|
|
|
import os
|
|
import sys
|
|
|
|
__version__ = "0.21.1"
|
|
__release_date__ = "2026.9.7"
|
|
|
|
|
|
def _ensure_utf8():
|
|
"""Force UTF-8 stdout/stderr to prevent UnicodeEncodeError crashes.
|
|
|
|
The CLI prints box-drawing characters and the ⚕ glyph in the setup wizard, doctor, and status
|
|
banners; under a non-UTF-8 codec that raises before the command can even start (e.g.
|
|
`hermes setup` on a fresh Pi).
|
|
"""
|
|
repaired = False
|
|
for stream_name in ("stdout", "stderr"):
|
|
stream = getattr(sys, stream_name, None)
|
|
if stream is None:
|
|
continue
|
|
try:
|
|
if (getattr(stream, "encoding", "") or "").lower().replace("-", "") == "utf8":
|
|
continue
|
|
# Preferred: reconfigure in place, preserving object identity so code already holding
|
|
# a reference to the old sys.stdout benefits from the repair too.
|
|
reconfigure = getattr(stream, "reconfigure", None)
|
|
if callable(reconfigure):
|
|
reconfigure(encoding="utf-8", errors="replace")
|
|
else:
|
|
# No reconfigure(): reopen the fd as UTF-8 (closefd=False keeps the original fd open).
|
|
new_stream = open(stream.fileno(), "w", encoding="utf-8", errors="replace", # windows-footgun: ok (stdout re-open for write, not a read)
|
|
buffering=1, closefd=False)
|
|
setattr(sys, stream_name, new_stream)
|
|
repaired = True
|
|
except (AttributeError, OSError, ValueError):
|
|
pass
|
|
# Only nudge child processes toward UTF-8 when a non-UTF-8 locale was actually detected; on a
|
|
# healthy UTF-8 host children inherit it from the locale already.
|
|
if repaired:
|
|
os.environ.setdefault("PYTHONUTF8", "1")
|
|
os.environ.setdefault("PYTHONIOENCODING", "utf-8")
|
|
|
|
|
|
_ensure_utf8()
|