terminal-pilot 0.0.6 → 0.0.7

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 (45) hide show
  1. package/dist/cli.js +5708 -1261
  2. package/dist/cli.js.map +4 -4
  3. package/dist/commands/close-session.js +249 -4
  4. package/dist/commands/close-session.js.map +4 -4
  5. package/dist/commands/create-session.js +249 -4
  6. package/dist/commands/create-session.js.map +4 -4
  7. package/dist/commands/fill.js +249 -4
  8. package/dist/commands/fill.js.map +4 -4
  9. package/dist/commands/get-session.js +249 -4
  10. package/dist/commands/get-session.js.map +4 -4
  11. package/dist/commands/index.js +2376 -184
  12. package/dist/commands/index.js.map +4 -4
  13. package/dist/commands/install.js +1377 -16
  14. package/dist/commands/install.js.map +4 -4
  15. package/dist/commands/installer.js +181 -15
  16. package/dist/commands/installer.js.map +4 -4
  17. package/dist/commands/list-sessions.js +249 -4
  18. package/dist/commands/list-sessions.js.map +4 -4
  19. package/dist/commands/press-key.js +249 -4
  20. package/dist/commands/press-key.js.map +4 -4
  21. package/dist/commands/read-history.js +249 -4
  22. package/dist/commands/read-history.js.map +4 -4
  23. package/dist/commands/read-screen.js +249 -4
  24. package/dist/commands/read-screen.js.map +4 -4
  25. package/dist/commands/resize.js +249 -4
  26. package/dist/commands/resize.js.map +4 -4
  27. package/dist/commands/runtime.js +8 -2
  28. package/dist/commands/runtime.js.map +3 -3
  29. package/dist/commands/screenshot.js +1014 -8
  30. package/dist/commands/screenshot.js.map +4 -4
  31. package/dist/commands/send-signal.js +249 -4
  32. package/dist/commands/send-signal.js.map +4 -4
  33. package/dist/commands/type.js +249 -4
  34. package/dist/commands/type.js.map +4 -4
  35. package/dist/commands/uninstall.js +421 -16
  36. package/dist/commands/uninstall.js.map +4 -4
  37. package/dist/commands/wait-for-exit.js +249 -4
  38. package/dist/commands/wait-for-exit.js.map +4 -4
  39. package/dist/commands/wait-for.js +249 -4
  40. package/dist/commands/wait-for.js.map +4 -4
  41. package/dist/testing/cli-repl.js +5633 -1185
  42. package/dist/testing/cli-repl.js.map +4 -4
  43. package/dist/testing/qa-cli.js +5674 -1226
  44. package/dist/testing/qa-cli.js.map +4 -4
  45. package/package.json +17 -8
@@ -1,9 +1,1015 @@
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";
@@ -14,7 +1020,7 @@ import { EventEmitter } from "node:events";
14
1020
  import * as nodePty from "node-pty";
15
1021
 
16
1022
  // src/ansi.ts
17
- var ESC = 27;
1023
+ var ESC2 = 27;
18
1024
  var BEL = 7;
19
1025
  var ST = 156;
20
1026
  var CSI = 155;
@@ -27,7 +1033,7 @@ function stripAnsi(input) {
27
1033
  let output = "";
28
1034
  for (let index = 0; index < input.length; index += 1) {
29
1035
  const code = input.charCodeAt(index);
30
- if (code === ESC) {
1036
+ if (code === ESC2) {
31
1037
  const nextCode = input.charCodeAt(index + 1);
32
1038
  if (nextCode === 91) {
33
1039
  index = consumeCsi(input, index + 2);
@@ -78,7 +1084,7 @@ function consumeTerminatedString(input, index, allowBellTerminator) {
78
1084
  if (code === ST || allowBellTerminator && code === BEL) {
79
1085
  return index;
80
1086
  }
81
- if (code === ESC && input.charCodeAt(index + 1) === 92) {
1087
+ if (code === ESC2 && input.charCodeAt(index + 1) === 92) {
82
1088
  return index + 1;
83
1089
  }
84
1090
  index += 1;