@cotal-ai/cli 0.137.0 → 0.138.1

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.
Files changed (57) hide show
  1. package/dist/chat/chat-view.d.ts +1 -1
  2. package/dist/chat/chat-view.d.ts.map +1 -1
  3. package/dist/chat/controller.d.ts +1 -1
  4. package/dist/chat/controller.d.ts.map +1 -1
  5. package/dist/chat/frontend.d.ts +1 -1
  6. package/dist/chat/frontend.d.ts.map +1 -1
  7. package/dist/chat/picker.d.ts +1 -1
  8. package/dist/chat/picker.d.ts.map +1 -1
  9. package/dist/chat/plain.d.ts +1 -1
  10. package/dist/chat/plain.d.ts.map +1 -1
  11. package/dist/chat/stdio-io.d.ts +1 -1
  12. package/dist/chat/stdio-io.d.ts.map +1 -1
  13. package/dist/chat/stdio.d.ts +1 -1
  14. package/dist/chat/stdio.d.ts.map +1 -1
  15. package/dist/chat/view.d.ts +1 -1
  16. package/dist/chat/view.d.ts.map +1 -1
  17. package/dist/commands/agents.d.ts +7 -149
  18. package/dist/commands/agents.d.ts.map +1 -1
  19. package/dist/commands/agents.js +15 -723
  20. package/dist/commands/agents.js.map +1 -1
  21. package/dist/commands/channels.js +1 -1
  22. package/dist/commands/channels.js.map +1 -1
  23. package/dist/commands/chat.d.ts +1 -24
  24. package/dist/commands/chat.d.ts.map +1 -1
  25. package/dist/commands/chat.js +3 -15
  26. package/dist/commands/chat.js.map +1 -1
  27. package/dist/console/app.js +1 -1
  28. package/dist/console/app.js.map +1 -1
  29. package/package.json +5 -6
  30. package/dist/chat/engine.d.ts +0 -111
  31. package/dist/chat/engine.d.ts.map +0 -1
  32. package/dist/chat/engine.js +0 -225
  33. package/dist/chat/engine.js.map +0 -1
  34. package/dist/chat/native-session.d.ts +0 -120
  35. package/dist/chat/native-session.d.ts.map +0 -1
  36. package/dist/chat/native-session.js +0 -487
  37. package/dist/chat/native-session.js.map +0 -1
  38. package/dist/chat/open-session.d.ts +0 -9
  39. package/dist/chat/open-session.d.ts.map +0 -1
  40. package/dist/chat/open-session.js +0 -120
  41. package/dist/chat/open-session.js.map +0 -1
  42. package/dist/chat/session.d.ts +0 -230
  43. package/dist/chat/session.d.ts.map +0 -1
  44. package/dist/chat/session.js +0 -2
  45. package/dist/chat/session.js.map +0 -1
  46. package/dist/chat/static-session.d.ts +0 -62
  47. package/dist/chat/static-session.d.ts.map +0 -1
  48. package/dist/chat/static-session.js +0 -236
  49. package/dist/chat/static-session.js.map +0 -1
  50. package/dist/chat/user-session.d.ts +0 -22
  51. package/dist/chat/user-session.d.ts.map +0 -1
  52. package/dist/chat/user-session.js +0 -180
  53. package/dist/chat/user-session.js.map +0 -1
  54. package/dist/lib/attach-client.d.ts +0 -112
  55. package/dist/lib/attach-client.d.ts.map +0 -1
  56. package/dist/lib/attach-client.js +0 -528
  57. package/dist/lib/attach-client.js.map +0 -1
