maesttro 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/maesttro.js CHANGED
@@ -1,4 +1,95 @@
1
1
  #!/usr/bin/env node
2
+ var __create = Object.create;
3
+ var __getProtoOf = Object.getPrototypeOf;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ function __accessProp(key) {
8
+ return this[key];
9
+ }
10
+ var __toESMCache_node;
11
+ var __toESMCache_esm;
12
+ var __toESM = (mod, isNodeMode, target) => {
13
+ var canCache = mod != null && typeof mod === "object";
14
+ if (canCache) {
15
+ var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
16
+ var cached = cache.get(mod);
17
+ if (cached)
18
+ return cached;
19
+ }
20
+ target = mod != null ? __create(__getProtoOf(mod)) : {};
21
+ const to = isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
22
+ if (mod && typeof mod === "object" || typeof mod === "function") {
23
+ for (let key of __getOwnPropNames(mod))
24
+ if (!__hasOwnProp.call(to, key))
25
+ __defProp(to, key, {
26
+ get: __accessProp.bind(mod, key),
27
+ enumerable: true
28
+ });
29
+ }
30
+ if (canCache)
31
+ cache.set(mod, to);
32
+ return to;
33
+ };
34
+ var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
35
+
36
+ // ../node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
37
+ var require_src = __commonJS(function(exports, module) {
38
+ var ESC = "\x1B";
39
+ var CSI = `${ESC}[`;
40
+ var beep = "\x07";
41
+ var cursor = {
42
+ to(x, y) {
43
+ if (!y)
44
+ return `${CSI}${x + 1}G`;
45
+ return `${CSI}${y + 1};${x + 1}H`;
46
+ },
47
+ move(x, y) {
48
+ let ret = "";
49
+ if (x < 0)
50
+ ret += `${CSI}${-x}D`;
51
+ else if (x > 0)
52
+ ret += `${CSI}${x}C`;
53
+ if (y < 0)
54
+ ret += `${CSI}${-y}A`;
55
+ else if (y > 0)
56
+ ret += `${CSI}${y}B`;
57
+ return ret;
58
+ },
59
+ up: (count = 1) => `${CSI}${count}A`,
60
+ down: (count = 1) => `${CSI}${count}B`,
61
+ forward: (count = 1) => `${CSI}${count}C`,
62
+ backward: (count = 1) => `${CSI}${count}D`,
63
+ nextLine: (count = 1) => `${CSI}E`.repeat(count),
64
+ prevLine: (count = 1) => `${CSI}F`.repeat(count),
65
+ left: `${CSI}G`,
66
+ hide: `${CSI}?25l`,
67
+ show: `${CSI}?25h`,
68
+ save: `${ESC}7`,
69
+ restore: `${ESC}8`
70
+ };
71
+ var scroll = {
72
+ up: (count = 1) => `${CSI}S`.repeat(count),
73
+ down: (count = 1) => `${CSI}T`.repeat(count)
74
+ };
75
+ var erase = {
76
+ screen: `${CSI}2J`,
77
+ up: (count = 1) => `${CSI}1J`.repeat(count),
78
+ down: (count = 1) => `${CSI}J`.repeat(count),
79
+ line: `${CSI}2K`,
80
+ lineEnd: `${CSI}K`,
81
+ lineStart: `${CSI}1K`,
82
+ lines(count) {
83
+ let clear = "";
84
+ for (let i = 0;i < count; i++)
85
+ clear += this.line + (i < count - 1 ? cursor.up() : "");
86
+ if (count)
87
+ clear += cursor.left;
88
+ return clear;
89
+ }
90
+ };
91
+ module.exports = { cursor, scroll, erase, beep };
92
+ });
2
93
 
3
94
  // src/credential-store.ts
