pi-interactive-shell 0.8.2 → 0.10.0
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/CHANGELOG.md +47 -1
- package/README.md +22 -14
- package/SKILL.md +4 -2
- package/background-widget.ts +76 -0
- package/config.ts +4 -4
- package/examples/prompts/codex-implement-plan.md +18 -7
- package/examples/prompts/codex-review-impl.md +16 -5
- package/examples/prompts/codex-review-plan.md +20 -10
- package/examples/skills/codex-5-3-prompting/SKILL.md +161 -0
- package/examples/skills/codex-cli/SKILL.md +16 -8
- package/examples/skills/gpt-5-4-prompting/SKILL.md +202 -0
- package/handoff-utils.ts +92 -0
- package/headless-monitor.ts +16 -3
- package/index.ts +240 -384
- package/notification-utils.ts +134 -0
- package/overlay-component.ts +61 -248
- package/package.json +26 -6
- package/pty-log.ts +59 -0
- package/pty-protocol.ts +33 -0
- package/pty-session.ts +11 -134
- package/reattach-overlay.ts +6 -74
- package/runtime-coordinator.ts +69 -0
- package/scripts/install.js +18 -3
- package/session-manager.ts +21 -11
- package/session-query.ts +170 -0
- package/spawn-helper.ts +37 -0
- package/tool-schema.ts +6 -2
- package/types.ts +6 -0
|
@@ -23,7 +23,7 @@ description: OpenAI Codex CLI reference. Use when running codex in interactive_s
|
|
|
23
23
|
|
|
24
24
|
| Flag | Description |
|
|
25
25
|
|------|-------------|
|
|
26
|
-
| `-m, --model <model>` | Switch model (default: `gpt-5.3-codex`) |
|
|
26
|
+
| `-m, --model <model>` | Switch model (default: `gpt-5.3-codex`). Options include `gpt-5.4` (newer, more thorough) and `gpt-5.3-codex` (faster) |
|
|
27
27
|
| `-c <key=value>` | Override config.toml values (dotted paths, parsed as TOML) |
|
|
28
28
|
| `-p, --profile <name>` | Use config profile from config.toml |
|
|
29
29
|
| `-s, --sandbox <mode>` | Sandbox policy: `read-only`, `workspace-write`, `danger-full-access` |
|
|
@@ -66,19 +66,27 @@ Define profiles for different projects/modes with `[profiles.<name>]` sections.
|
|
|
66
66
|
|
|
67
67
|
Do NOT pass `-s` / `--sandbox` flags. Codex's `read-only` and `workspace-write` sandbox modes apply OS-level filesystem restrictions that break basic shell operations inside the PTY -- zsh can't even create temp files for here-documents, so every write attempt fails with "operation not permitted." The interactive shell overlay already provides supervision (user watches in real-time, Ctrl+Q to kill, Ctrl+T to transfer output), making Codex's sandbox redundant.
|
|
68
68
|
|
|
69
|
-
Use explicit flags to control model and behavior per-run
|
|
69
|
+
Use explicit flags to control model and behavior per-run.
|
|
70
|
+
|
|
71
|
+
For delegated fire-and-forget runs, prefer `mode: "dispatch"` so the agent is notified automatically when Codex completes.
|
|
70
72
|
|
|
71
73
|
```typescript
|
|
72
|
-
//
|
|
74
|
+
// Delegated run with gpt-5.4 (recommended for thorough work)
|
|
75
|
+
interactive_shell({
|
|
76
|
+
command: 'codex -m gpt-5.4 -a never "Review this codebase for security issues"',
|
|
77
|
+
mode: "dispatch"
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Faster run with gpt-5.3-codex
|
|
73
81
|
interactive_shell({
|
|
74
|
-
command: 'codex -m gpt-5.3-codex -a never "
|
|
75
|
-
mode: "
|
|
82
|
+
command: 'codex -m gpt-5.3-codex -a never "Quick refactor task"',
|
|
83
|
+
mode: "dispatch"
|
|
76
84
|
})
|
|
77
85
|
|
|
78
|
-
// Override reasoning effort for
|
|
86
|
+
// Override reasoning effort for complex tasks
|
|
79
87
|
interactive_shell({
|
|
80
|
-
command: 'codex -m gpt-5.
|
|
81
|
-
mode: "
|
|
88
|
+
command: 'codex -m gpt-5.4 -c model_reasoning_effort="xhigh" -a never "Complex architecture review"',
|
|
89
|
+
mode: "dispatch"
|
|
82
90
|
})
|
|
83
91
|
|
|
84
92
|
// Headless - use bash instead
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gpt-5-4-prompting
|
|
3
|
+
description: How to write system prompts and instructions for GPT-5.4. Use when constructing or tuning prompts targeting GPT-5.4.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GPT-5.4 Prompting Guide
|
|
7
|
+
|
|
8
|
+
GPT-5.4 unifies reasoning, coding, and agentic capabilities into a single frontier model. It's extremely persistent, highly token-efficient, and delivers more human-like outputs than its predecessors. However, it has new failure modes: it moves fast without solid plans, expands scope aggressively, and can prematurely declare tasks complete—sometimes falsely claiming success. Prompts must account for these behaviors.
|
|
9
|
+
|
|
10
|
+
## Output shape
|
|
11
|
+
|
|
12
|
+
Always include.
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
<output_verbosity_spec>
|
|
16
|
+
- Default: 3-6 sentences or <=5 bullets for typical answers.
|
|
17
|
+
- Simple yes/no questions: <=2 sentences.
|
|
18
|
+
- Complex multi-step or multi-file tasks:
|
|
19
|
+
- 1 short overview paragraph
|
|
20
|
+
- then <=5 bullets tagged: What changed, Where, Risks, Next steps, Open questions.
|
|
21
|
+
- Avoid long narrative paragraphs; prefer compact bullets and short sections.
|
|
22
|
+
- Do not rephrase the user's request unless it changes semantics.
|
|
23
|
+
</output_verbosity_spec>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Scope constraints
|
|
27
|
+
|
|
28
|
+
Critical. GPT-5.4's primary failure mode is scope expansion—it adds features, refactors beyond the ask, and "helpfully" extends tasks. Fence it in hard.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
<design_and_scope_constraints>
|
|
32
|
+
- Implement EXACTLY and ONLY what the user requests. Nothing more.
|
|
33
|
+
- No extra features, no "while I'm here" improvements, no UX embellishments.
|
|
34
|
+
- Do NOT expand the task scope under any circumstances.
|
|
35
|
+
- If you notice adjacent issues or opportunities, note them in your summary but DO NOT act on them.
|
|
36
|
+
- If any instruction is ambiguous, choose the simplest valid interpretation.
|
|
37
|
+
- Style aligned to the existing design system. Do not invent new patterns.
|
|
38
|
+
- Do NOT invent colors, shadows, tokens, animations, or new UI elements unless explicitly requested.
|
|
39
|
+
</design_and_scope_constraints>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Verification requirements
|
|
43
|
+
|
|
44
|
+
Critical. GPT-5.4 can declare tasks complete prematurely or claim success when the implementation is incorrect. Force explicit verification.
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
<verification_requirements>
|
|
48
|
+
- Before declaring any task complete, perform explicit verification:
|
|
49
|
+
- Re-read the original requirements
|
|
50
|
+
- Check that every requirement is addressed in the actual code
|
|
51
|
+
- Run tests or validation steps if available
|
|
52
|
+
- Confirm the implementation actually works, don't assume
|
|
53
|
+
- Do NOT claim success based on intent—verify actual outcomes.
|
|
54
|
+
- If you cannot verify (no tests, can't run code), say so explicitly.
|
|
55
|
+
- When reporting completion, include concrete evidence: test results, verified file contents, or explicit acknowledgment of what couldn't be verified.
|
|
56
|
+
- If something failed or was skipped, say so clearly. Do not obscure failures.
|
|
57
|
+
</verification_requirements>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Context loading
|
|
61
|
+
|
|
62
|
+
Always include. GPT-5.4 is faster and may skip reading in favor of acting. Force thoroughness.
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
<context_loading>
|
|
66
|
+
- Read ALL files that will be modified—in full, not just the sections mentioned in the task.
|
|
67
|
+
- Also read key files they import from or that depend on them.
|
|
68
|
+
- Absorb surrounding patterns, naming conventions, error handling style, and architecture before writing any code.
|
|
69
|
+
- Do not ask clarifying questions about things that are answerable by reading the codebase.
|
|
70
|
+
- If modifying existing code, understand the full context before making changes.
|
|
71
|
+
</context_loading>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Plan-first mode
|
|
75
|
+
|
|
76
|
+
Include for multi-file work, refactors, or tasks with ordering dependencies. GPT-5.4 produces good natural-language plans but may skip validation steps.
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
<plan_first>
|
|
80
|
+
- Before writing any code, produce a brief implementation plan:
|
|
81
|
+
- Files to create vs. modify
|
|
82
|
+
- Implementation order and prerequisites
|
|
83
|
+
- Key design decisions and edge cases
|
|
84
|
+
- Acceptance criteria for "done"
|
|
85
|
+
- How you will verify each step
|
|
86
|
+
- Execute the plan step by step. After each step, verify it worked before proceeding.
|
|
87
|
+
- If the plan is provided externally, follow it faithfully—the job is execution, not second-guessing.
|
|
88
|
+
- Do NOT skip verification steps even if you're confident.
|
|
89
|
+
</plan_first>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Long-context handling
|
|
93
|
+
|
|
94
|
+
GPT-5.4 supports up to 1M tokens, but accuracy degrades beyond ~512K. Handle long inputs carefully.
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
<long_context_handling>
|
|
98
|
+
- For inputs longer than ~10k tokens:
|
|
99
|
+
- First, produce a short internal outline of the key sections relevant to the task.
|
|
100
|
+
- Re-state the constraints explicitly before answering.
|
|
101
|
+
- Anchor claims to sections ("In the 'Data Retention' section...") rather than speaking generically.
|
|
102
|
+
- If the answer depends on fine details (dates, thresholds, clauses), quote or paraphrase them.
|
|
103
|
+
- For very long contexts (200K+ tokens):
|
|
104
|
+
- Be extra vigilant about accuracy—retrieval quality degrades.
|
|
105
|
+
- Cross-reference claims against multiple sections.
|
|
106
|
+
- Prefer citing specific locations over making sweeping statements.
|
|
107
|
+
</long_context_handling>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Tool usage
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
<tool_usage_rules>
|
|
114
|
+
- Prefer tools over internal knowledge whenever:
|
|
115
|
+
- You need fresh or user-specific data (tickets, orders, configs, logs).
|
|
116
|
+
- You reference specific IDs, URLs, or document titles.
|
|
117
|
+
- Parallelize independent tool calls when possible to reduce latency.
|
|
118
|
+
- After any write/update tool call, verify the outcome—do not assume success.
|
|
119
|
+
- After any write/update tool call, briefly restate:
|
|
120
|
+
- What changed
|
|
121
|
+
- Where (ID or path)
|
|
122
|
+
- Verification performed or why verification was skipped
|
|
123
|
+
</tool_usage_rules>
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Backwards compatibility hedging
|
|
127
|
+
|
|
128
|
+
GPT-5.4 tends to preserve old patterns and add compatibility shims. Use **"cutover"** to signal a clean break.
|
|
129
|
+
|
|
130
|
+
Instead of:
|
|
131
|
+
> "Rewrite this and don't worry about backwards compatibility"
|
|
132
|
+
|
|
133
|
+
Say:
|
|
134
|
+
> "This is a cutover. No backwards compatibility. Rewrite using only Python 3.12+ features and current best practices. Do not preserve legacy code, polyfills, or deprecated patterns."
|
|
135
|
+
|
|
136
|
+
## Quick reference
|
|
137
|
+
|
|
138
|
+
- **Constrain scope aggressively.** GPT-5.4 expands tasks beyond the ask. "ONLY what is requested, nothing more."
|
|
139
|
+
- **Force verification.** Don't trust "done"—require evidence. "Verify before claiming complete."
|
|
140
|
+
- **Use cutover language.** "Cutover," "no fallbacks," "exactly as specified" get cleaner results.
|
|
141
|
+
- **Plan mode helps.** Explicit plan-first prompts ensure verification steps.
|
|
142
|
+
- **Watch for false success claims.** In agent harnesses, add explicit validation steps. Don't let it self-report completion.
|
|
143
|
+
- **Steer mid-task.** GPT-5.4 handles redirects well. Be direct: "Stop. That's out of scope." / "Verify that actually worked."
|
|
144
|
+
- **Use domain jargon.** "Cutover," "golden-path," "no fallbacks," "domain split," "exactly as specified" trigger precise behavior.
|
|
145
|
+
- **Long context degrades.** Above ~512K tokens, cross-reference claims and cite specific sections.
|
|
146
|
+
- **Token efficiency is real.** 5.4 uses fewer tokens per problem—but verify it didn't skip steps to get there.
|
|
147
|
+
|
|
148
|
+
## Example: implementation task prompt
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
<system>
|
|
152
|
+
You are implementing a feature in an existing codebase. Follow these rules strictly.
|
|
153
|
+
|
|
154
|
+
<design_and_scope_constraints>
|
|
155
|
+
- Implement EXACTLY and ONLY what the user requests. Nothing more.
|
|
156
|
+
- No extra features, no "while I'm here" improvements.
|
|
157
|
+
- If you notice adjacent issues, note them in your summary but DO NOT act on them.
|
|
158
|
+
</design_and_scope_constraints>
|
|
159
|
+
|
|
160
|
+
<context_loading>
|
|
161
|
+
- Read ALL files that will be modified—in full.
|
|
162
|
+
- Also read key files they import from or depend on.
|
|
163
|
+
- Absorb patterns before writing any code.
|
|
164
|
+
</context_loading>
|
|
165
|
+
|
|
166
|
+
<verification_requirements>
|
|
167
|
+
- Before declaring complete, verify each requirement is addressed in actual code.
|
|
168
|
+
- Run tests if available. If not, state what couldn't be verified.
|
|
169
|
+
- Include concrete evidence of completion in your summary.
|
|
170
|
+
</verification_requirements>
|
|
171
|
+
|
|
172
|
+
<output_verbosity_spec>
|
|
173
|
+
- Brief updates only on major phases or blockers.
|
|
174
|
+
- Final summary: What changed, Where, Risks, Next steps.
|
|
175
|
+
</output_verbosity_spec>
|
|
176
|
+
</system>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Example: code review prompt
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
<system>
|
|
183
|
+
You are reviewing code changes. Be thorough but stay in scope.
|
|
184
|
+
|
|
185
|
+
<context_loading>
|
|
186
|
+
- Read every changed file in full, not just the diff hunks.
|
|
187
|
+
- Also read files they import from and key dependents.
|
|
188
|
+
</context_loading>
|
|
189
|
+
|
|
190
|
+
<review_scope>
|
|
191
|
+
- Review for: bugs, logic errors, race conditions, resource leaks, null hazards, error handling gaps, type mismatches, dead code, unused imports, pattern inconsistencies.
|
|
192
|
+
- Fix issues you find with direct code edits.
|
|
193
|
+
- Do NOT refactor or restructure code that wasn't flagged in the review.
|
|
194
|
+
- If adjacent code looks problematic, note it but don't touch it.
|
|
195
|
+
</review_scope>
|
|
196
|
+
|
|
197
|
+
<verification_requirements>
|
|
198
|
+
- After fixes, verify the code still works. Run tests if available.
|
|
199
|
+
- In your summary, list what was found, what was fixed, and what couldn't be verified.
|
|
200
|
+
</verification_requirements>
|
|
201
|
+
</system>
|
|
202
|
+
```
|
package/handoff-utils.ts
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { getAgentDir } from "@mariozechner/pi-coding-agent";
|
|
4
|
+
import type { InteractiveShellConfig } from "./config.js";
|
|
5
|
+
import type { InteractiveShellOptions, InteractiveShellResult } from "./types.js";
|
|
6
|
+
import type { PtyTerminalSession } from "./pty-session.js";
|
|
7
|
+
|
|
8
|
+
export function captureCompletionOutput(
|
|
9
|
+
session: PtyTerminalSession,
|
|
10
|
+
config: InteractiveShellConfig,
|
|
11
|
+
): InteractiveShellResult["completionOutput"] {
|
|
12
|
+
const result = session.getTailLines({
|
|
13
|
+
lines: config.completionNotifyLines,
|
|
14
|
+
ansi: false,
|
|
15
|
+
maxChars: config.completionNotifyMaxChars,
|
|
16
|
+
});
|
|
17
|
+
return {
|
|
18
|
+
lines: result.lines,
|
|
19
|
+
totalLines: result.totalLinesInBuffer,
|
|
20
|
+
truncated: result.lines.length < result.totalLinesInBuffer || result.truncatedByChars,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function captureTransferOutput(
|
|
25
|
+
session: PtyTerminalSession,
|
|
26
|
+
config: InteractiveShellConfig,
|
|
27
|
+
): InteractiveShellResult["transferred"] {
|
|
28
|
+
const result = session.getTailLines({
|
|
29
|
+
lines: config.transferLines,
|
|
30
|
+
ansi: false,
|
|
31
|
+
maxChars: config.transferMaxChars,
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
lines: result.lines,
|
|
35
|
+
totalLines: result.totalLinesInBuffer,
|
|
36
|
+
truncated: result.lines.length < result.totalLinesInBuffer || result.truncatedByChars,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function maybeBuildHandoffPreview(
|
|
41
|
+
session: PtyTerminalSession,
|
|
42
|
+
when: "exit" | "detach" | "kill" | "timeout" | "transfer",
|
|
43
|
+
config: InteractiveShellConfig,
|
|
44
|
+
overrides?: Pick<InteractiveShellOptions, "handoffPreviewEnabled" | "handoffPreviewLines" | "handoffPreviewMaxChars">,
|
|
45
|
+
): InteractiveShellResult["handoffPreview"] | undefined {
|
|
46
|
+
const enabled = overrides?.handoffPreviewEnabled ?? config.handoffPreviewEnabled;
|
|
47
|
+
if (!enabled) return undefined;
|
|
48
|
+
const lines = overrides?.handoffPreviewLines ?? config.handoffPreviewLines;
|
|
49
|
+
const maxChars = overrides?.handoffPreviewMaxChars ?? config.handoffPreviewMaxChars;
|
|
50
|
+
if (lines <= 0 || maxChars <= 0) return undefined;
|
|
51
|
+
const result = session.getTailLines({ lines, ansi: false, maxChars });
|
|
52
|
+
return { type: "tail", when, lines: result.lines };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function maybeWriteHandoffSnapshot(
|
|
56
|
+
session: PtyTerminalSession,
|
|
57
|
+
when: "exit" | "detach" | "kill" | "timeout" | "transfer",
|
|
58
|
+
config: InteractiveShellConfig,
|
|
59
|
+
context: { command: string; cwd?: string },
|
|
60
|
+
overrides?: Pick<InteractiveShellOptions, "handoffSnapshotEnabled" | "handoffSnapshotLines" | "handoffSnapshotMaxChars">,
|
|
61
|
+
): InteractiveShellResult["handoff"] | undefined {
|
|
62
|
+
const enabled = overrides?.handoffSnapshotEnabled ?? config.handoffSnapshotEnabled;
|
|
63
|
+
if (!enabled) return undefined;
|
|
64
|
+
const lines = overrides?.handoffSnapshotLines ?? config.handoffSnapshotLines;
|
|
65
|
+
const maxChars = overrides?.handoffSnapshotMaxChars ?? config.handoffSnapshotMaxChars;
|
|
66
|
+
if (lines <= 0 || maxChars <= 0) return undefined;
|
|
67
|
+
|
|
68
|
+
const baseDir = join(getAgentDir(), "cache", "interactive-shell");
|
|
69
|
+
mkdirSync(baseDir, { recursive: true });
|
|
70
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
71
|
+
const pid = session.pid;
|
|
72
|
+
const filename = `snapshot-${timestamp}-pid${pid}.log`;
|
|
73
|
+
const transcriptPath = join(baseDir, filename);
|
|
74
|
+
const tailResult = session.getTailLines({
|
|
75
|
+
lines,
|
|
76
|
+
ansi: config.ansiReemit,
|
|
77
|
+
maxChars,
|
|
78
|
+
});
|
|
79
|
+
const header = [
|
|
80
|
+
`# interactive-shell snapshot (${when})`,
|
|
81
|
+
`time: ${new Date().toISOString()}`,
|
|
82
|
+
`command: ${context.command}`,
|
|
83
|
+
`cwd: ${context.cwd ?? ""}`,
|
|
84
|
+
`pid: ${pid}`,
|
|
85
|
+
`exitCode: ${session.exitCode ?? ""}`,
|
|
86
|
+
`signal: ${session.signal ?? ""}`,
|
|
87
|
+
`lines: ${tailResult.lines.length} (requested ${lines}, maxChars ${maxChars})`,
|
|
88
|
+
"",
|
|
89
|
+
].join("\n");
|
|
90
|
+
writeFileSync(transcriptPath, header + tailResult.lines.join("\n") + "\n", { encoding: "utf-8" });
|
|
91
|
+
return { type: "snapshot", when, transcriptPath, linesWritten: tailResult.lines.length };
|
|
92
|
+
}
|
package/headless-monitor.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
|
+
import { stripVTControlCharacters } from "node:util";
|
|
1
2
|
import type { PtyTerminalSession } from "./pty-session.js";
|
|
2
3
|
import type { InteractiveShellConfig } from "./config.js";
|
|
3
4
|
|
|
5
|
+
/** Runtime options for monitoring a headless dispatch session. */
|
|
4
6
|
export interface HeadlessMonitorOptions {
|
|
5
7
|
autoExitOnQuiet: boolean;
|
|
6
8
|
quietThreshold: number;
|
|
7
9
|
gracePeriod?: number;
|
|
8
10
|
timeout?: number;
|
|
11
|
+
/** Original session start time in ms since epoch, preserved when a foreground session moves headless. */
|
|
12
|
+
startedAt?: number;
|
|
9
13
|
}
|
|
10
14
|
|
|
15
|
+
/** Completion payload emitted when a headless dispatch session finishes. */
|
|
11
16
|
export interface HeadlessCompletionInfo {
|
|
12
17
|
exitCode: number | null;
|
|
13
18
|
signal?: number;
|
|
@@ -21,7 +26,7 @@ export interface HeadlessCompletionInfo {
|
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
export class HeadlessDispatchMonitor {
|
|
24
|
-
readonly startTime
|
|
29
|
+
readonly startTime: number;
|
|
25
30
|
private _disposed = false;
|
|
26
31
|
private quietTimer: ReturnType<typeof setTimeout> | null = null;
|
|
27
32
|
private timeoutTimer: ReturnType<typeof setTimeout> | null = null;
|
|
@@ -38,8 +43,13 @@ export class HeadlessDispatchMonitor {
|
|
|
38
43
|
private options: HeadlessMonitorOptions,
|
|
39
44
|
private onComplete: (info: HeadlessCompletionInfo) => void,
|
|
40
45
|
) {
|
|
46
|
+
this.startTime = options.startedAt ?? Date.now();
|
|
41
47
|
this.subscribe();
|
|
42
48
|
|
|
49
|
+
if (options.autoExitOnQuiet) {
|
|
50
|
+
this.resetQuietTimer();
|
|
51
|
+
}
|
|
52
|
+
|
|
43
53
|
if (options.timeout && options.timeout > 0) {
|
|
44
54
|
this.timeoutTimer = setTimeout(() => {
|
|
45
55
|
this.handleCompletion(null, undefined, true);
|
|
@@ -57,9 +67,12 @@ export class HeadlessDispatchMonitor {
|
|
|
57
67
|
|
|
58
68
|
private subscribe(): void {
|
|
59
69
|
this.unsubscribe();
|
|
60
|
-
this.unsubData = this.session.addDataListener(() => {
|
|
70
|
+
this.unsubData = this.session.addDataListener((data) => {
|
|
61
71
|
if (this.options.autoExitOnQuiet) {
|
|
62
|
-
|
|
72
|
+
const visible = stripVTControlCharacters(data);
|
|
73
|
+
if (visible.trim().length > 0) {
|
|
74
|
+
this.resetQuietTimer();
|
|
75
|
+
}
|
|
63
76
|
}
|
|
64
77
|
});
|
|
65
78
|
this.unsubExit = this.session.addExitListener((exitCode, signal) => {
|