terminal-pilot 0.0.17 → 0.0.19
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/cli.js +6271 -2048
- package/dist/cli.js.map +4 -4
- package/dist/commands/close-session.d.ts +4 -4
- package/dist/commands/close-session.js +437 -108
- package/dist/commands/close-session.js.map +2 -2
- package/dist/commands/create-session.d.ts +16 -16
- package/dist/commands/create-session.js +437 -108
- package/dist/commands/create-session.js.map +2 -2
- package/dist/commands/fill.d.ts +6 -6
- package/dist/commands/fill.js +437 -108
- package/dist/commands/fill.js.map +2 -2
- package/dist/commands/get-session.d.ts +4 -4
- package/dist/commands/get-session.js +437 -108
- package/dist/commands/get-session.js.map +2 -2
- package/dist/commands/index.d.ts +330 -107
- package/dist/commands/index.js +1951 -336
- package/dist/commands/index.js.map +4 -4
- package/dist/commands/install.d.ts +8 -8
- package/dist/commands/install.js +1242 -134
- package/dist/commands/install.js.map +4 -4
- package/dist/commands/installer.d.ts +5 -0
- package/dist/commands/installer.js +606 -37
- package/dist/commands/installer.js.map +4 -4
- package/dist/commands/list-sessions.d.ts +2 -2
- package/dist/commands/list-sessions.js +437 -108
- package/dist/commands/list-sessions.js.map +2 -2
- package/dist/commands/press-key.d.ts +6 -6
- package/dist/commands/press-key.js +437 -108
- package/dist/commands/press-key.js.map +2 -2
- package/dist/commands/read-history.d.ts +6 -6
- package/dist/commands/read-history.js +437 -108
- package/dist/commands/read-history.js.map +2 -2
- package/dist/commands/read-screen.d.ts +4 -4
- package/dist/commands/read-screen.js +437 -108
- package/dist/commands/read-screen.js.map +2 -2
- package/dist/commands/resize.d.ts +8 -8
- package/dist/commands/resize.js +437 -108
- package/dist/commands/resize.js.map +2 -2
- package/dist/commands/runtime.js +356 -89
- package/dist/commands/runtime.js.map +2 -2
- package/dist/commands/screenshot.d.ts +10 -10
- package/dist/commands/screenshot.js +672 -148
- package/dist/commands/screenshot.js.map +3 -3
- package/dist/commands/send-signal.d.ts +6 -6
- package/dist/commands/send-signal.js +437 -108
- package/dist/commands/send-signal.js.map +2 -2
- package/dist/commands/type.d.ts +6 -6
- package/dist/commands/type.js +437 -108
- package/dist/commands/type.js.map +2 -2
- package/dist/commands/uninstall.d.ts +4 -4
- package/dist/commands/uninstall.js +708 -64
- package/dist/commands/uninstall.js.map +4 -4
- package/dist/commands/wait-for-exit.d.ts +6 -6
- package/dist/commands/wait-for-exit.js +437 -108
- package/dist/commands/wait-for-exit.js.map +2 -2
- package/dist/commands/wait-for.d.ts +10 -10
- package/dist/commands/wait-for.js +437 -108
- package/dist/commands/wait-for.js.map +2 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.js +318 -80
- package/dist/index.js.map +3 -3
- package/dist/terminal-buffer.d.ts +18 -0
- package/dist/terminal-buffer.js +234 -43
- package/dist/terminal-buffer.js.map +2 -2
- package/dist/terminal-pilot.js +312 -73
- package/dist/terminal-pilot.js.map +2 -2
- package/dist/terminal-session.d.ts +2 -2
- package/dist/terminal-session.js +306 -68
- package/dist/terminal-session.js.map +2 -2
- package/dist/testing/cli-repl.js +6267 -2044
- package/dist/testing/cli-repl.js.map +4 -4
- package/dist/testing/qa-cli.js +6291 -2068
- package/dist/testing/qa-cli.js.map +4 -4
- package/package.json +6 -5
package/dist/commands/runtime.js
CHANGED
|
@@ -3,8 +3,8 @@ import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
|
3
3
|
|
|
4
4
|
// ../toolcraft/src/user-error.ts
|
|
5
5
|
var UserError = class extends Error {
|
|
6
|
-
constructor(message) {
|
|
7
|
-
super(message);
|
|
6
|
+
constructor(message, options) {
|
|
7
|
+
super(message, options);
|
|
8
8
|
this.name = "UserError";
|
|
9
9
|
}
|
|
10
10
|
};
|
|
@@ -99,27 +99,53 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
|
|
|
99
99
|
|
|
100
100
|
// src/terminal-buffer.ts
|
|
101
101
|
var RESET_SGR = "\x1B[0m";
|
|
102
|
+
var DEC_SPECIAL_GRAPHICS = {
|
|
103
|
+
j: "\u2518",
|
|
104
|
+
k: "\u2510",
|
|
105
|
+
l: "\u250C",
|
|
106
|
+
m: "\u2514",
|
|
107
|
+
n: "\u253C",
|
|
108
|
+
q: "\u2500",
|
|
109
|
+
t: "\u251C",
|
|
110
|
+
u: "\u2524",
|
|
111
|
+
v: "\u2534",
|
|
112
|
+
w: "\u252C",
|
|
113
|
+
x: "\u2502"
|
|
114
|
+
};
|
|
102
115
|
var TerminalBuffer = class {
|
|
103
116
|
_cols;
|
|
104
117
|
_rows;
|
|
105
118
|
_screen;
|
|
119
|
+
_primaryScreen = null;
|
|
106
120
|
_cursorX = 0;
|
|
107
121
|
_cursorY = 0;
|
|
108
|
-
_savedCursor
|
|
122
|
+
_savedCursor;
|
|
109
123
|
_scrollTop = 0;
|
|
110
124
|
_scrollBottom;
|
|
111
125
|
_state = 0 /* Normal */;
|
|
112
126
|
_csiParams = "";
|
|
113
127
|
_csiPrivate = "";
|
|
114
128
|
_autoWrap = true;
|
|
129
|
+
_pendingWrap = false;
|
|
130
|
+
_originMode = false;
|
|
131
|
+
_insertMode = false;
|
|
132
|
+
_tabStops;
|
|
133
|
+
_lastPrintedChar = null;
|
|
115
134
|
_style = createDefaultStyleState();
|
|
116
135
|
_styleSequence = "";
|
|
136
|
+
_stringState = 0 /* Normal */;
|
|
137
|
+
_charsetTarget = null;
|
|
138
|
+
_g0Charset = "ascii";
|
|
139
|
+
_g1Charset = "ascii";
|
|
140
|
+
_shiftOut = false;
|
|
117
141
|
displayBuffer;
|
|
118
142
|
constructor(cols, rows) {
|
|
119
143
|
this._cols = cols;
|
|
120
144
|
this._rows = rows;
|
|
121
145
|
this._scrollBottom = rows - 1;
|
|
122
146
|
this._screen = this._makeScreen(cols, rows);
|
|
147
|
+
this._tabStops = this._createDefaultTabStops(cols);
|
|
148
|
+
this._savedCursor = this._createSavedCursorState();
|
|
123
149
|
this.displayBuffer = Object.defineProperties(
|
|
124
150
|
{},
|
|
125
151
|
{
|
|
@@ -175,8 +201,12 @@ var TerminalBuffer = class {
|
|
|
175
201
|
}
|
|
176
202
|
this._cols = cols;
|
|
177
203
|
this._rows = rows;
|
|
178
|
-
this._scrollTop = 0;
|
|
179
|
-
this._scrollBottom = rows - 1;
|
|
204
|
+
this._scrollTop = this._clamp(this._scrollTop, 0, rows - 1);
|
|
205
|
+
this._scrollBottom = this._clamp(this._scrollBottom, 0, rows - 1);
|
|
206
|
+
if (this._scrollTop >= this._scrollBottom) {
|
|
207
|
+
this._scrollTop = 0;
|
|
208
|
+
this._scrollBottom = rows - 1;
|
|
209
|
+
}
|
|
180
210
|
this._cursorX = this._clamp(this._cursorX, 0, cols - 1);
|
|
181
211
|
this._cursorY = this._clamp(this._cursorY, 0, rows - 1);
|
|
182
212
|
}
|
|
@@ -186,13 +216,96 @@ var TerminalBuffer = class {
|
|
|
186
216
|
_makeRow(cols) {
|
|
187
217
|
return Array(cols).fill(null);
|
|
188
218
|
}
|
|
219
|
+
_createDefaultTabStops(cols) {
|
|
220
|
+
const tabStops = /* @__PURE__ */ new Set();
|
|
221
|
+
for (let column = 8; column < cols; column += 8) {
|
|
222
|
+
tabStops.add(column);
|
|
223
|
+
}
|
|
224
|
+
return tabStops;
|
|
225
|
+
}
|
|
189
226
|
_clamp(value, min, max) {
|
|
190
227
|
return Math.max(min, Math.min(max, value));
|
|
191
228
|
}
|
|
229
|
+
_createSavedCursorState() {
|
|
230
|
+
return {
|
|
231
|
+
x: this._cursorX,
|
|
232
|
+
y: this._cursorY,
|
|
233
|
+
autoWrap: this._autoWrap,
|
|
234
|
+
style: { ...this._style, fg: this._style.fg?.slice(), bg: this._style.bg?.slice() },
|
|
235
|
+
styleSequence: this._styleSequence
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
_saveCursor() {
|
|
239
|
+
this._savedCursor = this._createSavedCursorState();
|
|
240
|
+
}
|
|
241
|
+
_restoreCursor() {
|
|
242
|
+
this._cursorX = this._clamp(this._savedCursor.x, 0, this._cols - 1);
|
|
243
|
+
this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
|
|
244
|
+
this._autoWrap = this._savedCursor.autoWrap;
|
|
245
|
+
this._style = {
|
|
246
|
+
...this._savedCursor.style,
|
|
247
|
+
fg: this._savedCursor.style.fg?.slice(),
|
|
248
|
+
bg: this._savedCursor.style.bg?.slice()
|
|
249
|
+
};
|
|
250
|
+
this._styleSequence = this._savedCursor.styleSequence;
|
|
251
|
+
}
|
|
252
|
+
_resetModes() {
|
|
253
|
+
this._autoWrap = true;
|
|
254
|
+
this._originMode = false;
|
|
255
|
+
this._insertMode = false;
|
|
256
|
+
this._pendingWrap = false;
|
|
257
|
+
this._tabStops = this._createDefaultTabStops(this._cols);
|
|
258
|
+
this._g0Charset = "ascii";
|
|
259
|
+
this._g1Charset = "ascii";
|
|
260
|
+
this._shiftOut = false;
|
|
261
|
+
this._resetStyle();
|
|
262
|
+
}
|
|
263
|
+
_writePrintable(ch) {
|
|
264
|
+
const width = this._cellWidth(ch);
|
|
265
|
+
if (this._autoWrap && this._pendingWrap) {
|
|
266
|
+
this._cursorX = 0;
|
|
267
|
+
this._newline();
|
|
268
|
+
} else if (this._autoWrap && this._cursorX + width > this._cols) {
|
|
269
|
+
this._cursorX = 0;
|
|
270
|
+
this._newline();
|
|
271
|
+
}
|
|
272
|
+
if (this._insertMode) {
|
|
273
|
+
const row = this._screen[this._cursorY];
|
|
274
|
+
if (row) {
|
|
275
|
+
row.splice(this._cursorX, 0, ...Array(width).fill(null));
|
|
276
|
+
row.splice(this._cols);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
this._setChar(this._cursorY, this._cursorX, ch);
|
|
280
|
+
for (let column = 1; column < width && this._cursorX + column < this._cols; column += 1) {
|
|
281
|
+
const row = this._screen[this._cursorY];
|
|
282
|
+
if (row) row[this._cursorX + column] = null;
|
|
283
|
+
}
|
|
284
|
+
this._lastPrintedChar = ch;
|
|
285
|
+
if (!this._autoWrap) {
|
|
286
|
+
this._cursorX = Math.min(this._cursorX + width, this._cols - 1);
|
|
287
|
+
this._pendingWrap = false;
|
|
288
|
+
} else if (this._cursorX + width >= this._cols) {
|
|
289
|
+
this._cursorX = this._cols - 1;
|
|
290
|
+
this._pendingWrap = true;
|
|
291
|
+
} else {
|
|
292
|
+
this._cursorX += width;
|
|
293
|
+
this._pendingWrap = false;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
_cellWidth(ch) {
|
|
297
|
+
const codePoint = ch.codePointAt(0);
|
|
298
|
+
if (codePoint === void 0) return 0;
|
|
299
|
+
if (codePoint >= 4352 && codePoint <= 4447 || codePoint === 9001 || codePoint === 9002 || codePoint >= 11904 && codePoint <= 12350 || codePoint >= 12353 && codePoint <= 13247 || codePoint >= 13312 && codePoint <= 19903 || codePoint >= 19968 && codePoint <= 42191 || codePoint >= 44032 && codePoint <= 55215 || codePoint >= 63744 && codePoint <= 64255 || codePoint >= 65040 && codePoint <= 65049 || codePoint >= 65072 && codePoint <= 65135 || codePoint >= 65280 && codePoint <= 65376 || codePoint >= 65504 && codePoint <= 65510 || codePoint >= 127488 && codePoint <= 131069 || codePoint >= 131072 && codePoint <= 262141) {
|
|
300
|
+
return Math.min(2, this._cols);
|
|
301
|
+
}
|
|
302
|
+
return 1;
|
|
303
|
+
}
|
|
192
304
|
_setChar(y, x, ch) {
|
|
193
305
|
const row = this._screen[y];
|
|
194
306
|
if (row && x >= 0 && x < this._cols) {
|
|
195
|
-
const
|
|
307
|
+
const renderedChar = this._style.conceal ? " " : ch;
|
|
308
|
+
const cell = [renderedChar.charCodeAt(0), renderedChar];
|
|
196
309
|
if (this._styleSequence.length > 0) {
|
|
197
310
|
Object.defineProperty(cell, "style", {
|
|
198
311
|
value: this._styleSequence,
|
|
@@ -223,6 +336,7 @@ var TerminalBuffer = class {
|
|
|
223
336
|
}
|
|
224
337
|
}
|
|
225
338
|
_newline() {
|
|
339
|
+
this._pendingWrap = false;
|
|
226
340
|
if (this._cursorY === this._scrollBottom) {
|
|
227
341
|
this._scrollUp(1);
|
|
228
342
|
} else {
|
|
@@ -231,7 +345,11 @@ var TerminalBuffer = class {
|
|
|
231
345
|
}
|
|
232
346
|
_parseCsiParams() {
|
|
233
347
|
if (!this._csiParams) return [];
|
|
234
|
-
|
|
348
|
+
const values = this._csiParams.split(";").flatMap((segment) => segment.split(":")).map((segment) => segment === "" ? 0 : parseInt(segment, 10));
|
|
349
|
+
if ((values[0] === 38 || values[0] === 48) && values[1] === 2 && values[2] === 0) {
|
|
350
|
+
values.splice(2, 1);
|
|
351
|
+
}
|
|
352
|
+
return values;
|
|
235
353
|
}
|
|
236
354
|
_execCsi(final) {
|
|
237
355
|
const params = this._parseCsiParams();
|
|
@@ -242,21 +360,45 @@ var TerminalBuffer = class {
|
|
|
242
360
|
if (params.includes(7)) {
|
|
243
361
|
this._autoWrap = final === "h";
|
|
244
362
|
}
|
|
363
|
+
if (params.includes(6)) {
|
|
364
|
+
this._originMode = final === "h";
|
|
365
|
+
this._cursorX = 0;
|
|
366
|
+
this._cursorY = this._originMode ? this._scrollTop : 0;
|
|
367
|
+
}
|
|
245
368
|
if (params.includes(1049)) {
|
|
246
369
|
if (final === "h") {
|
|
370
|
+
this._primaryScreen = {
|
|
371
|
+
screen: this._screen,
|
|
372
|
+
cursorX: this._cursorX,
|
|
373
|
+
cursorY: this._cursorY,
|
|
374
|
+
pendingWrap: this._pendingWrap,
|
|
375
|
+
style: { ...this._style, fg: this._style.fg?.slice(), bg: this._style.bg?.slice() },
|
|
376
|
+
styleSequence: this._styleSequence
|
|
377
|
+
};
|
|
247
378
|
this._screen = this._makeScreen(this._cols, this._rows);
|
|
248
379
|
this._cursorX = 0;
|
|
249
380
|
this._cursorY = 0;
|
|
381
|
+
this._pendingWrap = false;
|
|
250
382
|
} else {
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
383
|
+
if (this._primaryScreen !== null) {
|
|
384
|
+
this._screen = this._primaryScreen.screen;
|
|
385
|
+
this._cursorX = this._primaryScreen.cursorX;
|
|
386
|
+
this._cursorY = this._primaryScreen.cursorY;
|
|
387
|
+
this._pendingWrap = this._primaryScreen.pendingWrap;
|
|
388
|
+
this._style = this._primaryScreen.style;
|
|
389
|
+
this._styleSequence = this._primaryScreen.styleSequence;
|
|
390
|
+
this._primaryScreen = null;
|
|
391
|
+
}
|
|
254
392
|
}
|
|
255
|
-
this._resetStyle();
|
|
393
|
+
if (final === "h") this._resetStyle();
|
|
256
394
|
}
|
|
257
395
|
}
|
|
258
396
|
return;
|
|
259
397
|
}
|
|
398
|
+
if ((final === "h" || final === "l") && params.includes(4)) {
|
|
399
|
+
this._insertMode = final === "h";
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
260
402
|
switch (final) {
|
|
261
403
|
case "A":
|
|
262
404
|
this._cursorY = this._clamp(this._cursorY - Math.max(1, p0), 0, this._rows - 1);
|
|
@@ -288,7 +430,7 @@ var TerminalBuffer = class {
|
|
|
288
430
|
case "H":
|
|
289
431
|
// cursor position
|
|
290
432
|
case "f":
|
|
291
|
-
this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
|
|
433
|
+
this._cursorY = this._originMode ? this._clamp(this._scrollTop + Math.max(1, p0) - 1, this._scrollTop, this._scrollBottom) : this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
|
|
292
434
|
this._cursorX = this._clamp(Math.max(1, p1) - 1, 0, this._cols - 1);
|
|
293
435
|
break;
|
|
294
436
|
case "I":
|
|
@@ -303,7 +445,7 @@ var TerminalBuffer = class {
|
|
|
303
445
|
} else if (p0 === 1) {
|
|
304
446
|
for (let y = 0; y < this._cursorY; y++) this._eraseLine(y, 0, this._cols - 1);
|
|
305
447
|
this._eraseLine(this._cursorY, 0, this._cursorX);
|
|
306
|
-
} else if (p0 === 2
|
|
448
|
+
} else if (p0 === 2) {
|
|
307
449
|
for (let y = 0; y < this._rows; y++) this._eraseLine(y, 0, this._cols - 1);
|
|
308
450
|
}
|
|
309
451
|
break;
|
|
@@ -316,6 +458,9 @@ var TerminalBuffer = class {
|
|
|
316
458
|
this._eraseLine(this._cursorY, this._cursorX, this._cursorX + Math.max(1, p0) - 1);
|
|
317
459
|
break;
|
|
318
460
|
case "L": {
|
|
461
|
+
if (this._cursorY < this._scrollTop || this._cursorY > this._scrollBottom) {
|
|
462
|
+
break;
|
|
463
|
+
}
|
|
319
464
|
const n = Math.max(1, p0);
|
|
320
465
|
for (let i = 0; i < n; i++) {
|
|
321
466
|
this._screen.splice(this._scrollBottom, 1);
|
|
@@ -324,6 +469,9 @@ var TerminalBuffer = class {
|
|
|
324
469
|
break;
|
|
325
470
|
}
|
|
326
471
|
case "M": {
|
|
472
|
+
if (this._cursorY < this._scrollTop || this._cursorY > this._scrollBottom) {
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
327
475
|
const n = Math.max(1, p0);
|
|
328
476
|
for (let i = 0; i < n; i++) {
|
|
329
477
|
this._screen.splice(this._cursorY, 1);
|
|
@@ -362,6 +510,13 @@ var TerminalBuffer = class {
|
|
|
362
510
|
}
|
|
363
511
|
break;
|
|
364
512
|
}
|
|
513
|
+
case "b":
|
|
514
|
+
if (this._lastPrintedChar !== null) {
|
|
515
|
+
for (let index = 0; index < Math.max(1, p0); index += 1) {
|
|
516
|
+
this._writePrintable(this._lastPrintedChar);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
break;
|
|
365
520
|
case "d":
|
|
366
521
|
this._cursorY = this._clamp(Math.max(1, p0) - 1, 0, this._rows - 1);
|
|
367
522
|
break;
|
|
@@ -376,15 +531,19 @@ var TerminalBuffer = class {
|
|
|
376
531
|
this._scrollBottom = bottom;
|
|
377
532
|
}
|
|
378
533
|
this._cursorX = 0;
|
|
379
|
-
this._cursorY = 0;
|
|
534
|
+
this._cursorY = this._originMode ? this._scrollTop : 0;
|
|
380
535
|
break;
|
|
381
536
|
}
|
|
382
537
|
case "s":
|
|
383
|
-
this.
|
|
538
|
+
this._saveCursor();
|
|
384
539
|
break;
|
|
385
540
|
case "u":
|
|
386
|
-
this.
|
|
387
|
-
|
|
541
|
+
this._restoreCursor();
|
|
542
|
+
break;
|
|
543
|
+
case "p":
|
|
544
|
+
if (this._csiPrivate === "!") {
|
|
545
|
+
this._resetModes();
|
|
546
|
+
}
|
|
388
547
|
break;
|
|
389
548
|
case "m":
|
|
390
549
|
this._applySgr(params);
|
|
@@ -395,6 +554,14 @@ var TerminalBuffer = class {
|
|
|
395
554
|
}
|
|
396
555
|
_feed(ch) {
|
|
397
556
|
const code = ch.charCodeAt(0);
|
|
557
|
+
if (this._state !== 0 /* Normal */ && (code === 24 || code === 26)) {
|
|
558
|
+
this._state = 0 /* Normal */;
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
if (this._state === 2 /* Csi */ && code === 27) {
|
|
562
|
+
this._state = 1 /* Escape */;
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
398
565
|
switch (this._state) {
|
|
399
566
|
case 0 /* Normal */:
|
|
400
567
|
this._feedNormal(ch, code);
|
|
@@ -409,20 +576,37 @@ var TerminalBuffer = class {
|
|
|
409
576
|
if (code === 7 || code === 156) {
|
|
410
577
|
this._state = 0 /* Normal */;
|
|
411
578
|
} else if (code === 27) {
|
|
412
|
-
this.
|
|
579
|
+
this._stringState = 3 /* Osc */;
|
|
580
|
+
this._state = 5 /* StringEscape */;
|
|
413
581
|
}
|
|
414
582
|
break;
|
|
415
583
|
case 4 /* Str */:
|
|
416
|
-
if (code === 156
|
|
584
|
+
if (code === 156) {
|
|
417
585
|
this._state = 0 /* Normal */;
|
|
418
586
|
} else if (code === 27) {
|
|
419
|
-
this.
|
|
587
|
+
this._stringState = 4 /* Str */;
|
|
588
|
+
this._state = 5 /* StringEscape */;
|
|
420
589
|
}
|
|
421
590
|
break;
|
|
422
|
-
case 5 /*
|
|
591
|
+
case 5 /* StringEscape */:
|
|
592
|
+
this._state = ch === "\\" ? 0 /* Normal */ : this._stringState;
|
|
593
|
+
break;
|
|
594
|
+
case 6 /* EscCharset */:
|
|
595
|
+
if (this._charsetTarget === "g0") this._g0Charset = ch === "0" ? "graphics" : "ascii";
|
|
596
|
+
if (this._charsetTarget === "g1") this._g1Charset = ch === "0" ? "graphics" : "ascii";
|
|
597
|
+
this._charsetTarget = null;
|
|
423
598
|
this._state = 0 /* Normal */;
|
|
424
599
|
break;
|
|
425
|
-
case
|
|
600
|
+
case 7 /* EscHash */:
|
|
601
|
+
if (ch === "8") {
|
|
602
|
+
for (let row = 0; row < this._rows; row += 1) {
|
|
603
|
+
for (let column = 0; column < this._cols; column += 1) {
|
|
604
|
+
this._setChar(row, column, "E");
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
this._cursorX = 0;
|
|
608
|
+
this._cursorY = 0;
|
|
609
|
+
}
|
|
426
610
|
this._state = 0 /* Normal */;
|
|
427
611
|
break;
|
|
428
612
|
}
|
|
@@ -438,32 +622,28 @@ var TerminalBuffer = class {
|
|
|
438
622
|
this._state = 3 /* Osc */;
|
|
439
623
|
} else if (code === 144 || code === 152 || code === 158 || code === 159) {
|
|
440
624
|
this._state = 4 /* Str */;
|
|
625
|
+
} else if (code === 133) {
|
|
626
|
+
this._cursorX = 0;
|
|
627
|
+
this._newline();
|
|
628
|
+
} else if (code === 156) {
|
|
441
629
|
} else if (code === 7 || code === 5 || code === 6) {
|
|
442
630
|
} else if (code === 8) {
|
|
631
|
+
this._pendingWrap = false;
|
|
443
632
|
if (this._cursorX > 0) this._cursorX--;
|
|
444
633
|
} else if (code === 127) {
|
|
445
|
-
if (this._cursorX > 0) {
|
|
446
|
-
this._cursorX--;
|
|
447
|
-
this._setChar(this._cursorY, this._cursorX, " ");
|
|
448
|
-
}
|
|
449
634
|
} else if (code === 9) {
|
|
450
|
-
|
|
635
|
+
const nextTabStop = [...this._tabStops].sort((left, right) => left - right).find((tabStop) => tabStop > this._cursorX);
|
|
636
|
+
this._cursorX = nextTabStop ?? this._cols - 1;
|
|
451
637
|
} else if (code === 10 || code === 11 || code === 12) {
|
|
452
638
|
this._newline();
|
|
453
639
|
} else if (code === 13) {
|
|
640
|
+
this._pendingWrap = false;
|
|
454
641
|
this._cursorX = 0;
|
|
455
642
|
} else if (code === 14 || code === 15) {
|
|
643
|
+
this._shiftOut = code === 14;
|
|
456
644
|
} else if (code >= 32 && code !== 127) {
|
|
457
|
-
this.
|
|
458
|
-
this.
|
|
459
|
-
if (!this._autoWrap) {
|
|
460
|
-
this._cursorX = Math.min(this._cursorX, this._cols - 1);
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
if (this._cursorX >= this._cols) {
|
|
464
|
-
this._cursorX = 0;
|
|
465
|
-
this._newline();
|
|
466
|
-
}
|
|
645
|
+
const charset = this._shiftOut ? this._g1Charset : this._g0Charset;
|
|
646
|
+
this._writePrintable(charset === "graphics" ? DEC_SPECIAL_GRAPHICS[ch] ?? ch : ch);
|
|
467
647
|
}
|
|
468
648
|
}
|
|
469
649
|
_feedEscape(ch, code) {
|
|
@@ -477,14 +657,14 @@ var TerminalBuffer = class {
|
|
|
477
657
|
} else if (code === 80 || code === 88 || code === 94 || code === 95) {
|
|
478
658
|
this._state = 4 /* Str */;
|
|
479
659
|
} else if (code === 40 || code === 41 || code === 42 || code === 43 || code === 45 || code === 46) {
|
|
480
|
-
this.
|
|
660
|
+
this._charsetTarget = code === 40 ? "g0" : code === 41 ? "g1" : null;
|
|
661
|
+
this._state = 6 /* EscCharset */;
|
|
481
662
|
} else if (code === 35) {
|
|
482
|
-
this._state =
|
|
663
|
+
this._state = 7 /* EscHash */;
|
|
483
664
|
} else if (code === 55) {
|
|
484
|
-
this.
|
|
665
|
+
this._saveCursor();
|
|
485
666
|
} else if (code === 56) {
|
|
486
|
-
this.
|
|
487
|
-
this._cursorY = this._clamp(this._savedCursor.y, 0, this._rows - 1);
|
|
667
|
+
this._restoreCursor();
|
|
488
668
|
} else if (code === 68) {
|
|
489
669
|
this._newline();
|
|
490
670
|
} else if (code === 69) {
|
|
@@ -497,14 +677,15 @@ var TerminalBuffer = class {
|
|
|
497
677
|
this._cursorY = Math.max(0, this._cursorY - 1);
|
|
498
678
|
}
|
|
499
679
|
} else if (code === 72) {
|
|
680
|
+
this._tabStops.add(this._cursorX);
|
|
500
681
|
} else if (code === 99) {
|
|
501
682
|
this._screen = this._makeScreen(this._cols, this._rows);
|
|
502
683
|
this._cursorX = 0;
|
|
503
684
|
this._cursorY = 0;
|
|
504
|
-
this._savedCursor = { x: 0, y: 0 };
|
|
505
685
|
this._scrollTop = 0;
|
|
506
686
|
this._scrollBottom = this._rows - 1;
|
|
507
|
-
this.
|
|
687
|
+
this._resetModes();
|
|
688
|
+
this._savedCursor = this._createSavedCursorState();
|
|
508
689
|
}
|
|
509
690
|
}
|
|
510
691
|
_feedCsi(ch, code) {
|
|
@@ -513,7 +694,7 @@ var TerminalBuffer = class {
|
|
|
513
694
|
this._state = 0 /* Normal */;
|
|
514
695
|
} else if (code === 63 || code === 33 || code === 62 || code === 32) {
|
|
515
696
|
this._csiPrivate = ch;
|
|
516
|
-
} else if (code >= 48 && code <= 57 || code === 59) {
|
|
697
|
+
} else if (code >= 48 && code <= 57 || code === 59 || code === 58) {
|
|
517
698
|
this._csiParams += ch;
|
|
518
699
|
}
|
|
519
700
|
}
|
|
@@ -544,6 +725,9 @@ var TerminalBuffer = class {
|
|
|
544
725
|
case 7:
|
|
545
726
|
this._style.inverse = true;
|
|
546
727
|
break;
|
|
728
|
+
case 8:
|
|
729
|
+
this._style.conceal = true;
|
|
730
|
+
break;
|
|
547
731
|
case 9:
|
|
548
732
|
this._style.strikethrough = true;
|
|
549
733
|
break;
|
|
@@ -561,6 +745,9 @@ var TerminalBuffer = class {
|
|
|
561
745
|
case 27:
|
|
562
746
|
this._style.inverse = false;
|
|
563
747
|
break;
|
|
748
|
+
case 28:
|
|
749
|
+
this._style.conceal = false;
|
|
750
|
+
break;
|
|
564
751
|
case 29:
|
|
565
752
|
this._style.strikethrough = false;
|
|
566
753
|
break;
|
|
@@ -615,6 +802,7 @@ function createDefaultStyleState() {
|
|
|
615
802
|
italic: false,
|
|
616
803
|
underline: false,
|
|
617
804
|
inverse: false,
|
|
805
|
+
conceal: false,
|
|
618
806
|
strikethrough: false
|
|
619
807
|
};
|
|
620
808
|
}
|
|
@@ -635,6 +823,9 @@ function serializeStyleState(state) {
|
|
|
635
823
|
if (state.inverse) {
|
|
636
824
|
codes.push(7);
|
|
637
825
|
}
|
|
826
|
+
if (state.conceal) {
|
|
827
|
+
codes.push(8);
|
|
828
|
+
}
|
|
638
829
|
if (state.strikethrough) {
|
|
639
830
|
codes.push(9);
|
|
640
831
|
}
|
|
@@ -753,6 +944,7 @@ var WAIT_FOR_POLL_MS = 10;
|
|
|
753
944
|
var TYPE_DELAY_MS = 15;
|
|
754
945
|
var CLOSE_AFTER_SIGNAL_GRACE_MS = 250;
|
|
755
946
|
var CLOSE_AFTER_SIGTERM_MS = 1e3;
|
|
947
|
+
var CLOSE_AFTER_SIGKILL_MS = 1e3;
|
|
756
948
|
var TerminalSession = class {
|
|
757
949
|
id;
|
|
758
950
|
command;
|
|
@@ -766,8 +958,7 @@ var TerminalSession = class {
|
|
|
766
958
|
lastDataAt = Date.now();
|
|
767
959
|
currentCols;
|
|
768
960
|
currentRows;
|
|
769
|
-
|
|
770
|
-
signalRequested = false;
|
|
961
|
+
closePromise = null;
|
|
771
962
|
constructor({
|
|
772
963
|
id,
|
|
773
964
|
command,
|
|
@@ -778,6 +969,7 @@ var TerminalSession = class {
|
|
|
778
969
|
rows = DEFAULT_ROWS,
|
|
779
970
|
observe = false
|
|
780
971
|
}) {
|
|
972
|
+
assertTerminalGeometry(cols, rows);
|
|
781
973
|
this.id = id;
|
|
782
974
|
this.command = command;
|
|
783
975
|
this.currentCols = cols;
|
|
@@ -822,7 +1014,7 @@ var TerminalSession = class {
|
|
|
822
1014
|
}
|
|
823
1015
|
async send(raw) {
|
|
824
1016
|
if (this.exitCode !== null) {
|
|
825
|
-
|
|
1017
|
+
throw new Error(`Terminal session "${this.id}" has already exited.`);
|
|
826
1018
|
}
|
|
827
1019
|
this.pty.write(raw);
|
|
828
1020
|
}
|
|
@@ -830,22 +1022,26 @@ var TerminalSession = class {
|
|
|
830
1022
|
if (this.exitCode !== null) {
|
|
831
1023
|
return;
|
|
832
1024
|
}
|
|
833
|
-
this.signalRequested = true;
|
|
834
1025
|
this.pty.kill(sig);
|
|
835
1026
|
}
|
|
836
1027
|
async waitFor(pattern, opts) {
|
|
837
1028
|
const timeout = opts?.timeout ?? DEFAULT_TIMEOUT_MS;
|
|
1029
|
+
assertTimeout(timeout);
|
|
838
1030
|
const startedAt = Date.now();
|
|
839
1031
|
while (Date.now() - startedAt <= timeout) {
|
|
840
1032
|
const matched = matchPattern(this.rawBuffer, pattern);
|
|
841
1033
|
if (matched !== null) {
|
|
842
1034
|
return matched;
|
|
843
1035
|
}
|
|
1036
|
+
if (this.exitCode !== null) {
|
|
1037
|
+
throw new Error(`Terminal session "${this.id}" exited before matching pattern: ${String(pattern)}`);
|
|
1038
|
+
}
|
|
844
1039
|
await sleep(WAIT_FOR_POLL_MS);
|
|
845
1040
|
}
|
|
846
1041
|
throw new Error(`Timed out waiting for pattern after ${timeout}ms: ${String(pattern)}`);
|
|
847
1042
|
}
|
|
848
1043
|
async waitForQuiet(ms) {
|
|
1044
|
+
assertQuietPeriod(ms);
|
|
849
1045
|
while (true) {
|
|
850
1046
|
const remaining = ms - (Date.now() - this.lastDataAt);
|
|
851
1047
|
if (remaining <= 0) {
|
|
@@ -878,10 +1074,14 @@ var TerminalSession = class {
|
|
|
878
1074
|
if (opts?.last === void 0) {
|
|
879
1075
|
return lines;
|
|
880
1076
|
}
|
|
1077
|
+
if (!Number.isInteger(opts.last) || opts.last < 0) {
|
|
1078
|
+
throw new Error("History last must be a non-negative integer.");
|
|
1079
|
+
}
|
|
881
1080
|
const start = Math.max(0, lines.length - opts.last);
|
|
882
1081
|
return lines.slice(start);
|
|
883
1082
|
}
|
|
884
1083
|
async resize(cols, rows) {
|
|
1084
|
+
assertTerminalGeometry(cols, rows);
|
|
885
1085
|
this.currentCols = cols;
|
|
886
1086
|
this.currentRows = rows;
|
|
887
1087
|
if (this.exitCode === null) {
|
|
@@ -890,6 +1090,9 @@ var TerminalSession = class {
|
|
|
890
1090
|
this.terminal.resize(cols, rows);
|
|
891
1091
|
}
|
|
892
1092
|
async waitForExit(opts) {
|
|
1093
|
+
if (opts?.timeout !== void 0) {
|
|
1094
|
+
assertTimeout(opts.timeout);
|
|
1095
|
+
}
|
|
893
1096
|
if (this.exitCode !== null) {
|
|
894
1097
|
return this.exitCode;
|
|
895
1098
|
}
|
|
@@ -906,32 +1109,52 @@ var TerminalSession = class {
|
|
|
906
1109
|
if (this.exitCode !== null) {
|
|
907
1110
|
return this.exitCode;
|
|
908
1111
|
}
|
|
909
|
-
|
|
910
|
-
this.
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
1112
|
+
this.closePromise ??= this.closeProcess().catch((error) => {
|
|
1113
|
+
this.closePromise = null;
|
|
1114
|
+
throw error;
|
|
1115
|
+
});
|
|
1116
|
+
return this.closePromise;
|
|
1117
|
+
}
|
|
1118
|
+
async closeProcess() {
|
|
1119
|
+
const gracefulExitCode = await waitForExit(this.exitPromise, CLOSE_AFTER_SIGNAL_GRACE_MS);
|
|
1120
|
+
if (gracefulExitCode !== null) {
|
|
1121
|
+
return gracefulExitCode;
|
|
1122
|
+
}
|
|
1123
|
+
if (this.exitCode === null) {
|
|
1124
|
+
this.pty.kill("SIGTERM");
|
|
1125
|
+
const afterSigterm = await waitForExit(this.exitPromise, CLOSE_AFTER_SIGTERM_MS);
|
|
1126
|
+
if (afterSigterm !== null) {
|
|
1127
|
+
return afterSigterm;
|
|
924
1128
|
}
|
|
925
|
-
|
|
926
|
-
|
|
1129
|
+
}
|
|
1130
|
+
if (this.exitCode === null) {
|
|
1131
|
+
this.pty.kill("SIGKILL");
|
|
1132
|
+
const afterSigkill = await waitForExit(this.exitPromise, CLOSE_AFTER_SIGKILL_MS);
|
|
1133
|
+
if (afterSigkill !== null) {
|
|
1134
|
+
return afterSigkill;
|
|
927
1135
|
}
|
|
928
1136
|
}
|
|
929
|
-
|
|
1137
|
+
throw new Error("Timed out waiting for process to exit after SIGKILL.");
|
|
930
1138
|
}
|
|
931
1139
|
on(event, cb) {
|
|
932
1140
|
this.emitter.on(event, cb);
|
|
933
1141
|
}
|
|
934
1142
|
};
|
|
1143
|
+
function assertTerminalGeometry(cols, rows) {
|
|
1144
|
+
if (!Number.isInteger(cols) || cols <= 0 || !Number.isInteger(rows) || rows <= 0) {
|
|
1145
|
+
throw new Error("Terminal columns and rows must be positive integers.");
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
function assertTimeout(timeout) {
|
|
1149
|
+
if (!Number.isFinite(timeout) || timeout < 0) {
|
|
1150
|
+
throw new Error("Timeout must be a finite non-negative number.");
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
function assertQuietPeriod(duration) {
|
|
1154
|
+
if (!Number.isFinite(duration) || duration < 0) {
|
|
1155
|
+
throw new Error("Quiet period must be a finite non-negative number.");
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
935
1158
|
function createPtyProcess({
|
|
936
1159
|
command,
|
|
937
1160
|
args,
|
|
@@ -1008,13 +1231,28 @@ function splitHistoryLines(input) {
|
|
|
1008
1231
|
}
|
|
1009
1232
|
function normalizeHistoryBuffer(input) {
|
|
1010
1233
|
let output = "";
|
|
1234
|
+
let line = "";
|
|
1235
|
+
let cursor = 0;
|
|
1011
1236
|
for (const character of input) {
|
|
1012
|
-
if (character === "\r"
|
|
1237
|
+
if (character === "\r") {
|
|
1238
|
+
cursor = 0;
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
if (character === "\b") {
|
|
1242
|
+
cursor = Math.max(0, cursor - 1);
|
|
1013
1243
|
continue;
|
|
1014
1244
|
}
|
|
1015
|
-
|
|
1245
|
+
if (character === "\n") {
|
|
1246
|
+
output += `${line}
|
|
1247
|
+
`;
|
|
1248
|
+
line = "";
|
|
1249
|
+
cursor = 0;
|
|
1250
|
+
continue;
|
|
1251
|
+
}
|
|
1252
|
+
line = `${line.slice(0, cursor)}${character}${line.slice(cursor + 1)}`;
|
|
1253
|
+
cursor += 1;
|
|
1016
1254
|
}
|
|
1017
|
-
return output;
|
|
1255
|
+
return output + line;
|
|
1018
1256
|
}
|
|
1019
1257
|
function sleep(ms) {
|
|
1020
1258
|
return new Promise((resolve) => {
|
|
@@ -1079,11 +1317,12 @@ var TerminalPilot = class _TerminalPilot {
|
|
|
1079
1317
|
}
|
|
1080
1318
|
async close() {
|
|
1081
1319
|
const sessions = [...this.sessionMap.values()];
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1320
|
+
await Promise.all(
|
|
1321
|
+
sessions.map(async (session) => {
|
|
1322
|
+
await session.close();
|
|
1323
|
+
this.sessionMap.delete(session.id);
|
|
1324
|
+
})
|
|
1325
|
+
);
|
|
1087
1326
|
}
|
|
1088
1327
|
};
|
|
1089
1328
|
|
|
@@ -1101,6 +1340,7 @@ function createTerminalPilotRuntime(options = {}) {
|
|
|
1101
1340
|
const launchPilot = options.launchPilot ?? TerminalPilot.launch;
|
|
1102
1341
|
const nameToId = /* @__PURE__ */ new Map();
|
|
1103
1342
|
const idToName = /* @__PURE__ */ new Map();
|
|
1343
|
+
const pendingNames = /* @__PURE__ */ new Set();
|
|
1104
1344
|
let pilotPromise;
|
|
1105
1345
|
function getRequestedName(name, env) {
|
|
1106
1346
|
return name ?? env?.get(SESSION_ENV_VAR);
|
|
@@ -1111,7 +1351,7 @@ function createTerminalPilotRuntime(options = {}) {
|
|
|
1111
1351
|
}
|
|
1112
1352
|
function nextSessionName() {
|
|
1113
1353
|
let index = 1;
|
|
1114
|
-
while (nameToId.has(`s${index}`)) {
|
|
1354
|
+
while (nameToId.has(`s${index}`) || pendingNames.has(`s${index}`)) {
|
|
1115
1355
|
index += 1;
|
|
1116
1356
|
}
|
|
1117
1357
|
return `s${index}`;
|
|
@@ -1122,8 +1362,12 @@ function createTerminalPilotRuntime(options = {}) {
|
|
|
1122
1362
|
return { name, session };
|
|
1123
1363
|
}
|
|
1124
1364
|
function forgetSession(name, sessionId) {
|
|
1125
|
-
nameToId.
|
|
1126
|
-
|
|
1365
|
+
if (nameToId.get(name) === sessionId) {
|
|
1366
|
+
nameToId.delete(name);
|
|
1367
|
+
}
|
|
1368
|
+
if (idToName.get(sessionId) === name) {
|
|
1369
|
+
idToName.delete(sessionId);
|
|
1370
|
+
}
|
|
1127
1371
|
}
|
|
1128
1372
|
function formatAvailableSessions(names) {
|
|
1129
1373
|
if (names.length === 0) {
|
|
@@ -1156,22 +1400,44 @@ function createTerminalPilotRuntime(options = {}) {
|
|
|
1156
1400
|
return [{ name, session }];
|
|
1157
1401
|
});
|
|
1158
1402
|
}
|
|
1403
|
+
async function discardExitedSessionName(name) {
|
|
1404
|
+
const sessionId = nameToId.get(name);
|
|
1405
|
+
if (sessionId === void 0) {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
const pilot = await getPilot();
|
|
1409
|
+
try {
|
|
1410
|
+
const session = pilot.getSession(sessionId);
|
|
1411
|
+
if (session.exitCode === null) {
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
pilot.deleteSession(sessionId);
|
|
1415
|
+
} catch {
|
|
1416
|
+
}
|
|
1417
|
+
forgetSession(name, sessionId);
|
|
1418
|
+
}
|
|
1159
1419
|
return {
|
|
1160
1420
|
async createSession(params, env) {
|
|
1161
1421
|
const requestedName = getRequestedName(params.session, env) ?? nextSessionName();
|
|
1162
|
-
|
|
1422
|
+
await discardExitedSessionName(requestedName);
|
|
1423
|
+
if (nameToId.has(requestedName) || pendingNames.has(requestedName)) {
|
|
1163
1424
|
throw new UserError(`Session "${requestedName}" already exists.`);
|
|
1164
1425
|
}
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1426
|
+
pendingNames.add(requestedName);
|
|
1427
|
+
try {
|
|
1428
|
+
const pilot = await getPilot();
|
|
1429
|
+
const session = await pilot.newSession({
|
|
1430
|
+
command: params.command,
|
|
1431
|
+
args: params.args,
|
|
1432
|
+
cwd: params.cwd,
|
|
1433
|
+
cols: params.cols,
|
|
1434
|
+
rows: params.rows,
|
|
1435
|
+
observe: params.observe
|
|
1436
|
+
});
|
|
1437
|
+
return rememberSession(requestedName, session);
|
|
1438
|
+
} finally {
|
|
1439
|
+
pendingNames.delete(requestedName);
|
|
1440
|
+
}
|
|
1175
1441
|
},
|
|
1176
1442
|
async resolveSession(name, env) {
|
|
1177
1443
|
const requestedName = getRequestedName(name, env);
|
|
@@ -1210,6 +1476,7 @@ function createTerminalPilotRuntime(options = {}) {
|
|
|
1210
1476
|
pilotPromise = void 0;
|
|
1211
1477
|
nameToId.clear();
|
|
1212
1478
|
idToName.clear();
|
|
1479
|
+
pendingNames.clear();
|
|
1213
1480
|
}
|
|
1214
1481
|
};
|
|
1215
1482
|
}
|