4
95
  import {
@@ -832,6 +923,13 @@ function runnerInstructions(context) {
832
923
  "- Work in this directory. Anything outside it is not persisted.",
833
924
  "- Commit on a branch you create here. The user pushes it from their machine with `maesttro push`; the runner cannot push, merge, or delete remote branches.",
834
925
  "",
926
+ "## Installing tools",
927
+ "",
928
+ "- Preinstalled: Node 24 (npm, pnpm, yarn), TypeScript (`tsc`), Bun, Python 3.14 and uv (`uv venv`, `uv pip`, `uv tool`; plain `pip` and `python -m venv` work too), the .NET 10 SDK, a C/C++ build toolchain, and common CLI tools (jq, ripgrep, fd, unzip, zip, sqlite3).",
929
+ "- You can install more yourself without root: `npm i -g`, `bun add -g`, `pip install`, `uv tool install`, `uv python install`, `dotnet tool install -g`. They work as usual and are on `PATH` right away.",
930
+ "- Installs last only until this container exits; install again when a new session needs them. Don't install into your home directory to make them stick.",
931
+ "- System packages are unavailable: there is no root, `sudo` or `apt`. If a task needs one, tell the user which package and why.",
932
+ "",
835
933
  "## Pushing",
836
934
  "",
837
935
  "- `git push` does not work here: the runner has read-only access to the remote. This is deliberate.",
@@ -1043,6 +1141,30 @@ function purgeLegacyTokenOnce({
1043
1141
  saveConfig({ ...config, legacyTokenPurged: true });
1044
1142
  }
1045
1143
 
1144
+ // src/network-probe.ts
1145
+ import { connect } from "node:net";
1146
+ async function reachable(host, port, {
1147
+ timeoutMs = 2000,
1148
+ connectImpl = connect
1149
+ } = {}) {
1150
+ return new Promise((resolve) => {
1151
+ const socket = connectImpl(port, host);
1152
+ const timer = setTimeout(() => {
1153
+ socket.destroy();
1154
+ resolve(false);
1155
+ }, timeoutMs);
1156
+ socket.once("connect", () => {
1157
+ clearTimeout(timer);
1158
+ socket.destroy();
1159
+ resolve(true);
1160
+ });
1161
+ socket.once("error", () => {
1162
+ clearTimeout(timer);
1163
+ resolve(false);
1164
+ });
1165
+ });
1166
+ }
1167
+
1046
1168
  // src/repo.ts
1047
1169
  import { appendFileSync, mkdirSync as mkdirSync5, realpathSync } from "node:fs";
1048
1170
  import { join as join5 } from "node:path";
@@ -1227,6 +1349,16 @@ async function doctor() {
1227
1349
  return broker;
1228
1350
  }
1229
1351
  ],
1352
+ [
1353
+ "dgx-spark reachable",
1354
+ async () => {
1355
+ const { hostname, port } = new URL(DGX_SPARK_URL);
1356
+ if (!await reachable(hostname, Number(port))) {
1357
+ throw new Error(`${DGX_SPARK_URL} (on the tailnet?)`);
1358
+ }
1359
+ return DGX_SPARK_URL;
1360
+ }
1361
+ ],
1230
1362
  [
1231
1363
  "Personal SSH key NOT visible inside runner (isolation intact)",
1232
1364
  () => {
@@ -1666,6 +1798,14 @@ function stripControl(text) {
1666
1798
  }
1667
1799
  return out;
1668
1800
  }
1801
+ var ESC = String.fromCharCode(27);
1802
+ var BEL = String.fromCharCode(7);
1803
+ var ANSI = new RegExp(`${ESC}(?:\\[[0-9;?]*[a-zA-Z]|\\][^${BEL}]*${BEL})?`, "g");
1804
+ function cleanOutput(text) {
1805
+ return text.split(`
1806
+ `).map((line) => stripControl(line.replace(ANSI, "")).replace(/\r+$/, "")).join(`
1807
+ `).trim();
1808
+ }
1669
1809
  var VALID_BRANCH = /^[A-Za-z0-9](?:[A-Za-z0-9._/-]*[A-Za-z0-9_-])?$/;
1670
1810
  function isSafeBranchName(name) {
1671
1811
  if (name.length === 0 || name.length > 255)
@@ -2283,6 +2423,1023 @@ async function launch({
2283
2423
 
2284
2424
  // src/push.ts
2285
2425
  import { spawnSync as spawnSync3 } from "node:child_process";
2426
+
2427
+ // ../node_modules/.bun/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
2428
+ import { stdout, stdin } from "node:process";
2429
+ import * as l from "node:readline";
2430
+ import l__default from "node:readline";
2431
+
2432
+ // ../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
2433
+ var getCodePointsLength = (() => {
2434
+ const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
2435
+ return (input) => {
2436
+ let surrogatePairsNr = 0;
2437
+ SURROGATE_PAIR_RE.lastIndex = 0;
2438
+ while (SURROGATE_PAIR_RE.test(input)) {
2439
+ surrogatePairsNr += 1;
2440
+ }
2441
+ return input.length - surrogatePairsNr;
2442
+ };
2443
+ })();
2444
+ var isFullWidth = (x) => {
2445
+ return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
2446
+ };
2447
+ var isWideNotCJKTNotEmoji = (x) => {
2448
+ return x === 8987 || x === 9001 || x >= 12272 && x <= 12287 || x >= 12289 && x <= 12350 || x >= 12441 && x <= 12543 || x >= 12549 && x <= 12591 || x >= 12593 && x <= 12686 || x >= 12688 && x <= 12771 || x >= 12783 && x <= 12830 || x >= 12832 && x <= 12871 || x >= 12880 && x <= 19903 || x >= 65040 && x <= 65049 || x >= 65072 && x <= 65106 || x >= 65108 && x <= 65126 || x >= 65128 && x <= 65131 || x >= 127488 && x <= 127490 || x >= 127504 && x <= 127547 || x >= 127552 && x <= 127560 || x >= 131072 && x <= 196605 || x >= 196608 && x <= 262141;
2449
+ };
2450
+
2451
+ // ../node_modules/.bun/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
2452
+ var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
2453
+ var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
2454
+ var CJKT_WIDE_RE = /(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu;
2455
+ var TAB_RE = /\t{1,1000}/y;
2456
+ var EMOJI_RE = /[\u{1F1E6}-\u{1F1FF}]{2}|\u{1F3F4}[\u{E0061}-\u{E007A}]{2}[\u{E0030}-\u{E0039}\u{E0061}-\u{E007A}]{1,3}\u{E007F}|(?:\p{Emoji}\uFE0F\u20E3?|\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation})(?:\u200D(?:\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F\u20E3?))*/yu;
2457
+ var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
2458
+ var MODIFIER_RE = /\p{M}+/gu;
2459
+ var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
2460
+ var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
2461
+ const LIMIT = truncationOptions.limit ?? Infinity;
2462
+ const ELLIPSIS = truncationOptions.ellipsis ?? "";
2463
+ const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
2464
+ const ANSI_WIDTH = 0;
2465
+ const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
2466
+ const TAB_WIDTH = widthOptions.tabWidth ?? 8;
2467
+ const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
2468
+ const FULL_WIDTH_WIDTH = 2;
2469
+ const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
2470
+ const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
2471
+ const PARSE_BLOCKS = [
2472
+ [LATIN_RE, REGULAR_WIDTH],
2473
+ [ANSI_RE, ANSI_WIDTH],
2474
+ [CONTROL_RE, CONTROL_WIDTH],
2475
+ [TAB_RE, TAB_WIDTH],
2476
+ [EMOJI_RE, EMOJI_WIDTH],
2477
+ [CJKT_WIDE_RE, WIDE_WIDTH]
2478
+ ];
2479
+ let indexPrev = 0;
2480
+ let index = 0;
2481
+ let length = input.length;
2482
+ let lengthExtra = 0;
2483
+ let truncationEnabled = false;
2484
+ let truncationIndex = length;
2485
+ let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
2486
+ let unmatchedStart = 0;
2487
+ let unmatchedEnd = 0;
2488
+ let width = 0;
2489
+ let widthExtra = 0;
2490
+ outer:
2491
+ while (true) {
2492
+ if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
2493
+ const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
2494
+ lengthExtra = 0;
2495
+ for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
2496
+ const codePoint = char.codePointAt(0) || 0;
2497
+ if (isFullWidth(codePoint)) {
2498
+ widthExtra = FULL_WIDTH_WIDTH;
2499
+ } else if (isWideNotCJKTNotEmoji(codePoint)) {
2500
+ widthExtra = WIDE_WIDTH;
2501
+ } else {
2502
+ widthExtra = REGULAR_WIDTH;
2503
+ }
2504
+ if (width + widthExtra > truncationLimit) {
2505
+ truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
2506
+ }
2507
+ if (width + widthExtra > LIMIT) {
2508
+ truncationEnabled = true;
2509
+ break outer;
2510
+ }
2511
+ lengthExtra += char.length;
2512
+ width += widthExtra;
2513
+ }
2514
+ unmatchedStart = unmatchedEnd = 0;
2515
+ }
2516
+ if (index >= length) {
2517
+ break outer;
2518
+ }
2519
+ for (let i = 0, l = PARSE_BLOCKS.length;i < l; i++) {
2520
+ const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
2521
+ BLOCK_RE.lastIndex = index;
2522
+ if (BLOCK_RE.test(input)) {
2523
+ lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
2524
+ widthExtra = lengthExtra * BLOCK_WIDTH;
2525
+ if (width + widthExtra > truncationLimit) {
2526
+ truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
2527
+ }
2528
+ if (width + widthExtra > LIMIT) {
2529
+ truncationEnabled = true;
2530
+ break outer;
2531
+ }
2532
+ width += widthExtra;
2533
+ unmatchedStart = indexPrev;
2534
+ unmatchedEnd = index;
2535
+ index = indexPrev = BLOCK_RE.lastIndex;
2536
+ continue outer;
2537
+ }
2538
+ }
2539
+ index += 1;
2540
+ }
2541
+ return {
2542
+ width: truncationEnabled ? truncationLimit : width,
2543
+ index: truncationEnabled ? truncationIndex : length,
2544
+ truncated: truncationEnabled,
2545
+ ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
2546
+ };
2547
+ };
2548
+ var dist_default = getStringTruncatedWidth;
2549
+
2550
+ // ../node_modules/.bun/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
2551
+ var NO_TRUNCATION2 = {
2552
+ limit: Infinity,
2553
+ ellipsis: "",
2554
+ ellipsisWidth: 0
2555
+ };
2556
+ var fastStringWidth = (input, options = {}) => {
2557
+ return dist_default(input, NO_TRUNCATION2, options).width;
2558
+ };
2559
+ var dist_default2 = fastStringWidth;
2560
+
2561
+ // ../node_modules/.bun/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
2562
+ var ESC2 = "\x1B";
2563
+ var CSI = "›";
2564
+ var END_CODE = 39;
2565
+ var ANSI_ESCAPE_BELL = "\x07";
2566
+ var ANSI_CSI = "[";
2567
+ var ANSI_OSC = "]";
2568
+ var ANSI_SGR_TERMINATOR = "m";
2569
+ var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
2570
+ var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
2571
+ var getClosingCode = (openingCode) => {
2572
+ if (openingCode >= 30 && openingCode <= 37)
2573
+ return 39;
2574
+ if (openingCode >= 90 && openingCode <= 97)
2575
+ return 39;
2576
+ if (openingCode >= 40 && openingCode <= 47)
2577
+ return 49;
2578
+ if (openingCode >= 100 && openingCode <= 107)
2579
+ return 49;
2580
+ if (openingCode === 1 || openingCode === 2)
2581
+ return 22;
2582
+ if (openingCode === 3)
2583
+ return 23;
2584
+ if (openingCode === 4)
2585
+ return 24;
2586
+ if (openingCode === 7)
2587
+ return 27;
2588
+ if (openingCode === 8)
2589
+ return 28;
2590
+ if (openingCode === 9)
2591
+ return 29;
2592
+ if (openingCode === 0)
2593
+ return 0;
2594
+ return;
2595
+ };
2596
+ var wrapAnsiCode = (code) => `${ESC2}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
2597
+ var wrapAnsiHyperlink = (url) => `${ESC2}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
2598
+ var wrapWord = (rows, word, columns) => {
2599
+ const characters = word[Symbol.iterator]();
2600
+ let isInsideEscape = false;
2601
+ let isInsideLinkEscape = false;
2602
+ let lastRow = rows.at(-1);
2603
+ let visible = lastRow === undefined ? 0 : dist_default2(lastRow);
2604
+ let currentCharacter = characters.next();
2605
+ let nextCharacter = characters.next();
2606
+ let rawCharacterIndex = 0;
2607
+ while (!currentCharacter.done) {
2608
+ const character = currentCharacter.value;
2609
+ const characterLength = dist_default2(character);
2610
+ if (visible + characterLength <= columns) {
2611
+ rows[rows.length - 1] += character;
2612
+ } else {
2613
+ rows.push(character);
2614
+ visible = 0;
2615
+ }
2616
+ if (character === ESC2 || character === CSI) {
2617
+ isInsideEscape = true;
2618
+ isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
2619
+ }
2620
+ if (isInsideEscape) {
2621
+ if (isInsideLinkEscape) {
2622
+ if (character === ANSI_ESCAPE_BELL) {
2623
+ isInsideEscape = false;
2624
+ isInsideLinkEscape = false;
2625
+ }
2626
+ } else if (character === ANSI_SGR_TERMINATOR) {
2627
+ isInsideEscape = false;
2628
+ }
2629
+ } else {
2630
+ visible += characterLength;
2631
+ if (visible === columns && !nextCharacter.done) {
2632
+ rows.push("");
2633
+ visible = 0;
2634
+ }
2635
+ }
2636
+ currentCharacter = nextCharacter;
2637
+ nextCharacter = characters.next();
2638
+ rawCharacterIndex += character.length;
2639
+ }
2640
+ lastRow = rows.at(-1);
2641
+ if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
2642
+ rows[rows.length - 2] += rows.pop();
2643
+ }
2644
+ };
2645
+ var stringVisibleTrimSpacesRight = (string) => {
2646
+ const words = string.split(" ");
2647
+ let last = words.length;
2648
+ while (last) {
2649
+ if (dist_default2(words[last - 1])) {
2650
+ break;
2651
+ }
2652
+ last--;
2653
+ }
2654
+ if (last === words.length) {
2655
+ return string;
2656
+ }
2657
+ return words.slice(0, last).join(" ") + words.slice(last).join("");
2658
+ };
2659
+ var exec = (string, columns, options = {}) => {
2660
+ if (options.trim !== false && string.trim() === "") {
2661
+ return "";
2662
+ }
2663
+ let returnValue = "";
2664
+ let escapeCode;
2665
+ let escapeUrl;
2666
+ const words = string.split(" ");
2667
+ let rows = [""];
2668
+ let rowLength = 0;
2669
+ for (let index = 0;index < words.length; index++) {
2670
+ const word = words[index];
2671
+ if (options.trim !== false) {
2672
+ const row = rows.at(-1) ?? "";
2673
+ const trimmed = row.trimStart();
2674
+ if (row.length !== trimmed.length) {
2675
+ rows[rows.length - 1] = trimmed;
2676
+ rowLength = dist_default2(trimmed);
2677
+ }
2678
+ }
2679
+ if (index !== 0) {
2680
+ if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
2681
+ rows.push("");
2682
+ rowLength = 0;
2683
+ }
2684
+ if (rowLength || options.trim === false) {
2685
+ rows[rows.length - 1] += " ";
2686
+ rowLength++;
2687
+ }
2688
+ }
2689
+ const wordLength = dist_default2(word);
2690
+ if (options.hard && wordLength > columns) {
2691
+ const remainingColumns = columns - rowLength;
2692
+ const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
2693
+ const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
2694
+ if (breaksStartingNextLine < breaksStartingThisLine) {
2695
+ rows.push("");
2696
+ }
2697
+ wrapWord(rows, word, columns);
2698
+ rowLength = dist_default2(rows.at(-1) ?? "");
2699
+ continue;
2700
+ }
2701
+ if (rowLength + wordLength > columns && rowLength && wordLength) {
2702
+ if (options.wordWrap === false && rowLength < columns) {
2703
+ wrapWord(rows, word, columns);
2704
+ rowLength = dist_default2(rows.at(-1) ?? "");
2705
+ continue;
2706
+ }
2707
+ rows.push("");
2708
+ rowLength = 0;
2709
+ }
2710
+ if (rowLength + wordLength > columns && options.wordWrap === false) {
2711
+ wrapWord(rows, word, columns);
2712
+ rowLength = dist_default2(rows.at(-1) ?? "");
2713
+ continue;
2714
+ }
2715
+ rows[rows.length - 1] += word;
2716
+ rowLength += wordLength;
2717
+ }
2718
+ if (options.trim !== false) {
2719
+ rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
2720
+ }
2721
+ const preString = rows.join(`
2722
+ `);
2723
+ let inSurrogate = false;
2724
+ for (let i = 0;i < preString.length; i++) {
2725
+ const character = preString[i];
2726
+ returnValue += character;
2727
+ if (!inSurrogate) {
2728
+ inSurrogate = character >= "\uD800" && character <= "\uDBFF";
2729
+ if (inSurrogate) {
2730
+ continue;
2731
+ }
2732
+ } else {
2733
+ inSurrogate = false;
2734
+ }
2735
+ if (character === ESC2 || character === CSI) {
2736
+ GROUP_REGEX.lastIndex = i + 1;
2737
+ const groupsResult = GROUP_REGEX.exec(preString);
2738
+ const groups = groupsResult?.groups;
2739
+ if (groups?.code !== undefined) {
2740
+ const code = Number.parseFloat(groups.code);
2741
+ escapeCode = code === END_CODE ? undefined : code;
2742
+ } else if (groups?.uri !== undefined) {
2743
+ escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
2744
+ }
2745
+ }
2746
+ if (preString[i + 1] === `
2747
+ `) {
2748
+ if (escapeUrl) {
2749
+ returnValue += wrapAnsiHyperlink("");
2750
+ }
2751
+ const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
2752
+ if (escapeCode && closingCode) {
2753
+ returnValue += wrapAnsiCode(closingCode);
2754
+ }
2755
+ } else if (character === `
2756
+ `) {
2757
+ if (escapeCode && getClosingCode(escapeCode)) {
2758
+ returnValue += wrapAnsiCode(escapeCode);
2759
+ }
2760
+ if (escapeUrl) {
2761
+ returnValue += wrapAnsiHyperlink(escapeUrl);
2762
+ }
2763
+ }
2764
+ }
2765
+ return returnValue;
2766
+ };
2767
+ var CRLF_OR_LF = /\r?\n/;
2768
+ function wrapAnsi(string, columns, options) {
2769
+ return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join(`
2770
+ `);
2771
+ }
2772
+
2773
+ // ../node_modules/.bun/@clack+core@1.5.1/node_modules/@clack/core/dist/index.mjs
2774
+ var import_sisteransi = __toESM(require_src(), 1);
2775
+ import { ReadStream } from "node:tty";
2776
+ function findCursor(s, o, l) {
2777
+ if (!l.some((r) => !r.disabled))
2778
+ return s;
2779
+ const t = s + o, n = Math.max(l.length - 1, 0), e = t < 0 ? n : t > n ? 0 : t;
2780
+ return l[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l) : e;
2781
+ }
2782
+ var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
2783
+ var t = [
2784
+ "January",
2785
+ "February",
2786
+ "March",
2787
+ "April",
2788
+ "May",
2789
+ "June",
2790
+ "July",
2791
+ "August",
2792
+ "September",
2793
+ "October",
2794
+ "November",
2795
+ "December"
2796
+ ];
2797
+ var settings = {
2798
+ actions: new Set(a$1),
2799
+ aliases: /* @__PURE__ */ new Map([
2800
+ ["k", "up"],
2801
+ ["j", "down"],
2802
+ ["h", "left"],
2803
+ ["l", "right"],
2804
+ ["\x03", "cancel"],
2805
+ ["escape", "cancel"]
2806
+ ]),
2807
+ messages: {
2808
+ cancel: "Canceled",
2809
+ error: "Something went wrong"
2810
+ },
2811
+ withGuide: true,
2812
+ accessible: undefined,
2813
+ date: {
2814
+ monthNames: [...t],
2815
+ messages: {
2816
+ required: "Please enter a valid date",
2817
+ invalidMonth: "There are only 12 months in a year",
2818
+ invalidDay: (n, e) => `There are only ${n} days in ${e}`,
2819
+ afterMin: (n) => `Date must be on or after ${n.toISOString().slice(0, 10)}`,
2820
+ beforeMax: (n) => `Date must be on or before ${n.toISOString().slice(0, 10)}`
2821
+ }
2822
+ }
2823
+ };
2824
+ function isAccessible(n) {
2825
+ if (n !== undefined)
2826
+ return n;
2827
+ if (settings.accessible !== undefined)
2828
+ return settings.accessible;
2829
+ const e = process.env.ACCESSIBLE;
2830
+ return e !== undefined && e !== "" && e !== "0" && e !== "false";
2831
+ }
2832
+ function isActionKey(n, e) {
2833
+ if (typeof n == "string")
2834
+ return settings.aliases.get(n) === e;
2835
+ for (const s of n)
2836
+ if (s !== undefined && isActionKey(s, e))
2837
+ return true;
2838
+ return false;
2839
+ }
2840
+ function diffLines(i, s) {
2841
+ if (i === s)
2842
+ return;
2843
+ const e = i.split(`
2844
+ `), t = s.split(`
2845
+ `), r = Math.max(e.length, t.length), f = [];
2846
+ for (let n = 0;n < r; n++)
2847
+ e[n] !== t[n] && f.push(n);
2848
+ return {
2849
+ lines: f,
2850
+ numLinesBefore: e.length,
2851
+ numLinesAfter: t.length,
2852
+ numLines: r
2853
+ };
2854
+ }
2855
+ var R = globalThis.process.platform.startsWith("win");
2856
+ var CANCEL_SYMBOL = Symbol("clack:cancel");
2857
+ function isCancel(e) {
2858
+ return e === CANCEL_SYMBOL;
2859
+ }
2860
+ function setRawMode(e, r) {
2861
+ const o = e;
2862
+ o.isTTY && o.setRawMode(r);
2863
+ }
2864
+ function block({
2865
+ input: e = stdin,
2866
+ output: r = stdout,
2867
+ overwrite: o = true,
2868
+ hideCursor: n = true
2869
+ } = {}) {
2870
+ const s = l.createInterface({
2871
+ input: e,
2872
+ output: r,
2873
+ prompt: "",
2874
+ tabSize: 1
2875
+ });
2876
+ l.emitKeypressEvents(e, s), e instanceof ReadStream && e.isTTY && e.setRawMode(true);
2877
+ const t = (f, { name: a, sequence: w }) => {
2878
+ const c = String(f);
2879
+ if (isActionKey([c, a, w], "cancel")) {
2880
+ n && r.write(import_sisteransi.cursor.show), process.exit(0);
2881
+ return;
2882
+ }
2883
+ if (!o)
2884
+ return;
2885
+ const i = a === "return" ? 0 : -1, m = a === "return" ? -1 : 0;
2886
+ l.moveCursor(r, i, m, () => {
2887
+ l.clearLine(r, 1, () => {
2888
+ e.once("keypress", t);
2889
+ });
2890
+ });
2891
+ };
2892
+ return n && r.write(import_sisteransi.cursor.hide), e.once("keypress", t), () => {
2893
+ e.off("keypress", t), n && r.write(import_sisteransi.cursor.show), e instanceof ReadStream && e.isTTY && !R && e.setRawMode(false), s.terminal = false, s.close();
2894
+ };
2895
+ }
2896
+ var getColumns = (e) => ("columns" in e) && typeof e.columns == "number" ? e.columns : 80;
2897
+ var getRows = (e) => ("rows" in e) && typeof e.rows == "number" ? e.rows : 20;
2898
+ function wrapTextWithPrefix(e, r, o, n = o, s = o, t) {
2899
+ const f = getColumns(e ?? stdout);
2900
+ return wrapAnsi(r, f - o.length, {
2901
+ hard: true,
2902
+ trim: false
2903
+ }).split(`
2904
+ `).map((c, i, m) => {
2905
+ const d = t ? t(c, i) : c;
2906
+ return i === 0 ? `${n}${d}` : i === m.length - 1 ? `${s}${d}` : `${o}${d}`;
2907
+ }).join(`
2908
+ `);
2909
+ }
2910
+ function runValidation(e, a) {
2911
+ if ("~standard" in e) {
2912
+ const n = e["~standard"].validate(a);
2913
+ return n instanceof Promise ? n.then((r) => r.issues?.at(0)?.message) : n.issues?.at(0)?.message;
2914
+ }
2915
+ return e(a);
2916
+ }
2917
+
2918
+ class y {
2919
+ input;
2920
+ output;
2921
+ _abortSignal;
2922
+ rl;
2923
+ opts;
2924
+ _render;
2925
+ _track = false;
2926
+ _prevFrame = "";
2927
+ _subscribers = /* @__PURE__ */ new Map;
2928
+ _cursor = 0;
2929
+ state = "initial";
2930
+ error = "";
2931
+ value;
2932
+ userInput = "";
2933
+ get accessible() {
2934
+ return isAccessible(this.opts.accessible);
2935
+ }
2936
+ constructor(t, e = true) {
2937
+ const { input: i = stdin, output: s = stdout, render: r, signal: n, ...o } = t;
2938
+ this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = r.bind(this), this._track = e, this._abortSignal = n, this.input = i, this.output = s;
2939
+ }
2940
+ unsubscribe() {
2941
+ this._subscribers.clear();
2942
+ }
2943
+ setSubscriber(t, e) {
2944
+ const i = this._subscribers.get(t) ?? [];
2945
+ i.push(e), this._subscribers.set(t, i);
2946
+ }
2947
+ on(t, e) {
2948
+ this.setSubscriber(t, { cb: e });
2949
+ }
2950
+ once(t, e) {
2951
+ this.setSubscriber(t, { cb: e, once: true });
2952
+ }
2953
+ emit(t, ...e) {
2954
+ const i = this._subscribers.get(t) ?? [], s = [];
2955
+ for (const r of i)
2956
+ r.cb(...e), r.once && s.push(() => i.splice(i.indexOf(r), 1));
2957
+ for (const r of s)
2958
+ r();
2959
+ }
2960
+ prompt() {
2961
+ return new Promise((t) => {
2962
+ if (this._abortSignal) {
2963
+ if (this._abortSignal.aborted)
2964
+ return this.state = "cancel", this.close(), t(CANCEL_SYMBOL);
2965
+ this._abortSignal.addEventListener("abort", () => {
2966
+ this.state = "cancel", this.close();
2967
+ }, { once: true });
2968
+ }
2969
+ this.rl = l__default.createInterface({
2970
+ input: this.input,
2971
+ tabSize: 2,
2972
+ prompt: "",
2973
+ escapeCodeTimeout: 50,
2974
+ terminal: true
2975
+ }), this.rl.prompt(), this.opts.initialUserInput !== undefined && this._setUserInput(this.opts.initialUserInput, true), this.input.on("keypress", this.onKeypress), setRawMode(this.input, true), this.output.on("resize", this.render), this.render(), this.once("submit", () => {
2976
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(this.value);
2977
+ }), this.once("cancel", () => {
2978
+ this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t(CANCEL_SYMBOL);
2979
+ });
2980
+ });
2981
+ }
2982
+ _isActionKey(t, e) {
2983
+ return t === "\t";
2984
+ }
2985
+ _shouldSubmit(t, e) {
2986
+ return true;
2987
+ }
2988
+ _setValue(t) {
2989
+ this.value = t, this.emit("value", this.value);
2990
+ }
2991
+ _setUserInput(t, e) {
2992
+ this.userInput = t ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
2993
+ }
2994
+ _clearUserInput() {
2995
+ this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
2996
+ }
2997
+ async onKeypress(t, e) {
2998
+ if (this.state !== "validating") {
2999
+ if (this._track && e.name !== "return" && (e.name && this._isActionKey(t, e) && this.rl?.write(null, { ctrl: true, name: "h" }), this._cursor = this.rl?.cursor ?? 0, this._setUserInput(this.rl?.line)), this.state === "error" && (this.state = "active"), e?.name && (!this._track && settings.aliases.has(e.name) && this.emit("cursor", settings.aliases.get(e.name)), settings.actions.has(e.name) && this.emit("cursor", e.name)), t && (t.toLowerCase() === "y" || t.toLowerCase() === "n") && this.emit("confirm", t.toLowerCase() === "y"), this.emit("key", t, e), e?.name === "return" && this._shouldSubmit(t, e)) {
3000
+ if (this.opts.validate) {
3001
+ const i = runValidation(this.opts.validate, this.value);
3002
+ let s;
3003
+ i instanceof Promise ? (this.state = "validating", this.render(), s = await i) : s = i, s && (this.error = s instanceof Error ? s.message : s, this.state = "error", this.rl?.write(this.userInput));
3004
+ }
3005
+ this.state !== "error" && (this.state = "submit");
3006
+ }
3007
+ isActionKey([t, e?.name, e?.sequence], "cancel") && (this.state = "cancel"), (this.state === "submit" || this.state === "cancel") && this.emit("finalize"), this.render(), (this.state === "submit" || this.state === "cancel") && this.close();
3008
+ }
3009
+ }
3010
+ close() {
3011
+ this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
3012
+ `), setRawMode(this.input, false), this.rl?.close(), this.rl = undefined, this.emit(`${this.state}`, this.value), this.unsubscribe();
3013
+ }
3014
+ restoreCursor() {
3015
+ const t = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
3016
+ `).length - 1;
3017
+ this.output.write(import_sisteransi.cursor.move(-999, t * -1));
3018
+ }
3019
+ render() {
3020
+ const t = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
3021
+ hard: true,
3022
+ trim: false
3023
+ });
3024
+ if (t !== this._prevFrame) {
3025
+ if (this.state === "initial")
3026
+ this.output.write(import_sisteransi.cursor.hide);
3027
+ else {
3028
+ const e = diffLines(this._prevFrame, t), i = getRows(this.output);
3029
+ if (this.restoreCursor(), e) {
3030
+ const s = Math.max(0, e.numLinesAfter - i), r = Math.max(0, e.numLinesBefore - i);
3031
+ let n = e.lines.find((o) => o >= s);
3032
+ if (n === undefined) {
3033
+ this._prevFrame = t;
3034
+ return;
3035
+ }
3036
+ if (e.lines.length === 1) {
3037
+ this.output.write(import_sisteransi.cursor.move(0, n - r)), this.output.write(import_sisteransi.erase.lines(1));
3038
+ const o = t.split(`
3039
+ `);
3040
+ this.output.write(o[n]), this._prevFrame = t, this.output.write(import_sisteransi.cursor.move(0, o.length - n - 1));
3041
+ return;
3042
+ } else if (e.lines.length > 1) {
3043
+ if (s < r)
3044
+ n = s;
3045
+ else {
3046
+ const h = n - r;
3047
+ h > 0 && this.output.write(import_sisteransi.cursor.move(0, h));
3048
+ }
3049
+ this.output.write(import_sisteransi.erase.down());
3050
+ const f = t.split(`
3051
+ `).slice(n);
3052
+ this.output.write(f.join(`
3053
+ `)), this._prevFrame = t;
3054
+ return;
3055
+ }
3056
+ }
3057
+ this.output.write(import_sisteransi.erase.down());
3058
+ }
3059
+ this.output.write(t), this.state === "initial" && (this.state = "active"), this._prevFrame = t;
3060
+ }
3061
+ }
3062
+ }
3063
+ class r extends y {
3064
+ get cursor() {
3065
+ return this.value ? 0 : 1;
3066
+ }
3067
+ get _value() {
3068
+ return this.cursor === 0;
3069
+ }
3070
+ constructor(t) {
3071
+ super(t, false), this.value = !!t.initialValue, this.on("userInput", () => {
3072
+ this.value = this._value;
3073
+ }), this.on("confirm", (i) => {
3074
+ this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i, this.state = "submit", this.close();
3075
+ }), this.on("cursor", () => {
3076
+ this.value = !this.value;
3077
+ });
3078
+ }
3079
+ }
3080
+ var n$1 = class n extends y {
3081
+ options;
3082
+ cursor = 0;
3083
+ get _selectedValue() {
3084
+ return this.options[this.cursor];
3085
+ }
3086
+ changeValue() {
3087
+ const e = this._selectedValue;
3088
+ this.value = e === undefined ? undefined : e.value;
3089
+ }
3090
+ constructor(e) {
3091
+ super(e, false), this.options = e.options;
3092
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t = o === -1 ? 0 : o;
3093
+ this.cursor = this.options[t]?.disabled ? findCursor(t, 1, this.options) : t, this.changeValue(), this.on("cursor", (s) => {
3094
+ switch (s) {
3095
+ case "left":
3096
+ case "up":
3097
+ this.cursor = findCursor(this.cursor, -1, this.options);
3098
+ break;
3099
+ case "down":
3100
+ case "right":
3101
+ this.cursor = findCursor(this.cursor, 1, this.options);
3102
+ break;
3103
+ }
3104
+ this.changeValue();
3105
+ });
3106
+ }
3107
+ };
3108
+
3109
+ // ../node_modules/.bun/@clack+prompts@1.8.1/node_modules/@clack/prompts/dist/index.mjs
3110
+ import { styleText, stripVTControlCharacters } from "node:util";
3111
+ import process$1 from "node:process";
3112
+ var import_sisteransi2 = __toESM(require_src(), 1);
3113
+ function isUnicodeSupported() {
3114
+ if (process$1.platform !== "win32") {
3115
+ return process$1.env.TERM !== "linux";
3116
+ }
3117
+ return Boolean(process$1.env.CI) || Boolean(process$1.env.WT_SESSION) || Boolean(process$1.env.TERMINUS_SUBLIME) || process$1.env.ConEmuTask === "{cmd::Cmder}" || process$1.env.TERM_PROGRAM === "Terminus-Sublime" || process$1.env.TERM_PROGRAM === "vscode" || process$1.env.TERM === "xterm-256color" || process$1.env.TERM === "alacritty" || process$1.env.TERMINAL_EMULATOR === "JetBrains-JediTerm";
3118
+ }
3119
+ var unicode = isUnicodeSupported();
3120
+ var isCI = () => process.env.CI === "true";
3121
+ var unicodeOr = (o, e) => unicode ? o : e;
3122
+ var S_STEP_ACTIVE = unicodeOr("◆", "*");
3123
+ var S_STEP_CANCEL = unicodeOr("■", "x");
3124
+ var S_STEP_ERROR = unicodeOr("▲", "x");
3125
+ var S_STEP_SUBMIT = unicodeOr("◇", "o");
3126
+ var S_BAR_START = unicodeOr("┌", "T");
3127
+ var S_BAR = unicodeOr("│", "|");
3128
+ var S_BAR_END = unicodeOr("└", "—");
3129
+ var S_BAR_START_RIGHT = unicodeOr("┐", "T");
3130
+ var S_BAR_END_RIGHT = unicodeOr("┘", "—");
3131
+ var S_RADIO_ACTIVE = unicodeOr("●", ">");
3132
+ var S_RADIO_INACTIVE = unicodeOr("○", " ");
3133
+ var S_CHECKBOX_ACTIVE = unicodeOr("◻", "[•]");
3134
+ var S_CHECKBOX_SELECTED = unicodeOr("◼", "[+]");
3135
+ var S_CHECKBOX_INACTIVE = unicodeOr("◻", "[ ]");
3136
+ var S_PASSWORD_MASK = unicodeOr("▪", "•");
3137
+ var S_BAR_H = unicodeOr("─", "-");
3138
+ var S_CORNER_TOP_RIGHT = unicodeOr("╮", "+");
3139
+ var S_CONNECT_LEFT = unicodeOr("├", "+");
3140
+ var S_CORNER_BOTTOM_RIGHT = unicodeOr("╯", "+");
3141
+ var S_CORNER_BOTTOM_LEFT = unicodeOr("╰", "+");
3142
+ var S_CORNER_TOP_LEFT = unicodeOr("╭", "+");
3143
+ var S_INFO = unicodeOr("●", "•");
3144
+ var S_SUCCESS = unicodeOr("◆", "*");
3145
+ var S_WARN = unicodeOr("▲", "!");
3146
+ var S_ERROR = unicodeOr("■", "x");
3147
+ var symbol = (o) => {
3148
+ switch (o) {
3149
+ case "initial":
3150
+ case "active":
3151
+ return styleText("cyan", S_STEP_ACTIVE);
3152
+ case "cancel":
3153
+ return styleText("red", S_STEP_CANCEL);
3154
+ case "error":
3155
+ return styleText("yellow", S_STEP_ERROR);
3156
+ case "submit":
3157
+ return styleText("green", S_STEP_SUBMIT);
3158
+ case "validating":
3159
+ return styleText("dim", S_STEP_ACTIVE);
3160
+ }
3161
+ };
3162
+ var symbolBar = (o) => {
3163
+ switch (o) {
3164
+ case "initial":
3165
+ case "active":
3166
+ return styleText("cyan", S_BAR);
3167
+ case "cancel":
3168
+ return styleText("red", S_BAR);
3169
+ case "error":
3170
+ return styleText("yellow", S_BAR);
3171
+ case "submit":
3172
+ return styleText("green", S_BAR);
3173
+ }
3174
+ };
3175
+ function formatInstructionFooter(o, e) {
3176
+ const r = [`${e ? `${styleText("cyan", S_BAR)} ` : ""}${o.join(" • ")}`];
3177
+ return e && r.push(styleText("cyan", S_BAR_END)), r;
3178
+ }
3179
+ var I = (l, e, w, p, b, C = false) => {
3180
+ let r = e, O = 0;
3181
+ if (C)
3182
+ for (let i = p - 1;i >= w; i--) {
3183
+ const m = l[i];
3184
+ if (m && (r -= m.length), O++, r <= b)
3185
+ break;
3186
+ }
3187
+ else
3188
+ for (let i = w;i < p; i++) {
3189
+ const m = l[i];
3190
+ if (m && (r -= m.length), O++, r <= b)
3191
+ break;
3192
+ }
3193
+ return { lineCount: r, removals: O };
3194
+ };
3195
+ var limitOptions = ({
3196
+ cursor: l,
3197
+ options: e,
3198
+ style: w,
3199
+ output: p = process.stdout,
3200
+ maxItems: b = Number.POSITIVE_INFINITY,
3201
+ columnPadding: C = 0,
3202
+ rowPadding: r = 4
3203
+ }) => {
3204
+ const i = getColumns(p) - C, m = getRows(p), M = styleText("dim", "..."), v = Math.max(m - r, 0), a = Math.max(Math.min(b, v), 5);
3205
+ let f = 0;
3206
+ l >= a - 3 && (f = Math.max(Math.min(l - a + 3, e.length - a), 0));
3207
+ let d = a < e.length && f > 0, c = a < e.length && f + a < e.length;
3208
+ const W = Math.min(f + a, e.length), s = [];
3209
+ let g = 0;
3210
+ d && g++, c && g++;
3211
+ const T = f + (d ? 1 : 0), y = W - (c ? 1 : 0);
3212
+ for (let t = T;t < y; t++) {
3213
+ const n = e[t], o = n ? w(n, t === l) : "", h = wrapAnsi(o, i, {
3214
+ hard: true,
3215
+ trim: false
3216
+ }).split(`
3217
+ `);
3218
+ s.push(h), g += h.length;
3219
+ }
3220
+ if (g > v) {
3221
+ let t = 0, n = 0, o = g;
3222
+ const h = l - T;
3223
+ let u = v;
3224
+ const L = () => I(s, o, 0, h, u), E = () => I(s, o, h + 1, s.length, u, true);
3225
+ d ? ({ lineCount: o, removals: t } = L(), o > u && (c || (u -= 1), { lineCount: o, removals: n } = E())) : (c || (u -= 1), { lineCount: o, removals: n } = E(), o > u && (u -= 1, { lineCount: o, removals: t } = L())), t > 0 && (d = true, s.splice(0, t)), n > 0 && (c = true, s.splice(s.length - n, n));
3226
+ }
3227
+ const x = [];
3228
+ d && x.push(M);
3229
+ for (const t of s)
3230
+ for (const n of t)
3231
+ x.push(n);
3232
+ return c && x.push(M), x;
3233
+ };
3234
+ var confirm = (e) => {
3235
+ const a = e.active ?? "Yes", o = e.inactive ?? "No";
3236
+ return new r({
3237
+ active: a,
3238
+ inactive: o,
3239
+ signal: e.signal,
3240
+ input: e.input,
3241
+ output: e.output,
3242
+ initialValue: e.initialValue ?? true,
3243
+ render() {
3244
+ const i = e.withGuide ?? settings.withGuide, u = `${symbol(this.state)} `, l = i ? `${styleText("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(e.output, e.message, l, u), s = `${i ? `${styleText("gray", S_BAR)}
3245
+ ` : ""}${f}
3246
+ `, c = this.value ? a : o;
3247
+ switch (this.state) {
3248
+ case "submit": {
3249
+ const r = i ? `${styleText("gray", S_BAR)} ` : "";
3250
+ return `${s}${r}${styleText("dim", c)}`;
3251
+ }
3252
+ case "cancel": {
3253
+ const r = i ? `${styleText("gray", S_BAR)} ` : "";
3254
+ return `${s}${r}${styleText(["strikethrough", "dim"], c)}${i ? `
3255
+ ${styleText("gray", S_BAR)}` : ""}`;
3256
+ }
3257
+ default: {
3258
+ const r = i ? `${styleText("cyan", S_BAR)} ` : "", g = i ? styleText("cyan", S_BAR_END) : "";
3259
+ return `${s}${r}${this.value ? `${styleText("green", S_RADIO_ACTIVE)} ${a}` : `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", a)}`}${e.vertical ? i ? `
3260
+ ${styleText("cyan", S_BAR)} ` : `
3261
+ ` : ` ${styleText("dim", "/")} `}${this.value ? `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", o)}` : `${styleText("green", S_RADIO_ACTIVE)} ${o}`}
3262
+ ${g}
3263
+ `;
3264
+ }
3265
+ }
3266
+ }
3267
+ }).prompt();
3268
+ };
3269
+ var MULTISELECT_INSTRUCTIONS = [
3270
+ `${styleText("dim", "↑/↓")} to navigate`,
3271
+ `${styleText("dim", "Space:")} select`,
3272
+ `${styleText("dim", "Enter:")} confirm`
3273
+ ];
3274
+ var intro = (o = "", t) => {
3275
+ const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_START)} ` : "";
3276
+ i.write(`${e}${o}
3277
+ `);
3278
+ };
3279
+ var outro = (o = "", t) => {
3280
+ const i = t?.output ?? process.stdout, e = t?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR)}
3281
+ ${styleText("gray", S_BAR_END)} ` : "";
3282
+ i.write(`${e}${o}
3283
+
3284
+ `);
3285
+ };
3286
+ var W = (l) => styleText("magenta", l);
3287
+ var spinner = ({
3288
+ indicator: l = "dots",
3289
+ onCancel: h,
3290
+ output: n = process.stdout,
3291
+ cancelMessage: G,
3292
+ errorMessage: O,
3293
+ frames: E = unicode ? ["◒", "◐", "◓", "◑"] : ["•", "o", "O", "0"],
3294
+ delay: F = unicode ? 80 : 120,
3295
+ signal: m,
3296
+ ...I
3297
+ } = {}) => {
3298
+ const u = isCI();
3299
+ let M, T, d = false, S = false, s = "", p, w = performance.now();
3300
+ const x = getColumns(n), k = I?.styleFrame ?? W, g = (e) => {
3301
+ const r = e > 1 ? O ?? settings.messages.error : G ?? settings.messages.cancel;
3302
+ S = e === 1, d && (a(r, e), S && typeof h == "function" && h());
3303
+ }, f = () => g(2), i = () => g(1), A = () => {
3304
+ process.on("uncaughtExceptionMonitor", f), process.on("unhandledRejection", f), process.on("SIGINT", i), process.on("SIGTERM", i), process.on("exit", g), m && m.addEventListener("abort", i);
3305
+ }, H = () => {
3306
+ process.removeListener("uncaughtExceptionMonitor", f), process.removeListener("unhandledRejection", f), process.removeListener("SIGINT", i), process.removeListener("SIGTERM", i), process.removeListener("exit", g), m && m.removeEventListener("abort", i);
3307
+ }, y = () => {
3308
+ if (p === undefined)
3309
+ return;
3310
+ u && n.write(`
3311
+ `);
3312
+ const r = wrapAnsi(p, x, {
3313
+ hard: true,
3314
+ trim: false
3315
+ }).split(`
3316
+ `);
3317
+ r.length > 1 && n.write(import_sisteransi2.cursor.up(r.length - 1)), n.write(import_sisteransi2.cursor.to(0)), n.write(import_sisteransi2.erase.down());
3318
+ }, C = (e) => e.replace(/\.+$/, ""), _ = (e) => {
3319
+ const r = (performance.now() - e) / 1000, t = Math.floor(r / 60), o = Math.floor(r % 60);
3320
+ return t > 0 ? `[${t}m ${o}s]` : `[${o}s]`;
3321
+ }, N = I.withGuide ?? settings.withGuide, P = (e = "") => {
3322
+ d = true, M = block({ output: n }), s = C(e), w = performance.now(), N && n.write(`${styleText("gray", S_BAR)}
3323
+ `);
3324
+ let r = 0, t = 0;
3325
+ A(), T = setInterval(() => {
3326
+ if (u && s === p)
3327
+ return;
3328
+ y(), p = s;
3329
+ const o = k(E[r]);
3330
+ let v;
3331
+ if (u)
3332
+ v = `${o} ${s}...`;
3333
+ else if (l === "timer")
3334
+ v = `${o} ${s} ${_(w)}`;
3335
+ else {
3336
+ const B = ".".repeat(Math.floor(t)).slice(0, 3);
3337
+ v = `${o} ${s}${B}`;
3338
+ }
3339
+ const j = wrapAnsi(v, x, {
3340
+ hard: true,
3341
+ trim: false
3342
+ });
3343
+ n.write(j), r = r + 1 < E.length ? r + 1 : 0, t = t < 4 ? t + 0.125 : 0;
3344
+ }, F);
3345
+ }, a = (e = "", r = 0, t = false) => {
3346
+ if (!d)
3347
+ return;
3348
+ d = false, clearInterval(T), y();
3349
+ const o = r === 0 ? styleText("green", S_STEP_SUBMIT) : r === 1 ? styleText("red", S_STEP_CANCEL) : styleText("red", S_STEP_ERROR);
3350
+ s = e ?? s, t || (l === "timer" ? n.write(`${o} ${s} ${_(w)}
3351
+ `) : n.write(`${o} ${s}
3352
+ `)), H(), M();
3353
+ };
3354
+ return {
3355
+ start: P,
3356
+ stop: (e = "") => a(e, 0),
3357
+ message: (e = "") => {
3358
+ s = C(e ?? s);
3359
+ },
3360
+ cancel: (e = "") => a(e, 1),
3361
+ error: (e = "") => a(e, 2),
3362
+ clear: () => a("", 0, true),
3363
+ get isCancelled() {
3364
+ return S;
3365
+ }
3366
+ };
3367
+ };
3368
+ var u2 = {
3369
+ light: unicodeOr("─", "-"),
3370
+ heavy: unicodeOr("━", "="),
3371
+ block: unicodeOr("█", "#")
3372
+ };
3373
+ var SELECT_INSTRUCTIONS = [
3374
+ `${styleText("dim", "↑/↓")} to navigate`,
3375
+ `${styleText("dim", "Enter:")} confirm`
3376
+ ];
3377
+ var c = (t, o) => t.includes(`
3378
+ `) ? t.split(`
3379
+ `).map((d) => o(d)).join(`
3380
+ `) : o(t);
3381
+ var select = (t) => {
3382
+ const o = (n, m) => {
3383
+ if (n === undefined)
3384
+ return "";
3385
+ const s = n.label ?? String(n.value);
3386
+ switch (m) {
3387
+ case "disabled":
3388
+ return `${styleText("gray", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("gray", i))}${n.hint ? ` ${styleText("dim", `(${n.hint ?? "disabled"})`)}` : ""}`;
3389
+ case "selected":
3390
+ return `${c(s, (i) => styleText("dim", i))}`;
3391
+ case "active":
3392
+ return `${styleText("green", S_RADIO_ACTIVE)} ${s}${n.hint ? ` ${styleText("dim", `(${n.hint})`)}` : ""}`;
3393
+ case "cancelled":
3394
+ return `${c(s, (i) => styleText(["strikethrough", "dim"], i))}`;
3395
+ default:
3396
+ return `${styleText("dim", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("dim", i))}`;
3397
+ }
3398
+ }, d = t.showInstructions ?? true;
3399
+ return new n$1({
3400
+ options: t.options,
3401
+ signal: t.signal,
3402
+ input: t.input,
3403
+ output: t.output,
3404
+ initialValue: t.initialValue,
3405
+ render() {
3406
+ const n = t.withGuide ?? settings.withGuide, m = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i = wrapTextWithPrefix(t.output, t.message, s, m), u = `${n ? `${styleText("gray", S_BAR)}
3407
+ ` : ""}${i}
3408
+ `;
3409
+ switch (this.state) {
3410
+ case "submit": {
3411
+ const r = n ? `${styleText("gray", S_BAR)} ` : "", a = wrapTextWithPrefix(t.output, o(this.options[this.cursor], "selected"), r);
3412
+ return `${u}${a}`;
3413
+ }
3414
+ case "cancel": {
3415
+ const r = n ? `${styleText("gray", S_BAR)} ` : "", a = wrapTextWithPrefix(t.output, o(this.options[this.cursor], "cancelled"), r);
3416
+ return `${u}${a}${n ? `
3417
+ ${styleText("gray", S_BAR)}` : ""}`;
3418
+ }
3419
+ default: {
3420
+ const r = n ? `${styleText("cyan", S_BAR)} ` : "", a = u.split(`
3421
+ `).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n) : n ? [styleText("cyan", S_BAR_END)] : [], f = p.join(`
3422
+ `), b = p.length + 1;
3423
+ return `${u}${r}${limitOptions({
3424
+ output: t.output,
3425
+ cursor: this.cursor,
3426
+ options: this.options,
3427
+ maxItems: t.maxItems,
3428
+ columnPadding: r.length,
3429
+ rowPadding: a + b,
3430
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
3431
+ }).join(`
3432
+ ${r}`)}
3433
+ ${f}
3434
+ `;
3435
+ }
3436
+ }
3437
+ }
3438
+ }).prompt();
3439
+ };
3440
+ var i = `${styleText("gray", S_BAR)} `;
3441
+
3442
+ // src/push.ts
2286
3443
  var CONFIRM_FLAGS = new Set(["--yes", "-y"]);
2287
3444
  var FORWARDED_GIT_FLAGS = new Set(["--force"]);
2288
3445
  function parsePushArgs(args) {
@@ -2352,26 +3509,46 @@ function planPush({
2352
3509
  reason: names.length === 0 ? "No session in this repo has a branch ready to push." : "Several session branches are ready; pick one."
2353
3510
  };
2354
3511
  }
2355
- async function choose(candidates) {
2356
- if (!process.stdin.isTTY)
2357
- return;
2358
- console.log(candidates.map((name, index) => ` ${index + 1}) ${name}`).join(`
2359
- `));
2360
- const answer = await ask("Branch to push: ");
2361
- return candidates[Number(answer) - 1];
3512
+ function branchHint(run, candidate) {
3513
+ const count = git(run, candidate.dir, [
3514
+ "rev-list",
3515
+ "--count",
3516
+ `${candidate.baseSha}..${candidate.branch}`
3517
+ ]).out;
3518
+ const stat = cleanOutput(git(run, candidate.dir, [
3519
+ "diff",
3520
+ "--no-color",
3521
+ "--stat",
3522
+ `${candidate.baseSha}...${candidate.branch}`
3523
+ ]).out);
3524
+ const files = stat.split(`
3525
+ `).pop() ?? "";
3526
+ return [
3527
+ `${count || "0"} commit${count === "1" ? "" : "s"}`,
3528
+ files || "no file changes"
3529
+ ].join(" | ");
3530
+ }
3531
+ async function chooseInteractive(run, names, candidates) {
3532
+ return select({
3533
+ message: "Branch to push",
3534
+ options: names.map((name) => ({
3535
+ value: name,
3536
+ label: name,
3537
+ hint: branchHint(run, candidates.get(name))
3538
+ }))
3539
+ });
2362
3540
  }
2363
3541
  function describe(run, root, branch, base, tip, gitFlags) {
2364
- const commits = git(run, root, [
2365
- "log",
2366
- "--format= %h %s (%an / %cn)",
2367
- `${base}..${tip}`
2368
- ]).out;
2369
- const stat = git(run, root, ["diff", "--stat", `${base}...${tip}`]).out;
3542
+ const commits = cleanOutput(git(run, root, ["log", "--format= %h %s (%an / %cn)", `${base}..${tip}`]).out);
3543
+ const stat = cleanOutput(git(run, root, ["diff", "--no-color", "--stat", `${base}...${tip}`]).out);
2370
3544
  return [
2371
3545
  `Pushing ${branch} to origin${gitFlags.length ? ` with ${gitFlags.join(" ")}` : ""} (compared with ${base}):`,
2372
- stripControl(commits) || " (no new commits)",
3546
+ `
3547
+ Commits:`,
3548
+ commits || " (no new commits)",
2373
3549
  stat ? `
2374
- ${stripControl(stat)}` : ""
3550
+ Changed files:
3551
+ ${stat}` : ""
2375
3552
  ].join(`
2376
3553
  `);
