mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-22 16:25:58 +00:00
Add the flag-gated compute-host supervisor, delta/control protocol, PPID orphan guard, inline fail-open path, synthetic GIL-heavy turn seam, and AC-4 certify harness. Verified on current origin/main: 343 focused tests pass; Ruff and diff checks pass; 360s AC-4 run with six heavy lanes passes at 6.11ms serving p99 with zero stalls and valid load. Co-authored-by: Kyzcreig <9063726+Kyzcreig@users.noreply.github.com>
85 lines
2.5 KiB
Python
85 lines
2.5 KiB
Python
import json
|
|
import os
|
|
import queue
|
|
import subprocess
|
|
import sys
|
|
import threading
|
|
from pathlib import Path
|
|
|
|
|
|
def _stdout_queue(proc: subprocess.Popen) -> queue.Queue[dict]:
|
|
out: queue.Queue[dict] = queue.Queue()
|
|
assert proc.stdout is not None
|
|
|
|
def drain() -> None:
|
|
for line in proc.stdout or []:
|
|
out.put(json.loads(line))
|
|
|
|
threading.Thread(target=drain, daemon=True).start()
|
|
return out
|
|
|
|
|
|
def _read_json_line(out: queue.Queue[dict], timeout: float = 2.0) -> dict:
|
|
try:
|
|
return out.get(timeout=timeout)
|
|
except queue.Empty as exc:
|
|
raise AssertionError("timed out waiting for compute host JSON") from exc
|
|
|
|
|
|
def test_compute_host_line_json_seed_turn_interrupt():
|
|
repo = Path(__file__).resolve().parents[2]
|
|
env = dict(os.environ)
|
|
env["PYTHONPATH"] = str(repo) + os.pathsep + env.get("PYTHONPATH", "")
|
|
proc = subprocess.Popen(
|
|
[sys.executable, "-m", "tui_gateway.compute_host"],
|
|
cwd=str(repo),
|
|
env=env,
|
|
stdin=subprocess.PIPE,
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE,
|
|
text=True,
|
|
bufsize=1,
|
|
)
|
|
assert proc.stdin is not None
|
|
out = _stdout_queue(proc)
|
|
try:
|
|
hello = _read_json_line(out)
|
|
assert hello["type"] == "hello"
|
|
assert hello["host_pid"] == proc.pid
|
|
|
|
proc.stdin.write(json.dumps({"type": "session.seed", "sid": "s1", "request_id": "seed"}) + "\n")
|
|
proc.stdin.flush()
|
|
assert _read_json_line(out)["type"] == "session.seeded"
|
|
|
|
proc.stdin.write(
|
|
json.dumps(
|
|
{
|
|
"type": "turn.start",
|
|
"sid": "s1",
|
|
"request_id": "turn",
|
|
"prompt": "hello",
|
|
"delta_count": 3,
|
|
"delay_s": 0,
|
|
}
|
|
)
|
|
+ "\n"
|
|
)
|
|
proc.stdin.flush()
|
|
|
|
seen = []
|
|
while True:
|
|
frame = _read_json_line(out)
|
|
seen.append(frame["type"])
|
|
if frame["type"] == "turn.end":
|
|
assert frame["history_version"] == 1
|
|
assert frame["message_count"] == 2
|
|
break
|
|
assert seen.count("delta") == 3
|
|
|
|
proc.stdin.write(json.dumps({"type": "shutdown", "request_id": "stop"}) + "\n")
|
|
proc.stdin.flush()
|
|
assert _read_json_line(out)["type"] == "shutdown.ack"
|
|
proc.wait(timeout=2)
|
|
finally:
|
|
if proc.poll() is None:
|
|
proc.kill()
|