@cplieger/web-terminal-engine 3.5.0 → 3.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/types.ts CHANGED
@@ -108,6 +108,18 @@ export interface ResumeAckMessage {
108
108
  * shows a "history trimmed" marker rather than misaligning.
109
109
  */
110
110
  oldestIndex?: number;
111
+ /**
112
+ * The server DECLARES that it serves demand-paged scrollback (`history`
113
+ * controls) and that its ring is deep enough to back the client shrinking its
114
+ * resident tail. Absent on any server too old to carry the ack's third
115
+ * length-gated tail, which reads the same as false: no paging.
116
+ *
117
+ * Capability is declared here rather than probed with a request because this
118
+ * ack is the first frame of every resume batch — the client knows one RTT
119
+ * after attach, with nothing sent and no way to mistake a slow link for an
120
+ * old server.
121
+ */
122
+ historyPaging?: boolean;
111
123
  /**
112
124
  * The server's wire-protocol revision (third length-gated tail, absent on
113
125
  * older servers). A value OUTSIDE the client's supported range means one
@@ -229,7 +241,23 @@ export type ControlMessage =
229
241
  sentBytes: number;
230
242
  haveThrough: number;
231
243
  protocolVersion: number;
244
+ /**
245
+ * Bound the replay to the newest N missing lines. Optional: omitted means
246
+ * "no bound", which is every pre-paging client's behavior and what an
247
+ * old server does regardless. Honored only by a server that declares
248
+ * paging, and clamped by BOTH sides to the same constant so the value
249
+ * sent equals the value honored (docs/paged-scrollback.md §4.5).
250
+ */
251
+ replayMax?: number;
232
252
  }
253
+ /**
254
+ * Request a page of retained scrollback: at most `maxLines` lines starting at
255
+ * absolute index `fromAbs`. The reply is an ordinary scroll frame, made
256
+ * correlatable by falling inside the requested window rather than by a request
257
+ * id — within a boot epoch an absolute index is immutable, so a frame that
258
+ * satisfies the window carries the same bytes the awaited reply would have.
259
+ */
260
+ | { type: "history"; fromAbs: number; maxLines: number }
233
261
  | { type: "ping" }
234
262
  /**
235
263
  * v4 typed-framing transition (see WIRE_PROTOCOL_VERSION in
@@ -143,12 +143,16 @@ function decodeWireBinaryInner(buf: ArrayBuffer): ServerMessage | null {
143
143
  // Optional tails, length-gated for back-compat with older servers:
144
144
  // >= 17 bytes: + serverEpoch (restart detection)
145
145
  // >= 33 bytes: + committed + oldestIndex (resume gap detection)
146
- // >= 35 bytes: + serverWireVersion + ackFlags (bit0 = ledgerLost)
146
+ // >= 35 bytes: + serverWireVersion + ackFlags (bit0 = ledgerLost,
147
+ // bit1 = historyPaging). Unknown bits are IGNORED, which
148
+ // is what lets the server add capabilities here without a
149
+ // protocol bump.
147
150
  let serverEpoch: number | undefined;
148
151
  let committed: number | undefined;
149
152
  let oldestIndex: number | undefined;
150
153
  let serverWireVersion: number | undefined;
151
154
  let ledgerLost: boolean | undefined;
155
+ let historyPaging: boolean | undefined;
152
156
  if (buf.byteLength >= 17) {
153
157
  serverEpoch = c.u64();
154
158
  }
@@ -160,6 +164,7 @@ function decodeWireBinaryInner(buf: ArrayBuffer): ServerMessage | null {
160
164
  serverWireVersion = c.u8();
161
165
  const ackFlags = c.u8();
162
166
  ledgerLost = (ackFlags & 1) !== 0;
167
+ historyPaging = (ackFlags & 2) !== 0;
163
168
  }
164
169
  const msg: ResumeAckMessage = { type: "resumeAck", received: inputAck };
165
170
  if (serverEpoch !== undefined) {
@@ -177,6 +182,9 @@ function decodeWireBinaryInner(buf: ArrayBuffer): ServerMessage | null {
177
182
  if (ledgerLost !== undefined) {
178
183
  msg.ledgerLost = ledgerLost;
179
184
  }
185
+ if (historyPaging !== undefined) {
186
+ msg.historyPaging = historyPaging;
187
+ }
180
188
  return msg;
181
189
  }
182
190
  if (msgType === MSG_ACK_ONLY) {