feat(tui): print resume command on exit

This commit is contained in:
chengyongru
2026-08-20 17:20:36 +08:00
committed by chengyongru
parent 997bdfc79d
commit 415df576b4
8 changed files with 57 additions and 9 deletions
+8 -1
View File
@@ -13,6 +13,7 @@ from typing import Any
ROOT = Path(__file__).resolve().parents[1]
ENTER_ALT_SCREEN = "\x1b[?1049h"
LEAVE_ALT_SCREEN = "\x1b[?1049l"
RESUME_COMMAND = "Resume with: nanobot agent --session websocket:resume-chat"
def _read(process: Any, timeout: float) -> str:
@@ -71,6 +72,7 @@ def main() -> int:
"NANOBOT_TUI_WS_URL": "ws://127.0.0.1:9/ws",
"NANOBOT_TUI_API_URL": "",
"NANOBOT_TUI_API_TOKEN": "",
"NANOBOT_TUI_CHAT_ID": "resume-chat",
"NANOBOT_TUI_MODEL": "test/model",
"NANOBOT_TUI_WORKSPACE": r"C:\nanobot-tui-conpty",
"NANOBOT_TUI_VERSION": "test",
@@ -111,6 +113,7 @@ def main() -> int:
process.write("exit\r")
output.append(_wait_for(process, LEAVE_ALT_SCREEN, 8))
exit_code = _wait_for_exit(process, 8)
output.append(_read(process, 0.5))
finally:
if process.isalive():
process.close(force=True)
@@ -123,7 +126,11 @@ def main() -> int:
raise AssertionError(f"TUI did not render committed input {glyph!r}")
if "Traceback" in text or "Task exception was never retrieved" in text:
raise AssertionError("TUI emitted an exception during shutdown")
print("ConPTY smoke test passed: Unicode input, resize, and terminal restoration")
if text.count(RESUME_COMMAND) != 1:
raise AssertionError("TUI did not print exactly one reusable session command")
if text.index(RESUME_COMMAND) < text.index(LEAVE_ALT_SCREEN):
raise AssertionError("TUI printed the session command before restoring the terminal")
print("ConPTY smoke test passed: Unicode input, resize, restoration, and session resume")
return 0
+8 -1
View File
@@ -24,6 +24,7 @@ from pathlib import Path
ROOT = Path(__file__).resolve().parents[1]
ENTER_ALT_SCREEN = b"\x1b[?1049h"
LEAVE_ALT_SCREEN = b"\x1b[?1049l"
RESUME_COMMAND = b"Resume with: nanobot agent --session websocket:resume-chat"
def _resize(fd: int, rows: int, columns: int) -> None:
@@ -82,6 +83,7 @@ def main() -> int:
"NANOBOT_TUI_WS_URL": "ws://127.0.0.1:9/ws",
"NANOBOT_TUI_API_URL": "",
"NANOBOT_TUI_API_TOKEN": "",
"NANOBOT_TUI_CHAT_ID": "resume-chat",
"NANOBOT_TUI_MODEL": "test/model",
"NANOBOT_TUI_WORKSPACE": "/tmp/nanobot-tui-pty",
"NANOBOT_TUI_VERSION": "test",
@@ -126,6 +128,7 @@ def main() -> int:
os.write(master, b"exit\r")
output.extend(_wait_for(master, LEAVE_ALT_SCREEN, 5))
exit_code = _wait_for_exit(pid, 5)
output.extend(_read(master, 0.5))
reaped = True
finally:
if not reaped:
@@ -146,6 +149,10 @@ def main() -> int:
raise AssertionError(f"TUI did not render committed input {glyph!r}")
if "Traceback" in text or "Task exception was never retrieved" in text:
raise AssertionError("TUI emitted an exception during shutdown")
if output.count(RESUME_COMMAND) != 1:
raise AssertionError("TUI did not print exactly one reusable session command")
if output.index(RESUME_COMMAND) < output.index(LEAVE_ALT_SCREEN):
raise AssertionError("TUI printed the session command before restoring the terminal")
# The UI must inherit the host terminal background. Fixed RGB/indexed
# surfaces become black strips in embedded terminals after long output.
for escape in (
@@ -156,7 +163,7 @@ def main() -> int:
):
if escape in output:
raise AssertionError(f"TUI painted a fixed background: {escape!r}")
print("PTY smoke test passed: Unicode input, resize, and terminal restoration")
print("PTY smoke test passed: Unicode input, resize, restoration, and session resume")
return 0