Module: Terminalwire::V2::Frames
- Defined in:
- lib/terminalwire/v2/frames.rb
Overview
Builders for each frame type. Keep frame construction in one place so the wire shape is defined once. All builders return a Hash with string keys.
Constant Summary collapse
- DEFAULT_FLOW =
The client's initial flow-control offer: how many bytes of output it will accept per stream before the server must wait for a window_adjust.
{ "window" => Protocol::DEFAULT_WINDOW }.freeze
- DEFAULT_TERMINAL =
The client's terminal at connect time (structured per TERMINAL.md: per-stream kinds + a device block); resize/mode frames update the device thereafter.
{ "stdin" => { "kind" => "tty" }, "stdout" => { "kind" => "tty" }, "stderr" => { "kind" => "tty" }, "device" => { "cols" => 80, "rows" => 24, "xpixels" => 0, "ypixels" => 0, "term" => "", "color" => "none", "encoding" => "UTF-8", "mode" => "cooked" } }.freeze
Class Method Summary collapse
- .close(sid:) ⇒ Object
- .data(sid:, bytes:) ⇒ Object
- .exit(status:) ⇒ Object
- .hello(protocol:, capabilities:, program:, entitlement:, terminal: DEFAULT_TERMINAL, flow: DEFAULT_FLOW) ⇒ Object
- .incompatible(supported:, message:) ⇒ Object
- .interrupt ⇒ Object
- .open(sid:, stream:, mode: nil) ⇒ Object
- .request(sid:, resource:, method:, params: {}) ⇒ Object
- .resize(cols:, rows:) ⇒ Object
- .response_error(sid:, code:, message:) ⇒ Object
- .response_ok(sid:, value:) ⇒ Object
-
.signal(name, payload = {}) ⇒ Object
Generic async terminal signal (client -> server).
- .welcome(protocol:, capabilities:) ⇒ Object
-
.window_adjust(sid:, bytes:) ⇒ Object
Client -> server: extend the output window for a stream by
bytes.
Class Method Details
.close(sid:) ⇒ Object
85 86 87 |
# File 'lib/terminalwire/v2/frames.rb', line 85 def close(sid:) { "t" => Protocol::Type::CLOSE, "sid" => sid } end |
.data(sid:, bytes:) ⇒ Object
81 82 83 |
# File 'lib/terminalwire/v2/frames.rb', line 81 def data(sid:, bytes:) { "t" => Protocol::Type::DATA, "sid" => sid, "bytes" => bytes.b } end |
.exit(status:) ⇒ Object
71 72 73 |
# File 'lib/terminalwire/v2/frames.rb', line 71 def exit(status:) { "t" => Protocol::Type::EXIT, "sid" => Protocol::CONTROL_SID, "status" => status } end |
.hello(protocol:, capabilities:, program:, entitlement:, terminal: DEFAULT_TERMINAL, flow: DEFAULT_FLOW) ⇒ Object
9 10 11 12 13 14 15 16 |
# File 'lib/terminalwire/v2/frames.rb', line 9 def hello(protocol:, capabilities:, program:, entitlement:, terminal: DEFAULT_TERMINAL, flow: DEFAULT_FLOW) { "t" => Protocol::Type::HELLO, "sid" => Protocol::CONTROL_SID, "protocol" => protocol, "capabilities" => capabilities, "program" => program, "entitlement" => entitlement, "terminal" => terminal, "flow" => flow } end |
.incompatible(supported:, message:) ⇒ Object
60 61 62 63 64 65 66 67 68 69 |
# File 'lib/terminalwire/v2/frames.rb', line 60 def incompatible(supported:, message:) # Normalize to string keys so every wire frame is uniformly string-keyed # (the negotiator hands us a symbol-keyed Ruby hash). min = supported[:min] || supported["min"] max = supported[:max] || supported["max"] { "t" => Protocol::Type::INCOMPATIBLE, "sid" => Protocol::CONTROL_SID, "supported" => { "min" => min, "max" => max }, "message" => } end |
.interrupt ⇒ Object
49 50 51 |
# File 'lib/terminalwire/v2/frames.rb', line 49 def interrupt signal(Protocol::Signal::INTERRUPT) end |
.open(sid:, stream:, mode: nil) ⇒ Object
75 76 77 78 79 |
# File 'lib/terminalwire/v2/frames.rb', line 75 def open(sid:, stream:, mode: nil) frame = { "t" => Protocol::Type::OPEN, "sid" => sid, "stream" => stream } frame["mode"] = mode if mode # input streams carry the line-discipline mode frame end |
.request(sid:, resource:, method:, params: {}) ⇒ Object
89 90 91 92 93 94 |
# File 'lib/terminalwire/v2/frames.rb', line 89 def request(sid:, resource:, method:, params: {}) { "t" => Protocol::Type::REQUEST, "sid" => sid, "resource" => resource, "method" => method, "params" => params } end |
.resize(cols:, rows:) ⇒ Object
45 46 47 |
# File 'lib/terminalwire/v2/frames.rb', line 45 def resize(cols:, rows:) signal(Protocol::Signal::RESIZE, { "cols" => cols, "rows" => rows }) end |
.response_error(sid:, code:, message:) ⇒ Object
100 101 102 103 104 105 |
# File 'lib/terminalwire/v2/frames.rb', line 100 def response_error(sid:, code:, message:) { "t" => Protocol::Type::RESPONSE, "sid" => sid, "ok" => false, "error" => { "code" => code, "message" => } } end |
.response_ok(sid:, value:) ⇒ Object
96 97 98 |
# File 'lib/terminalwire/v2/frames.rb', line 96 def response_ok(sid:, value:) { "t" => Protocol::Type::RESPONSE, "sid" => sid, "ok" => true, "value" => value } end |
.signal(name, payload = {}) ⇒ Object
Generic async terminal signal (client -> server). resize/interrupt are the named variants; collapsing them into one frame type keeps the protocol small.
41 42 43 |
# File 'lib/terminalwire/v2/frames.rb', line 41 def signal(name, payload = {}) { "t" => Protocol::Type::SIGNAL, "sid" => Protocol::CONTROL_SID, "name" => name }.merge(payload) end |
.welcome(protocol:, capabilities:) ⇒ Object
53 54 55 56 57 58 |
# File 'lib/terminalwire/v2/frames.rb', line 53 def welcome(protocol:, capabilities:) { "t" => Protocol::Type::WELCOME, "sid" => Protocol::CONTROL_SID, "protocol" => protocol, "capabilities" => capabilities } end |
.window_adjust(sid:, bytes:) ⇒ Object
Client -> server: extend the output window for a stream by bytes.
23 24 25 |
# File 'lib/terminalwire/v2/frames.rb', line 23 def window_adjust(sid:, bytes:) { "t" => Protocol::Type::WINDOW_ADJUST, "sid" => sid, "bytes" => bytes } end |