pty-manager 1.2.15 → 1.2.17

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/dist/index.d.mts CHANGED
@@ -422,6 +422,7 @@ declare class PTYSession extends EventEmitter {
422
422
  private _stallDetectionEnabled;
423
423
  private _lastStallHash;
424
424
  private _stallStartedAt;
425
+ private _lastContentHash;
425
426
  readonly id: string;
426
427
  readonly config: SpawnConfig;
427
428
  constructor(adapter: CLIAdapter, config: SpawnConfig, logger?: Logger, stallDetectionEnabled?: boolean, defaultStallTimeoutMs?: number);
@@ -453,7 +454,12 @@ declare class PTYSession extends EventEmitter {
453
454
  clearAutoResponseRules(): void;
454
455
  /**
455
456
  * Start or reset the stall detection timer.
456
- * Only active when status is "busy" and stall detection is enabled.
457
+ * Active when status is "busy" or "authenticating" and stall detection is enabled.
458
+ *
459
+ * Content-based: hashes the ANSI-stripped buffer tail and only resets the
460
+ * timer when visible content actually changes. This prevents TUI spinners
461
+ * (which produce new ANSI sequences but no new visible text) from endlessly
462
+ * resetting the timer.
457
463
  */
458
464
  private resetStallTimer;
459
465
  /**
@@ -829,7 +835,7 @@ interface WorkerSessionHandle {
829
835
  id: string;
830
836
  name: string;
831
837
  type: string;
832
- status: 'starting' | 'ready' | 'stopped' | 'error';
838
+ status: SessionStatus;
833
839
  pid: number | undefined;
834
840
  cols: number;
835
841
  rows: number;
package/dist/index.d.ts CHANGED
@@ -422,6 +422,7 @@ declare class PTYSession extends EventEmitter {
422
422
  private _stallDetectionEnabled;
423
423
  private _lastStallHash;
424
424
  private _stallStartedAt;
425
+ private _lastContentHash;
425
426
  readonly id: string;
426
427
  readonly config: SpawnConfig;
427
428
  constructor(adapter: CLIAdapter, config: SpawnConfig, logger?: Logger, stallDetectionEnabled?: boolean, defaultStallTimeoutMs?: number);
@@ -453,7 +454,12 @@ declare class PTYSession extends EventEmitter {
453
454
  clearAutoResponseRules(): void;
454
455
  /**
455
456
  * Start or reset the stall detection timer.
456
- * Only active when status is "busy" and stall detection is enabled.
457
+ * Active when status is "busy" or "authenticating" and stall detection is enabled.
458
+ *
459
+ * Content-based: hashes the ANSI-stripped buffer tail and only resets the
460
+ * timer when visible content actually changes. This prevents TUI spinners
461
+ * (which produce new ANSI sequences but no new visible text) from endlessly
462
+ * resetting the timer.
457
463
  */
458
464
  private resetStallTimer;
459
465
  /**
@@ -829,7 +835,7 @@ interface WorkerSessionHandle {
829
835
  id: string;
830
836
  name: string;
831
837
  type: string;
832
- status: 'starting' | 'ready' | 'stopped' | 'error';
838
+ status: SessionStatus;
833
839
  pid: number | undefined;
834
840
  cols: number;
835
841
  rows: number;
package/dist/index.js CHANGED
@@ -331,6 +331,7 @@ var PTYSession = class extends import_events.EventEmitter {
331
331
  _stallDetectionEnabled;
332
332
  _lastStallHash = null;
333
333
  _stallStartedAt = null;
334
+ _lastContentHash = null;
334
335
  id;
335
336
  config;
336
337
  get status() {
@@ -416,13 +417,29 @@ var PTYSession = class extends import_events.EventEmitter {
416
417
  // ─────────────────────────────────────────────────────────────────────────────
417
418
  /**
418
419
  * Start or reset the stall detection timer.
419
- * Only active when status is "busy" and stall detection is enabled.
420
+ * Active when status is "busy" or "authenticating" and stall detection is enabled.
421
+ *
422
+ * Content-based: hashes the ANSI-stripped buffer tail and only resets the
423
+ * timer when visible content actually changes. This prevents TUI spinners
424
+ * (which produce new ANSI sequences but no new visible text) from endlessly
425
+ * resetting the timer.
420
426
  */
421
427
  resetStallTimer() {
422
- this.clearStallTimer();
423
- if (!this._stallDetectionEnabled || this._status !== "busy") {
428
+ if (!this._stallDetectionEnabled || this._status !== "busy" && this._status !== "authenticating") {
429
+ this.clearStallTimer();
430
+ return;
431
+ }
432
+ const tail = this.outputBuffer.slice(-500);
433
+ const stripped = this.stripAnsiForStall(tail);
434
+ const hash = this.simpleHash(stripped);
435
+ if (hash === this._lastContentHash) {
424
436
  return;
425
437
  }
438
+ this._lastContentHash = hash;
439
+ if (this._stallTimer) {
440
+ clearTimeout(this._stallTimer);
441
+ this._stallTimer = null;
442
+ }
426
443
  this._stallStartedAt = Date.now();
427
444
  this._lastStallHash = null;
428
445
  this._stallTimer = setTimeout(() => {
@@ -438,12 +455,13 @@ var PTYSession = class extends import_events.EventEmitter {
438
455
  this._stallTimer = null;
439
456
  }
440
457
  this._stallStartedAt = null;
458
+ this._lastContentHash = null;
441
459
  }
442
460
  /**
443
461
  * Called when the stall timer fires (no output for stallTimeoutMs).
444
462
  */
445
463
  onStallTimerFired() {
446
- if (this._status !== "busy") {
464
+ if (this._status !== "busy" && this._status !== "authenticating") {
447
465
  return;
448
466
  }
449
467
  const tail = this.outputBuffer.slice(-500);
@@ -494,10 +512,11 @@ var PTYSession = class extends import_events.EventEmitter {
494
512
  * Called by the manager after onStallClassify resolves.
495
513
  */
496
514
  handleStallClassification(classification) {
497
- if (this._status !== "busy") {
515
+ if (this._status !== "busy" && this._status !== "authenticating") {
498
516
  return;
499
517
  }
500
518
  if (!classification || classification.state === "still_working") {
519
+ this._lastContentHash = null;
501
520
  this.resetStallTimer();
502
521
  return;
503
522
  }
@@ -598,10 +617,14 @@ var PTYSession = class extends import_events.EventEmitter {
598
617
  this.ptyProcess.onData((data) => {
599
618
  this._lastActivityAt = /* @__PURE__ */ new Date();
600
619
  this.outputBuffer += data;
601
- if (this._status === "busy") {
620
+ if (this._status === "busy" || this._status === "authenticating") {
602
621
  this.resetStallTimer();
603
622
  }
604
623
  this.emit("output", data);
624
+ const blockingPrompt = this.detectAndHandleBlockingPrompt();
625
+ if (blockingPrompt) {
626
+ return;
627
+ }
605
628
  if ((this._status === "starting" || this._status === "authenticating") && this.adapter.detectReady(this.outputBuffer)) {
606
629
  this._status = "ready";
607
630
  this._lastBlockingPromptHash = null;
@@ -611,10 +634,6 @@ var PTYSession = class extends import_events.EventEmitter {
611
634
  this.logger.info({ sessionId: this.id }, "Session ready");
612
635
  return;
613
636
  }
614
- const blockingPrompt = this.detectAndHandleBlockingPrompt();
615
- if (blockingPrompt) {
616
- return;
617
- }
618
637
  if (this._status !== "ready" && this._status !== "busy") {
619
638
  const loginDetection = this.adapter.detectLogin(this.outputBuffer);
620
639
  if (loginDetection.required && this._status !== "authenticating") {
@@ -1921,6 +1940,7 @@ var BunCompatiblePTYManager = class extends import_events3.EventEmitter {
1921
1940
  case "login_required": {
1922
1941
  const session = this.sessions.get(id);
1923
1942
  if (session) {
1943
+ session.status = "authenticating";
1924
1944
  this.emit("login_required", session, event.instructions, event.url);
1925
1945
  }
1926
1946
  break;