pty-manager 1.2.22 → 1.3.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.
- package/README.md +36 -2
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +22 -0
- package/dist/index.mjs.map +1 -1
- package/dist/pty-worker.js +14 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,6 +10,7 @@ PTY session manager with lifecycle management, pluggable adapters, and blocking
|
|
|
10
10
|
- **Auto-response rules** - Automatically respond to known prompts with text or key sequences
|
|
11
11
|
- **TUI menu navigation** - Navigate arrow-key menus via `selectMenuOption()` and key-sequence rules
|
|
12
12
|
- **Stall detection** - Content-based stall detection with pluggable external classifiers
|
|
13
|
+
- **Task completion detection** - Adapter-level fast-path that short-circuits the LLM stall classifier when the CLI returns to its idle prompt
|
|
13
14
|
- **Terminal attachment** - Attach to sessions for raw I/O streaming
|
|
14
15
|
- **Special key support** - Send Ctrl, Alt, Shift, and function key combinations via `sendKeys()`
|
|
15
16
|
- **Bracketed paste** - Proper paste handling with bracketed paste mode support
|
|
@@ -130,6 +131,11 @@ class MyCLIAdapter extends BaseCLIAdapter {
|
|
|
130
131
|
return /ready>/.test(output);
|
|
131
132
|
}
|
|
132
133
|
|
|
134
|
+
// Optional: high-confidence task completion detection
|
|
135
|
+
detectTaskComplete(output) {
|
|
136
|
+
return /done in \d+s/.test(output) && /ready>/.test(output);
|
|
137
|
+
}
|
|
138
|
+
|
|
133
139
|
parseOutput(output) {
|
|
134
140
|
return {
|
|
135
141
|
type: 'response',
|
|
@@ -189,6 +195,8 @@ class PTYManager extends EventEmitter {
|
|
|
189
195
|
| `blocking_prompt` | `SessionHandle, promptInfo, autoResponded` | Prompt detected |
|
|
190
196
|
| `message` | `SessionMessage` | Parsed message received |
|
|
191
197
|
| `question` | `SessionHandle, question` | Question detected |
|
|
198
|
+
| `stall_detected` | `SessionHandle, recentOutput, stallDurationMs` | Output stalled, needs classification |
|
|
199
|
+
| `task_complete` | `SessionHandle` | Agent finished task, returned to idle |
|
|
192
200
|
|
|
193
201
|
### SpawnConfig
|
|
194
202
|
|
|
@@ -435,9 +443,11 @@ Adapters can declare `usesTuiMenus: true` to indicate they use arrow-key menus i
|
|
|
435
443
|
await session.selectMenuOption(2); // Sends Down, Down, Enter with 50ms delays
|
|
436
444
|
```
|
|
437
445
|
|
|
438
|
-
## Stall Detection
|
|
446
|
+
## Stall Detection & Task Completion
|
|
439
447
|
|
|
440
|
-
Content-based stall detection monitors sessions for output that stops changing. When a stall is detected, the session
|
|
448
|
+
Content-based stall detection monitors sessions for output that stops changing. The content hash normalizes ANSI escape codes, TUI spinner characters, and countdown/duration text (e.g. `8m 17s` → constant) so that live timers don't perpetually reset the stall timer. When a stall is detected, the session first tries the adapter's `detectTaskComplete()` fast-path. If the adapter recognizes the output as a completed task (e.g. duration summary + idle prompt), it transitions directly to `ready` and emits `task_complete` — skipping the expensive LLM stall classifier entirely.
|
|
449
|
+
|
|
450
|
+
If the adapter doesn't recognize the output, the session falls back to emitting `stall_detected` for external classification.
|
|
441
451
|
|
|
442
452
|
```typescript
|
|
443
453
|
// Enable stall detection with a pluggable classifier
|
|
@@ -460,6 +470,30 @@ const session = await manager.spawn({
|
|
|
460
470
|
});
|
|
461
471
|
```
|
|
462
472
|
|
|
473
|
+
### Adapter-Level Task Completion (Fast Path)
|
|
474
|
+
|
|
475
|
+
Adapters can implement `detectTaskComplete(output)` to recognize high-confidence completion patterns specific to their CLI. This avoids the latency and cost of an LLM classifier call.
|
|
476
|
+
|
|
477
|
+
```typescript
|
|
478
|
+
class MyCLIAdapter extends BaseCLIAdapter {
|
|
479
|
+
// ...
|
|
480
|
+
|
|
481
|
+
detectTaskComplete(output: string): boolean {
|
|
482
|
+
// Match CLI-specific patterns that indicate work is done
|
|
483
|
+
return /completed in \d+s/.test(output) && /my-cli>/.test(output);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
The default `BaseCLIAdapter` implementation delegates to `detectReady()`. Coding agent adapters override this with CLI-specific patterns:
|
|
489
|
+
|
|
490
|
+
| Adapter | Completion Indicators |
|
|
491
|
+
|---------|----------------------|
|
|
492
|
+
| Claude Code | Turn duration (`Cooked for 3m 12s`) + `❯` prompt |
|
|
493
|
+
| Gemini CLI | `◇ Ready` window title, `Type your message` composer |
|
|
494
|
+
| Codex | `Worked for 1m 05s` separator + `›` prompt |
|
|
495
|
+
| Aider | `Aider is waiting for your input`, mode prompts with edit markers |
|
|
496
|
+
|
|
463
497
|
## Blocking Prompt Types
|
|
464
498
|
|
|
465
499
|
The library recognizes these blocking prompt types:
|
package/dist/index.d.mts
CHANGED
|
@@ -334,6 +334,15 @@ interface CLIAdapter {
|
|
|
334
334
|
* Get prompt pattern to detect when CLI is waiting for input
|
|
335
335
|
*/
|
|
336
336
|
getPromptPattern(): RegExp;
|
|
337
|
+
/**
|
|
338
|
+
* Optional: Detect if the CLI has completed a task and returned to its idle prompt.
|
|
339
|
+
* More specific than detectReady — matches high-confidence completion indicators
|
|
340
|
+
* (e.g. duration summaries, explicit "done" messages) alongside the idle prompt.
|
|
341
|
+
*
|
|
342
|
+
* Used as a fast-path in stall detection to avoid expensive LLM classifier calls.
|
|
343
|
+
* If not implemented, the stall classifier is used as the fallback.
|
|
344
|
+
*/
|
|
345
|
+
detectTaskComplete?(output: string): boolean;
|
|
337
346
|
/**
|
|
338
347
|
* Optional: Validate that the CLI is installed and accessible
|
|
339
348
|
*/
|
|
@@ -774,6 +783,12 @@ declare abstract class BaseCLIAdapter implements CLIAdapter {
|
|
|
774
783
|
* Subclasses should override for CLI-specific detection.
|
|
775
784
|
*/
|
|
776
785
|
detectBlockingPrompt(output: string): BlockingPromptDetection;
|
|
786
|
+
/**
|
|
787
|
+
* Default task completion detection — delegates to detectReady().
|
|
788
|
+
* Subclasses should override to match high-confidence completion patterns
|
|
789
|
+
* (e.g. duration summaries) that short-circuit the LLM stall classifier.
|
|
790
|
+
*/
|
|
791
|
+
detectTaskComplete(output: string): boolean;
|
|
777
792
|
/**
|
|
778
793
|
* Default input formatting - just return as-is
|
|
779
794
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -334,6 +334,15 @@ interface CLIAdapter {
|
|
|
334
334
|
* Get prompt pattern to detect when CLI is waiting for input
|
|
335
335
|
*/
|
|
336
336
|
getPromptPattern(): RegExp;
|
|
337
|
+
/**
|
|
338
|
+
* Optional: Detect if the CLI has completed a task and returned to its idle prompt.
|
|
339
|
+
* More specific than detectReady — matches high-confidence completion indicators
|
|
340
|
+
* (e.g. duration summaries, explicit "done" messages) alongside the idle prompt.
|
|
341
|
+
*
|
|
342
|
+
* Used as a fast-path in stall detection to avoid expensive LLM classifier calls.
|
|
343
|
+
* If not implemented, the stall classifier is used as the fallback.
|
|
344
|
+
*/
|
|
345
|
+
detectTaskComplete?(output: string): boolean;
|
|
337
346
|
/**
|
|
338
347
|
* Optional: Validate that the CLI is installed and accessible
|
|
339
348
|
*/
|
|
@@ -774,6 +783,12 @@ declare abstract class BaseCLIAdapter implements CLIAdapter {
|
|
|
774
783
|
* Subclasses should override for CLI-specific detection.
|
|
775
784
|
*/
|
|
776
785
|
detectBlockingPrompt(output: string): BlockingPromptDetection;
|
|
786
|
+
/**
|
|
787
|
+
* Default task completion detection — delegates to detectReady().
|
|
788
|
+
* Subclasses should override to match high-confidence completion patterns
|
|
789
|
+
* (e.g. duration summaries) that short-circuit the LLM stall classifier.
|
|
790
|
+
*/
|
|
791
|
+
detectTaskComplete(output: string): boolean;
|
|
777
792
|
/**
|
|
778
793
|
* Default input formatting - just return as-is
|
|
779
794
|
*/
|
package/dist/index.js
CHANGED
|
@@ -486,6 +486,19 @@ var PTYSession = class _PTYSession extends import_events.EventEmitter {
|
|
|
486
486
|
return;
|
|
487
487
|
}
|
|
488
488
|
this._lastStallHash = hash;
|
|
489
|
+
if (this._status === "busy" && this.adapter.detectTaskComplete?.(this.outputBuffer)) {
|
|
490
|
+
this._status = "ready";
|
|
491
|
+
this._lastBlockingPromptHash = null;
|
|
492
|
+
this.outputBuffer = "";
|
|
493
|
+
this.clearStallTimer();
|
|
494
|
+
this.emit("status_changed", "ready");
|
|
495
|
+
this.emit("task_complete");
|
|
496
|
+
this.logger.info(
|
|
497
|
+
{ sessionId: this.id },
|
|
498
|
+
"Task complete (adapter fast-path) \u2014 agent returned to idle prompt"
|
|
499
|
+
);
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
489
502
|
const recentRaw = this.outputBuffer.slice(-2e3);
|
|
490
503
|
const recentOutput = this.stripAnsiForStall(recentRaw);
|
|
491
504
|
const stallDurationMs = this._stallStartedAt ? Date.now() - this._stallStartedAt : this._stallTimeoutMs;
|
|
@@ -528,6 +541,7 @@ var PTYSession = class _PTYSession extends import_events.EventEmitter {
|
|
|
528
541
|
result = result.replace(/\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])/g, "");
|
|
529
542
|
result = result.replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g, "");
|
|
530
543
|
result = result.replace(/[│╭╰╮╯─═╌║╔╗╚╝╠╣╦╩╬┌┐└┘├┤┬┴┼●○❯❮▶◀⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏⣾⣽⣻⢿⡿⣟⣯⣷✻✶✳✢⏺←→↑↓⬆⬇◆◇▪▫■□▲△▼▽◈⟨⟩⌘⏎⏏⌫⌦⇧⇪⌥]/g, " ");
|
|
544
|
+
result = result.replace(/\d+[hms](?:\s+\d+[hms])*/g, "0s");
|
|
531
545
|
result = result.replace(/ {2,}/g, " ");
|
|
532
546
|
return result;
|
|
533
547
|
}
|
|
@@ -1594,6 +1608,14 @@ var BaseCLIAdapter = class {
|
|
|
1594
1608
|
}
|
|
1595
1609
|
return { detected: false };
|
|
1596
1610
|
}
|
|
1611
|
+
/**
|
|
1612
|
+
* Default task completion detection — delegates to detectReady().
|
|
1613
|
+
* Subclasses should override to match high-confidence completion patterns
|
|
1614
|
+
* (e.g. duration summaries) that short-circuit the LLM stall classifier.
|
|
1615
|
+
*/
|
|
1616
|
+
detectTaskComplete(output) {
|
|
1617
|
+
return this.detectReady(output);
|
|
1618
|
+
}
|
|
1597
1619
|
/**
|
|
1598
1620
|
* Default input formatting - just return as-is
|
|
1599
1621
|
*/
|