maesttro 0.4.3 → 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/README.md +3 -0
- package/dist/maesttro.js +1411 -48
- package/docker/Dockerfile +62 -3
- package/docker/entrypoint.sh +3 -0
- package/package.json +5 -2
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
|
() => {
|
|
@@ -1265,8 +1397,14 @@ Usage:
|
|
|
1265
1397
|
Same, in strict mode: no GitHub token reaches the runner, so \`gh\` is off
|
|
1266
1398
|
maesttro resume <id> Continue a kept session in its clone, in the mode it started with
|
|
1267
1399
|
(\`--strict\` or \`--no-strict\` after the id changes it)
|
|
1268
|
-
maesttro sessions List this repo's sessions
|
|
1269
|
-
maesttro
|
|
1400
|
+
maesttro sessions List this repo's sessions
|
|
1401
|
+
maesttro sessions remove <id>
|
|
1402
|
+
Drop one. Preserves its branches; asks before discarding commits that
|
|
1403
|
+
aren't on a branch (--force skips the ask)
|
|
1404
|
+
maesttro sessions remove --all
|
|
1405
|
+
Drop all of this repo's sessions
|
|
1406
|
+
maesttro push [branch] [--force]
|
|
1407
|
+
Push a branch a session created, after showing what goes out
|
|
1270
1408
|
maesttro list Show available clients
|
|
1271
1409
|
maesttro setup One-time: build image, create volume, log in to GitHub
|
|
1272
1410
|
maesttro login Log in to GitHub (device flow) so sessions get repo access
|
|
@@ -1660,6 +1798,14 @@ function stripControl(text) {
|
|
|
1660
1798
|
}
|
|
1661
1799
|
return out;
|
|
1662
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
|
+
}
|
|
1663
1809
|
var VALID_BRANCH = /^[A-Za-z0-9](?:[A-Za-z0-9._/-]*[A-Za-z0-9_-])?$/;
|
|
1664
1810
|
function isSafeBranchName(name) {
|
|
1665
1811
|
if (name.length === 0 || name.length > 255)
|
|
@@ -2277,6 +2423,1049 @@ async function launch({
|
|
|
2277
2423
|
|
|
2278
2424
|
// src/push.ts
|
|
2279
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
|
|
3443
|
+
var CONFIRM_FLAGS = new Set(["--yes", "-y"]);
|
|
3444
|
+
var FORWARDED_GIT_FLAGS = new Set(["--force"]);
|
|
3445
|
+
function parsePushArgs(args) {
|
|
3446
|
+
const positionals = args.filter((arg) => !arg.startsWith("-"));
|
|
3447
|
+
if (positionals.length > 1) {
|
|
3448
|
+
return {
|
|
3449
|
+
ok: false,
|
|
3450
|
+
reason: `Expected at most one branch, got ${positionals.join(", ")}.`
|
|
3451
|
+
};
|
|
3452
|
+
}
|
|
3453
|
+
const flags = args.filter((arg) => arg.startsWith("-"));
|
|
3454
|
+
const unsupported = flags.filter((flag) => !CONFIRM_FLAGS.has(flag) && !FORWARDED_GIT_FLAGS.has(flag));
|
|
3455
|
+
if (unsupported.length > 0) {
|
|
3456
|
+
return {
|
|
3457
|
+
ok: false,
|
|
3458
|
+
reason: `maesttro push doesn't accept ${unsupported.join(", ")}; it takes --yes and --force.`
|
|
3459
|
+
};
|
|
3460
|
+
}
|
|
3461
|
+
const [requested] = positionals;
|
|
3462
|
+
return {
|
|
3463
|
+
ok: true,
|
|
3464
|
+
...requested === undefined ? {} : { requested },
|
|
3465
|
+
yes: flags.some((flag) => CONFIRM_FLAGS.has(flag)),
|
|
3466
|
+
gitFlags: flags.filter((flag) => FORWARDED_GIT_FLAGS.has(flag))
|
|
3467
|
+
};
|
|
3468
|
+
}
|
|
2280
3469
|
function pushCandidates(sessions) {
|
|
2281
3470
|
const candidates = new Map;
|
|
2282
3471
|
for (const session of sessions) {
|
|
@@ -2320,43 +3509,78 @@ function planPush({
|
|
|
2320
3509
|
reason: names.length === 0 ? "No session in this repo has a branch ready to push." : "Several session branches are ready; pick one."
|
|
2321
3510
|
};
|
|
2322
3511
|
}
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
`
|
|
2328
|
-
const answer = await ask("Branch to push: ");
|
|
2329
|
-
return candidates[Number(answer) - 1];
|
|
2330
|
-
}
|
|
2331
|
-
function describe(run, root, branch, base, tip) {
|
|
2332
|
-
const commits = git(run, root, [
|
|
2333
|
-
"log",
|
|
2334
|
-
"--format= %h %s (%an / %cn)",
|
|
2335
|
-
`${base}..${tip}`
|
|
3512
|
+
function branchHint(run, candidate) {
|
|
3513
|
+
const count = git(run, candidate.dir, [
|
|
3514
|
+
"rev-list",
|
|
3515
|
+
"--count",
|
|
3516
|
+
`${candidate.baseSha}..${candidate.branch}`
|
|
2336
3517
|
]).out;
|
|
2337
|
-
const stat = git(run,
|
|
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() ?? "";
|
|
2338
3526
|
return [
|
|
2339
|
-
|
|
2340
|
-
|
|
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
|
+
});
|
|
3540
|
+
}
|
|
3541
|
+
function describe(run, root, branch, base, tip, gitFlags) {
|
|
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);
|
|
3544
|
+
return [
|
|
3545
|
+
`Pushing ${branch} to origin${gitFlags.length ? ` with ${gitFlags.join(" ")}` : ""} (compared with ${base}):`,
|
|
3546
|
+
`
|
|
3547
|
+
Commits:`,
|
|
3548
|
+
commits || " (no new commits)",
|
|
2341
3549
|
stat ? `
|
|
2342
|
-
|
|
3550
|
+
Changed files:
|
|
3551
|
+
${stat}` : ""
|
|
2343
3552
|
].join(`
|
|
2344
3553
|
`);
|
|
2345
3554
|
}
|
|
2346
3555
|
async function push({ args }) {
|
|
2347
3556
|
const run = runCommand;
|
|
2348
|
-
const
|
|
2349
|
-
|
|
3557
|
+
const parsed = parsePushArgs(args);
|
|
3558
|
+
if (!parsed.ok) {
|
|
3559
|
+
console.error(parsed.reason);
|
|
3560
|
+
process.exitCode = 1;
|
|
3561
|
+
return;
|
|
3562
|
+
}
|
|
3563
|
+
const { requested, yes, gitFlags } = parsed;
|
|
2350
3564
|
let root;
|
|
2351
3565
|
try {
|
|
2352
3566
|
root = repoRoot(run, process.cwd());
|
|
2353
3567
|
} catch (error) {
|
|
2354
3568
|
throw error instanceof LaunchError ? error : new LaunchError(String(error));
|
|
2355
3569
|
}
|
|
3570
|
+
const tty = process.stdin.isTTY === true;
|
|
2356
3571
|
const candidates = pushCandidates(sessionsForRepo(root));
|
|
2357
3572
|
let plan = planPush({ requested, candidates });
|
|
2358
3573
|
if (!plan.ok && !requested && plan.candidates.length > 1) {
|
|
2359
|
-
|
|
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
|
+
}
|
|
2360
3584
|
if (picked)
|
|
2361
3585
|
plan = planPush({ requested: picked, candidates });
|
|
2362
3586
|
}
|
|
@@ -2366,62 +3590,125 @@ async function push({ args }) {
|
|
|
2366
3590
|
return;
|
|
2367
3591
|
}
|
|
2368
3592
|
const { branch, base, baseSha, dir, sessionId } = plan.candidate;
|
|
3593
|
+
const prepare = tty ? spinner() : undefined;
|
|
3594
|
+
prepare?.start(`Preparing ${branch}...`);
|
|
2369
3595
|
const tip = branchTip(dir, branch);
|
|
2370
3596
|
if (!tip || !importObjects(run, root, dir, tip)) {
|
|
3597
|
+
prepare?.stop(`Could not prepare ${branch}.`);
|
|
2371
3598
|
console.error(`Could not read ${branch} from session ${sessionId}.`);
|
|
2372
3599
|
process.exitCode = 1;
|
|
2373
3600
|
return;
|
|
2374
3601
|
}
|
|
2375
3602
|
git(run, root, ["update-ref", `refs/maesttro/${sessionId}/${branch}`, tip]);
|
|
2376
|
-
|
|
3603
|
+
prepare?.stop(`Prepared ${branch}.`);
|
|
3604
|
+
console.log(describe(run, root, branch, base, tip, gitFlags));
|
|
2377
3605
|
if (!yes) {
|
|
2378
|
-
if (!
|
|
3606
|
+
if (!tty) {
|
|
2379
3607
|
console.error("Not a terminal; re-run with --yes to push without confirming.");
|
|
2380
3608
|
process.exitCode = 1;
|
|
2381
3609
|
return;
|
|
2382
3610
|
}
|
|
2383
|
-
const answer = await
|
|
2384
|
-
|
|
2385
|
-
if (!/^y(es)?$/i.test(answer)) {
|
|
3611
|
+
const answer = await confirm({ message: `Push ${branch} to origin?` });
|
|
3612
|
+
if (isCancel(answer) || !answer) {
|
|
2386
3613
|
console.log("Not pushed.");
|
|
2387
3614
|
return;
|
|
2388
3615
|
}
|
|
2389
3616
|
}
|
|
2390
|
-
const pushed = spawnSync3("git", ["-C", root, "push", "origin", `${tip}:refs/heads/${branch}`], { stdio: "inherit" });
|
|
3617
|
+
const pushed = spawnSync3("git", ["-C", root, "push", ...gitFlags, "origin", `${tip}:refs/heads/${branch}`], { stdio: "inherit" });
|
|
2391
3618
|
if (pushed.status === 0) {
|
|
2392
|
-
|
|
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);
|
|
2393
3624
|
}
|
|
2394
3625
|
process.exitCode = pushed.status ?? 1;
|
|
2395
3626
|
}
|
|
2396
3627
|
|
|
2397
3628
|
// src/sessions-command.ts
|
|
2398
3629
|
import { existsSync as existsSync5, rmSync as rmSync7 } from "node:fs";
|
|
2399
|
-
function
|
|
3630
|
+
function parseRemoveArgs(args) {
|
|
3631
|
+
let all = false;
|
|
3632
|
+
let force = false;
|
|
3633
|
+
let id;
|
|
3634
|
+
for (const arg of args) {
|
|
3635
|
+
if (arg === "--all")
|
|
3636
|
+
all = true;
|
|
3637
|
+
else if (arg === "--force")
|
|
3638
|
+
force = true;
|
|
3639
|
+
else if (id === undefined)
|
|
3640
|
+
id = arg;
|
|
3641
|
+
}
|
|
3642
|
+
return { all, force, id };
|
|
3643
|
+
}
|
|
3644
|
+
async function removeSession(run, session, force, ask, interactive) {
|
|
3645
|
+
if (existsSync5(session.worktree)) {
|
|
3646
|
+
const preserved = preserveBranches(run, session);
|
|
3647
|
+
const head = cloneHead(session.worktree);
|
|
3648
|
+
const unbranched = preserved.length === 0 && head?.detached !== undefined && head.detached !== session.baseSha;
|
|
3649
|
+
if (unbranched && !force) {
|
|
3650
|
+
let proceed;
|
|
3651
|
+
if (interactive) {
|
|
3652
|
+
const answer = await ask(`Session ${session.id} has commits on a detached HEAD not on any branch. Removing it discards them. Remove anyway? [y/N] `);
|
|
3653
|
+
proceed = /^(y(es)?)?$/i.test(answer);
|
|
3654
|
+
} else {
|
|
3655
|
+
proceed = false;
|
|
3656
|
+
console.error(`Session ${session.id} has commits on a detached HEAD not on any branch. Resume and create a branch, or re-run with --force.`);
|
|
3657
|
+
}
|
|
3658
|
+
if (!proceed) {
|
|
3659
|
+
console.log(`Kept session ${session.id}.`);
|
|
3660
|
+
return "kept";
|
|
3661
|
+
}
|
|
3662
|
+
}
|
|
3663
|
+
rmSync7(session.worktree, { recursive: true, force: true });
|
|
3664
|
+
const kept = preserved.length > 0 ? ` Its branches are kept as refs/maesttro/${session.id}/*.` : "";
|
|
3665
|
+
console.log(`Removed session ${session.id}.${kept}`);
|
|
3666
|
+
} else {
|
|
3667
|
+
console.log(`Removed session ${session.id}.`);
|
|
3668
|
+
}
|
|
3669
|
+
deleteSession(session.id);
|
|
3670
|
+
return "removed";
|
|
3671
|
+
}
|
|
3672
|
+
async function sessionsCommand({
|
|
3673
|
+
args,
|
|
3674
|
+
ask: ask2 = ask,
|
|
3675
|
+
interactive = process.stdin.isTTY === true
|
|
3676
|
+
}) {
|
|
2400
3677
|
const run = runCommand;
|
|
2401
3678
|
const root = repoRoot(run, process.cwd());
|
|
2402
|
-
const [action,
|
|
3679
|
+
const [action, ...rest] = args;
|
|
2403
3680
|
if (action === "remove") {
|
|
2404
|
-
const
|
|
2405
|
-
if (
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
return;
|
|
2409
|
-
}
|
|
2410
|
-
if (existsSync5(session.worktree)) {
|
|
2411
|
-
const preserved = preserveBranches(run, session);
|
|
2412
|
-
const head = cloneHead(session.worktree);
|
|
2413
|
-
if (preserved.length === 0 && head?.detached !== undefined && head.detached !== session.baseSha) {
|
|
2414
|
-
console.error(`${session.id} has commits on a detached HEAD not on any branch; resume and create a branch first.`);
|
|
3681
|
+
const { all, force, id } = parseRemoveArgs(rest);
|
|
3682
|
+
if (all) {
|
|
3683
|
+
if (id !== undefined) {
|
|
3684
|
+
console.error("`maesttro sessions remove` takes either `--all` or a session id, not both.");
|
|
2415
3685
|
process.exitCode = 1;
|
|
2416
3686
|
return;
|
|
2417
3687
|
}
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
3688
|
+
const sessions = sessionsForRepo(root);
|
|
3689
|
+
if (sessions.length === 0) {
|
|
3690
|
+
console.log("No maesttro sessions in this repo.");
|
|
3691
|
+
return;
|
|
3692
|
+
}
|
|
3693
|
+
for (const session of sessions) {
|
|
3694
|
+
await removeSession(run, session, force, ask2, interactive);
|
|
3695
|
+
}
|
|
3696
|
+
return;
|
|
2423
3697
|
}
|
|
2424
|
-
|
|
3698
|
+
if (id === undefined) {
|
|
3699
|
+
console.error("Usage: maesttro sessions remove <id> | maesttro sessions remove --all");
|
|
3700
|
+
process.exitCode = 1;
|
|
3701
|
+
return;
|
|
3702
|
+
}
|
|
3703
|
+
const session = readSession(id);
|
|
3704
|
+
if (!session || session.repoRoot !== root) {
|
|
3705
|
+
console.error(`No session ${id} in this repo.`);
|
|
3706
|
+
process.exitCode = 1;
|
|
3707
|
+
return;
|
|
3708
|
+
}
|
|
3709
|
+
const result = await removeSession(run, session, force, ask2, interactive);
|
|
3710
|
+
if (result === "kept")
|
|
3711
|
+
process.exitCode = 1;
|
|
2425
3712
|
return;
|
|
2426
3713
|
}
|
|
2427
3714
|
const sessions = sessionsForRepo(root);
|
|
@@ -2482,6 +3769,78 @@ async function setup({ args }) {
|
|
|
2482
3769
|
// src/update.ts
|
|
2483
3770
|
import { execSync as execSync5 } from "node:child_process";
|
|
2484
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
|
+
|
|
2485
3844
|
// src/version-check.ts
|
|
2486
3845
|
import { execFile } from "node:child_process";
|
|
2487
3846
|
import { existsSync as existsSync6, readFileSync as readFileSync8 } from "node:fs";
|
|
@@ -2541,6 +3900,10 @@ function update() {
|
|
|
2541
3900
|
-> Rebuilding runner image with refreshed client configs...`);
|
|
2542
3901
|
execSync5(`docker build -t ${IMAGE} "${DOCKERFILE_DIR}"`, { stdio: "inherit" });
|
|
2543
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(`
|
|
2544
3907
|
Update complete. Bot identity and your project files are untouched —`);
|
|
2545
3908
|
console.log("only the runner image (client versions + curated configs) was refreshed.");
|
|
2546
3909
|
}
|