opentui(phase3): launcher integration — HERMES_TUI_ENGINE dual-engine

hermes --tui launches the native OpenTUI engine (Bun) when
HERMES_TUI_ENGINE=opentui (env) or display.tui_engine=opentui (config);
Ink stays the default and the shipping path is untouched.

- _resolve_tui_engine() (env > config > ink); refuses opentui on
  Windows/Termux (no Bun) -> falls back to ink with a notice.
- _make_opentui_argv() -> [bun, src/entry.real.tsx] (no build step).
- _bun_bin() with HERMES_BUN override.
- Branch at top of _make_tui_argv BEFORE _ensure_tui_node (Bun-only host
  must not bootstrap Node).
- Gate _launch_tui NODE_OPTIONS/--max-old-space-size on engine==ink (Bun
  is JSC; the V8 flag errors/ignores).

Verified end-to-end via tmux: real hermes --tui -> Bun -> OpenTUI ->
real Python gateway streamed a real reply. No-flag default still ink.
This commit is contained in:
alt-glitch
2026-06-08 11:11:54 +00:00
parent 24f74eb888
commit 2bd9c9b881
741 changed files with 17733 additions and 79889 deletions
-97
View File
@@ -88,103 +88,6 @@ def test_lazy_installable_extras_excluded_from_all():
)
def _exact_pins(specs):
pins = {}
for spec in specs:
requirement = spec.split(";", 1)[0].strip()
if "==" not in requirement:
continue
package, version = requirement.split("==", 1)
package = package.split("[", 1)[0].lower().replace("_", "-")
pins[package] = version
return pins
def test_pyproject_aiohttp_pins_match_lazy_slack_pin():
"""Avoid update/lazy-install churn from conflicting aiohttp pins.
pyproject extras (messaging/slack/homeassistant/sms) exact-pin aiohttp.
The Slack lazy-install deps (LAZY_DEPS['platform.slack']) also pin it.
If the two drift, `hermes update` resolves the pyproject pin and
downgrades aiohttp, reopening the CVEs the lazy pin fixed (#31817) —
only for Slack's lazy refresh to upgrade it again on next use.
"""
from tools.lazy_deps import LAZY_DEPS
optional_dependencies = _load_optional_dependencies()
lazy_aiohttp = _exact_pins(LAZY_DEPS["platform.slack"])["aiohttp"]
pyproject_aiohttp_pins = {
extra: pins["aiohttp"]
for extra, specs in optional_dependencies.items()
if "aiohttp" in (pins := _exact_pins(specs))
}
assert pyproject_aiohttp_pins, "expected at least one pyproject extra to pin aiohttp"
mismatches = {
extra: pin
for extra, pin in pyproject_aiohttp_pins.items()
if pin != lazy_aiohttp
}
assert not mismatches, (
"pyproject.toml aiohttp pins must match "
"LAZY_DEPS['platform.slack'] to avoid hermes update downgrading "
"aiohttp before Slack's lazy refresh upgrades it again. "
f"lazy aiohttp=={lazy_aiohttp}; mismatched extras: {mismatches}"
)
def test_pyproject_pins_match_lazy_deps_pins():
"""Generalize #31817 to the whole pin surface, not just aiohttp.
Any package that is exact-pinned in BOTH a pyproject extra and a
`tools/lazy_deps.py` LAZY_DEPS entry must use the SAME version in both
places. When they drift, `hermes update` resolves the pyproject extra
pin and downgrades the package to the older version, reopening whatever
the lazy pin fixed (the aiohttp #31817 case, and the anthropic
CVE-2026-34450/34452 case found alongside it) — only for the lazy
refresh to re-upgrade it on next feature use. The lazy pin is the
security-current source of truth; extras must track it.
"""
from tools.lazy_deps import LAZY_DEPS
optional_dependencies = _load_optional_dependencies()
# package -> version, as pinned across all pyproject extras. If an
# extra pins a package at a different version than another extra, that
# is itself a bug (caught below); here we just collect the set.
pyproject_pins: dict[str, set[str]] = {}
for specs in optional_dependencies.values():
for package, version in _exact_pins(specs).items():
pyproject_pins.setdefault(package, set()).add(version)
# package -> version, as pinned across all LAZY_DEPS entries.
lazy_pins: dict[str, set[str]] = {}
for specs in LAZY_DEPS.values():
if isinstance(specs, str):
specs = (specs,)
for package, version in _exact_pins(specs).items():
lazy_pins.setdefault(package, set()).add(version)
shared = sorted(set(pyproject_pins) & set(lazy_pins))
assert shared, "expected at least one package pinned in both pyproject and LAZY_DEPS"
drift = {
package: {
"pyproject": sorted(pyproject_pins[package]),
"lazy_deps": sorted(lazy_pins[package]),
}
for package in shared
if pyproject_pins[package] != lazy_pins[package]
}
assert not drift, (
"pyproject extras pins must match tools/lazy_deps.py LAZY_DEPS pins "
"for every shared package — otherwise `hermes update` downgrades the "
"package below the security-current lazy pin (see #31817). Drift: "
f"{drift}"
)
def test_dev_extra_excluded_from_all():
"""End-user installs should not pull test/lint/debug tooling."""
optional_dependencies = _load_optional_dependencies()