terminal-pilot 0.0.3 → 0.0.5

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 CHANGED
@@ -61,8 +61,9 @@ type NewSessionOptions = {
61
61
  class TerminalPilot {
62
62
  static launch(): Promise<TerminalPilot>;
63
63
  newSession(options: NewSessionOptions): Promise<TerminalSession>;
64
- getSession(id: string): TerminalSession; // throws if missing
65
- sessions(): TerminalSession[]; // active sessions only
64
+ getSession(id: string): TerminalSession; // throws if not in map; works for exited sessions until deleteSession
65
+ deleteSession(id: string): void; // explicit removal from session map
66
+ sessions(): TerminalSession[]; // running sessions only (exitCode === null)
66
67
  close(): Promise<void>;
67
68
  }
68
69
  ```
@@ -122,12 +123,13 @@ class TerminalSession {
122
123
  readonly pid: number;
123
124
  exitCode: number | null;
124
125
 
125
- type(text: string): Promise<void>; // character-by-character
126
- fill(text: string): Promise<void>; // bulk write
126
+ type(text: string): Promise<void>; // character-by-character with delay
127
+ fill(text: string): Promise<void>; // bulk write (\n → \r)
127
128
  press(key: TerminalKey): Promise<void>;
128
129
  send(raw: string): Promise<void>; // raw bytes / escape sequences
129
130
  signal(signal: string): Promise<void>;
130
131
  waitFor(pattern: string | RegExp, options?: WaitForOptions): Promise<string>;
132
+ waitForExit(options?: { timeout?: number }): Promise<number>; // throws on timeout
131
133
  waitForQuiet(ms: number): Promise<void>;
132
134
  screen(): Promise<TerminalScreen>;
133
135
  history(options?: HistoryOptions): Promise<string[]>;
@@ -0,0 +1,38 @@
1
+ type Cell = [number, string] | null;
2
+ type Row = Cell[];
3
+ export declare class TerminalBuffer {
4
+ private _cols;
5
+ private _rows;
6
+ private _screen;
7
+ private _cursorX;
8
+ private _cursorY;
9
+ private _savedCursor;
10
+ private _scrollTop;
11
+ private _scrollBottom;
12
+ private _state;
13
+ private _csiParams;
14
+ private _csiPrivate;
15
+ readonly displayBuffer: {
16
+ readonly cursorX: number;
17
+ readonly cursorY: number;
18
+ readonly data: Array<Row | undefined>;
19
+ };
20
+ constructor(cols: number, rows: number);
21
+ write(data: string): void;
22
+ resize(cols: number, rows: number): void;
23
+ private _makeScreen;
24
+ private _makeRow;
25
+ private _clamp;
26
+ private _setChar;
27
+ private _eraseLine;
28
+ private _scrollUp;
29
+ private _scrollDown;
30
+ private _newline;
31
+ private _parseCsiParams;
32
+ private _execCsi;
33
+ private _feed;
34
+ private _feedNormal;
35
+ private _feedEscape;
36
+ private _feedCsi;
37
+ }
38
+ export {};
@@ -0,0 +1,445 @@
1
+ export class TerminalBuffer {
2
+ _cols;
3
+ _rows;
4
+ _screen;
5
+ _cursorX = 0;
6
+ _cursorY = 0;
7
+ _savedCursor = { x: 0, y: 0 };
8
+ _scrollTop = 0;
9
+ _scrollBottom;
10
+ _state = 0 /* State.Normal */;
11
+ _csiParams = "";
12
+ _csiPrivate = "";
13
+ displayBuffer;
14
+ constructor(cols, rows) {
15
+ this._cols = cols;
16
+ this._rows = rows;
17
+ this._scrollBottom = rows - 1;
18
+ this._screen = this._makeScreen(cols, rows);
19
+ this.displayBuffer = Object.defineProperties({}, {
20
+ cursorX: { get: () => this._cursorX, enumerable: true },
21
+ cursorY: { get: () => this._cursorY, enumerable: true },
22
+ data: { get: () => this._screen, enumerable: true },
23
+ });
24
+ }
25
+ write(data) {
26
+ for (const ch of data) {
27
+ this._feed(ch);
28
+ }
29
+ }
30
+ resize(cols, rows) {
31
+ // Adjust row count
32
+ while (this._screen.length < rows) {
33
+ this._screen.push(this._makeRow(cols));
34
+ }
35
+ this._screen.length = rows;
36
+ // Adjust col count for each row
37
+ for (let y = 0; y < rows; y++) {
38
+ const row = this._screen[y] ?? this._makeRow(cols);
39
+ while (row.length < cols)
40
+ row.push(null);
41
+ row.length = cols;
42
+ this._screen[y] = row;
43
+ }
44
+ this._cols = cols;
45
+ this._rows = rows;
46
+ this._scrollTop = 0;
47
+ this._scrollBottom = rows - 1;
48
+ this._cursorX = this._clamp(this._cursorX, 0, cols - 1);
49
+ this._cursorY = this._clamp(this._cursorY, 0, rows - 1);
50
+ }
51
+ _makeScreen(cols, rows) {
52
+ return Array.from({ length: rows }, () => this._makeRow(cols));
53
+ }
54
+ _makeRow(cols) {
55
+ return Array(cols).fill(null);
56
+ }
57
+ _clamp(value, min, max) {
58
+ return Math.max(min, Math.min(max, value));
59
+ }
60
+ _setChar(y, x, ch) {
61
+ const row = this._screen[y];
62
+ if (row && x >= 0 && x < this._cols) {
63
+ row[x] = [ch.charCodeAt(0), ch];
64
+ }
65
+ }
66
+ _eraseLine(y, fromX, toX) {
67
+ const row = this._screen[y];
68
+ if (!row)
69
+ return;
70
+ for (let x = fromX; x <= toX && x < this._cols; x++) {
71
+ row[x] = null;
72
+ }
73
+ }
74
+ _scrollUp(count) {
75
+ for (let i = 0; i < count; i++) {
76
+ this._screen.splice(this._scrollTop, 1);
77
+ this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
78
+ }
79
+ }
80
+ _scrollDown(count) {
81
+ for (let i = 0; i < count; i++) {
82
+ this._screen.splice(this._scrollBottom, 1);
83
+ this._screen.splice(this._scrollTop, 0, this._makeRow(this._cols));
84
+ }
85
+ }
86
+ _newline() {
87
+ if (this._cursorY === this._scrollBottom) {
88
+ this._scrollUp(1);
89
+ }
90
+ else {
91
+ this._cursorY = Math.min(this._cursorY + 1, this._rows - 1);
92
+ }
93
+ }
94
+ _parseCsiParams() {
95
+ if (!this._csiParams)
96
+ return [];
97
+ return this._csiParams.split(";").map((s) => (s === "" ? 0 : parseInt(s, 10)));
98
+ }
99
+ _execCsi(final) {
100
+ const params = this._parseCsiParams();
101
+ const p0 = params[0] ?? 0;
102
+ const p1 = params[1] ?? 0;
103
+ if (this._csiPrivate === "?") {
104
+ if (final === "h" || final === "l") {
105
+ // Only handle alt screen (1049) — ignore everything else
106
+ if (params.includes(1049)) {
107
+ if (final === "h") {
108
+ this._screen = this._makeScreen(this._cols, this._rows);
109
+ this._cursorX = 0;
110
+ this._cursorY = 0;
111
+ }
112
+ else {
113
+ this._screen = this._makeScreen(this._cols, this._rows);
114
+ this._cursorX = 0;
115
+ this._cursorY = 0;
116
+ }
117
+ }
118
+ }
119
+ return;
120
+ }
121
+ switch (final) {
122
+ case "A": // cursor up
123
+ this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
124
+ break;
125
+ case "B": // cursor down
126
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
127
+ break;
128
+ case "C": // cursor forward
129
+ case "a":
130
+ this._cursorX = this._clamp(this._cursorX + Math.max(1, p0), 0, this._cols - 1);
131
+ break;
132
+ case "D": // cursor backward
133
+ this._cursorX = this._clamp(this._cursorX - Math.max(1, p0), 0, this._cols - 1);
134
+ break;
135
+ case "E": // cursor next line
136
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
137
+ this._cursorX = 0;
138
+ break;
139
+ case "F": // cursor preceding line
140
+ this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
141
+ this._cursorX = 0;
142
+ break;
143
+ case "G": // cursor horizontal absolute
144
+ case "`":
145
+ this._cursorX = this._clamp(Math.max(1, p0) - 1, 0, this._cols - 1);
146
+ break;
147
+ case "H": // cursor position
148
+ case "f":
149
+ this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
150
+ this._cursorX = this._clamp(Math.max(1, p1) - 1, 0, this._cols - 1);
151
+ break;
152
+ case "I": // cursor forward tabulation
153
+ for (let i = 0; i < Math.max(1, p0); i++) {
154
+ this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
155
+ }
156
+ break;
157
+ case "J": // erase in display
158
+ if (p0 === 0) {
159
+ this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
160
+ for (let y = this._cursorY + 1; y < this._rows; y++)
161
+ this._eraseLine(y, 0, this._cols - 1);
162
+ }
163
+ else if (p0 === 1) {
164
+ for (let y = 0; y < this._cursorY; y++)
165
+ this._eraseLine(y, 0, this._cols - 1);
166
+ this._eraseLine(this._cursorY, 0, this._cursorX);
167
+ }
168
+ else if (p0 === 2 || p0 === 3) {
169
+ for (let y = 0; y < this._rows; y++)
170
+ this._eraseLine(y, 0, this._cols - 1);
171
+ }
172
+ break;
173
+ case "K": // erase in line
174
+ if (p0 === 0)
175
+ this._eraseLine(this._cursorY, this._cursorX, this._cols - 1);
176
+ else if (p0 === 1)
177
+ this._eraseLine(this._cursorY, 0, this._cursorX);
178
+ else if (p0 === 2)
179
+ this._eraseLine(this._cursorY, 0, this._cols - 1);
180
+ break;
181
+ case "X": // erase characters (ECH)
182
+ this._eraseLine(this._cursorY, this._cursorX, this._cursorX + Math.max(1, p0) - 1);
183
+ break;
184
+ case "L": { // insert lines
185
+ const n = Math.max(1, p0);
186
+ for (let i = 0; i < n; i++) {
187
+ this._screen.splice(this._scrollBottom, 1);
188
+ this._screen.splice(this._cursorY, 0, this._makeRow(this._cols));
189
+ }
190
+ break;
191
+ }
192
+ case "M": { // delete lines
193
+ const n = Math.max(1, p0);
194
+ for (let i = 0; i < n; i++) {
195
+ this._screen.splice(this._cursorY, 1);
196
+ this._screen.splice(this._scrollBottom, 0, this._makeRow(this._cols));
197
+ }
198
+ break;
199
+ }
200
+ case "P": { // delete characters
201
+ const row = this._screen[this._cursorY];
202
+ if (row) {
203
+ const n = Math.max(1, p0);
204
+ row.splice(this._cursorX, n);
205
+ while (row.length < this._cols)
206
+ row.push(null);
207
+ }
208
+ break;
209
+ }
210
+ case "@": { // insert blank characters
211
+ const row = this._screen[this._cursorY];
212
+ if (row) {
213
+ const n = Math.max(1, p0);
214
+ for (let i = 0; i < n; i++)
215
+ row.splice(this._cursorX, 0, null);
216
+ row.splice(this._cols);
217
+ }
218
+ break;
219
+ }
220
+ case "S": // scroll up
221
+ this._scrollUp(Math.max(1, p0));
222
+ break;
223
+ case "T": // scroll down
224
+ if (params.length <= 1)
225
+ this._scrollDown(Math.max(1, p0));
226
+ break;
227
+ case "Z": { // cursor backward tabulation
228
+ const n = Math.max(1, p0);
229
+ for (let i = 0; i < n; i++) {
230
+ this._cursorX = Math.max(0, (Math.ceil(this._cursorX / 8) - 1) * 8);
231
+ }
232
+ break;
233
+ }
234
+ case "d": // line position absolute
235
+ this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
236
+ break;
237
+ case "e": // vertical position relative
238
+ this._cursorY = this._clamp(this._cursorY + Math.max(1, p0), 0, this._rows - 1);
239
+ break;
240
+ case "r": { // set scrolling region
241
+ const top = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
242
+ const bottom = this._clamp((p1 === 0 ? this._rows : p1) - 1, 0, this._rows - 1);
243
+ if (top < bottom) {
244
+ this._scrollTop = top;
245
+ this._scrollBottom = bottom;
246
+ }
247
+ this._cursorX = 0;
248
+ this._cursorY = 0;
249
+ break;
250
+ }
251
+ case "s": // save cursor
252
+ this._savedCursor = { x: this._cursorX, y: this._cursorY };
253
+ break;
254
+ case "u": // restore cursor
255
+ this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
256
+ this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
257
+ break;
258
+ case "m": // SGR — ignore (we don't track attributes)
259
+ break;
260
+ default:
261
+ break;
262
+ }
263
+ }
264
+ _feed(ch) {
265
+ const code = ch.charCodeAt(0);
266
+ switch (this._state) {
267
+ case 0 /* State.Normal */:
268
+ this._feedNormal(ch, code);
269
+ break;
270
+ case 1 /* State.Escape */:
271
+ this._feedEscape(ch, code);
272
+ break;
273
+ case 2 /* State.Csi */:
274
+ this._feedCsi(ch, code);
275
+ break;
276
+ case 3 /* State.Osc */:
277
+ // consume until BEL or ESC (ESC \ = ST)
278
+ if (code === 0x07 || code === 0x9c) {
279
+ this._state = 0 /* State.Normal */;
280
+ }
281
+ else if (code === 0x1b) {
282
+ // next char should be `\` — just return to normal, it will be consumed
283
+ this._state = 0 /* State.Normal */;
284
+ }
285
+ break;
286
+ case 4 /* State.Str */:
287
+ // consume until ST (0x9c) or BEL
288
+ if (code === 0x9c || code === 0x07) {
289
+ this._state = 0 /* State.Normal */;
290
+ }
291
+ else if (code === 0x1b) {
292
+ this._state = 0 /* State.Normal */;
293
+ }
294
+ break;
295
+ case 5 /* State.EscCharset */:
296
+ // consume one character for charset designation
297
+ this._state = 0 /* State.Normal */;
298
+ break;
299
+ case 6 /* State.EscHash */:
300
+ // consume one character for line attributes
301
+ this._state = 0 /* State.Normal */;
302
+ break;
303
+ }
304
+ }
305
+ _feedNormal(ch, code) {
306
+ if (code === 0x1b) {
307
+ this._state = 1 /* State.Escape */;
308
+ }
309
+ else if (code === 0x9b) {
310
+ // C1 CSI
311
+ this._csiParams = "";
312
+ this._csiPrivate = "";
313
+ this._state = 2 /* State.Csi */;
314
+ }
315
+ else if (code === 0x9d) {
316
+ // C1 OSC
317
+ this._state = 3 /* State.Osc */;
318
+ }
319
+ else if (code === 0x90 || code === 0x98 || code === 0x9e || code === 0x9f) {
320
+ // DCS, SOS, PM, APC
321
+ this._state = 4 /* State.Str */;
322
+ }
323
+ else if (code === 0x07 || code === 0x05 || code === 0x06) {
324
+ // BEL, ENQ, ACK — ignore
325
+ }
326
+ else if (code === 0x08) {
327
+ // BS
328
+ if (this._cursorX > 0)
329
+ this._cursorX--;
330
+ }
331
+ else if (code === 0x7f) {
332
+ // DEL
333
+ if (this._cursorX > 0) {
334
+ this._cursorX--;
335
+ this._setChar(this._cursorY, this._cursorX, " ");
336
+ }
337
+ }
338
+ else if (code === 0x09) {
339
+ // HT
340
+ this._cursorX = Math.min(this._cols - 1, (Math.floor(this._cursorX / 8) + 1) * 8);
341
+ }
342
+ else if (code === 0x0a || code === 0x0b || code === 0x0c) {
343
+ // LF, VT, FF
344
+ this._newline();
345
+ }
346
+ else if (code === 0x0d) {
347
+ // CR
348
+ this._cursorX = 0;
349
+ }
350
+ else if (code === 0x0e || code === 0x0f) {
351
+ // SO, SI — charset switch, ignore
352
+ }
353
+ else if (code >= 0x20 && code !== 0x7f) {
354
+ // Printable character (including multi-byte Unicode via code points)
355
+ this._setChar(this._cursorY, this._cursorX, ch);
356
+ this._cursorX++;
357
+ if (this._cursorX >= this._cols) {
358
+ // Auto-wrap
359
+ this._cursorX = 0;
360
+ this._newline();
361
+ }
362
+ }
363
+ }
364
+ _feedEscape(ch, code) {
365
+ this._state = 0 /* State.Normal */;
366
+ if (code === 0x5b) {
367
+ // ESC [ = CSI
368
+ this._csiParams = "";
369
+ this._csiPrivate = "";
370
+ this._state = 2 /* State.Csi */;
371
+ }
372
+ else if (code === 0x5d) {
373
+ // ESC ] = OSC
374
+ this._state = 3 /* State.Osc */;
375
+ }
376
+ else if (code === 0x50 || code === 0x58 || code === 0x5e || code === 0x5f) {
377
+ // DCS, SOS, PM, APC
378
+ this._state = 4 /* State.Str */;
379
+ }
380
+ else if (code === 0x28 || code === 0x29 || code === 0x2a || code === 0x2b || code === 0x2d || code === 0x2e) {
381
+ // ESC ( ) * + - . = charset designation (consume next char)
382
+ this._state = 5 /* State.EscCharset */;
383
+ }
384
+ else if (code === 0x23) {
385
+ // ESC # = line attributes (consume next char)
386
+ this._state = 6 /* State.EscHash */;
387
+ }
388
+ else if (code === 0x37) {
389
+ // ESC 7 = save cursor
390
+ this._savedCursor = { x: this._cursorX, y: this._cursorY };
391
+ }
392
+ else if (code === 0x38) {
393
+ // ESC 8 = restore cursor
394
+ this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
395
+ this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
396
+ }
397
+ else if (code === 0x44) {
398
+ // ESC D = index (LF)
399
+ this._newline();
400
+ }
401
+ else if (code === 0x45) {
402
+ // ESC E = next line
403
+ this._cursorX = 0;
404
+ this._newline();
405
+ }
406
+ else if (code === 0x4d) {
407
+ // ESC M = reverse index
408
+ if (this._cursorY === this._scrollTop) {
409
+ this._scrollDown(1);
410
+ }
411
+ else {
412
+ this._cursorY = Math.max(0, this._cursorY - 1);
413
+ }
414
+ }
415
+ else if (code === 0x48) {
416
+ // ESC H = tab set (ignore)
417
+ }
418
+ else if (code === 0x63) {
419
+ // ESC c = full reset
420
+ this._screen = this._makeScreen(this._cols, this._rows);
421
+ this._cursorX = 0;
422
+ this._cursorY = 0;
423
+ this._savedCursor = { x: 0, y: 0 };
424
+ this._scrollTop = 0;
425
+ this._scrollBottom = this._rows - 1;
426
+ }
427
+ // All other ESC sequences: two-char, already consumed — ignore
428
+ }
429
+ _feedCsi(ch, code) {
430
+ if (code >= 0x40 && code <= 0x7e) {
431
+ // Final byte
432
+ this._execCsi(ch);
433
+ this._state = 0 /* State.Normal */;
434
+ }
435
+ else if (code === 0x3f || code === 0x21 || code === 0x3e || code === 0x20) {
436
+ // Private/intermediate marker (?, !, >, space)
437
+ this._csiPrivate = ch;
438
+ }
439
+ else if ((code >= 0x30 && code <= 0x39) || code === 0x3b) {
440
+ // Digit or semicolon — parameter byte
441
+ this._csiParams += ch;
442
+ }
443
+ // Other bytes ignored
444
+ }
445
+ }
@@ -13,6 +13,7 @@ export declare class TerminalPilot {
13
13
  static launch(): Promise<TerminalPilot>;
14
14
  newSession(opts: NewSessionOptions): Promise<TerminalSession>;
15
15
  getSession(id: string): TerminalSession;
16
+ deleteSession(id: string): void;
16
17
  sessions(): TerminalSession[];
17
18
  close(): Promise<void>;
18
19
  }
