agent-relay 10.1.0 → 10.2.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.
@@ -14,19 +14,24 @@ import { resolveBrokerConnection, } from './broker-connection.js';
14
14
  import { createBrokerClient, mapBrokerSdkFailure } from './attach-broker.js';
15
15
  /**
16
16
  * Fetch a worker's current visible screen as ANSI reproduction bytes and
17
- * write them to the caller's output. Callers should invoke this BEFORE
18
- * subscribing to the WebSocket event stream so the user sees the agent's
19
- * current state before live deltas start arriving.
17
+ * write them to the caller's output.
20
18
  *
21
- * There is a tiny window between the snapshot capture and the live stream
22
- * starting in which the agent's output could be missed (≤10ms in practice).
23
- * Most TUI agents repaint heavily so the next update overwrites anything
24
- * lost; subscribe-first + buffer + drain would close the gap at the cost
25
- * of risking double-application of bytes that arrive in both the snapshot
26
- * and the buffered stream, which is the worse failure mode for TUIs.
19
+ * The attach clients open and subscribe to the WebSocket event stream
20
+ * *first*, buffer incoming `worker_stream` chunks, then call this to paint
21
+ * the snapshot, and finally reconcile the buffer against the snapshot's
22
+ * `offset` (see {@link StreamSyncBuffer}). That ordering closes the gap
23
+ * between the snapshot and the live stream: no output emitted around attach
24
+ * time is lost, and the per-worker byte offset lets the client drop exactly
25
+ * the chunks the snapshot already reflects so nothing is double-applied.
26
+ *
27
+ * On brokers that don't report an `offset`, the clients fall back to
28
+ * snapshot-authoritative behaviour (paint the snapshot, discard chunks that
29
+ * arrived before it), which trades a tiny gap for no duplication — the same
30
+ * bias the pre-offset code had.
27
31
  *
28
32
  * @returns A status describing the outcome. `ok` means the screen was
29
- * rendered; other variants carry a message the caller can surface.
33
+ * rendered; other variants carry a message the caller can surface. `offset`
34
+ * is populated on `ok` when the broker reports one.
30
35
  */
