terminal-pilot 0.0.6 → 0.0.8

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.
Files changed (51) hide show
  1. package/dist/cli.js +5663 -1269
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +268 -87
  4. package/dist/commands/close-session.js.map +4 -4
  5. package/dist/commands/create-session.js +268 -87
  6. package/dist/commands/create-session.js.map +4 -4
  7. package/dist/commands/fill.js +268 -87
  8. package/dist/commands/fill.js.map +4 -4
  9. package/dist/commands/get-session.js +268 -87
  10. package/dist/commands/get-session.js.map +4 -4
  11. package/dist/commands/index.js +2404 -279
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +1372 -14
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +178 -15
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +268 -87
  18. package/dist/commands/list-sessions.js.map +4 -4
  19. package/dist/commands/press-key.js +268 -87
  20. package/dist/commands/press-key.js.map +4 -4
  21. package/dist/commands/read-history.js +268 -87
  22. package/dist/commands/read-history.js.map +4 -4
  23. package/dist/commands/read-screen.js +268 -87
  24. package/dist/commands/read-screen.js.map +4 -4
  25. package/dist/commands/resize.js +268 -87
  26. package/dist/commands/resize.js.map +4 -4
  27. package/dist/commands/runtime.js +27 -85
  28. package/dist/commands/runtime.js.map +4 -4
  29. package/dist/commands/screenshot.js +1033 -91
  30. package/dist/commands/screenshot.js.map +4 -4
  31. package/dist/commands/send-signal.js +268 -87
  32. package/dist/commands/send-signal.js.map +4 -4
  33. package/dist/commands/type.js +268 -87
  34. package/dist/commands/type.js.map +4 -4
  35. package/dist/commands/uninstall.js +419 -17
  36. package/dist/commands/uninstall.js.map +4 -4
  37. package/dist/commands/wait-for-exit.js +268 -87
  38. package/dist/commands/wait-for-exit.js.map +4 -4
  39. package/dist/commands/wait-for.js +268 -87
  40. package/dist/commands/wait-for.js.map +4 -4
  41. package/dist/index.js +19 -83
  42. package/dist/index.js.map +3 -3
  43. package/dist/terminal-pilot.js +19 -83
  44. package/dist/terminal-pilot.js.map +3 -3
  45. package/dist/terminal-session.js +19 -83
  46. package/dist/terminal-session.js.map +3 -3
  47. package/dist/testing/cli-repl.js +5598 -1203
  48. package/dist/testing/cli-repl.js.map +4 -4
  49. package/dist/testing/qa-cli.js +5601 -1206
  50. package/dist/testing/qa-cli.js.map +4 -4
  51. package/package.json +17 -8
@@ -1,20 +1,1028 @@
1
- // src/commands/screenshot.ts
2
- import { defineCommand, S } from "@poe-code/cmdkit";
3
- import { renderTerminalPng } from "terminal-png";
1
+ // ../cmdkit/src/index.ts
2
+ import { fileURLToPath } from "node:url";
4
3
 