@@ -1,528 +0,0 @@
1
- import { openSessionRail, encodeTerminalData, terminalFrameBytes, decodeTerminalFrame } from "@cotal-ai/core";
2
- import { cachedPreferences, describeLayer, parseDetachKey, resolvePreference } from "@cotal-ai/workspace";
3
- import { c, stderrLine } from "../ui.js";
4
- /**
5
- * The detach key — Ctrl-] (0x1d) by default, as in telnet/ssh escape conventions. The `detach-key`
6
- * preference rebinds it to another control key when Ctrl-] clashes with a keybinding inside the
7
- * agent's TUI: `COTAL_DETACH_KEY`, then the saved preference (`cotal config set detach-key`). Both
8
- * accept `ctrl-<char>` or `^<char>` (e.g. `ctrl-b`, `^_`). An unparseable `COTAL_DETACH_KEY` —
9
- * including a set-but-empty or whitespace-only one — throws (named), never silently falling back;
10
- * the caller turns that into a loud exit. A saved value was validated when it was written.
11
- */
12
- export function detachKey() {
13
- const resolved = resolvePreference("detach-key", { preferences: cachedPreferences() });
14
- const winner = resolved.winner;
15
- const key = parseDetachKey(winner.value);
16
- if (!key) {
17
- throw new Error(`invalid ${describeLayer(winner)} "${winner.value}" - expected ctrl-<char> or ^<char> for a control key ` +
18
- `(a-z, or one of @ [ \\ ] ^ _), e.g. ctrl-b`);
19
- }
20
- return { ...key, overridden: winner.source !== "default", from: describeLayer(winner) };
21
- }
22
- /**
23
- * Whether a whole chunk `d` is exactly one press of the detach key `byte`, in any of three
24
- * encodings: the legacy single control byte; the kitty keyboard protocol's `CSI <codepoint> ;
25
- * <mods> u`; or xterm `modifyOtherKeys`'s `CSI 27 ; <mods> ; <codepoint> ~`. `<codepoint>` is the
26
- * decimal codepoint kitty/xterm report for the unshifted key: `byte | 0x40` for the control
27
- * punctuation (`@ [ \ ] ^ _`) and `byte | 0x60` for a letter (kitty reports the lowercase key even
28
- * though Ctrl was held). `<mods>` is 1 + the modifier bitmask and must carry the Ctrl bit
29
- * (`(mods - 1) & 4`), so plain Ctrl (5) and Ctrl+Shift (6) match but a modifier field without Ctrl
30
- * does not, and a field of 0, which neither protocol emits, is not a press either (the test needs
31
- * that floor: `(0 - 1) & 4` is 4 in ToInt32 arithmetic, so 0 would otherwise read as Ctrl). The match is on the WHOLE chunk:
32
- * a sequence with company (a paste, a second keystroke, a trailing byte) is not a press, which is
33
- * the same paste-safety property the one-byte test already had. This assumes one press arrives in
34
- * one read, as measured on a pty (issue #598); a sequence split across two reads is not buffered
35
- * and is not recognised. A kitty `CSI u` with an alternate-key `<codepoint>:<shifted>:<base>` triple
36
- * is accepted by matching only the leading codepoint before an optional `:...` group; no other
37
- * kitty event type (release, repeat) is recognised.
38
- */
39
- export function isDetachPress(d, byte) {
40
- if (d.length === 0)
41
- return false;
42
- if (d.length === 1 && d[0] === byte)
43
- return true;
44
- const s = d.toString("latin1");
45
- const codepoints = byte >= 0x01 && byte <= 0x1a ? [byte | 0x40, byte | 0x60] : [byte | 0x40];
46
- const hasCtrl = (mods) => mods >= 1 && ((mods - 1) & 4) !== 0;
47
- const kitty = /^\x1b\[(\d+)(?::\d+(?::\d+)?)?;(\d+)u$/.exec(s);
48
- if (kitty) {
49
- const cp = Number(kitty[1]);
50
- const mods = Number(kitty[2]);
51
- if (codepoints.includes(cp) && hasCtrl(mods))
52
- return true;
53
- }
54
- const xterm = /^\x1b\[27;(\d+);(\d+)~$/.exec(s);
55
- if (xterm) {
56
- const mods = Number(xterm[1]);
57
- const cp = Number(xterm[2]);
58
- if (codepoints.includes(cp) && hasCtrl(mods))
59
- return true;
60
- }
61
- return false;
62
- }
63
- /**
64
- * Terminal modes a full-screen child (a fullscreen TUI: OpenCode, or Claude under `/tui fullscreen`)
65
- * commonly turns on but that we must undo locally on detach/exit: the agent keeps running after
66
- * Ctrl-], so it never restores OUR terminal. Without this, detaching from a mouse-tracking TUI leaves
67
- * the terminal reporting every cursor move as input (a stream of `ESC[<…M` escape codes), or its
68
- * focus in/out as `ESC[I`/`ESC[O`. Disables all mouse-report modes + focus reporting + bracketed
69
- * paste, resets the keypad/cursor-key modes, shows the cursor, and resets attributes. Leaving the
70
- * alternate screen is handled separately (ALT_LEAVE_SEQ), only when we actually entered it — see
71
- * cleanup().
72
- */
73
- const MOUSE_OFF = "\x1b[?1000l\x1b[?1002l\x1b[?1003l\x1b[?1005l\x1b[?1006l\x1b[?1015l"; // all mouse tracking off
74
- const RESTORE = MOUSE_OFF +
75
- "\x1b[?1004l" + // focus reporting off
76
- "\x1b[?2004l" + // bracketed paste off
77
- "\x1b[?1l" + // application cursor keys off (DECCKM): a full-screen TUI enables it; left on, arrows emit ESC O A not ESC [ A
78
- "\x1b>" + // keypad → numeric (DECKPNM)
79
- "\x1b[?25h" + // show cursor
80
- "\x1b[0m"; // reset attributes
81
- // Leave the alternate screen on detach, but ONLY if the child put us there (altScreen). The attach
82
- // snapshot faithfully re-enters the child's alt-screen (`?1049h`) on our terminal; without a matching
83
- // leave we strand it in the alt buffer, which has no scrollback and — with xterm alt-scroll — turns
84
- // the wheel into ↑/↓ that walk shell history. Leaving the alt buffer IS the whole fix: alt-scroll
85
- // (`?1007`) only acts inside the alt buffer, so `?1049l` alone makes it inert. We deliberately don't
86
- // send `?1007l` — nothing on this path ever enabled it (unlike console.ts, which sets `?1007h` on
87
- // entry), so disabling it would clobber the operator's own alternate-scroll preference for later apps.
88
- const ALT_LEAVE_SEQ = "\x1b[?1049l"; // leave alt-screen — alt-scroll is inert once back in the main buffer
89
- // Wheel-scroll for full-screen children. A fullscreen TUI (OpenCode, or Claude under `/tui
90
- // fullscreen`) runs in the alternate screen — where the terminal's native scrollback is dead — and
91
- // scrolls its content itself off mouse reports. But it enables that mouse capture on ITS pty, and the
92
- // enable doesn't reliably survive the attach hop (backlog eviction / nested pty), so our terminal
93
- // never reports the wheel and scrolling dies. So while the child is in the alternate screen we enable
94
- // SGR mouse reporting on OUR terminal and translate each wheel tick into PageUp/PageDown — the
95
- // keystrokes a fullscreen TUI treats as "scroll the view" (OpenCode: `messages_page_up`/`_down`;
96
- // Claude's fullscreen binds PageUp/PageDown too). A child in the normal screen (inline Claude) keeps
97
- // altScreen=false, so this stays off and its native terminal-scrollback wheel is untouched.
98
- const MOUSE_ON = "\x1b[?1002h\x1b[?1006h"; // button+drag tracking, SGR encoding
99
- const PAGE_UP = "\x1b[5~";
100
- const PAGE_DOWN = "\x1b[6~";
101
- /** Collapse a wheel burst to at most one page command per display frame. Each raw wheel report used
102
- * to become a separate session frame and TUI redraw; rapid scrolling could fill the 64-frame rail
103
- * before the caller returned credit, even though the operator only intended one continuous scroll. */
104
- const WHEEL_COALESCE_MS = 16;
105
- // Enter/leave the alternate screen: xterm `?1049`, plus the older `?1047`/`?47`.
106
- const ALT_ENTER = /\x1b\[\?(?:1049|1047|47)h/g;
107
- const ALT_LEAVE = /\x1b\[\?(?:1049|1047|47)l/g;
108
- // A complete SGR mouse report: `ESC [ < btn ; col ; row (M|m)`.
109
- const SGR_MOUSE = /^\x1b\[<(\d+);\d+;\d+[Mm]/;
110
- const lastIndexOfRe = (re, s) => {
111
- re.lastIndex = 0;
112
- let last = -1;
113
- for (let m = re.exec(s); m; m = re.exec(s))
114
- last = m.index;
115
- return last;
116
- };
117
- export function holdTerminal() {
118
- const stdin = process.stdin;
119
- const wasRaw = stdin.isRaw ?? false;
120
- let entered = false;
121
- let restored = false;
122
- return {
123
- altScreen: false,
124
- enterRaw() {
125
- if (entered)
126
- return;
127
- entered = true;
128
- if (stdin.isTTY)
129
- stdin.setRawMode(true);
130
- },
131
- restore() {
132
- if (restored)
133
- return;
134
- restored = true;
135
- if (process.stdout.isTTY)
136
- process.stdout.write(RESTORE + (this.altScreen ? ALT_LEAVE_SEQ : ""));
137
- if (stdin.isTTY)
138
- stdin.setRawMode(wasRaw);
139
- stdin.pause();
140
- },
141
- };
142
- }
143
- /** Register the stdout EPIPE/EIO no-op ONCE for the process. Idempotent by construction: a
144
- * reconnecting attach calls {@link attachClient} once per attempt and each call would otherwise
145
- * add another listener that nothing ever removes. */
146
- let stdoutErrorSwallowed = false;
147
- function swallowStdoutPipeErrors() {
148
- if (stdoutErrorSwallowed)
149
- return;
150
- stdoutErrorSwallowed = true;
151
- process.stdout.on("error", () => { });
152
- }
153
- /** Resolve when stdout accepted a write. A destroyed pipe is a terminal that no longer consumes, not
154
- * a reason to wedge the mesh rail forever; `error`/`close` therefore release the wait like `drain`. */
155
- function writeStdout(bytes) {
156
- if (process.stdout.write(bytes) || process.stdout.destroyed)
157
- return;
158
- return new Promise((resolve) => {
159
- const done = () => {
160
- process.stdout.off("drain", done);
161
- process.stdout.off("error", done);
162
- process.stdout.off("close", done);
163
- resolve();
164
- };
165
- process.stdout.once("drain", done);
166
- process.stdout.once("error", done);
167
- process.stdout.once("close", done);
168
- });
169
- }
170
- /**
171
- * The TRANSPORT-class end reasons: the link broke, the session did not finish. Every one of these
172
- * means the seat is still there and a fresh session would reach it.
173
- *
174
- * The nine fault names are core's own, not a list invented here: `openSessionRail`'s
175
- * `onProtocolError` documents its whole vocabulary as "the session is broken — close and
176
- * re-establish" (SPEC 13.6). Added to them are the three ends that are not rail faults but are
177
- * still the link dying: the peer closing its rail, and this side's NATS connection going away.
178
- *
179
- * Deliberately NOT here, so a reconnect never papers over a finished session: `detached` (the
180
- * operator pressed the key), and the manager's terminal reasons — `process-exit` (the agent
181
- * exited), `target-despawn`, `manager-restart`, `expired` (the grant's TTL elapsed). Those end the
182
- * attach, and the CLI says which.
183
- */
184
- const TRANSPORT_END_REASONS = new Set([
185
- "garbled-frame", "gap", "credit-overrun", "flood", "subscription", "stall", "handler", "publish", "seq-exhausted",
186
- "peer-closed", "closed", "connection-closed",
187
- ]);
188
- /** Did the session end because the LINK broke (so re-establishing is the honest response)? */
189
- export function isTransportEnd(reason) {
190
- return TRANSPORT_END_REASONS.has(reason);
191
- }
192
- /**
193
- * Drive a manager's attach session from the terminal: raw-mode stdin streams to the remote PTY,
194
- * PTY output streams to stdout, and SIGWINCH-style resizes are forwarded. The detach key (Ctrl-]
195
- * by default, {@link detachKey}) detaches without killing the agent. Transport-agnostic over the
196
- * mesh §13.6 session.
197
- */
198
- export function attachClient(transport, hold, takeStdin) {
199
- // Resolve the detach key before connecting so a bad COTAL_DETACH_KEY fails loudly up front
200
- // (matching the manager's other fail-fast exits) instead of after an attach we'd only tear down.
201
- let detach;
202
- try {
203
- detach = detachKey();
204
- }
205
- catch (e) {
206
- stderrLine("✗ ", `${e.message}`, c.red);
207
- process.exit(1);
208
- }
209
- // A caller that reconnects owns the terminal across attempts and undoes it once at the end;
210
- // without a hold this session owns it, which is the one-shot behaviour.
211
- const ownsTerminal = hold === undefined;
212
- const term = hold ?? holdTerminal();
213
- return new Promise((resolve) => {
214
- const stdin = process.stdin;
215
- // A broken local pipe (terminal closed / SIGHUP) makes stdout writes async-error on a later
216
- // tick; with no listener that EPIPE/EIO becomes an uncaughtException — crashing on the per-frame
217
- // PTY write or the on-detach restore write. It must outlive the async error tick, so it is NOT
218
- // removed in cleanup — which is exactly why it is registered once per PROCESS rather than once
219
- // per attempt: a reconnect loop calls this function again on every re-establishment, and one
220
- // listener per attempt walks into MaxListenersExceededWarning during a long outage.
221
- swallowStdoutPipeErrors();
222
- // Wheel-scroll state (see MOUSE_ON above): whether the child is in the alternate screen (on the
223
- // hold, since it outlives one session) and a buffer for an SGR mouse report split across stdin
224
- // reads (per-session: bytes still in flight when a link dies are gone with it).
225
- // Did this session ever put bytes on the terminal (see AttachOutcome.carried)?
226
- let carried = false;
227
- // Did THIS session ever take the stream? A reconnecting caller holds a reader between sessions,
228
- // and a session that ends before its `ready` fires never ran the handoff below, so it never
229
- // took anything: pausing on the way out would pause a stream it does not own, under a reader
230
- // that is still installed and now reads nothing. Measured before this line existed: a link
231
- // killed while a session's opening flush was in flight left the loop's watcher listening over a
232
- // paused stream for the whole backoff, and everything typed at that frozen terminal was flushed
233
- // into the agent by the NEXT session's resume. Cell O of `smoke:attach-stdin` is that window.
234
- let tookStdin = false;
235
- let mouseBuf = "";
236
- let wheelDelta = 0;
237
- let wheelTimer;
238
- const flushWheel = () => {
239
- if (wheelTimer)
240
- clearTimeout(wheelTimer);
241
- wheelTimer = undefined;
242
- const delta = wheelDelta;
243
- wheelDelta = 0;
244
- if (delta === 0)
245
- return;
246
- transport.send(Buffer.from(delta > 0 ? PAGE_DOWN : PAGE_UP, "latin1"));
247
- };
248
- const clearWheel = () => {
249
- if (wheelTimer)
250
- clearTimeout(wheelTimer);
251
- wheelTimer = undefined;
252
- wheelDelta = 0;
253
- };
254
- const queueWheel = (delta) => {
255
- wheelDelta = Math.max(-8, Math.min(8, wheelDelta + delta));
256
- if (wheelTimer)
257
- return;
258
- wheelTimer = setTimeout(flushWheel, WHEEL_COALESCE_MS);
259
- wheelTimer.unref?.();
260
- };
261
- // Carry the tail of the previous output frame so an alt-screen escape split across ws frames
262
- // (e.g. `ESC[?10` then `49h`) is still detected; 16 bytes covers these private-mode sequences.
263
- // Acting only on state *change* below makes re-scanning the carried bytes idempotent.
264
- let scanTail = "";
265
- // Track the child's alt-screen transitions in its output so we can arm/disarm wheel translation.
266
- const trackAltScreen = (data) => {
267
- const s = scanTail + data.toString("latin1");
268
- scanTail = s.slice(-16);
269
- const enter = lastIndexOfRe(ALT_ENTER, s);
270
- const leave = lastIndexOfRe(ALT_LEAVE, s);
271
- if (enter === -1 && leave === -1)
272
- return;
273
- const nowAlt = enter > leave;
274
- if (nowAlt === term.altScreen)
275
- return;
276
- term.altScreen = nowAlt;
277
- if (term.altScreen) {
278
- if (process.stdout.isTTY)
279
- process.stdout.write(MOUSE_ON);
280
- }
281
- else {
282
- // Leaving alt-screen mid-session: undo the mouse modes WE enabled so the terminal stops
283
- // reporting the wheel/clicks and native scrollback works again — don't wait for detach.
284
- mouseBuf = "";
285
- clearWheel();
286
- if (process.stdout.isTTY)
287
- process.stdout.write(MOUSE_OFF);
288
- }
289
- };
290
- const sendResize = () => transport.resize(process.stdout.columns ?? 80, process.stdout.rows ?? 24);
291
- const onInput = (data) => {
292
- // Under the console, Ink has called `stdin.setEncoding("utf8")`, and an encoding persists on
293
- // the stream after Ink releases raw mode, so data arrives as a STRING there (the standalone
294
- // command gets Buffers). Normalize first: the one-byte detach compare below would otherwise
295
- // silently never match (a one-character string is not the number 0x1d), Ctrl-] would just
296
- // forward to the child, and detaching from a console attach would be impossible.
297
- const d = Buffer.isBuffer(data) ? data : Buffer.from(data, "utf8");
298
- if (isDetachPress(d, detach.byte)) {
299
- clearWheel();
300
- transport.close();
301
- return;
302
- }
303
- // Inline child: forward keystrokes raw (its wheel scrolls the local terminal, not the app).
304
- if (!term.altScreen) {
305
- transport.send(d);
306
- return;
307
- }
308
- // Full-screen child: rewrite wheel reports to PageUp/PageDown, pass everything else through.
309
- // Wheel reports are coalesced ACROSS stdin reads; raw input flushes the pending wheel first so
310
- // keyboard/mouse ordering remains exact.
311
- mouseBuf += d.toString("latin1");
312
- let out = "";
313
- const flushOut = () => {
314
- if (!out)
315
- return;
316
- transport.send(Buffer.from(out, "latin1"));
317
- out = "";
318
- };
319
- const appendRaw = (raw) => {
320
- if (!raw)
321
- return;
322
- flushWheel();
323
- out += raw;
324
- };
325
- for (;;) {
326
- const i = mouseBuf.indexOf("\x1b[<");
327
- if (i === -1) {
328
- // A report split right before `<` (`ESC[` now, `<…M` next) would slip through untranslated:
329
- // hold a trailing `ESC[` for the next read. Never hold a bare trailing `ESC` — that's the
330
- // Escape key and must forward at once (e.g. OpenCode's interrupt); the rarer `ESC`|`[<…`
331
- // split stays raw by design.
332
- const keep = mouseBuf.endsWith("\x1b[") ? 2 : 0;
333
- appendRaw(mouseBuf.slice(0, mouseBuf.length - keep));
334
- mouseBuf = mouseBuf.slice(mouseBuf.length - keep);
335
- break;
336
- }
337
- appendRaw(mouseBuf.slice(0, i));
338
- const rest = mouseBuf.slice(i);
339
- const m = SGR_MOUSE.exec(rest);
340
- if (!m) {
341
- // Hold only a still-valid partial report (`ESC[<` + digits/semicolons) for the next read;
342
- // anything else can't become an SGR mouse report, so pass it straight through.
343
- if (/^\x1b\[<[\d;]*$/.test(rest))
344
- mouseBuf = rest;
345
- else {
346
- appendRaw(rest);
347
- mouseBuf = "";
348
- }
349
- break;
350
- }
351
- const btn = Number(m[1]);
352
- if (btn & 0x40) {
353
- flushOut();
354
- queueWheel(btn & 1 ? 1 : -1); // wheel: 64=up, 65=down
355
- }
356
- else
357
- appendRaw(m[0]); // other mouse (click/drag): forward raw so the TUI still gets it
358
- mouseBuf = rest.slice(m[0].length);
359
- }
360
- flushOut();
361
- };
362
- const cleanup = () => {
363
- clearWheel();
364
- stdin.off("data", onInput);
365
- process.stdout.off("resize", sendResize);
366
- // Undo terminal modes the (still-running) agent's TUI enabled — it won't restore us on detach.
367
- // If the child put us in its alternate screen, leave it too so the terminal isn't stranded in
368
- // the alt buffer; an inline child keeps its scrollback. Only when this session OWNS the
369
- // terminal: a reconnecting caller undoes it once, after the last attempt, so the screen does
370
- // not flash back to the shell and get repainted over between sessions.
371
- if (ownsTerminal)
372
- term.restore();
373
- else if (tookStdin)
374
- stdin.pause();
375
- };
376
- transport.onReady(() => {
377
- // Take stdin from whoever was holding it BETWEEN sessions, synchronously and before anything
378
- // below touches the stream. A reconnecting caller keeps a reader installed for the whole
379
- // non-session period so bytes typed at a terminal with no session are read and dropped rather
380
- // than buffered; without this handoff both readers would be live at once and a detach byte
381
- // would be seen twice. Synchronous by construction: `data` is emitted on a later tick, so the
382
- // gap between the caller's `off` and the `on` below cannot lose a byte.
383
- //
384
- // It ANSWERS, because the byte it may have just eaten is a detach. The caller's reader owns
385
- // stdin until this line, and this line runs when the session is READY, which is a round trip
386
- // after the caller announced the reconnect. A key pressed in between is seen by that reader
387
- // and by nobody else: without this branch the operator's detach vanishes and the session they
388
- // meant to leave comes up and keeps their keystrokes. So a press that already landed detaches
389
- // the session that is opening, before it takes the terminal or reads a byte.
390
- if (takeStdin?.()) {
391
- transport.close();
392
- return;
393
- }
394
- // Make an override visible (the CLI's "attached to X — Ctrl-] to detach" hint still prints the
395
- // default label). Only on override, so the default case stays free of duplicate noise.
396
- if (detach.overridden)
397
- console.error(c.dim(`detach key: ${detach.label} (from ${detach.from})`));
398
- term.enterRaw();
399
- stdin.resume();
400
- tookStdin = true;
401
- sendResize();
402
- process.stdout.on("resize", sendResize);
403
- stdin.on("data", onInput);
404
- });
405
- transport.onData(async (data) => {
406
- carried = true;
407
- trackAltScreen(data);
408
- await writeStdout(data);
409
- });
410
- transport.onEnd((err, reason) => {
411
- cleanup();
412
- // The reason is DATA, not an exception: a reconnecting caller reads it to decide whether the
413
- // link broke or the session finished. A transport with nothing to say about a faulted end
414
- // reports `error`, which is never in the transport-class set; the loop exits non-zero on it
415
- // rather than calling it a detach, so an unnamed fault is still loud.
416
- resolve({ reason: reason ?? (err ? "error" : "detached"), carried, ...(err ? { error: err } : {}) });
417
- });
418
- });
419
- }
420
- /**
421
- * The mesh §13.6 SESSION transport: the item-6 replacement for the loopback WebSocket. Given a
422
- * connection scoped to the session's eps rails and the redeemed grant, it opens the caller rail,
423
- * asks the serving side to replay the reconstructed backlog (the `ready` handshake — PR #158 over
424
- * the mesh), and speaks the core terminal-session frame codec. A `drop` frame is surfaced INLINE
425
- * (never a silent loss); a peer `end`/close or a protocol fault ends the session with the distinct
426
- * reason. No `127.0.0.1`, no bearer URL — the grant is holder-bound.
427
- */
428
- export function meshSessionTransport(nc, grant) {
429
- let onDataCb;
430
- let onEndCb;
431
- let onReadyCb;
432
- let ended = false;
433
- let repaintTimer;
434
- let rail;
435
- const fireEnd = (err, reason) => {
436
- if (ended)
437
- return;
438
- ended = true;
439
- if (repaintTimer)
440
- clearTimeout(repaintTimer);
441
- repaintTimer = undefined;
442
- onEndCb?.(err, reason);
443
- };
444
- // Schedule after the rail's async handler returns so the reverse data frame piggybacks the NEW
445
- // receive watermark, including the drop notice itself. That ack reopens the serving window before
446
- // the repeat `ready` asks for a fresh canonical screen snapshot.
447
- const requestRepaint = () => {
448
- if (ended || repaintTimer)
449
- return;
450
- repaintTimer = setTimeout(() => {
451
- repaintTimer = undefined;
452
- if (ended)
453
- return;
454
- try {
455
- rail.send({ k: "ready" });
456
- }
457
- catch { /* broken/full: the rail fault path ends the session */ }
458
- }, 0);
459
- repaintTimer.unref?.();
460
- };
461
- rail = openSessionRail({
462
- nc,
463
- grant,
464
- role: "caller",
465
- onData: async (data) => {
466
- let frame;
467
- try {
468
- frame = decodeTerminalFrame(data);
469
- }
470
- catch {
471
- return;
472
- } // garbled: the rail already surfaced it
473
- if (frame.k === "data")
474
- await onDataCb?.(Buffer.from(terminalFrameBytes(frame)));
475
- else if (frame.k === "end")
476
- fireEnd(undefined, frame.reason);
477
- else if (frame.k === "drop") {
478
- await onDataCb?.(Buffer.from(`\r\n[cotal: ${frame.bytes} bytes dropped - backpressure]\r\n`));
479
- requestRepaint();
480
- }
481
- },
482
- onClose: () => fireEnd(undefined, "peer-closed"),
483
- // The fault NAME rides alongside the error. It used to live only inside the message, where the
484
- // only way to tell a broken link from a finished session was to parse English.
485
- onProtocolError: (reason) => fireEnd(new Error(`mesh session transport error: ${reason}`), reason),
486
- });
487
- // The connection going away ends the session, and says so. Without this a link that dies past the
488
- // serving side's stall watchdog leaves the caller subscribed to a session nobody is serving: the
489
- // manager's `end` and `close` frames were published while this side was disconnected and EPS has
490
- // no retention, so they are simply gone, and the attach hangs on a dead session with no output,
491
- // no error and no end. `nc.closed()` is the one signal that still arrives.
492
- void nc.closed().then((err) => fireEnd(err ?? undefined, "connection-closed"));
493
- // The caller's `out` subscription must be live before the serving side is asked to replay (EPS is
494
- // at-most-once, no retention). flush() forces the SUB, then we send `ready` and go.
495
- void nc.flush().then(() => {
496
- if (ended)
497
- return;
498
- try {
499
- rail.send({ k: "ready" });
500
- }
501
- catch { /* broken/full: the onProtocolError path ends the session */ }
502
- onReadyCb?.();
503
- // A flush that FAILS means the connection went away before the session ever opened, which is the
504
- // link and not the session. Without a reason here the end reads as a plain `error`, which is in
505
- // no classification, so a reconnect would treat a link that died between connect() and the first
506
- // flush as a finished session and stop: the exact failure this path exists to remove, in the
507
- // window where a flapping link is most likely to land.
508
- }).catch((e) => fireEnd(e, "connection-closed"));
509
- return {
510
- onReady: (cb) => { onReadyCb = cb; },
511
- onData: (cb) => { onDataCb = cb; },
512
- onEnd: (cb) => { onEndCb = cb; },
513
- send: (bytes) => { try {
514
- rail.send(encodeTerminalData(bytes));
515
- }
516
- catch { /* interactive keystrokes are low-volume; a stuck window ends via the stall watchdog */ } },
517
- // Guard degenerate geometry: the §13.6 codec rejects a non-positive dimension (a terminal
518
- // reporting 0 during a transient) — never emit it (the serving side tolerates it regardless).
519
- resize: (cols, rows) => { if (cols > 0 && rows > 0) {
520
- try {
521
- rail.send({ k: "resize", cols, rows });
522
- }
523
- catch { /* advisory */ }
524
- } },
525
- close: () => { rail.close(); fireEnd(undefined, "detached"); },
526
- };
527
- }
528
- //# sourceMappingURL=attach-client.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"attach-client.js","sourceRoot":"","sources":["../../src/lib/attach-client.ts"],"names":[],"mappings":"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"}