@f5xc-salesdemos/pi-tui 19.29.2 → 19.29.4

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@f5xc-salesdemos/pi-tui",
4
- "version": "19.29.2",
4
+ "version": "19.29.4",
5
5
  "description": "Terminal User Interface library with differential rendering for efficient text-based applications",
6
6
  "homepage": "https://github.com/f5xc-salesdemos/xcsh",
7
7
  "author": "Can Boluk",
@@ -37,8 +37,8 @@
37
37
  "fmt": "biome format --write ."
38
38
  },
39
39
  "dependencies": {
40
- "@f5xc-salesdemos/pi-natives": "19.29.2",
41
- "@f5xc-salesdemos/pi-utils": "19.29.2",
40
+ "@f5xc-salesdemos/pi-natives": "19.29.4",
41
+ "@f5xc-salesdemos/pi-utils": "19.29.4",
42
42
  "marked": "^17.0"
43
43
  },
44
44
  "devDependencies": {
package/src/terminal.ts CHANGED
@@ -120,6 +120,15 @@ export class ProcessTerminal implements Terminal {
120
120
  #osc11PollTimer?: Timer;
121
121
  #mode2031Active = false;
122
122
  #mode2031DebounceTimer?: Timer;
123
+ // Capability-probe results that persist across stop()/start() cycles. After
124
+ // the first handshake, a restart (e.g. the credential-fix ui.stop()→cooked
125
+ // subprocess→ui.start() cycle) must re-enable protocols WITHOUT re-querying:
126
+ // a re-query's response lands during the cooked-mode window and the terminal
127
+ // echoes it as visible "gibberish". These flags are deliberately NOT reset in
128
+ // stop() — they remember what we already learned about the terminal.
129
+ #hasProbedCapabilities = false;
130
+ #kittySupported = false;
131
+ #modifyOtherKeysSupported = false;
123
132
 
124
133
  get kittyProtocolActive(): boolean {
125
134
  return this.#kittyProtocolActive;
@@ -165,8 +174,11 @@ export class ProcessTerminal implements Terminal {
165
174
  // events that lose modifier information. Must run after setRawMode(true)
166
175
  // since that resets console mode flags.
167
176
  this.#enableWindowsVTInput();
168
- // Query and enable Kitty keyboard protocol
169
- // The query handler intercepts input temporarily, then installs the user's handler
177
+ // Query and enable Kitty keyboard protocol.
178
+ // The query handler intercepts input temporarily, then installs the user's handler.
179
+ // On a restart this re-enables the protocol directly from the cached result
180
+ // instead of re-querying (a re-query response would echo as gibberish during
181
+ // a stop/start cooked-mode window).
170
182
  // See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/
171
183
  this.#queryAndEnableKittyProtocol();
172
184
 
@@ -175,7 +187,13 @@ export class ProcessTerminal implements Terminal {
175
187
  // sequences in order, so if DA1 arrives before OSC 11 response,
176
188
  // the terminal does not support OSC 11. This avoids indefinite hangs.
177
189
  // Technique used by Neovim, bat, fish, and terminal-colorsaurus.
178
- this.#queryBackgroundColor();
190
+ //
191
+ // Only on the FIRST start: on a restart we keep the cached appearance and
192
+ // rely on Mode 2031 notifications / the OSC 11 poll to pick up any change,
193
+ // so the query response can never leak during a stop/start cycle.
194
+ if (!this.#hasProbedCapabilities) {
195
+ this.#queryBackgroundColor();
196
+ }
179
197
 
180
198
  // Subscribe to Mode 2031 appearance change notifications.
181
199
  // When the terminal reports a change, we re-query OSC 11 to get the
@@ -186,6 +204,9 @@ export class ProcessTerminal implements Terminal {
186
204
  // (Warp, Alacritty, WezTerm, iTerm2). Self-disables once Mode 2031 fires.
187
205
  this.#startOsc11Poll();
188
206
 
207
+ // Capabilities are now probed; subsequent start() calls re-enable from cache.
208
+ this.#hasProbedCapabilities = true;
209
+
189
210
  // Defer activating the user input handler until terminal capability
190
211
  // queries have settled. Without this, query responses (Kitty, DA1,
191
212
  // OSC 11) race into the editor as typed text.
@@ -273,6 +294,8 @@ export class ProcessTerminal implements Terminal {
273
294
  // Kitty protocol response — always swallow, enable protocol on first match
274
295
  const kittyMatch = sequence.match(kittyResponsePattern);
275
296
  if (kittyMatch) {
297
+ // Remember support so a restart can re-enable without re-querying.
298
+ this.#kittySupported = true;
276
299
  if (!this.#kittyProtocolActive) {
277
300
  if (this.#modifyOtherKeysTimeout) {
278
301
  clearTimeout(this.#modifyOtherKeysTimeout);
@@ -451,6 +474,22 @@ export class ProcessTerminal implements Terminal {
451
474
  #queryAndEnableKittyProtocol(): void {
452
475
  this.#setupStdinBuffer();
453
476
  process.stdin.on("data", this.#stdinDataHandler!);
477
+
478
+ // Restart path: capabilities are already known. Re-enable the keyboard
479
+ // protocol directly — no query means no response means nothing to echo as
480
+ // gibberish during the cooked-mode window of a stop/start cycle.
481
+ if (this.#hasProbedCapabilities) {
482
+ if (this.#kittySupported) {
483
+ this.#kittyProtocolActive = true;
484
+ setKittyProtocolActive(true);
485
+ this.#safeWrite("\x1b[>7u");
486
+ } else if (this.#modifyOtherKeysSupported) {
487
+ this.#safeWrite("\x1b[>4;2m");
488
+ this.#modifyOtherKeysActive = true;
489
+ }
490
+ return;
491
+ }
492
+
454
493
  this.#safeWrite("\x1b[?u");
455
494
  this.#modifyOtherKeysTimeout = setTimeout(() => {
456
495
  this.#modifyOtherKeysTimeout = undefined;
@@ -459,10 +498,15 @@ export class ProcessTerminal implements Terminal {
459
498
  }
460
499
  this.#safeWrite("\x1b[>4;2m");
461
500
  this.#modifyOtherKeysActive = true;
501
+ this.#modifyOtherKeysSupported = true;
462
502
  }, 150);
463
503
  }
464
504
 
465
505
  async drainInput(maxMs = 1000, idleMs = 50): Promise<void> {
506
+ // Stop the periodic OSC 11 poll first. drainInput precedes relinquishing
507
+ // the TTY (exit, or a cooked-mode subprocess); a poll query fired now would
508
+ // have its response echoed as gibberish once raw mode is gone.
509
+ this.#stopOsc11Poll();
466
510
  if (this.#kittyProtocolActive) {
467
511
  // Disable Kitty keyboard protocol first so any late key releases
468
512
  // do not generate new Kitty escape sequences.
package/src/tui.ts CHANGED
@@ -580,6 +580,18 @@ export class TUI extends Container {
580
580
  this.terminal.stop();
581
581
  }
582
582
 
583
+ /**
584
+ * Suspend the UI to hand the TTY to a cooked-mode subprocess (e.g. an
585
+ * interactive `aws sso login`). Drains pending terminal input while still in
586
+ * raw mode, then stops — so a late capability-probe response (notably the
587
+ * periodic OSC 11 poll) cannot be echoed as gibberish during the cooked-mode
588
+ * window. Pair with start() once the subprocess exits.
589
+ */
590
+ async suspendForSubprocess(maxDrainMs = 150): Promise<void> {
591
+ await this.terminal.drainInput(maxDrainMs);
592
+ this.stop();
593
+ }
594
+
583
595
  requestRender(force = false): void {
584
596
  if (force) {
585
597
  this.#previousLines = [];