@@ -18,9 +18,6 @@ export class TerminalPilot {
18
18
  rows: opts.rows ?? DEFAULT_ROWS,
19
19
  observe: opts.observe ?? false
20
20
  });
21
- session.on("exit", () => {
22
- this.sessionMap.delete(session.id);
23
- });
24
21
  this.sessionMap.set(session.id, session);
25
22
  return session;
26
23
  }
@@ -31,8 +28,11 @@ export class TerminalPilot {
31
28
  }
32
29
  return session;
33
30
  }
31
+ deleteSession(id) {
32
+ this.sessionMap.delete(id);
33
+ }
34
34
  sessions() {
35
- return [...this.sessionMap.values()];
35
+ return [...this.sessionMap.values()].filter((s) => s.exitCode === null);
36
36
  }
37
37
  async close() {
38
38
  const sessions = [...this.sessionMap.values()];
@@ -42,6 +42,9 @@ export declare class TerminalSession {
42
42
  screen(): Promise<TerminalScreen>;
43
43
  history(opts?: HistoryOptions): Promise<string[]>;
44
44
  resize(cols: number, rows: number): Promise<void>;
45
+ waitForExit(opts?: {
46
+ timeout?: number;
47
+ }): Promise<number>;
45
48
  close(): Promise<number>;
46
49
  on(event: "exit", cb: (code: number) => void): void;
47
50
  }
@@ -1,12 +1,10 @@
1
1
  import { spawn as spawnChildProcess } from "node:child_process";
2
2
  import { EventEmitter } from "node:events";
3
- import { createRequire } from "node:module";
4
3
  import * as nodePty from "node-pty";
5
4
  import { stripAnsi } from "./ansi.js";
5
+ import { TerminalBuffer } from "./terminal-buffer.js";
6
6
  import { keyToSequence } from "./keys.js";
7
7
  import { TerminalScreen } from "./terminal-screen.js";
8
- const require = createRequire(import.meta.url);
9
- const HeadlessTerminal = require("headless-terminal");
10
8
  const DEFAULT_COLS = 120;
11
9
  const DEFAULT_ROWS = 40;
12
10
  const DEFAULT_TIMEOUT_MS = 10_000;
@@ -33,7 +31,7 @@ export class TerminalSession {
33
31
  this.command = command;
34
32
  this.currentCols = cols;
35
33
  this.currentRows = rows;
36
- this.terminal = new HeadlessTerminal(cols, rows);
34
+ this.terminal = new TerminalBuffer(cols, rows);
37
35
  this.pty = createPtyProcess({ command, args, cwd, env, cols, rows });
38
36
  this.pid = this.pty.pid;
39
37
  const dataSubscription = this.pty.onData((chunk) => {
@@ -145,6 +143,19 @@ export class TerminalSession {
145
143
  }
146
144
  this.terminal.resize(cols, rows);
147
145
  }
146
+ async waitForExit(opts) {
147
+ if (this.exitCode !== null) {
148
+ return this.exitCode;
149
+ }
150
+ if (opts?.timeout !== undefined) {
151
+ const result = await waitForExit(this.exitPromise, opts.timeout);
152
+ if (result === null) {
153
+ throw new Error(`Timed out waiting for process to exit after ${opts.timeout}ms`);
154
+ }
155
+ return result;
156
+ }
157
+ return this.exitPromise;
158
+ }
148
159
  async close() {
149
160
  if (this.exitCode !== null) {
150
161
  return this.exitCode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "terminal-pilot",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Playwright-like SDK for automating interactive CLI apps through a real PTY",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -34,7 +34,6 @@
34
34
  "headless"
35
35
  ],
36
36
  "dependencies": {
37
- "headless-terminal": "^0.4.0",
38
37
  "node-pty": "^1.1.0"
39
38
  },
40
39
  "devDependencies": {}