pty-manager 1.2.21 → 1.2.22
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 +17 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +76 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +76 -7
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +71 -7
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -268,7 +268,7 @@ var SPECIAL_KEYS = {
|
|
|
268
268
|
};
|
|
269
269
|
var BRACKETED_PASTE_START = "\x1B[200~";
|
|
270
270
|
var BRACKETED_PASTE_END = "\x1B[201~";
|
|
271
|
-
var PTYSession = class extends EventEmitter {
|
|
271
|
+
var PTYSession = class _PTYSession extends EventEmitter {
|
|
272
272
|
constructor(adapter, config, logger, stallDetectionEnabled, defaultStallTimeoutMs) {
|
|
273
273
|
super();
|
|
274
274
|
this.adapter = adapter;
|
|
@@ -306,6 +306,9 @@ var PTYSession = class extends EventEmitter {
|
|
|
306
306
|
_lastStallHash = null;
|
|
307
307
|
_stallStartedAt = null;
|
|
308
308
|
_lastContentHash = null;
|
|
309
|
+
// Task completion detection (idle detection when busy)
|
|
310
|
+
_taskCompleteTimer = null;
|
|
311
|
+
static TASK_COMPLETE_DEBOUNCE_MS = 1500;
|
|
309
312
|
id;
|
|
310
313
|
config;
|
|
311
314
|
get status() {
|
|
@@ -481,10 +484,12 @@ var PTYSession = class extends EventEmitter {
|
|
|
481
484
|
* word boundaries — e.g. "Do\x1b[5Cyou" becomes "Do you", not "Doyou".
|
|
482
485
|
*/
|
|
483
486
|
stripAnsiForStall(str) {
|
|
484
|
-
let result = str.replace(/\x1b\[\d*[
|
|
487
|
+
let result = str.replace(/\x1b\[\d*[CDABGdEF]/g, " ");
|
|
485
488
|
result = result.replace(/\x1b\[\d*(?:;\d+)?[Hf]/g, " ");
|
|
489
|
+
result = result.replace(/\x1b\[\d*[JK]/g, " ");
|
|
486
490
|
result = result.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
487
|
-
result = result.replace(/[
|
|
491
|
+
result = result.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
492
|
+
result = result.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆◇▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥]/g, " ");
|
|
488
493
|
result = result.replace(/ {2,}/g, " ");
|
|
489
494
|
return result;
|
|
490
495
|
}
|
|
@@ -542,6 +547,39 @@ var PTYSession = class extends EventEmitter {
|
|
|
542
547
|
}
|
|
543
548
|
}
|
|
544
549
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
550
|
+
// Task Completion Detection
|
|
551
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
552
|
+
/**
|
|
553
|
+
* Schedule a task_complete transition after a debounce period.
|
|
554
|
+
* If new non-whitespace output arrives before the timer fires,
|
|
555
|
+
* the timer is cancelled (by cancelTaskComplete in onData).
|
|
556
|
+
*/
|
|
557
|
+
scheduleTaskComplete() {
|
|
558
|
+
if (this._taskCompleteTimer) return;
|
|
559
|
+
this._taskCompleteTimer = setTimeout(() => {
|
|
560
|
+
this._taskCompleteTimer = null;
|
|
561
|
+
if (this._status !== "busy") return;
|
|
562
|
+
if (!this.adapter.detectReady(this.outputBuffer)) return;
|
|
563
|
+
this._status = "ready";
|
|
564
|
+
this._lastBlockingPromptHash = null;
|
|
565
|
+
this.outputBuffer = "";
|
|
566
|
+
this.clearStallTimer();
|
|
567
|
+
this.emit("status_changed", "ready");
|
|
568
|
+
this.emit("task_complete");
|
|
569
|
+
this.logger.info({ sessionId: this.id }, "Task complete \u2014 agent returned to idle prompt");
|
|
570
|
+
}, _PTYSession.TASK_COMPLETE_DEBOUNCE_MS);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Cancel a pending task_complete timer (new output arrived that
|
|
574
|
+
* doesn't match the idle prompt, so the agent is still working).
|
|
575
|
+
*/
|
|
576
|
+
cancelTaskComplete() {
|
|
577
|
+
if (this._taskCompleteTimer) {
|
|
578
|
+
clearTimeout(this._taskCompleteTimer);
|
|
579
|
+
this._taskCompleteTimer = null;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
545
583
|
// Lifecycle
|
|
546
584
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
547
585
|
/**
|
|
@@ -603,10 +641,6 @@ var PTYSession = class extends EventEmitter {
|
|
|
603
641
|
this.resetStallTimer();
|
|
604
642
|
}
|
|
605
643
|
this.emit("output", data);
|
|
606
|
-
const blockingPrompt = this.detectAndHandleBlockingPrompt();
|
|
607
|
-
if (blockingPrompt) {
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
644
|
if ((this._status === "starting" || this._status === "authenticating") && this.adapter.detectReady(this.outputBuffer)) {
|
|
611
645
|
this._status = "ready";
|
|
612
646
|
this._lastBlockingPromptHash = null;
|
|
@@ -616,6 +650,15 @@ var PTYSession = class extends EventEmitter {
|
|
|
616
650
|
this.logger.info({ sessionId: this.id }, "Session ready");
|
|
617
651
|
return;
|
|
618
652
|
}
|
|
653
|
+
if (this._status === "busy" && this.adapter.detectReady(this.outputBuffer)) {
|
|
654
|
+
this.scheduleTaskComplete();
|
|
655
|
+
} else {
|
|
656
|
+
this.cancelTaskComplete();
|
|
657
|
+
}
|
|
658
|
+
const blockingPrompt = this.detectAndHandleBlockingPrompt();
|
|
659
|
+
if (blockingPrompt) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
619
662
|
if (this._status !== "ready" && this._status !== "busy") {
|
|
620
663
|
const loginDetection = this.adapter.detectLogin(this.outputBuffer);
|
|
621
664
|
if (loginDetection.required && this._status !== "authenticating") {
|
|
@@ -838,6 +881,7 @@ var PTYSession = class extends EventEmitter {
|
|
|
838
881
|
*/
|
|
839
882
|
send(message) {
|
|
840
883
|
this._status = "busy";
|
|
884
|
+
this.emit("status_changed", "busy");
|
|
841
885
|
this.resetStallTimer();
|
|
842
886
|
const msg = {
|
|
843
887
|
id: `${this.id}-msg-${++this.messageCounter}`,
|
|
@@ -948,6 +992,7 @@ var PTYSession = class extends EventEmitter {
|
|
|
948
992
|
if (this.ptyProcess) {
|
|
949
993
|
this._status = "stopping";
|
|
950
994
|
this.clearStallTimer();
|
|
995
|
+
this.cancelTaskComplete();
|
|
951
996
|
this.ptyProcess.kill(signal);
|
|
952
997
|
this.logger.info({ sessionId: this.id, signal }, "Killing PTY session");
|
|
953
998
|
}
|
|
@@ -1101,6 +1146,12 @@ var PTYManager = class extends EventEmitter2 {
|
|
|
1101
1146
|
session.on("error", (error) => {
|
|
1102
1147
|
this.emit("session_error", session.toHandle(), error.message);
|
|
1103
1148
|
});
|
|
1149
|
+
session.on("status_changed", () => {
|
|
1150
|
+
this.emit("session_status_changed", session.toHandle());
|
|
1151
|
+
});
|
|
1152
|
+
session.on("task_complete", () => {
|
|
1153
|
+
this.emit("task_complete", session.toHandle());
|
|
1154
|
+
});
|
|
1104
1155
|
session.on("stall_detected", (recentOutput, stallDurationMs) => {
|
|
1105
1156
|
const handle = session.toHandle();
|
|
1106
1157
|
this.emit("stall_detected", handle, recentOutput, stallDurationMs);
|
|
@@ -1954,6 +2005,24 @@ var BunCompatiblePTYManager = class extends EventEmitter3 {
|
|
|
1954
2005
|
}
|
|
1955
2006
|
break;
|
|
1956
2007
|
}
|
|
2008
|
+
case "status_changed": {
|
|
2009
|
+
const session = this.sessions.get(id);
|
|
2010
|
+
if (session) {
|
|
2011
|
+
session.status = event.status;
|
|
2012
|
+
session.lastActivityAt = /* @__PURE__ */ new Date();
|
|
2013
|
+
this.emit("session_status_changed", session);
|
|
2014
|
+
}
|
|
2015
|
+
break;
|
|
2016
|
+
}
|
|
2017
|
+
case "task_complete": {
|
|
2018
|
+
const session = this.sessions.get(id);
|
|
2019
|
+
if (session) {
|
|
2020
|
+
session.status = "ready";
|
|
2021
|
+
session.lastActivityAt = /* @__PURE__ */ new Date();
|
|
2022
|
+
this.emit("task_complete", session);
|
|
2023
|
+
}
|
|
2024
|
+
break;
|
|
2025
|
+
}
|
|
1957
2026
|
case "stall_detected": {
|
|
1958
2027
|
const session = this.sessions.get(id);
|
|
1959
2028
|
if (session) {
|