31
36
  export async function captureAndRenderSnapshot(connection, agentName, deps) {
32
37
  let body;
@@ -64,6 +69,7 @@ export async function captureAndRenderSnapshot(connection, agentName, deps) {
64
69
  deps.writeChunk(decoded);
65
70
  const rows = typeof obj.rows === 'number' ? obj.rows : undefined;
66
71
  const cols = typeof obj.cols === 'number' ? obj.cols : undefined;
72
+ const offset = typeof obj.offset === 'number' ? obj.offset : undefined;
67
73
  const cursorRaw = Array.isArray(obj.cursor) ? obj.cursor : undefined;
68
74
  const cursor = cursorRaw &&
69
75
  cursorRaw.length === 2 &&
@@ -71,7 +77,171 @@ export async function captureAndRenderSnapshot(connection, agentName, deps) {
71
77
  typeof cursorRaw[1] === 'number'
72
78
  ? [cursorRaw[0], cursorRaw[1]]
73
79
  : undefined;
74
- return { status: 'ok', rows, cols, cursor };
80
+ return { status: 'ok', rows, cols, cursor, offset };
81
+ }
82
+ /**
83
+ * Reconciles a visible-screen snapshot with the live `worker_stream` byte
84
+ * stream so an attaching client neither loses nor double-applies output
85
+ * around attach time.
86
+ *
87
+ * Usage (subscribe-first):
88
+ *
89
+ * 1. Open + subscribe the event WS. Feed every `worker_stream` chunk to
90
+ * {@link push} as it arrives, applying the chunk only when `push`
91
+ * returns `true`.
92
+ * 2. Fetch and paint the snapshot.
93
+ * 3. Call {@link reconcile} with the snapshot's `offset`. Apply the
94
+ * returned chunks in order. From then on, `push` returns `true` for
95
+ * every chunk (live pass-through).
96
+ *
97
+ * Correlation rule: the snapshot reflects every byte with offset `<=`
98
+ * `snapshotOffset`. A buffered chunk carries the cumulative byte offset at
99
+ * its *end*; if that end offset is `<=` the snapshot offset the chunk is
100
+ * already on screen and is dropped, otherwise it is applied.
101
+ *
102
+ * The snapshot offset is retained as a post-reconcile *watermark*: once
103
+ * buffering ends, {@link push} keeps suppressing any live frame whose end
104
+ * offset is `<=` the watermark. This closes a broker-side race — the PTY
105
+ * reader advances `consumed_offset` and the grid *before* the decoded chunk
106
+ * reaches the broadcast queue, so a chunk with `offset <= snapshotOffset`
107
+ * can still arrive *after* the client reconciles. Offsets are cumulative and
108
+ * monotonic, so the watermark drops exactly those already-painted stragglers
109
+ * without touching genuinely new output.
110
+ */
111
+ export class StreamSyncBuffer {
112
+ buffering = true;
113
+ buffered = [];
114
+ /**
115
+ * Post-reconcile suppression watermark: the snapshot offset the grid had
116
+ * already painted. `undefined` until {@link reconcile} runs with a defined
117
+ * offset (or forever, on brokers without offset support / after
118
+ * {@link flushAll}), in which case no post-reconcile suppression happens.
119
+ */
120
+ watermark = undefined;
121
+ /**
122
+ * Record a live `worker_stream` chunk. Returns `true` when the caller
123
+ * should apply the chunk immediately, `false` when the chunk must be held
124
+ * or dropped. While buffering, the chunk is retained for {@link reconcile}.
125
+ * After reconcile, a chunk whose end offset is `<=` the snapshot watermark
126
+ * is a late-arriving straggler the snapshot already painted and is
127
+ * suppressed (see the class docstring's race note); everything else passes
128
+ * through live.
129
+ */
130
+ push(chunk, offset) {
131
+ if (this.buffering) {
132
+ this.buffered.push({ chunk, offset });
133
+ return false;
134
+ }
135
+ // Live pass-through, minus stragglers the snapshot already reflects.
136
+ if (this.watermark !== undefined && offset !== undefined && offset <= this.watermark) {
137
+ return false;
138
+ }
139
+ return true;
140
+ }
141
+ /**
142
+ * Reconcile the buffered chunks against the painted snapshot's offset and
143
+ * return the chunks to apply, in order. Switches to live pass-through and
144
+ * arms the post-reconcile watermark (see {@link push}).
145
+ *
146
+ * When `snapshotOffset` is `undefined` (broker without offset support) all
147
+ * buffered chunks are discarded: they arrived before the snapshot was
148
+ * painted, so dropping them matches the snapshot-authoritative fallback
149
+ * and avoids double-painting what the snapshot already shows. No watermark
150
+ * is armed in that case — there is no offset to compare live frames to.
151
+ */
152
+ reconcile(snapshotOffset) {
153
+ const out = [];
154
+ if (snapshotOffset !== undefined) {
155
+ for (const item of this.buffered) {
156
+ // Drop chunks the snapshot already reflects; apply the rest. A chunk
157
+ // with no offset (mixed/legacy frame) is applied rather than risk
158
+ // silently dropping live output.
159
+ if (item.offset !== undefined && item.offset <= snapshotOffset)
160
+ continue;
161
+ out.push(item.chunk);
162
+ }
163
+ }
164
+ this.watermark = snapshotOffset;
165
+ this.buffered.length = 0;
166
+ this.buffering = false;
167
+ return out;
168
+ }
169
+ /**
170
+ * Return every buffered chunk unchanged and switch to live pass-through.
171
+ * Used when no snapshot was painted (transient snapshot failure): there is
172
+ * nothing to reconcile against, so applying everything preserves output
173
+ * rather than dropping the buffered live stream.
174
+ */
175
+ flushAll() {
176
+ const out = this.buffered.map((item) => item.chunk);
177
+ this.buffered.length = 0;
178
+ this.buffering = false;
179
+ return out;
180
+ }
181
+ /** True while chunks are still being buffered (before reconcile). */
182
+ get isBuffering() {
183
+ return this.buffering;
184
+ }
185
+ }
186
+ /**
187
+ * Conservative terminal-reset control sequence emitted on detach (see #1247).
188
+ *
189
+ * A drive/view/passthrough session paints the agent's snapshot (which now
190
+ * re-emits terminal modes) and then relays the live stream, either of which can
191
+ * leave the *local* terminal in application-cursor-keys, mouse-reporting,
192
+ * bracketed-paste, or alt-screen mode. Without a reset on detach the user is
193
+ * dropped back to their shell with arrows emitting escape codes, mouse clicks
194
+ * spewing coordinates, or a blank alt screen.
195
+ *
196
+ * The sequence is intentionally direction-explicit and idempotent. Ordering is
197
+ * load-bearing (see #1251): a few of these controls move the cursor, and
198
+ * `\x1b[?1049l` (leave alt screen) *restores* the main-buffer cursor that was
199
+ * saved on alt-screen entry. Anything that homes the cursor must therefore run
200
+ * *before* the alt-screen leave, or it clobbers that restored position and the
201
+ * next shell prompt lands at top-left. Two controls home the cursor:
202
+ *
203
+ * - `\x1b[r` (DECSTBM scroll-region reset) homes the cursor on xterm/DEC-style
204
+ * terminals. The scroll-region margins are shared terminal state, so
205
+ * resetting them while still in the alt buffer heals a stale region and the
206
+ * homing is harmless (the pending `?1049l` restore supersedes it).
207
+ * - `\x1b[?6l` (DECOM origin-mode reset) also moves the cursor to home per the
208
+ * DEC spec, so it belongs in the same pre-leave group.
209
+ *
210
+ * Everything after the alt-screen leave is position-independent (mode flags
211
+ * that never move the cursor): show cursor, application cursor keys off,
212
+ * autowrap on, every mouse-reporting mode off, bracketed paste off, numeric
213
+ * keypad, and a final SGR reset. Only written when stdout is a TTY, consistent
214
+ * with how the sessions gate raw-mode restore and the status line.
215
+ */
216
+ export const LOCAL_TERMINAL_RESET_SEQUENCE =
217
+ // --- cursor-homing resets: must precede the alt-screen leave/restore ---
218
+ '\x1b[?6l' + // origin mode off (DECOM) — homes the cursor
219
+ '\x1b[r' + // reset scroll region to full screen (DECSTBM) — homes the cursor
220
+ // --- leave alt screen: restores the main-buffer cursor saved on entry ---
221
+ '\x1b[?1049l' + // leave alternate screen buffer
222
+ // --- position-independent mode resets (none move the cursor) ---
223
+ '\x1b[?25h' + // show cursor (DECTCEM)
224
+ '\x1b[?1l' + // application cursor keys off (DECCKM)
225
+ '\x1b[?7h' + // autowrap on (DECAWM)
226
+ '\x1b[?1000l' + // mouse click reporting off
227
+ '\x1b[?1002l' + // mouse button-event (drag) reporting off
228
+ '\x1b[?1003l' + // mouse any-event (motion) reporting off
229
+ '\x1b[?1004l' + // focus in/out reporting off
230
+ '\x1b[?1005l' + // UTF-8 mouse coordinates off
231
+ '\x1b[?1006l' + // SGR mouse coordinates off
232
+ '\x1b[?1007l' + // alternate scroll off
233
+ '\x1b[?2004l' + // bracketed paste off
234
+ '\x1b>' + // keypad normal (DECKPNM)
235
+ '\x1b[0m'; // reset SGR
236
+ /**
237
+ * Emit {@link LOCAL_TERMINAL_RESET_SEQUENCE} to the local terminal on detach,
238
+ * but only when stdout is a TTY. A no-op for piped/redirected stdout so the
239
+ * reset never corrupts a captured log.
240
+ */
241
+ export function resetLocalTerminalOnDetach(write, isTty) {
242
+ if (!isTty)
243
+ return;
244
+ write(LOCAL_TERMINAL_RESET_SEQUENCE);
75
245
  }
76
246
  /**
77
247
  * Trim the agent name and resolve the broker connection (flag → env →
@@ -113,11 +283,11 @@ export function pickInitialTerminalRows(localSize, snapshotRows) {
113
283
  * Best-effort: a failure is annoying but not fatal. Skipped entirely
114
284
  * when `localSize` is `null` (stdout isn't a TTY).
115
285
  */
116
- export async function syncInitialPtySize(connection, name, localSize, verb, deps) {
286
+ export async function syncInitialPtySize(connection, name, localSize, verb, deps, options) {
117
287
  if (!localSize)
118
288
  return;
119
289
  try {
120
- await createBrokerClient(connection, deps.fetch).resizePty(name, localSize.rows, localSize.cols);
290
+ await createBrokerClient(connection, deps.fetch).resizePty(name, localSize.rows, localSize.cols, options);
121
291
  }
122
292
  catch (err) {
123
293
  const failure = mapBrokerSdkFailure(err);
@@ -145,8 +315,8 @@ export async function switchInboundDeliveryModeOrAbort(connection, name, targetM
145
315
  // `auto_inject` in that case so the queue can't grow indefinitely.
146
316
  }
147
317
  try {
148
- await createBrokerClient(connection, deps.fetch).setInboundDeliveryMode(name, targetMode);
149
- return { previousMode };
318
+ const result = await createBrokerClient(connection, deps.fetch).setInboundDeliveryMode(name, targetMode);
319
+ return { previousMode, sessionRevision: result.revision };
150
320
  }
151
321
  catch (err) {
152
322
  const failure = mapBrokerSdkFailure(err);
@@ -159,6 +329,317 @@ export async function switchInboundDeliveryModeOrAbort(connection, name, targetM
159
329
  return null;
160
330
  }
161
331
  }
332
+ /**
333
+ * Upper bound (ms) on the best-effort detach teardown — resize-ownership
334
+ * release and inbound-delivery-mode restore. Both are HTTP round-trips to the
335
+ * broker that can stall if the broker is down; the terminal must still exit
336
+ * promptly, so `finish()` resolves the exit code once these settle *or* this
337
+ * deadline elapses, whichever comes first. The broker's idle-takeover net
338
+ * still frees any ownership left behind.
339
+ */
340
+ export const DETACH_CLEANUP_DEADLINE_MS = 2000;
341
+ /**
342
+ * Best-effort restore of a worker's inbound delivery mode on detach.
343
+ *
344
+ * Two hazards this guards against (see #1247):
345
+ *
346
+ * 1. Concurrent-change race — a second session attaching while this one is
347
+ * active would read *this* session's mode as the "previous" one, so blindly
348
+ * writing `previousMode` back on detach can clobber a change another
349
+ * session/CLI made in the meantime. We restore via the broker's atomic
350
+ * compare-and-set (`expectedMode: sessionMode`): the broker applies
351
+ * `previousMode` only if the worker's current mode still equals what *this*
352
+ * session set, and no-ops (`matched: false`) otherwise. This removes the
353
+ * read-then-set TOCTOU a client-side re-read still had (a change landing
354
+ * between the read and the restore PUT).
355
+ * 2. Failed initial read — when the pre-attach mode was never learned
356
+ * (`previousMode === null`), forcing a default (`auto_inject`) would
357
+ * silently cancel an explicit `agent message hold`. In that case we leave
358
+ * the mode untouched and warn.
359
+ *
360
+ * The broker's monotonic mode revision closes ABA races where another session
361
+ * changes the mode away and back to `sessionMode` before this restore.
362
+ */
363
+ export async function restoreInboundDeliveryModeOnDetach(connection, name, previousMode, sessionMode, sessionRevision, verb, deps) {
364
+ if (previousMode === null) {
365
+ deps.log(`[${verb}] could not restore '${name}' inbound delivery mode (pre-attach mode was unknown); leaving it unchanged`);
366
+ return;
367
+ }
368
+ if (sessionRevision === null) {
369
+ deps.log(`[${verb}] could not safely restore '${name}' inbound delivery mode (broker did not report a mode revision); leaving it unchanged`);
370
+ return;
371
+ }
372
+ try {
373
+ // Atomic compare-and-set: restore only if both the mode and its monotonic
374
+ // revision still match this session's write. If another session changed it
375
+ // (including an ABA away-and-back), the broker no-ops.
376
+ const result = await createBrokerClient(connection, deps.fetch).setInboundDeliveryMode(name, previousMode, {
377
+ expectedMode: sessionMode,
378
+ expectedRevision: sessionRevision,
379
+ });
380
+ if (!result.matched) {
381
+ deps.log(`[${verb}] did not restore '${name}' inbound delivery mode because another session changed it; leaving it unchanged`);
382
+ }
383
+ }
384
+ catch {
385
+ // best-effort
386
+ }
387
+ }
388
+ /**
389
+ * Streaming scanner that tracks whether a byte stream currently *ends* inside
390
+ * an incomplete ANSI escape sequence (ESC, CSI, OSC, or DCS/SOS/PM/APC string).
391
+ *
392
+ * The attach status line wraps its repaint in cursor save/restore controls;
393
+ * splicing that in while the agent is mid-transmission of its own CSI sequence
394
+ * corrupts the agent's output. Feeding every server chunk through this scanner
395
+ * lets the status painter hold its repaint until the stream is back at a
396
+ * sequence boundary. State persists across chunks (a sequence may span several
397
+ * `worker_stream` frames).
398
+ *
399
+ * Only ASCII control bytes drive the state machine; multi-byte UTF-8 payload
400
+ * bytes are printable in the ground state and never appear inside a CSI/escape
401
+ * sequence, so scanning UTF-16 code units is safe here.
402
+ */
403
+ export class AnsiBoundaryScanner {
404
+ state = 'ground';
405
+ push(chunk) {
406
+ for (let i = 0; i < chunk.length; i += 1) {
407
+ this.step(chunk.charCodeAt(i));
408
+ }
409
+ }
410
+ reset() {
411
+ this.state = 'ground';
412
+ }
413
+ /** True when the stream ends at a safe boundary (not mid-sequence). */
414
+ get atBoundary() {
415
+ return this.state === 'ground';
416
+ }
417
+ step(c) {
418
+ switch (this.state) {
419
+ case 'ground':
420
+ if (c === 0x1b)
421
+ this.state = 'esc';
422
+ return;
423
+ case 'esc':
424
+ if (c === 0x5b)
425
+ this.state = 'csi'; // ESC [
426
+ else if (c === 0x5d)
427
+ this.state = 'osc'; // ESC ]
428
+ else if (c === 0x50 || c === 0x58 || c === 0x5e || c === 0x5f)
429
+ this.state = 'str'; // DCS / SOS / PM / APC
430
+ else
431
+ this.state = 'ground'; // 2-byte escape (ESC 7, ESC 8, ESC c, …)
432
+ return;
433
+ case 'csi':
434
+ if (c === 0x1b)
435
+ this.state = 'esc'; // stray ESC restarts
436
+ else if (c >= 0x40 && c <= 0x7e)
437
+ this.state = 'ground'; // final byte ends the CSI
438
+ return;
439
+ case 'osc':
440
+ if (c === 0x07)
441
+ this.state = 'ground'; // BEL terminator
442
+ else if (c === 0x1b)
443
+ this.state = 'osc_esc'; // possible ST (ESC \)
444
+ return;
445
+ case 'osc_esc':
446
+ this.state = c === 0x5c ? 'ground' : 'osc';
447
+ return;
448
+ case 'str':
449
+ if (c === 0x1b)
450
+ this.state = 'str_esc';
451
+ return;
452
+ case 'str_esc':
453
+ this.state = c === 0x5c ? 'ground' : 'str';
454
+ return;
455
+ }
456
+ }
457
+ }
458
+ /**
459
+ * Coordinates status-line repaints for the interactive attach clients.
460
+ *
461
+ * Correctness properties (see #1247):
462
+ * - **Non-TTY skip** — when `enabled` is false, nothing is ever written.
463
+ * - **Boundary-hold** — a repaint is deferred while the observed output ends
464
+ * mid ANSI escape sequence, so the status line never splices into a
465
+ * half-transmitted CSI. It paints as soon as the next chunk lands at a
466
+ * boundary (or after `boundaryHoldMs` as a bounded fallback).
467
+ * - **Coalescing** — repaints are rate-limited to at most one per
468
+ * `coalesceMs`, shrinking the window in which our save/restore-cursor wrap
469
+ * can clobber the agent's own pending DECSC.
470
+ * - **Teardown-safe** — after {@link dispose} no further writes happen.
471
+ *
472
+ * Residual risk (documented): ESC 7/ESC 8 (and CSI s/u) share a single
473
+ * saved-cursor slot on many terminals, so a repaint landing between the
474
+ * agent's DECSC and DECRC can still restore to the wrong spot. Boundary-hold +
475
+ * coalescing shrink but do not eliminate that window.
476
+ */
477
+ export class StatusLineController {
478
+ opts;
479
+ scanner = new AnsiBoundaryScanner();
480
+ timer = null;
481
+ timerForce = false;
482
+ wantPaint = false;
483
+ lastPaintAt = Number.NEGATIVE_INFINITY;
484
+ disposed = false;
485
+ constructor(opts) {
486
+ this.opts = opts;
487
+ }
488
+ /** Record server output for boundary tracking; flush a held repaint if the
489
+ * stream is now back at a sequence boundary. */
490
+ observeOutput(chunk) {
491
+ if (this.disposed)
492
+ return;
493
+ this.scanner.push(chunk);
494
+ if (this.wantPaint)
495
+ this.flush();
496
+ }
497
+ /** Request a repaint (coalesced + boundary-held). */
498
+ request() {
499
+ if (this.disposed || !this.opts.enabled)
500
+ return;
501
+ this.wantPaint = true;
502
+ this.flush();
503
+ }
504
+ /** Stop all painting and cancel any pending timer. */
505
+ dispose() {
506
+ this.disposed = true;
507
+ this.wantPaint = false;
508
+ this.clearTimer();
509
+ }
510
+ now() {
511
+ return (this.opts.now ?? Date.now)();
512
+ }
513
+ flush() {
514
+ if (this.disposed || !this.wantPaint)
515
+ return;
516
+ if (!this.scanner.atBoundary) {
517
+ this.arm(this.opts.boundaryHoldMs ?? 100, true);
518
+ return;
519
+ }
520
+ // Back at a boundary: any pending *force* (boundary-hold) timer carries the
521
+ // wrong deadline now — it was armed to paint mid-sequence after
522
+ // `boundaryHoldMs`, which would either paint later than the coalescing
523
+ // window needs or bypass the window entirely. Clear it so the normal
524
+ // coalescing logic below re-arms a plain timer for the correct remainder.
525
+ // A non-force (coalescing) timer already has the right deadline, so leave
526
+ // it in place.
527
+ if (this.timer && this.timerForce)
528
+ this.clearTimer();
529
+ const elapsed = this.now() - this.lastPaintAt;
530
+ if (elapsed >= this.opts.coalesceMs) {
531
+ this.paintNow();
532
+ }
533
+ else {
534
+ this.arm(this.opts.coalesceMs - elapsed, false);
535
+ }
536
+ }
537
+ paintNow() {
538
+ this.clearTimer();
539
+ this.wantPaint = false;
540
+ this.lastPaintAt = this.now();
541
+ this.opts.write(this.opts.render());
542
+ }
543
+ arm(ms, force) {
544
+ if (this.timer)
545
+ return;
546
+ this.timerForce = force;
547
+ const set = this.opts.setTimer ??
548
+ ((fn, delay) => {
549
+ const t = setTimeout(fn, delay);
550
+ t.unref?.();
551
+ return t;
552
+ });
553
+ this.timer = set(() => {
554
+ this.timer = null;
555
+ if (this.disposed || !this.wantPaint)
556
+ return;
557
+ if (this.timerForce)
558
+ this.paintNow();
559
+ else
560
+ this.flush();
561
+ }, ms);
562
+ }
563
+ clearTimer() {
564
+ if (this.timer) {
565
+ (this.opts.clearTimer ?? clearTimeout)(this.timer);
566
+ this.timer = null;
567
+ }
568
+ }
569
+ }
570
+ /**
571
+ * Default stdout writer that respects backpressure (see #1247, item 7).
572
+ *
573
+ * When the underlying stream reports saturation (`write()` returns false) we
574
+ * hold subsequent chunks in a bounded in-memory queue and flush them on
575
+ * `'drain'`, rather than letting Node's stdout buffer grow without limit under
576
+ * a fast agent + slow terminal.
577
+ *
578
+ * FIFO is preserved even when our own queue reaches `maxQueuedBytes`: rather
579
+ * than writing the overflow chunk straight through (which would jump it ahead
580
+ * of older queued chunks and reorder/split the PTY byte stream), we first flush
581
+ * the entire local queue into stdout's internal buffer — `stdout.write` buffers
582
+ * internally when saturated, so ignoring its return value here is safe — then
583
+ * write the new chunk last. Bounded extra buffering, never dropped or reordered
584
+ * output. Documented residual risk: under sustained overload Node's internal
585
+ * stdout buffer can still grow.
586
+ */
587
+ export function createBackpressureAwareWriter(stdout, maxQueuedBytes = 4 * 1024 * 1024) {
588
+ let paused = false;
589
+ let disposed = false;
590
+ let queue = [];
591
+ let queuedBytes = 0;
592
+ const flushQueue = () => {
593
+ if (disposed)
594
+ return;
595
+ while (queue.length > 0) {
596
+ const next = queue.shift();
597
+ queuedBytes -= Buffer.byteLength(next, 'utf8');
598
+ if (!stdout.write(next)) {
599
+ stdout.once('drain', flushQueue);
600
+ return;
601
+ }
602
+ }
603
+ paused = false;
604
+ };
605
+ const write = (chunk) => {
606
+ if (disposed)
607
+ return;
608
+ if (paused) {
609
+ const bytes = Buffer.byteLength(chunk, 'utf8');
610
+ if (queuedBytes + bytes <= maxQueuedBytes) {
611
+ queue.push(chunk);
612
+ queuedBytes += bytes;
613
+ return;
614
+ }
615
+ // Queue cap hit. Preserve FIFO: flush the whole local queue into
616
+ // stdout's internal buffer first (write buffers internally when
617
+ // saturated, so the return value is intentionally ignored), then write
618
+ // the new chunk last so it never jumps ahead of older output.
619
+ for (const queued of queue)
620
+ stdout.write(queued);
621
+ queue = [];
622
+ queuedBytes = 0;
623
+ stdout.write(chunk);
624
+ return;
625
+ }
626
+ if (!stdout.write(chunk)) {
627
+ paused = true;
628
+ stdout.once('drain', flushQueue);
629
+ }
630
+ };
631
+ const dispose = () => {
632
+ if (disposed)
633
+ return;
634
+ disposed = true;
635
+ queue = [];
636
+ queuedBytes = 0;
637
+ paused = false;
638
+ const off = stdout.off ?? stdout.removeListener;
639
+ off?.call(stdout, 'drain', flushQueue);
640
+ };
641
+ return { write, dispose };
642
+ }
162
643
  /**
163
644
  * Render the agent's current visible screen, then dispatch on the
164
645
  * outcome. Hard errors (`not_found`, `no_pty`) abort: this helper
@@ -1 +1 @@
1
- {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../../src/cli/lib/attach.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"attach.js","sourceRoot":"","sources":["../../../src/cli/lib/attach.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-relay",
3
- "version": "10.1.0",
3
+ "version": "10.2.0",
4
4
  "description": "Real-time agent-to-agent communication system",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -43,12 +43,12 @@
43
43
  "pack:validate": "npm pack --dry-run"
44
44
  },
45
45
  "dependencies": {
46
- "@agent-relay/cloud": "10.1.0",
47
- "@agent-relay/config": "10.1.0",
48
- "@agent-relay/fleet": "10.1.0",
49
- "@agent-relay/harness-driver": "10.1.0",
50
- "@agent-relay/sdk": "10.1.0",
51
- "@agent-relay/utils": "10.1.0",
46
+ "@agent-relay/cloud": "10.2.0",
47
+ "@agent-relay/config": "10.2.0",
48
+ "@agent-relay/fleet": "10.2.0",
49
+ "@agent-relay/harness-driver": "10.2.0",
50
+ "@agent-relay/sdk": "10.2.0",
51
+ "@agent-relay/utils": "10.2.0",
52
52
  "@modelcontextprotocol/sdk": "^1.0.0",
53
53
  "@relayfile/client": "^0.10.21",
54
54
  "@relayflows/cli": "^1.0.1",