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
+11 -18
View File
@@ -1,9 +1,9 @@
"""Regression coverage for #35344: a resumed session must not let a stale
historical task snapshot from an inherited compaction handoff hijack the reply to a
``## Active Task`` from an inherited compaction handoff hijack the reply to a
new, unrelated user message.
The failure mode (real report): a lineage was compacted, producing a handoff
whose historical task snapshot described task A. The lineage was resumed later and
whose ``## Active Task`` described task A. The lineage was resumed later and
the user asked about an unrelated task B. The model answered with A because
the handoff's resume directive outranked the fresh ask.
@@ -16,15 +16,14 @@ named reverse-signal verbs. Two invariants guard the resume path specifically:
pre-fix stale handoff cannot keep its "resume exactly" directive forever.
2. The current handoff prefix contains an unambiguous "latest message wins /
discard stale historical task" rule, so an unrelated new ask is privileged over
the inherited task snapshot.
discard stale Active Task" rule, so an unrelated new ask is privileged over
the inherited ``## Active Task``.
These are content/structural assertions (no live model call) — they pin the
mechanism that makes the stale task historical rather than active.
"""
from agent.context_compressor import (
HISTORICAL_TASK_HEADING,
SUMMARY_PREFIX,
LEGACY_SUMMARY_PREFIX,
ContextCompressor,
@@ -49,17 +48,13 @@ _OLD_CONFLICTING_PREFIX = (
def test_latest_message_wins_over_inherited_active_task():
"""The handoff must explicitly privilege the latest user message over a
stale historical task snapshot — the core #35344 contract."""
stale ``## Active Task`` — the core #35344 contract."""
lower = SUMMARY_PREFIX.lower()
assert "latest user message" in lower
assert HISTORICAL_TASK_HEADING.lower() in lower
assert "## active task" in lower
# Conflict-resolution must be explicit, not implied.
assert "wins" in lower or "supersede" in lower
assert "discard" in lower
# The "consistent -> use as background" carveout licensed stale-task
# resumption on topic overlap (#41607, #38364) — it must stay gone.
assert "you may use the summary as background" not in lower
assert "topic overlap" in lower
def test_no_resume_exactly_directive_can_hijack():
@@ -74,7 +69,7 @@ def test_resumed_stale_handoff_gets_renormalized_to_current_prefix():
prefix when re-normalized on re-compaction — so the "resume exactly"
directive cannot survive into a resumed session."""
stale_body = (
f"{HISTORICAL_TASK_HEADING}\n"
"## Active Task\n"
"User asked: 'Migrate the billing module to Stripe'\n\n"
"## Goal\nMigrate billing.\n"
)
@@ -91,15 +86,13 @@ def test_resumed_stale_handoff_gets_renormalized_to_current_prefix():
# current latest-message-wins framing.
assert "resume exactly" not in renormalized.lower()
assert renormalized.startswith(SUMMARY_PREFIX)
assert ("wins" in renormalized.lower()
or "priority" in renormalized.lower()
or "supersede" in renormalized.lower())
assert "wins" in renormalized.lower()
def test_legacy_prefix_handoff_also_renormalized():
"""The same upgrade applies to the oldest ``[CONTEXT SUMMARY]:`` handoff
format that may sit in a long-lived resumed lineage."""
legacy = f"{LEGACY_SUMMARY_PREFIX} {HISTORICAL_TASK_HEADING}\nUser asked: 'task A'"
legacy = f"{LEGACY_SUMMARY_PREFIX} ## Active Task\nUser asked: 'task A'"
renormalized = ContextCompressor._with_summary_prefix(legacy)
assert renormalized.startswith(SUMMARY_PREFIX)
assert LEGACY_SUMMARY_PREFIX not in renormalized
@@ -114,7 +107,7 @@ def test_inherited_handoff_detected_in_resumed_protected_head():
Task read as live intent)."""
messages = [
{"role": "system", "content": "system prompt"},
{"role": "user", "content": f"{SUMMARY_PREFIX}\n{HISTORICAL_TASK_HEADING}\nUser asked: 'task A'"},
{"role": "user", "content": f"{SUMMARY_PREFIX}\n## Active Task\nUser asked: 'task A'"},
{"role": "assistant", "content": "ok"},
{"role": "user", "content": "Unrelated task B: what's the capital of France?"},
]
@@ -136,7 +129,7 @@ def test_historical_prefixed_handoff_detected_and_stripped():
stale 'resume exactly' text as a fresh turn."""
messages = [
{"role": "system", "content": "system prompt"},
{"role": "user", "content": f"{_OLD_CONFLICTING_PREFIX}\n{HISTORICAL_TASK_HEADING}\nUser asked: 'task A'"},
{"role": "user", "content": f"{_OLD_CONFLICTING_PREFIX}\n## Active Task\nUser asked: 'task A'"},
{"role": "assistant", "content": "ok"},
{"role": "user", "content": "Unrelated task B"},
]