atlas-iac/dockerfiles/patch-hermes-terminal-replay.py

84 lines
3.4 KiB
Python
Raw Normal View History

"""Restore dashboard terminal modes and visible history on PTY reattachment."""
from __future__ import annotations
import argparse
from pathlib import Path
def patch_sources(root: Path) -> None:
"""Patch the pinned upstream sources, rejecting drift before writing files."""
patches = {
"hermes_cli/pty_bridge.py": (
(
" self._closed = False\n",
" self._closed = False\n"
" self._dashboard_redraw_on_attach = False\n",
),
(
" return cls(proc)\n",
" bridge = cls(proc)\n"
" bridge._dashboard_redraw_on_attach = (\n"
" spawn_env.get(\"HERMES_TUI_DASHBOARD\") == \"1\"\n"
" and spawn_env.get(\"HERMES_TUI_INLINE\") == \"0\"\n"
" )\n"
" return bridge\n",
),
(
" # -- I/O --------------------------------------------------------------\n",
''' def redraw_after_attach(self) -> None:
"""Ask an opted-in dashboard TUI to restore its screen without input."""
if not self._dashboard_redraw_on_attach or not self.is_alive():
return
try:
# Ink's SIGCONT handler restores alternate-screen/mouse modes and
# paints the current viewport, even after replay bytes were evicted.
os.kill(self.pid, signal.SIGCONT)
except OSError:
# The child may exit between the liveness check and the signal.
pass
# -- I/O --------------------------------------------------------------
''',
),
),
"hermes_cli/pty_session.py": (
(
" self.attached = False\n"
" self.last_detached_at: Optional[float] = None\n",
" self.attached = False\n"
" self._has_attached = False\n"
" self.last_detached_at: Optional[float] = None\n",
),
(
" if snap:\n await ws.send_bytes(snap)\n",
" if snap:\n await ws.send_bytes(snap)\n"
" # A byte-bounded replay is not a complete terminal snapshot.\n"
" # Restore modes and repaint only a reused dashboard TUI.\n"
" if self._has_attached:\n"
" redraw = getattr(self.bridge, \"redraw_after_attach\", None)\n"
" if redraw is not None:\n"
" redraw()\n"
" self._has_attached = True\n",
),
),
}
prepared = {}
for relative, replacements in patches.items():
path = root / relative
source = path.read_text()
for before, after in replacements:
if source.count(before) != 1:
raise ValueError(f"Hermes terminal replay patch context changed: {relative}")
source = source.replace(before, after, 1)
compile(source, str(path), "exec")
prepared[path] = source
for path, source in prepared.items():
path.write_text(source)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--root", type=Path, default=Path("/opt/hermes"))
patch_sources(parser.parse_args().root)