mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-29 06:31:32 +00:00
Tasks 0.2-0.6 of the s6-overlay supervision plan. Locks the user-visible behavior we must preserve through the Phase 2 init- system swap: - test_main_invocation.py (Task 0.2): docker run <image> with no args, chat subcommand passthrough, bare executable passthrough, bash pattern, exit-code propagation - test_tui_passthrough.py (Task 0.3): TTY allocation via docker -t using the host's script(1) for a PTY - test_dashboard.py (Task 0.4): HERMES_DASHBOARD=1 opt-in, HERMES_DASHBOARD_PORT override - test_profile_gateway.py (Task 0.5): per-profile gateway start/stop and profile-delete-stops-gateway. Both marked xfail(strict=True) because the current tini image refuses gateway lifecycle commands inside the container; Phase 4 Task 4.3 flips them to passing. - test_zombie_reaping.py (Task 0.6): PID 1 reaps orphaned zombies. tini does this today; s6-overlay's /init must continue to. Refs: docs/plans/2026-05-07-s6-overlay-dynamic-subagent-gateways.md
51 lines
1.7 KiB
Python
51 lines
1.7 KiB
Python
"""Harness: interactive TUI TTY passthrough.
|
|
|
|
Uses ``script -qc`` on the host to allocate a PTY for the docker client,
|
|
which then allocates a container-side PTY via ``-t``. The probe inside
|
|
the container is ``tput cols``, which returns a real column count when
|
|
stdout is a TTY and either prints ``80`` (the terminfo fallback) or
|
|
nothing when it is not.
|
|
|
|
These tests MUST pass on the current tini-based image AND continue to
|
|
pass after the Phase 2 s6 migration. Any drift is a regression.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import shlex
|
|
import shutil
|
|
import subprocess
|
|
|
|
import pytest
|
|
|
|
pytestmark = pytest.mark.skipif(
|
|
shutil.which("script") is None,
|
|
reason="`script` command not available on this host",
|
|
)
|
|
|
|
|
|
def test_tty_passthrough_to_container(built_image: str) -> None:
|
|
"""``docker run -t`` must deliver a real TTY to the container process."""
|
|
probe = "if [ -t 1 ]; then tput cols; else echo NO_TTY; fi"
|
|
cmd = (
|
|
f"docker run --rm -t -e COLUMNS=123 {built_image} "
|
|
f"sh -c {shlex.quote(probe)}"
|
|
)
|
|
r = subprocess.run(
|
|
["script", "-qc", cmd, "/dev/null"],
|
|
capture_output=True, text=True, timeout=120,
|
|
)
|
|
output = r.stdout.strip()
|
|
assert "NO_TTY" not in output, f"TTY passthrough failed: {output!r}"
|
|
numeric_lines = [s for s in output.split() if s.strip().isdigit()]
|
|
assert numeric_lines, f"No numeric width in output: {output!r}"
|
|
assert int(numeric_lines[0]) > 0
|
|
|
|
|
|
def test_tui_flag_recognized(built_image: str) -> None:
|
|
"""``docker run -it <image> --help`` should run without crashing."""
|
|
cmd = f"docker run --rm -t {built_image} --help"
|
|
r = subprocess.run(
|
|
["script", "-qc", cmd, "/dev/null"],
|
|
capture_output=True, text=True, timeout=60,
|
|
)
|
|
assert r.returncode == 0
|