2377
3554
  }
@@ -2390,10 +3567,20 @@ async function push({ args }) {
2390
3567
  } catch (error) {
2391
3568
  throw error instanceof LaunchError ? error : new LaunchError(String(error));
2392
3569
  }
3570
+ const tty = process.stdin.isTTY === true;
2393
3571
  const candidates = pushCandidates(sessionsForRepo(root));
2394
3572
  let plan = planPush({ requested, candidates });
2395
3573
  if (!plan.ok && !requested && plan.candidates.length > 1) {
2396
- const picked = await choose(plan.candidates);
3574
+ let picked;
3575
+ if (tty) {
3576
+ intro("maesttro push");
3577
+ const chosen = await chooseInteractive(run, plan.candidates, candidates);
3578
+ if (isCancel(chosen)) {
3579
+ console.log("Not pushed.");
3580
+ return;
3581
+ }
3582
+ picked = chosen;
3583
+ }
2397
3584
  if (picked)
2398
3585
  plan = planPush({ requested: picked, candidates });
2399
3586
  }
@@ -2403,30 +3590,37 @@ async function push({ args }) {
2403
3590
  return;
2404
3591
  }
2405
3592
  const { branch, base, baseSha, dir, sessionId } = plan.candidate;
3593
+ const prepare = tty ? spinner() : undefined;
3594
+ prepare?.start(`Preparing ${branch}...`);
2406
3595
  const tip = branchTip(dir, branch);