5
- // src/commands/runtime.ts
6
- import { UserError } from "@poe-code/cmdkit";
4
+ // ../cmdkit-schema/src/index.ts
5
+ function assertValidEnumValues(values) {
6
+ if (values.length === 0) {
7
+ throw new Error("Enum schema requires at least one value");
8
+ }
9
+ const uniqueValues = new Set(values);
10
+ if (uniqueValues.size !== values.length) {
11
+ throw new Error("Enum schema values must be unique");
12
+ }
13
+ }
14
+ var S = {
15
+ String(options = {}) {
16
+ return {
17
+ kind: "string",
18
+ ...options
19
+ };
20
+ },
21
+ Number(options = {}) {
22
+ return {
23
+ kind: "number",
24
+ ...options
25
+ };
26
+ },
27
+ Boolean(options = {}) {
28
+ return {
29
+ kind: "boolean",
30
+ ...options
31
+ };
32
+ },
33
+ Enum(values, options = {}) {
34
+ assertValidEnumValues(values);
35
+ return {
36
+ kind: "enum",
37
+ values,
38
+ ...options
39
+ };
40
+ },
41
+ Array(item, options = {}) {
42
+ return {
43
+ kind: "array",
44
+ item,
45
+ ...options
46
+ };
47
+ },
48
+ Object(shape) {
49
+ return {
50
+ kind: "object",
51
+ shape
52
+ };
53
+ },
54
+ Optional(inner) {
55
+ return {
56
+ kind: "optional",
57
+ inner
58
+ };
59
+ }
60
+ };
61
+
62
+ // ../cmdkit/src/index.ts
63
+ var commandConfigSymbol = /* @__PURE__ */ Symbol("cmdkit.command.config");
64
+ var commandSourcePathSymbol = /* @__PURE__ */ Symbol("cmdkit.command.sourcePath");
65
+ var UserError = class extends Error {
66
+ constructor(message) {
67
+ super(message);
68
+ this.name = "UserError";
69
+ }
70
+ };
71
+ function cloneScope(scope) {
72
+ return scope === void 0 ? void 0 : [...scope];
73
+ }
74
+ function cloneSecretDefinition(secret) {
75
+ return {
76
+ env: secret.env,
77
+ description: secret.description,
78
+ optional: secret.optional
79
+ };
80
+ }
81
+ function cloneSecrets(secrets) {
82
+ if (secrets === void 0) {
83
+ return {};
84
+ }
85
+ return Object.fromEntries(
86
+ Object.entries(secrets).map(([key, secret]) => [key, cloneSecretDefinition(secret)])
87
+ );
88
+ }
89
+ function cloneRequires(requires) {
90
+ if (requires === void 0) {
91
+ return void 0;
92
+ }
93
+ return {
94
+ auth: requires.auth,
95
+ apiVersion: requires.apiVersion,
96
+ check: requires.check
97
+ };
98
+ }
99
+ function parseStackPath(candidate) {
100
+ if (candidate.startsWith("file://")) {
101
+ try {
102
+ return fileURLToPath(candidate);
103
+ } catch {
104
+ return void 0;
105
+ }
106
+ }
107
+ if (candidate.startsWith("/")) {
108
+ return candidate;
109
+ }
110
+ return void 0;
111
+ }
112
+ function extractStackPath(line) {
113
+ const trimmed = line.trim();
114
+ const fileIndex = trimmed.indexOf("file://");
115
+ if (fileIndex >= 0) {
116
+ const location2 = trimmed.slice(fileIndex);
117
+ const separatorIndex2 = location2.lastIndexOf(":");
118
+ const previousSeparatorIndex2 = separatorIndex2 >= 0 ? location2.lastIndexOf(":", separatorIndex2 - 1) : -1;
119
+ const candidate2 = separatorIndex2 >= 0 && previousSeparatorIndex2 >= 0 ? location2.slice(0, previousSeparatorIndex2) : location2;
120
+ return parseStackPath(candidate2);
121
+ }
122
+ const slashIndex = trimmed.indexOf("/");
123
+ if (slashIndex < 0) {
124
+ return void 0;
125
+ }
126
+ const location = trimmed.slice(slashIndex);
127
+ const separatorIndex = location.lastIndexOf(":");
128
+ const previousSeparatorIndex = separatorIndex >= 0 ? location.lastIndexOf(":", separatorIndex - 1) : -1;
129
+ const candidate = separatorIndex >= 0 && previousSeparatorIndex >= 0 ? location.slice(0, previousSeparatorIndex) : location;
130
+ return parseStackPath(candidate);
131
+ }
132
+ function inferCommandSourcePath() {
133
+ const stack = new Error().stack;
134
+ if (typeof stack !== "string") {
135
+ return void 0;
136
+ }
137
+ for (const line of stack.split("\n").slice(1)) {
138
+ const candidate = extractStackPath(line);
139
+ if (candidate === void 0) {
140
+ continue;
141
+ }
142
+ if (candidate.includes("/packages/cmdkit/src/index.ts") || candidate.includes("/packages/cmdkit/dist/index.js")) {
143
+ continue;
144
+ }
145
+ return candidate;
146
+ }
147
+ return void 0;
148
+ }
149
+ function composeChecks(parentCheck, childCheck) {
150
+ if (parentCheck === void 0) {
151
+ return childCheck;
152
+ }
153
+ if (childCheck === void 0) {
154
+ return parentCheck;
155
+ }
156
+ return async (ctx) => {
157
+ const parentResult = await parentCheck(ctx);
158
+ if (!parentResult.ok) {
159
+ return parentResult;
160
+ }
161
+ return childCheck(ctx);
162
+ };
163
+ }
164
+ function mergeRequires(parent, child) {
165
+ if (parent === void 0 && child === void 0) {
166
+ return void 0;
167
+ }
168
+ const merged = {
169
+ auth: child?.auth ?? parent?.auth,
170
+ apiVersion: child?.apiVersion ?? parent?.apiVersion,
171
+ check: composeChecks(parent?.check, child?.check)
172
+ };
173
+ if (merged.auth === void 0 && merged.apiVersion === void 0 && merged.check === void 0) {
174
+ return void 0;
175
+ }
176
+ return merged;
177
+ }
178
+ function mergeSecrets(parent, child) {
179
+ return cloneSecrets({
180
+ ...parent,
181
+ ...child
182
+ });
183
+ }
184
+ function resolveCommandScope(ownScope, inheritedScope) {
185
+ return cloneScope(ownScope ?? inheritedScope) ?? ["cli", "sdk"];
186
+ }
187
+ function createBaseCommand(config) {
188
+ const command = {
189
+ kind: "command",
190
+ name: config.name,
191
+ description: config.description,
192
+ aliases: [...config.aliases ?? []],
193
+ positional: [...config.positional ?? []],
194
+ params: config.params,
195
+ secrets: cloneSecrets(config.secrets),
196
+ scope: resolveCommandScope(config.scope, void 0),
197
+ confirm: config.confirm ?? false,
198
+ requires: cloneRequires(config.requires),
199
+ handler: config.handler,
200
+ render: config.render
201
+ };
202
+ Object.defineProperty(command, commandConfigSymbol, {
203
+ value: {
204
+ scope: cloneScope(config.scope),
205
+ secrets: cloneSecrets(config.secrets),
206
+ requires: cloneRequires(config.requires),
207
+ sourcePath: inferCommandSourcePath()
208
+ }
209
+ });
210
+ return command;
211
+ }
212
+ function getInternalCommandConfig(command) {
213
+ return command[commandConfigSymbol];
214
+ }
215
+ function materializeCommand(command, inherited) {
216
+ const internal = getInternalCommandConfig(command);
217
+ const materialized = {
218
+ kind: "command",
219
+ name: command.name,
220
+ description: command.description,
221
+ aliases: [...command.aliases],
222
+ positional: [...command.positional],
223
+ params: command.params,
224
+ secrets: mergeSecrets(inherited.secrets, internal.secrets),
225
+ scope: resolveCommandScope(internal.scope, inherited.scope),
226
+ confirm: command.confirm,
227
+ requires: mergeRequires(inherited.requires, internal.requires),
228
+ handler: command.handler,
229
+ render: command.render
230
+ };
231
+ Object.defineProperty(materialized, commandConfigSymbol, {
232
+ value: {
233
+ scope: cloneScope(internal.scope),
234
+ secrets: cloneSecrets(internal.secrets),
235
+ requires: cloneRequires(internal.requires),
236
+ sourcePath: internal.sourcePath
237
+ }
238
+ });
239
+ Object.defineProperty(materialized, commandSourcePathSymbol, {
240
+ value: internal.sourcePath
241
+ });
242
+ return materialized;
243
+ }
244
+ function defineCommand(config) {
245
+ return materializeCommand(createBaseCommand(config), {
246
+ scope: void 0,
247
+ secrets: {},
248
+ requires: void 0
249
+ });
250
+ }
251
+
252
+ // ../terminal-png/src/index.ts
253
+ import { writeFile } from "node:fs/promises";
254
+
255
+ // ../terminal-png/src/ansi-parser.ts
256
+ var ESC = "\x1B";
257
+ function createDefaultStyle() {
258
+ return {
259
+ fg: null,
260
+ bg: null,
261
+ bold: false,
262
+ italic: false,
263
+ underline: false,
264
+ strikethrough: false,
265
+ dim: false
266
+ };
267
+ }
268
+ function cloneStyle(style) {
269
+ return { ...style };
270
+ }
271
+ function stylesEqual(left, right) {
272
+ return left.bold === right.bold && left.italic === right.italic && left.underline === right.underline && left.strikethrough === right.strikethrough && left.dim === right.dim && colorsEqual(left.fg, right.fg) && colorsEqual(left.bg, right.bg);
273
+ }
274
+ function colorsEqual(left, right) {
275
+ if (left === right) {
276
+ return true;
277
+ }
278
+ if (!left || !right || left.type !== right.type) {
279
+ return false;
280
+ }
281
+ if (left.type === "rgb" && right.type === "rgb") {
282
+ return left.r === right.r && left.g === right.g && left.b === right.b;
283
+ }
284
+ if ((left.type === "ansi4" || left.type === "ansi8") && left.type === right.type) {
285
+ return left.index === right.index;
286
+ }
287
+ return false;
288
+ }
289
+ function pushRun(runs, style, text) {
290
+ if (text.length === 0) {
291
+ return;
292
+ }
293
+ const previous = runs.at(-1);
294
+ if (previous && text !== "\n" && previous.text !== "\n" && stylesEqual(previous, style)) {
295
+ previous.text += text;
296
+ return;
297
+ }
298
+ runs.push({
299
+ text,
300
+ fg: style.fg,
301
+ bg: style.bg,
302
+ bold: style.bold,
303
+ italic: style.italic,
304
+ underline: style.underline,
305
+ strikethrough: style.strikethrough,
306
+ dim: style.dim
307
+ });
308
+ }
309
+ function parseCsi(input, start) {
310
+ let index = start + 2;
311
+ while (index < input.length) {
312
+ const code = input.charCodeAt(index);
313
+ if (code >= 64 && code <= 126) {
314
+ return {
315
+ end: index + 1,
316
+ final: input[index],
317
+ params: input.slice(start + 2, index)
318
+ };
319
+ }
320
+ index += 1;
321
+ }
322
+ return {
323
+ end: input.length,
324
+ final: null,
325
+ params: input.slice(start + 2)
326
+ };
327
+ }
328
+ function toInteger(value) {
329
+ if (!value || value.length === 0) {
330
+ return null;
331
+ }
332
+ for (const char of value) {
333
+ if (char < "0" || char > "9") {
334
+ return null;
335
+ }
336
+ }
337
+ return Number.parseInt(value, 10);
338
+ }
339
+ function clampByte(value) {
340
+ if (value < 0) {
341
+ return 0;
342
+ }
343
+ if (value > 255) {
344
+ return 255;
345
+ }
346
+ return value;
347
+ }
348
+ function applyExtendedColor(params2, start) {
349
+ const mode = params2[start];
350
+ if (mode === 5) {
351
+ const index = params2[start + 1];
352
+ if (index === void 0) {
353
+ return null;
354
+ }
355
+ return {
356
+ color: { type: "ansi8", index: clampByte(index) },
357
+ consumed: 2
358
+ };
359
+ }
360
+ if (mode === 2) {
361
+ const r = params2[start + 1];
362
+ const g = params2[start + 2];
363
+ const b = params2[start + 3];
364
+ if (r === void 0 || g === void 0 || b === void 0) {
365
+ return null;
366
+ }
367
+ return {
368
+ color: { type: "rgb", r: clampByte(r), g: clampByte(g), b: clampByte(b) },
369
+ consumed: 4
370
+ };
371
+ }
372
+ return null;
373
+ }
374
+ function applySgr(style, paramsText) {
375
+ const nextStyle = cloneStyle(style);
376
+ const rawParams = paramsText.length === 0 ? ["0"] : paramsText.split(";");
377
+ const params2 = [];
378
+ for (const rawParam of rawParams) {
379
+ const value = toInteger(rawParam);
380
+ if (value === null) {
381
+ return nextStyle;
382
+ }
383
+ params2.push(value);
384
+ }
385
+ for (let index = 0; index < params2.length; index += 1) {
386
+ const value = params2[index];
387
+ if (value === 0) {
388
+ Object.assign(nextStyle, createDefaultStyle());
389
+ continue;
390
+ }
391
+ if (value === 1) {
392
+ nextStyle.bold = true;
393
+ continue;
394
+ }
395
+ if (value === 2) {
396
+ nextStyle.dim = true;
397
+ continue;
398
+ }
399
+ if (value === 22) {
400
+ nextStyle.bold = false;
401
+ nextStyle.dim = false;
402
+ continue;
403
+ }
404
+ if (value === 3) {
405
+ nextStyle.italic = true;
406
+ continue;
407
+ }
408
+ if (value === 23) {
409
+ nextStyle.italic = false;
410
+ continue;
411
+ }
412
+ if (value === 4) {
413
+ nextStyle.underline = true;
414
+ continue;
415
+ }
416
+ if (value === 24) {
417
+ nextStyle.underline = false;
418
+ continue;
419
+ }
420
+ if (value === 9) {
421
+ nextStyle.strikethrough = true;
422
+ continue;
423
+ }
424
+ if (value === 29) {
425
+ nextStyle.strikethrough = false;
426
+ continue;
427
+ }
428
+ if (value === 39) {
429
+ nextStyle.fg = null;
430
+ continue;
431
+ }
432
+ if (value === 49) {
433
+ nextStyle.bg = null;
434
+ continue;
435
+ }
436
+ if (value >= 30 && value <= 37) {
437
+ nextStyle.fg = { type: "ansi4", index: value - 30 };
438
+ continue;
439
+ }
440
+ if (value >= 90 && value <= 97) {
441
+ nextStyle.fg = { type: "ansi4", index: value - 90 + 8 };
442
+ continue;
443
+ }
444
+ if (value >= 40 && value <= 47) {
445
+ nextStyle.bg = { type: "ansi4", index: value - 40 };
446
+ continue;
447
+ }
448
+ if (value >= 100 && value <= 107) {
449
+ nextStyle.bg = { type: "ansi4", index: value - 100 + 8 };
450
+ continue;
451
+ }
452
+ if (value === 38 || value === 48) {
453
+ const extended = applyExtendedColor(params2, index + 1);
454
+ if (!extended) {
455
+ continue;
456
+ }
457
+ if (value === 38) {
458
+ nextStyle.fg = extended.color;
459
+ } else {
460
+ nextStyle.bg = extended.color;
461
+ }
462
+ index += extended.consumed;
463
+ }
464
+ }
465
+ return nextStyle;
466
+ }
467
+ function parseAnsi(input) {
468
+ const runs = [];
469
+ let style = createDefaultStyle();
470
+ let textStart = 0;
471
+ let index = 0;
472
+ while (index < input.length) {
473
+ const char = input[index];
474
+ if (char === "\n") {
475
+ pushRun(runs, style, input.slice(textStart, index));
476
+ pushRun(runs, style, "\n");
477
+ index += 1;
478
+ textStart = index;
479
+ continue;
480
+ }
481
+ if (char === ESC && input[index + 1] === "[") {
482
+ pushRun(runs, style, input.slice(textStart, index));
483
+ const sequence = parseCsi(input, index);
484
+ if (sequence.final === "m") {
485
+ style = applySgr(style, sequence.params);
486
+ }
487
+ index = sequence.end;
488
+ textStart = index;
489
+ continue;
490
+ }
491
+ index += 1;
492
+ }
493
+ pushRun(runs, style, input.slice(textStart));
494
+ return runs;
495
+ }
496
+
497
+ // ../terminal-png/src/png-renderer.ts
498
+ import { Resvg } from "@resvg/resvg-js";
499
+
500
+ // ../terminal-png/src/font.ts
501
+ import { readFileSync } from "node:fs";
502
+ import { createRequire } from "node:module";
503
+ import { dirname, join } from "node:path";
504
+ import { fileURLToPath as fileURLToPath2 } from "node:url";
505
+ var require2 = createRequire(import.meta.url);
506
+ var fontPackageRoot = dirname(require2.resolve("jetbrains-mono/package.json"));
507
+ var webfontRoot = join(fontPackageRoot, "fonts/webfonts");
508
+ function readWebfontBase64(filename) {
509
+ return readFileSync(join(webfontRoot, filename)).toString("base64");
510
+ }
511
+ function resolveAssetPath(filename) {
512
+ return fileURLToPath2(new URL(`../assets/${filename}`, import.meta.url));
513
+ }
514
+ function createFontFace(base64, weight, style) {
515
+ return `@font-face {
516
+ font-family: 'JetBrains Mono';
517
+ font-style: ${style};
518
+ font-weight: ${weight};
519
+ src: url('data:font/woff2;base64,${base64}') format('woff2');
520
+ }`;
521
+ }
522
+ var JETBRAINS_MONO_BASE64 = readWebfontBase64("JetBrainsMono-Regular.woff2");
523
+ var JETBRAINS_MONO_FONT_FILES = [
524
+ resolveAssetPath("jetbrains-mono-400-normal.ttf"),
525
+ resolveAssetPath("jetbrains-mono-700-normal.ttf"),
526
+ resolveAssetPath("jetbrains-mono-400-italic.ttf"),
527
+ resolveAssetPath("jetbrains-mono-700-italic.ttf")
528
+ ];
529
+ var JETBRAINS_MONO_TTF_PATH = JETBRAINS_MONO_FONT_FILES[0];
530
+ var FONT_FACE_CSS = [
531
+ createFontFace(JETBRAINS_MONO_BASE64, 400, "normal"),
532
+ createFontFace(readWebfontBase64("JetBrainsMono-Bold.woff2"), 700, "normal"),
533
+ createFontFace(readWebfontBase64("JetBrainsMono-Italic.woff2"), 400, "italic"),
534
+ createFontFace(readWebfontBase64("JetBrainsMono-BoldItalic.woff2"), 700, "italic")
535
+ ].join("\n");
536
+
537
+ // ../terminal-png/src/png-renderer.ts
538
+ function renderPng(svg) {
539
+ const resvg = new Resvg(svg, {
540
+ font: {
541
+ defaultFontFamily: "JetBrains Mono",
542
+ fontFiles: [...JETBRAINS_MONO_FONT_FILES],
543
+ loadSystemFonts: false,
544
+ monospaceFamily: "JetBrains Mono"
545
+ },
546
+ fitTo: {
547
+ mode: "zoom",
548
+ value: 4
549
+ }
550
+ });
551
+ const png = resvg.render();
552
+ return Buffer.from(png.asPng());
553
+ }
554
+
555
+ // ../terminal-png/src/svg-renderer.ts
556
+ var ANSI_16_PALETTE = [
557
+ "#282a2e",
558
+ "#D74E6F",
559
+ "#31BB71",
560
+ "#D3E561",
561
+ "#8056FF",
562
+ "#ED61D7",
563
+ "#04D7D7",
564
+ "#C5C8C6",
565
+ "#4B4B4B",
566
+ "#FE5F86",
567
+ "#00D787",
568
+ "#EBFF71",
569
+ "#8F69FF",
570
+ "#FF7AEA",
571
+ "#00FEFE",
572
+ "#FFFFFF"
573
+ ];
574
+ var XTERM_256_PALETTE = [
575
+ "#000000",
576
+ "#800000",
577
+ "#008000",
578
+ "#808000",
579
+ "#000080",
580
+ "#800080",
581
+ "#008080",
582
+ "#c0c0c0",
583
+ "#808080",
584
+ "#ff0000",
585
+ "#00ff00",
586
+ "#ffff00",
587
+ "#0000ff",
588
+ "#ff00ff",
589
+ "#00ffff",
590
+ "#ffffff",
591
+ "#000000",
592
+ "#00005f",
593
+ "#000087",
594
+ "#0000af",
595
+ "#0000d7",
596
+ "#0000ff",
597
+ "#005f00",
598
+ "#005f5f",
599
+ "#005f87",
600
+ "#005faf",
601
+ "#005fd7",
602
+ "#005fff",
603
+ "#008700",
604
+ "#00875f",
605
+ "#008787",
606
+ "#0087af",
607
+ "#0087d7",
608
+ "#0087ff",
609
+ "#00af00",
610
+ "#00af5f",
611
+ "#00af87",
612
+ "#00afaf",
613
+ "#00afd7",
614
+ "#00afff",
615
+ "#00d700",
616
+ "#00d75f",
617
+ "#00d787",
618
+ "#00d7af",
619
+ "#00d7d7",
620
+ "#00d7ff",
621
+ "#00ff00",
622
+ "#00ff5f",
623
+ "#00ff87",
624
+ "#00ffaf",
625
+ "#00ffd7",
626
+ "#00ffff",
627
+ "#5f0000",
628
+ "#5f005f",
629
+ "#5f0087",
630
+ "#5f00af",
631
+ "#5f00d7",
632
+ "#5f00ff",
633
+ "#5f5f00",
634
+ "#5f5f5f",
635
+ "#5f5f87",
636
+ "#5f5faf",
637
+ "#5f5fd7",
638
+ "#5f5fff",
639
+ "#5f8700",
640
+ "#5f875f",
641
+ "#5f8787",
642
+ "#5f87af",
643
+ "#5f87d7",
644
+ "#5f87ff",
645
+ "#5faf00",
646
+ "#5faf5f",
647
+ "#5faf87",
648
+ "#5fafaf",
649
+ "#5fafd7",
650
+ "#5fafff",
651
+ "#5fd700",
652
+ "#5fd75f",
653
+ "#5fd787",
654
+ "#5fd7af",
655
+ "#5fd7d7",
656
+ "#5fd7ff",
657
+ "#5fff00",
658
+ "#5fff5f",
659
+ "#5fff87",
660
+ "#5fffaf",
661
+ "#5fffd7",
662
+ "#5fffff",
663
+ "#870000",
664
+ "#87005f",
665
+ "#870087",
666
+ "#8700af",
667
+ "#8700d7",
668
+ "#8700ff",
669
+ "#875f00",
670
+ "#875f5f",
671
+ "#875f87",
672
+ "#875faf",
673
+ "#875fd7",
674
+ "#875fff",
675
+ "#878700",
676
+ "#87875f",
677
+ "#878787",
678
+ "#8787af",
679
+ "#8787d7",
680
+ "#8787ff",
681
+ "#87af00",
682
+ "#87af5f",
683
+ "#87af87",
684
+ "#87afaf",
685
+ "#87afd7",
686
+ "#87afff",
687
+ "#87d700",
688
+ "#87d75f",
689
+ "#87d787",
690
+ "#87d7af",
691
+ "#87d7d7",
692
+ "#87d7ff",
693
+ "#87ff00",
694
+ "#87ff5f",
695
+ "#87ff87",
696
+ "#87ffaf",
697
+ "#87ffd7",
698
+ "#87ffff",
699
+ "#af0000",
700
+ "#af005f",
701
+ "#af0087",
702
+ "#af00af",
703
+ "#af00d7",
704
+ "#af00ff",
705
+ "#af5f00",
706
+ "#af5f5f",
707
+ "#af5f87",
708
+ "#af5faf",
709
+ "#af5fd7",
710
+ "#af5fff",
711
+ "#af8700",
712
+ "#af875f",
713
+ "#af8787",
714
+ "#af87af",
715
+ "#af87d7",
716
+ "#af87ff",
717
+ "#afaf00",
718
+ "#afaf5f",
719
+ "#afaf87",
720
+ "#afafaf",
721
+ "#afafd7",
722
+ "#afafff",
723
+ "#afd700",
724
+ "#afd75f",
725
+ "#afd787",
726
+ "#afd7af",
727
+ "#afd7d7",
728
+ "#afd7ff",
729
+ "#afff00",
730
+ "#afff5f",
731
+ "#afff87",
732
+ "#afffaf",
733
+ "#afffd7",
734
+ "#afffff",
735
+ "#d70000",
736
+ "#d7005f",
737
+ "#d70087",
738
+ "#d700af",
739
+ "#d700d7",
740
+ "#d700ff",
741
+ "#d75f00",
742
+ "#d75f5f",
743
+ "#d75f87",
744
+ "#d75faf",
745
+ "#d75fd7",
746
+ "#d75fff",
747
+ "#d78700",
748
+ "#d7875f",
749
+ "#d78787",
750
+ "#d787af",
751
+ "#d787d7",
752
+ "#d787ff",
753
+ "#d7af00",
754
+ "#d7af5f",
755
+ "#d7af87",
756
+ "#d7afaf",
757
+ "#d7afd7",
758
+ "#d7afff",
759
+ "#d7d700",
760
+ "#d7d75f",
761
+ "#d7d787",
762
+ "#d7d7af",
763
+ "#d7d7d7",
764
+ "#d7d7ff",
765
+ "#d7ff00",
766
+ "#d7ff5f",
767
+ "#d7ff87",
768
+ "#d7ffaf",
769
+ "#d7ffd7",
770
+ "#d7ffff",
771
+ "#ff0000",
772
+ "#ff005f",
773
+ "#ff0087",
774
+ "#ff00af",
775
+ "#ff00d7",
776
+ "#ff00ff",
777
+ "#ff5f00",
778
+ "#ff5f5f",
779
+ "#ff5f87",
780
+ "#ff5faf",
781
+ "#ff5fd7",
782
+ "#ff5fff",
783
+ "#ff8700",
784
+ "#ff875f",
785
+ "#ff8787",
786
+ "#ff87af",
787
+ "#ff87d7",
788
+ "#ff87ff",
789
+ "#ffaf00",
790
+ "#ffaf5f",
791
+ "#ffaf87",
792
+ "#ffafaf",
793
+ "#ffafd7",
794
+ "#ffafff",
795
+ "#ffd700",
796
+ "#ffd75f",
797
+ "#ffd787",
798
+ "#ffd7af",
799
+ "#ffd7d7",
800
+ "#ffd7ff",
801
+ "#ffff00",
802
+ "#ffff5f",
803
+ "#ffff87",
804
+ "#ffffaf",
805
+ "#ffffd7",
806
+ "#ffffff",
807
+ "#080808",
808
+ "#121212",
809
+ "#1c1c1c",
810
+ "#262626",
811
+ "#303030",
812
+ "#3a3a3a",
813
+ "#444444",
814
+ "#4e4e4e",
815
+ "#585858",
816
+ "#606060",
817
+ "#666666",
818
+ "#767676",
819
+ "#808080",
820
+ "#8a8a8a",
821
+ "#949494",
822
+ "#9e9e9e",
823
+ "#a8a8a8",
824
+ "#b2b2b2",
825
+ "#bcbcbc",
826
+ "#c6c6c6",
827
+ "#d0d0d0",
828
+ "#dadada",
829
+ "#e4e4e4",
830
+ "#eeeeee"
831
+ ];
832
+ var BACKGROUND = "#171717";
833
+ var DEFAULT_FOREGROUND = "#c4c4c4";
834
+ var FONT_FAMILY = "JetBrains Mono";
835
+ var FONT_SIZE = 14;
836
+ var LINE_HEIGHT = 1.2;
837
+ var CHARACTER_WIDTH = 8.412666666666667;
838
+ var TEXT_BOTTOM_PADDING = 11.6;
839
+ var DEFAULT_PADDING = {
840
+ top: 20,
841
+ right: 40,
842
+ bottom: 20,
843
+ left: 20
844
+ };
845
+ var WINDOW_BAR_HEIGHT = 15;
846
+ function renderSvg(runs, options = {}) {
847
+ const padding = options.padding === void 0 ? DEFAULT_PADDING : {
848
+ top: options.padding,
849
+ right: options.padding,
850
+ bottom: options.padding,
851
+ left: options.padding
852
+ };
853
+ const showWindow = options.window ?? true;
854
+ const titleBarHeight = showWindow ? WINDOW_BAR_HEIGHT : 0;
855
+ const textStartX = padding.left;
856
+ const lineHeightPx = FONT_SIZE * LINE_HEIGHT;
857
+ const textStartY = titleBarHeight + padding.top + lineHeightPx;
858
+ const lines = splitIntoLines(runs);
859
+ const contentWidth = measureLines(lines);
860
+ const width = padding.left + contentWidth + padding.right;
861
+ const height = titleBarHeight + padding.top + lines.length * lineHeightPx + padding.bottom + TEXT_BOTTOM_PADDING;
862
+ const svgWidth = formatNumber(width);
863
+ const svgHeight = formatNumber(height);
864
+ const viewBox = `0 0 ${svgWidth} ${svgHeight}`;
865
+ const textElements = renderLines(lines, textStartX, textStartY, lineHeightPx);
866
+ return [
867
+ `<svg xmlns="http://www.w3.org/2000/svg" width="${svgWidth}" height="${svgHeight}" viewBox="${viewBox}">`,
868
+ "<defs>",
869
+ "<style><![CDATA[",
870
+ FONT_FACE_CSS,
871
+ "]]></style>",
872
+ "</defs>",
873
+ `<rect x="0" y="0" width="${svgWidth}" height="${svgHeight}" fill="${BACKGROUND}" />`,
874
+ showWindow ? renderWindowControls() : "",
875
+ `<g font-family="${FONT_FAMILY}" font-size="${formatNumber(FONT_SIZE)}px" fill="${DEFAULT_FOREGROUND}">`,
876
+ textElements,
877
+ "</g>",
878
+ "</svg>"
879
+ ].join("");
880
+ }
881
+ function splitIntoLines(runs) {
882
+ const lines = [[]];
883
+ for (const run of runs) {
884
+ if (run.text === "\n") {
885
+ lines.push([]);
886
+ continue;
887
+ }
888
+ lines[lines.length - 1]?.push(run);
889
+ }
890
+ return lines;
891
+ }
892
+ function measureLines(lines) {
893
+ return Math.max(
894
+ ...lines.map((line) => line.reduce((width, run) => width + displayWidth(run.text) * CHARACTER_WIDTH, 0)),
895
+ 0
896
+ );
897
+ }
898
+ function displayWidth(text) {
899
+ const segmenter = new Intl.Segmenter();
900
+ let width = 0;
901
+ for (const { segment } of segmenter.segment(text)) {
902
+ const cp = segment.codePointAt(0);
903
+ width += cp !== void 0 && isWideCodePoint(cp) ? 2 : 1;
904
+ }
905
+ return width;
906
+ }
907
+ function isWideCodePoint(cp) {
908
+ return cp >= 4352 && cp <= 4447 || // Hangul Jamo
909
+ cp === 9001 || cp === 9002 || // Angle brackets
910
+ cp >= 11904 && cp <= 12350 || // CJK Radicals, Kangxi
911
+ cp >= 12353 && cp <= 13247 || // Hiragana, Katakana, CJK symbols
912
+ cp >= 13312 && cp <= 19903 || // CJK Extension A
913
+ cp >= 19968 && cp <= 42191 || // CJK Unified Ideographs
914
+ cp >= 43360 && cp <= 43391 || // Hangul Jamo Extended-A
915
+ cp >= 44032 && cp <= 55215 || // Hangul Syllables
916
+ cp >= 63744 && cp <= 64255 || // CJK Compatibility Ideographs
917
+ cp >= 65040 && cp <= 65049 || // Vertical Forms
918
+ cp >= 65072 && cp <= 65135 || // CJK Compatibility Forms
919
+ cp >= 65280 && cp <= 65376 || // Fullwidth Latin, Halfwidth Katakana
920
+ cp >= 65504 && cp <= 65510 || // Fullwidth Signs
921
+ cp >= 110592 && cp <= 110847 || // Kana Supplement
922
+ cp >= 126980 && cp <= 126980 || // Mahjong tile
923
+ cp >= 127183 && cp <= 127183 || // Playing card black joker
924
+ cp >= 127488 && cp <= 131069 || // Enclosed CJK + Emoji
925
+ cp >= 131072 && cp <= 196605 || // CJK Extension B–F
926
+ cp >= 196608 && cp <= 262141;
927
+ }
928
+ function renderLines(lines, textStartX, textStartY, lineHeightPx) {
929
+ return lines.map((line, index) => {
930
+ const y = formatNumber(textStartY + index * lineHeightPx);
931
+ if (line.length === 0) {
932
+ return `<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve"/>`;
933
+ }
934
+ return [
935
+ `<text x="${formatNumber(textStartX)}" y="${y}" xml:space="preserve">`,
936
+ line.map(renderRun).join(""),
937
+ "</text>"
938
+ ].join("");
939
+ }).join("");
940
+ }
941
+ function renderRun(run) {
942
+ const attributes = ['xml:space="preserve"'];
943
+ const color = resolveColor(run.fg);
944
+ const textDecorations = [];
945
+ if (color !== DEFAULT_FOREGROUND) {
946
+ attributes.push(`fill="${escapeXmlAttribute(color)}"`);
947
+ }
948
+ if (run.bold) {
949
+ attributes.push('font-weight="bold"');
950
+ }
951
+ if (run.italic) {
952
+ attributes.push('font-style="italic"');
953
+ }
954
+ if (run.underline) {
955
+ textDecorations.push("underline");
956
+ }
957
+ if (run.strikethrough) {
958
+ textDecorations.push("line-through");
959
+ }
960
+ if (textDecorations.length > 0) {
961
+ attributes.push(`text-decoration="${textDecorations.join(" ")}"`);
962
+ }
963
+ if (run.dim) {
964
+ attributes.push('opacity="0.7"');
965
+ }
966
+ return `<tspan ${attributes.join(" ")}>${escapeXmlText(run.text)}</tspan>`;
967
+ }
968
+ function renderWindowControls() {
969
+ return [
970
+ '<circle cx="13.5" cy="12" r="5.5" fill="#FF5A54" />',
971
+ '<circle cx="32.5" cy="12" r="5.5" fill="#E6BF29" />',
972
+ '<circle cx="51.5" cy="12" r="5.5" fill="#52C12B" />'
973
+ ].join("");
974
+ }
975
+ function resolveColor(color) {
976
+ if (color === null) {
977
+ return DEFAULT_FOREGROUND;
978
+ }
979
+ if (color.type === "ansi4") {
980
+ return ANSI_16_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
981
+ }
982
+ if (color.type === "ansi8") {
983
+ if (color.index < ANSI_16_PALETTE.length) {
984
+ return ANSI_16_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
985
+ }
986
+ return XTERM_256_PALETTE[color.index] ?? DEFAULT_FOREGROUND;
987
+ }
988
+ return `rgb(${color.r},${color.g},${color.b})`;
989
+ }
990
+ function escapeXmlText(value) {
991
+ return value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
992
+ }
993
+ function escapeXmlAttribute(value) {
994
+ return escapeXmlText(value).replaceAll('"', "&quot;").replaceAll("'", "&apos;");
995
+ }
996
+ function formatNumber(value) {
997
+ return value.toFixed(2);
998
+ }
999
+
1000
+ // ../terminal-png/src/index.ts
1001
+ async function renderTerminalPng(ansiText, options = {}) {
1002
+ const runs = parseAnsi(ansiText);
1003
+ const svg = renderSvg(runs, {
1004
+ padding: options.padding,
1005
+ window: options.window
1006
+ });
1007
+ const png = renderPng(svg);
1008
+ if (options.output) {
1009
+ await writeFile(options.output, png);
1010
+ }
1011
+ return png;
1012
+ }
7
1013
 
