Initial CLI source import
This commit is contained in:
@@ -0,0 +1,97 @@
|
||||
"""Terminal protocol constants and small frame helpers.
|
||||
|
||||
The relay adapter will encrypt these payloads before sending them over the
|
||||
gateway relay. Keep this module content-only: no terminal output logging and no
|
||||
network side effects.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any
|
||||
|
||||
TERMINAL_OPEN = "terminal.open"
|
||||
TERMINAL_OPENED = "terminal.opened"
|
||||
TERMINAL_DATA = "terminal.data"
|
||||
TERMINAL_OUTPUT = "terminal.output"
|
||||
TERMINAL_RESIZE = "terminal.resize"
|
||||
TERMINAL_DETACH = "terminal.detach"
|
||||
TERMINAL_CLOSE = "terminal.close"
|
||||
TERMINAL_REPLAY_GAP = "terminal.replay_gap"
|
||||
TERMINAL_ERROR = "terminal.error"
|
||||
|
||||
|
||||
def utc_timestamp() -> str:
|
||||
return datetime.now(timezone.utc).isoformat()
|
||||
|
||||
|
||||
def encode_bytes(data: bytes) -> str:
|
||||
return base64.b64encode(data).decode("ascii")
|
||||
|
||||
|
||||
def decode_bytes(value: str) -> bytes:
|
||||
return base64.b64decode(value.encode("ascii"), validate=True)
|
||||
|
||||
|
||||
def output_frame(terminal_id: str, seq: int, data: bytes) -> dict[str, Any]:
|
||||
return {
|
||||
"type": TERMINAL_OUTPUT,
|
||||
"terminal_id": terminal_id,
|
||||
"seq": seq,
|
||||
"data_b64": encode_bytes(data),
|
||||
"gateway_output_sent_at": utc_timestamp(),
|
||||
}
|
||||
|
||||
|
||||
def opened_frame(
|
||||
terminal_id: str,
|
||||
*,
|
||||
rows: int,
|
||||
cols: int,
|
||||
output_seq: int = 0,
|
||||
attached: bool = True,
|
||||
pid: int | None = None,
|
||||
) -> dict[str, Any]:
|
||||
frame: dict[str, Any] = {
|
||||
"type": TERMINAL_OPENED,
|
||||
"terminal_id": terminal_id,
|
||||
"rows": rows,
|
||||
"cols": cols,
|
||||
"output_seq": output_seq,
|
||||
"attached": attached,
|
||||
}
|
||||
if pid is not None:
|
||||
frame["pid"] = pid
|
||||
return frame
|
||||
|
||||
|
||||
def replay_gap_frame(
|
||||
terminal_id: str,
|
||||
*,
|
||||
requested_after_seq: int | None,
|
||||
oldest_seq: int | None,
|
||||
newest_seq: int,
|
||||
) -> dict[str, Any]:
|
||||
return {
|
||||
"type": TERMINAL_REPLAY_GAP,
|
||||
"terminal_id": terminal_id,
|
||||
"requested_after_seq": requested_after_seq,
|
||||
"oldest_seq": oldest_seq,
|
||||
"newest_seq": newest_seq,
|
||||
}
|
||||
|
||||
|
||||
def error_frame(
|
||||
terminal_id: str | None,
|
||||
code: str,
|
||||
message: str,
|
||||
) -> dict[str, Any]:
|
||||
frame: dict[str, Any] = {
|
||||
"type": TERMINAL_ERROR,
|
||||
"code": code,
|
||||
"message": message,
|
||||
}
|
||||
if terminal_id:
|
||||
frame["terminal_id"] = terminal_id
|
||||
return frame
|
||||
Reference in New Issue
Block a user