2407
3596
  if (!tip || !importObjects(run, root, dir, tip)) {
3597
+ prepare?.stop(`Could not prepare ${branch}.`);
2408
3598
  console.error(`Could not read ${branch} from session ${sessionId}.`);
2409
3599
  process.exitCode = 1;
2410
3600
  return;
2411
3601
  }
2412
3602
  git(run, root, ["update-ref", `refs/maesttro/${sessionId}/${branch}`, tip]);
3603
+ prepare?.stop(`Prepared ${branch}.`);
2413
3604
  console.log(describe(run, root, branch, base, tip, gitFlags));
2414
3605
  if (!yes) {
2415
- if (!process.stdin.isTTY) {
3606
+ if (!tty) {
2416
3607
  console.error("Not a terminal; re-run with --yes to push without confirming.");
2417
3608
  process.exitCode = 1;
2418
3609
  return;
2419
3610
  }
2420
- const answer = await ask(`
2421
- Push? [y/N] `);
2422
- if (!/^y(es)?$/i.test(answer)) {
3611
+ const answer = await confirm({ message: `Push ${branch} to origin?` });
3612
+ if (isCancel(answer) || !answer) {
2423
3613
  console.log("Not pushed.");
2424
3614
  return;
2425
3615
  }
2426
3616
  }
2427
3617
  const pushed = spawnSync3("git", ["-C", root, "push", ...gitFlags, "origin", `${tip}:refs/heads/${branch}`], { stdio: "inherit" });
2428
3618
  if (pushed.status === 0) {
2429
- console.log(`Pushed ${branch}. Base for comparison was ${baseSha.slice(0, 8)}.`);
3619
+ const done = `Pushed ${branch}. Base for comparison was ${baseSha.slice(0, 8)}.`;
3620
+ if (tty && !yes)
3621
+ outro(done);
3622
+ else
3623
+ console.log(done);
2430
3624
  }
2431
3625
  process.exitCode = pushed.status ?? 1;
2432
3626
  }
@@ -2575,6 +3769,78 @@ async function setup({ args }) {
2575
3769
  // src/update.ts
2576
3770
  import { execSync as execSync5 } from "node:child_process";
2577
3771
 
3772
+ // src/runner-images.ts
3773
+ var RUNNER_LABEL = "org.maesttro.runner";
3774
+ var RUNNER_ENTRYPOINT = "/usr/local/bin/maesttro-entrypoint";
3775
+ var INSPECT_FORMAT = "{{.Id}}\t{{json .Config}}\t{{json .RepoTags}}";
3776
+ function parseJson(text, fallback) {
3777
+ try {
3778
+ return JSON.parse(text ?? "") ?? fallback;
3779
+ } catch {
3780
+ return fallback;
3781
+ }
3782
+ }
3783
+ function parseImageRows(stdout) {
3784
+ return stdout.split(`
3785
+ `).filter((line) => line.trim() !== "").map((line) => {
3786
+ const [id = "", config, tags] = line.split("\t");
3787
+ const { Entrypoint, Labels } = parseJson(config, {});
3788
+ return {
3789
+ id,
3790
+ entrypoint: Entrypoint ?? [],
3791
+ labels: Labels ?? {},
3792
+ tags: parseJson(tags, [])
3793
+ };
3794
+ });
3795
+ }
3796
+ function isRunnerImage(row) {
3797
+ return row.labels[RUNNER_LABEL] !== undefined || row.entrypoint.includes(RUNNER_ENTRYPOINT);
3798
+ }
3799
+ function staleRunnerImages({
3800
+ rows,
3801
+ latestId
3802
+ }) {
3803
+ if (!latestId)
3804
+ return [];
3805
+ return rows.filter((row) => row.id !== latestId && isRunnerImage(row));
3806
+ }
3807
+ function currentLatestId(run) {
3808
+ const result = run("docker", [
3809
+ "image",
3810
+ "inspect",
3811
+ "--format",
3812
+ "{{.Id}}",
3813
+ IMAGE
3814
+ ]);
3815
+ return result.status === 0 ? result.stdout.trim() || undefined : undefined;
3816
+ }
3817
+ function removeStaleRunnerImages({
3818
+ run = runCommand,
3819
+ latestId = () => currentLatestId(run)
3820
+ } = {}) {
3821
+ const listed = run("docker", ["image", "ls", "--quiet", "--no-trunc"]);
3822
+ if (listed.status !== 0)
3823
+ return 0;
3824
+ const ids = [
3825
+ ...new Set(listed.stdout.split(`
3826
+ `).map((id) => id.trim()).filter(Boolean))
3827
+ ];
3828
+ if (ids.length === 0)
3829
+ return 0;
3830
+ const inspected = run("docker", [
3831
+ "image",
3832
+ "inspect",
3833
+ "--format",
3834
+ INSPECT_FORMAT,
3835
+ ...ids
3836
+ ]);
3837
+ const stale = staleRunnerImages({
3838
+ rows: parseImageRows(inspected.stdout),
3839
+ latestId: latestId()
3840
+ });
3841
+ return stale.filter((image) => run("docker", ["rmi", ...image.tags, image.id]).status === 0).length;
3842
+ }
3843
+
2578
3844
  // src/version-check.ts
2579
3845
  import { execFile } from "node:child_process";
2580
3846
  import { existsSync as existsSync6, readFileSync as readFileSync8 } from "node:fs";
@@ -2634,6 +3900,10 @@ function update() {
2634
3900
  -> Rebuilding runner image with refreshed client configs...`);
2635
3901
  execSync5(`docker build -t ${IMAGE} "${DOCKERFILE_DIR}"`, { stdio: "inherit" });
2636
3902
  console.log(`
3903
+ -> Removing older runner images...`);
3904
+ const removed = removeStaleRunnerImages();
3905
+ console.log(removed > 0 ? ` Removed ${removed} older runner image${removed === 1 ? "" : "s"}.` : " None to remove.");
3906
+ console.log(`
2637
3907
  Update complete. Bot identity and your project files are untouched —`);
2638
3908
  console.log("only the runner image (client versions + curated configs) was refreshed.");
2639
3909
  }