8
1014
  // src/terminal-pilot.ts
9
1015
  import { randomUUID } from "node:crypto";
10
1016
 
11
1017
  // src/terminal-session.ts
12
- import { spawn as spawnChildProcess } from "node:child_process";
13
1018
  import { EventEmitter } from "node:events";
1019
+ import { accessSync, chmodSync, constants } from "node:fs";
1020
+ import { createRequire as createRequire2 } from "node:module";
1021
+ import { dirname as dirname2, join as join2 } from "node:path";
14
1022
  import * as nodePty from "node-pty";
15
1023
 
16
1024
  // src/ansi.ts
17
- var ESC = 27;
1025
+ var ESC2 = 27;
18
1026
  var BEL = 7;
19
1027
  var ST = 156;
20
1028
  var CSI = 155;
@@ -27,7 +1035,7 @@ function stripAnsi(input) {
27
1035
  let output = "";
28
1036
  for (let index = 0; index < input.length; index += 1) {
29
1037
  const code = input.charCodeAt(index);
30
- if (code === ESC) {
1038
+ if (code === ESC2) {
31
1039
  const nextCode = input.charCodeAt(index + 1);
32
1040
  if (nextCode === 91) {
33
1041
  index = consumeCsi(input, index + 2);
@@ -78,7 +1086,7 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
78
1086
  if (code === ST || allowBellTerminator && code === BEL) {
79
1087
  return index;
80
1088
  }
81
- if (code === ESC && input.charCodeAt(index + 1) === 92) {
1089
+ if (code === ESC2 && input.charCodeAt(index + 1) === 92) {
82
1090
  return index + 1;
83
1091
  }
84
1092
  index += 1;
@@ -921,93 +1929,27 @@ function createPtyProcess({
921
1929
  cols,
922
1930
  rows
923
1931
  }) {
924
- try {
925
- return nodePty.spawn(command, args, {
926
- cwd,
927
- env,
928
- cols,
929
- rows,
930
- encoding: "utf8"
931
- });
932
- } catch {
933
- return createChildProcessFallback({ command, args, cwd, env });
934
- }
935
- }
936
- function createChildProcessFallback({
937
- command,
938
- args,
939
- cwd,
940
- env
941
- }) {
942
- const child = spawnChildProcess(command, args, {
1932
+ ensureSpawnHelperExecutable();
1933
+ return nodePty.spawn(command, args, {
943
1934
  cwd,
944
1935
  env,
945
- stdio: ["pipe", "pipe", "pipe"]
1936
+ cols,
1937
+ rows,
1938
+ encoding: "utf8"
946
1939
  });
947
- return new ChildProcessFallback(child);
948
1940
  }
949
- var ChildProcessFallback = class {
950
- pid;
951
- child;
952
- dataEmitter = new EventEmitter();
953
- exitEmitter = new EventEmitter();
954
- constructor(child) {
955
- this.child = child;
956
- this.pid = child.pid ?? -1;
957
- child.stdout.setEncoding("utf8");
958
- child.stderr.setEncoding("utf8");
959
- child.stdout.on("data", this.handleData);
960
- child.stderr.on("data", this.handleData);
961
- child.on("exit", (exitCode, signal) => {
962
- this.exitEmitter.emit("exit", {
963
- exitCode: exitCode ?? signalToExitCode(signal),
964
- signal: void 0
965
- });
966
- });
967
- }
968
- write(data) {
969
- this.child.stdin.write(data);
970
- }
971
- resize() {
972
- }
973
- kill(signal) {
974
- this.child.kill(signal);
975
- }
976
- onData(listener) {
977
- this.dataEmitter.on("data", listener);
978
- return {
979
- dispose: () => {
980
- this.dataEmitter.off("data", listener);
981
- }
982
- };
983
- }
984
- onExit(listener) {
985
- this.exitEmitter.on("exit", listener);
986
- return {
987
- dispose: () => {
988
- this.exitEmitter.off("exit", listener);
989
- }
990
- };
991
- }
992
- handleData = (chunk) => {
993
- this.dataEmitter.emit("data", String(chunk));
994
- };
995
- };
996
- function signalToExitCode(signal) {
997
- if (signal === null) {
998
- return 0;
999
- }
1000
- const signalNumbers = {
1001
- SIGTERM: 15,
1002
- SIGINT: 2,
1003
- SIGHUP: 1,
1004
- SIGKILL: 9
1005
- };
1006
- const signalNumber = signalNumbers[signal];
1007
- if (signalNumber === void 0) {
1008
- return 1;
1941
+ var spawnHelperChecked = false;
1942
+ function ensureSpawnHelperExecutable() {
1943
+ if (spawnHelperChecked) return;
1944
+ spawnHelperChecked = true;
1945
+ const require3 = createRequire2(import.meta.url);
1946
+ const nodePtyDir = dirname2(require3.resolve("node-pty"));
1947
+ const helper = join2(nodePtyDir, "..", "prebuilds", `${process.platform}-${process.arch}`, "spawn-helper");
1948
+ try {
1949
+ accessSync(helper, constants.X_OK);
1950
+ } catch {
1951
+ chmodSync(helper, 493);
1009
1952
  }
1010
- return 128 + signalNumber;
1011
1953
  }
1012
1954
  function matchPattern(buffer, pattern) {
1013
1955
  const clean = normalizeHistoryBuffer(stripAnsi(buffer));