memroot 0.1.0-alpha.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 +32 -0
- package/dist/index.js +1703 -0
- package/dist/plugins/claude/.claude-plugin/plugin.json +9 -0
- package/dist/plugins/claude/README.md +14 -0
- package/dist/plugins/claude/hooks/hooks.json +16 -0
- package/dist/plugins/claude/scripts/session-start.mjs +63 -0
- package/dist/plugins/claude/scripts/status.mjs +20 -0
- package/dist/plugins/claude/skills/status/SKILL.md +18 -0
- package/dist/plugins/codex/.codex-plugin/plugin.json +18 -0
- package/dist/plugins/codex/README.md +16 -0
- package/dist/plugins/codex/hooks/hooks.json +16 -0
- package/dist/plugins/codex/scripts/session-start.mjs +63 -0
- package/dist/plugins/codex/scripts/status.mjs +20 -0
- package/dist/plugins/codex/skills/status/SKILL.md +18 -0
- package/dist/plugins/grok/.claude-plugin/plugin.json +9 -0
- package/dist/plugins/grok/README.md +14 -0
- package/dist/plugins/grok/hooks/hooks.json +3 -0
- package/dist/plugins/grok/scripts/status.mjs +20 -0
- package/dist/plugins/grok/skills/status/SKILL.md +18 -0
- package/package.json +36 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1703 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __commonJS = (cb, mod) => function __require() {
|
|
9
|
+
try {
|
|
10
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
11
|
+
} catch (e) {
|
|
12
|
+
throw mod = 0, e;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
|
|
32
|
+
// ../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
|
|
33
|
+
var require_src = __commonJS({
|
|
34
|
+
"../../node_modules/.pnpm/sisteransi@1.0.5/node_modules/sisteransi/src/index.js"(exports, module) {
|
|
35
|
+
"use strict";
|
|
36
|
+
var ESC2 = "\x1B";
|
|
37
|
+
var CSI2 = `${ESC2}[`;
|
|
38
|
+
var beep = "\x07";
|
|
39
|
+
var cursor3 = {
|
|
40
|
+
to(x, y2) {
|
|
41
|
+
if (!y2) return `${CSI2}${x + 1}G`;
|
|
42
|
+
return `${CSI2}${y2 + 1};${x + 1}H`;
|
|
43
|
+
},
|
|
44
|
+
move(x, y2) {
|
|
45
|
+
let ret = "";
|
|
46
|
+
if (x < 0) ret += `${CSI2}${-x}D`;
|
|
47
|
+
else if (x > 0) ret += `${CSI2}${x}C`;
|
|
48
|
+
if (y2 < 0) ret += `${CSI2}${-y2}A`;
|
|
49
|
+
else if (y2 > 0) ret += `${CSI2}${y2}B`;
|
|
50
|
+
return ret;
|
|
51
|
+
},
|
|
52
|
+
up: (count = 1) => `${CSI2}${count}A`,
|
|
53
|
+
down: (count = 1) => `${CSI2}${count}B`,
|
|
54
|
+
forward: (count = 1) => `${CSI2}${count}C`,
|
|
55
|
+
backward: (count = 1) => `${CSI2}${count}D`,
|
|
56
|
+
nextLine: (count = 1) => `${CSI2}E`.repeat(count),
|
|
57
|
+
prevLine: (count = 1) => `${CSI2}F`.repeat(count),
|
|
58
|
+
left: `${CSI2}G`,
|
|
59
|
+
hide: `${CSI2}?25l`,
|
|
60
|
+
show: `${CSI2}?25h`,
|
|
61
|
+
save: `${ESC2}7`,
|
|
62
|
+
restore: `${ESC2}8`
|
|
63
|
+
};
|
|
64
|
+
var scroll = {
|
|
65
|
+
up: (count = 1) => `${CSI2}S`.repeat(count),
|
|
66
|
+
down: (count = 1) => `${CSI2}T`.repeat(count)
|
|
67
|
+
};
|
|
68
|
+
var erase3 = {
|
|
69
|
+
screen: `${CSI2}2J`,
|
|
70
|
+
up: (count = 1) => `${CSI2}1J`.repeat(count),
|
|
71
|
+
down: (count = 1) => `${CSI2}J`.repeat(count),
|
|
72
|
+
line: `${CSI2}2K`,
|
|
73
|
+
lineEnd: `${CSI2}K`,
|
|
74
|
+
lineStart: `${CSI2}1K`,
|
|
75
|
+
lines(count) {
|
|
76
|
+
let clear = "";
|
|
77
|
+
for (let i2 = 0; i2 < count; i2++)
|
|
78
|
+
clear += this.line + (i2 < count - 1 ? cursor3.up() : "");
|
|
79
|
+
if (count)
|
|
80
|
+
clear += cursor3.left;
|
|
81
|
+
return clear;
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
module.exports = { cursor: cursor3, scroll, erase: erase3, beep };
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ../../node_modules/.pnpm/@clack+core@1.5.0/node_modules/@clack/core/dist/index.mjs
|
|
89
|
+
import { stdout, stdin } from "node:process";
|
|
90
|
+
import l__default from "node:readline";
|
|
91
|
+
|
|
92
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/utils.js
|
|
93
|
+
var getCodePointsLength = /* @__PURE__ */ (() => {
|
|
94
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
95
|
+
return (input) => {
|
|
96
|
+
let surrogatePairsNr = 0;
|
|
97
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
98
|
+
while (SURROGATE_PAIR_RE.test(input)) {
|
|
99
|
+
surrogatePairsNr += 1;
|
|
100
|
+
}
|
|
101
|
+
return input.length - surrogatePairsNr;
|
|
102
|
+
};
|
|
103
|
+
})();
|
|
104
|
+
var isFullWidth = (x) => {
|
|
105
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
106
|
+
};
|
|
107
|
+
var isWideNotCJKTNotEmoji = (x) => {
|
|
108
|
+
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;
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// ../../node_modules/.pnpm/fast-string-truncated-width@3.0.3/node_modules/fast-string-truncated-width/dist/index.js
|
|
112
|
+
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
113
|
+
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
114
|
+
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;
|
|
115
|
+
var TAB_RE = /\t{1,1000}/y;
|
|
116
|
+
var EMOJI_RE = new RegExp("[\\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");
|
|
117
|
+
var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
118
|
+
var MODIFIER_RE = new RegExp("\\p{M}+", "gu");
|
|
119
|
+
var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
120
|
+
var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
121
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
122
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
123
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
124
|
+
const ANSI_WIDTH = 0;
|
|
125
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
126
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
127
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
128
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
129
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
130
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
131
|
+
const PARSE_BLOCKS = [
|
|
132
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
133
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
134
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
135
|
+
[TAB_RE, TAB_WIDTH],
|
|
136
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
137
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
138
|
+
];
|
|
139
|
+
let indexPrev = 0;
|
|
140
|
+
let index = 0;
|
|
141
|
+
let length = input.length;
|
|
142
|
+
let lengthExtra = 0;
|
|
143
|
+
let truncationEnabled = false;
|
|
144
|
+
let truncationIndex = length;
|
|
145
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
146
|
+
let unmatchedStart = 0;
|
|
147
|
+
let unmatchedEnd = 0;
|
|
148
|
+
let width = 0;
|
|
149
|
+
let widthExtra = 0;
|
|
150
|
+
outer: while (true) {
|
|
151
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
152
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
153
|
+
lengthExtra = 0;
|
|
154
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
155
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
156
|
+
if (isFullWidth(codePoint)) {
|
|
157
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
158
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
159
|
+
widthExtra = WIDE_WIDTH;
|
|
160
|
+
} else {
|
|
161
|
+
widthExtra = REGULAR_WIDTH;
|
|
162
|
+
}
|
|
163
|
+
if (width + widthExtra > truncationLimit) {
|
|
164
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
165
|
+
}
|
|
166
|
+
if (width + widthExtra > LIMIT) {
|
|
167
|
+
truncationEnabled = true;
|
|
168
|
+
break outer;
|
|
169
|
+
}
|
|
170
|
+
lengthExtra += char.length;
|
|
171
|
+
width += widthExtra;
|
|
172
|
+
}
|
|
173
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
174
|
+
}
|
|
175
|
+
if (index >= length) {
|
|
176
|
+
break outer;
|
|
177
|
+
}
|
|
178
|
+
for (let i2 = 0, l = PARSE_BLOCKS.length; i2 < l; i2++) {
|
|
179
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i2];
|
|
180
|
+
BLOCK_RE.lastIndex = index;
|
|
181
|
+
if (BLOCK_RE.test(input)) {
|
|
182
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
183
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
184
|
+
if (width + widthExtra > truncationLimit) {
|
|
185
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
186
|
+
}
|
|
187
|
+
if (width + widthExtra > LIMIT) {
|
|
188
|
+
truncationEnabled = true;
|
|
189
|
+
break outer;
|
|
190
|
+
}
|
|
191
|
+
width += widthExtra;
|
|
192
|
+
unmatchedStart = indexPrev;
|
|
193
|
+
unmatchedEnd = index;
|
|
194
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
195
|
+
continue outer;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
index += 1;
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
202
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
203
|
+
truncated: truncationEnabled,
|
|
204
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
205
|
+
};
|
|
206
|
+
};
|
|
207
|
+
var dist_default = getStringTruncatedWidth;
|
|
208
|
+
|
|
209
|
+
// ../../node_modules/.pnpm/fast-string-width@3.0.2/node_modules/fast-string-width/dist/index.js
|
|
210
|
+
var NO_TRUNCATION2 = {
|
|
211
|
+
limit: Infinity,
|
|
212
|
+
ellipsis: "",
|
|
213
|
+
ellipsisWidth: 0
|
|
214
|
+
};
|
|
215
|
+
var fastStringWidth = (input, options = {}) => {
|
|
216
|
+
return dist_default(input, NO_TRUNCATION2, options).width;
|
|
217
|
+
};
|
|
218
|
+
var dist_default2 = fastStringWidth;
|
|
219
|
+
|
|
220
|
+
// ../../node_modules/.pnpm/fast-wrap-ansi@0.2.2/node_modules/fast-wrap-ansi/lib/main.js
|
|
221
|
+
var ESC = "\x1B";
|
|
222
|
+
var CSI = "\x9B";
|
|
223
|
+
var END_CODE = 39;
|
|
224
|
+
var ANSI_ESCAPE_BELL = "\x07";
|
|
225
|
+
var ANSI_CSI = "[";
|
|
226
|
+
var ANSI_OSC = "]";
|
|
227
|
+
var ANSI_SGR_TERMINATOR = "m";
|
|
228
|
+
var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
229
|
+
var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
230
|
+
var getClosingCode = (openingCode) => {
|
|
231
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
232
|
+
return 39;
|
|
233
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
234
|
+
return 39;
|
|
235
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
236
|
+
return 49;
|
|
237
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
238
|
+
return 49;
|
|
239
|
+
if (openingCode === 1 || openingCode === 2)
|
|
240
|
+
return 22;
|
|
241
|
+
if (openingCode === 3)
|
|
242
|
+
return 23;
|
|
243
|
+
if (openingCode === 4)
|
|
244
|
+
return 24;
|
|
245
|
+
if (openingCode === 7)
|
|
246
|
+
return 27;
|
|
247
|
+
if (openingCode === 8)
|
|
248
|
+
return 28;
|
|
249
|
+
if (openingCode === 9)
|
|
250
|
+
return 29;
|
|
251
|
+
if (openingCode === 0)
|
|
252
|
+
return 0;
|
|
253
|
+
return void 0;
|
|
254
|
+
};
|
|
255
|
+
var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
256
|
+
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
257
|
+
var wrapWord = (rows2, word, columns) => {
|
|
258
|
+
const characters = word[Symbol.iterator]();
|
|
259
|
+
let isInsideEscape = false;
|
|
260
|
+
let isInsideLinkEscape = false;
|
|
261
|
+
let lastRow = rows2.at(-1);
|
|
262
|
+
let visible = lastRow === void 0 ? 0 : dist_default2(lastRow);
|
|
263
|
+
let currentCharacter = characters.next();
|
|
264
|
+
let nextCharacter = characters.next();
|
|
265
|
+
let rawCharacterIndex = 0;
|
|
266
|
+
while (!currentCharacter.done) {
|
|
267
|
+
const character = currentCharacter.value;
|
|
268
|
+
const characterLength = dist_default2(character);
|
|
269
|
+
if (visible + characterLength <= columns) {
|
|
270
|
+
rows2[rows2.length - 1] += character;
|
|
271
|
+
} else {
|
|
272
|
+
rows2.push(character);
|
|
273
|
+
visible = 0;
|
|
274
|
+
}
|
|
275
|
+
if (character === ESC || character === CSI) {
|
|
276
|
+
isInsideEscape = true;
|
|
277
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
278
|
+
}
|
|
279
|
+
if (isInsideEscape) {
|
|
280
|
+
if (isInsideLinkEscape) {
|
|
281
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
282
|
+
isInsideEscape = false;
|
|
283
|
+
isInsideLinkEscape = false;
|
|
284
|
+
}
|
|
285
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
286
|
+
isInsideEscape = false;
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
visible += characterLength;
|
|
290
|
+
if (visible === columns && !nextCharacter.done) {
|
|
291
|
+
rows2.push("");
|
|
292
|
+
visible = 0;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
currentCharacter = nextCharacter;
|
|
296
|
+
nextCharacter = characters.next();
|
|
297
|
+
rawCharacterIndex += character.length;
|
|
298
|
+
}
|
|
299
|
+
lastRow = rows2.at(-1);
|
|
300
|
+
if (!visible && lastRow !== void 0 && lastRow.length && rows2.length > 1) {
|
|
301
|
+
rows2[rows2.length - 2] += rows2.pop();
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
var stringVisibleTrimSpacesRight = (string) => {
|
|
305
|
+
const words = string.split(" ");
|
|
306
|
+
let last = words.length;
|
|
307
|
+
while (last) {
|
|
308
|
+
if (dist_default2(words[last - 1])) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
last--;
|
|
312
|
+
}
|
|
313
|
+
if (last === words.length) {
|
|
314
|
+
return string;
|
|
315
|
+
}
|
|
316
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
317
|
+
};
|
|
318
|
+
var exec = (string, columns, options = {}) => {
|
|
319
|
+
if (options.trim !== false && string.trim() === "") {
|
|
320
|
+
return "";
|
|
321
|
+
}
|
|
322
|
+
let returnValue = "";
|
|
323
|
+
let escapeCode;
|
|
324
|
+
let escapeUrl;
|
|
325
|
+
const words = string.split(" ");
|
|
326
|
+
let rows2 = [""];
|
|
327
|
+
let rowLength = 0;
|
|
328
|
+
for (let index = 0; index < words.length; index++) {
|
|
329
|
+
const word = words[index];
|
|
330
|
+
if (options.trim !== false) {
|
|
331
|
+
const row = rows2.at(-1) ?? "";
|
|
332
|
+
const trimmed = row.trimStart();
|
|
333
|
+
if (row.length !== trimmed.length) {
|
|
334
|
+
rows2[rows2.length - 1] = trimmed;
|
|
335
|
+
rowLength = dist_default2(trimmed);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
if (index !== 0) {
|
|
339
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
340
|
+
rows2.push("");
|
|
341
|
+
rowLength = 0;
|
|
342
|
+
}
|
|
343
|
+
if (rowLength || options.trim === false) {
|
|
344
|
+
rows2[rows2.length - 1] += " ";
|
|
345
|
+
rowLength++;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const wordLength = dist_default2(word);
|
|
349
|
+
if (options.hard && wordLength > columns) {
|
|
350
|
+
const remainingColumns = columns - rowLength;
|
|
351
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
352
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
353
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
354
|
+
rows2.push("");
|
|
355
|
+
}
|
|
356
|
+
wrapWord(rows2, word, columns);
|
|
357
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
358
|
+
continue;
|
|
359
|
+
}
|
|
360
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
361
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
362
|
+
wrapWord(rows2, word, columns);
|
|
363
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
rows2.push("");
|
|
367
|
+
rowLength = 0;
|
|
368
|
+
}
|
|
369
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
370
|
+
wrapWord(rows2, word, columns);
|
|
371
|
+
rowLength = dist_default2(rows2.at(-1) ?? "");
|
|
372
|
+
continue;
|
|
373
|
+
}
|
|
374
|
+
rows2[rows2.length - 1] += word;
|
|
375
|
+
rowLength += wordLength;
|
|
376
|
+
}
|
|
377
|
+
if (options.trim !== false) {
|
|
378
|
+
rows2 = rows2.map((row) => stringVisibleTrimSpacesRight(row));
|
|
379
|
+
}
|
|
380
|
+
const preString = rows2.join("\n");
|
|
381
|
+
let inSurrogate = false;
|
|
382
|
+
for (let i2 = 0; i2 < preString.length; i2++) {
|
|
383
|
+
const character = preString[i2];
|
|
384
|
+
returnValue += character;
|
|
385
|
+
if (!inSurrogate) {
|
|
386
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
387
|
+
if (inSurrogate) {
|
|
388
|
+
continue;
|
|
389
|
+
}
|
|
390
|
+
} else {
|
|
391
|
+
inSurrogate = false;
|
|
392
|
+
}
|
|
393
|
+
if (character === ESC || character === CSI) {
|
|
394
|
+
GROUP_REGEX.lastIndex = i2 + 1;
|
|
395
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
396
|
+
const groups = groupsResult?.groups;
|
|
397
|
+
if (groups?.code !== void 0) {
|
|
398
|
+
const code = Number.parseFloat(groups.code);
|
|
399
|
+
escapeCode = code === END_CODE ? void 0 : code;
|
|
400
|
+
} else if (groups?.uri !== void 0) {
|
|
401
|
+
escapeUrl = groups.uri.length === 0 ? void 0 : groups.uri;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
if (preString[i2 + 1] === "\n") {
|
|
405
|
+
if (escapeUrl) {
|
|
406
|
+
returnValue += wrapAnsiHyperlink("");
|
|
407
|
+
}
|
|
408
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : void 0;
|
|
409
|
+
if (escapeCode && closingCode) {
|
|
410
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
411
|
+
}
|
|
412
|
+
} else if (character === "\n") {
|
|
413
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
414
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
415
|
+
}
|
|
416
|
+
if (escapeUrl) {
|
|
417
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return returnValue;
|
|
422
|
+
};
|
|
423
|
+
var CRLF_OR_LF = /\r?\n/;
|
|
424
|
+
function wrapAnsi(string, columns, options) {
|
|
425
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join("\n");
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
// ../../node_modules/.pnpm/@clack+core@1.5.0/node_modules/@clack/core/dist/index.mjs
|
|
429
|
+
var import_sisteransi = __toESM(require_src(), 1);
|
|
430
|
+
function findCursor(s, o, l) {
|
|
431
|
+
if (!l.some((r2) => !r2.disabled))
|
|
432
|
+
return s;
|
|
433
|
+
const t2 = s + o, n2 = Math.max(l.length - 1, 0), e = t2 < 0 ? n2 : t2 > n2 ? 0 : t2;
|
|
434
|
+
return l[e]?.disabled ? findCursor(e, o < 0 ? -1 : 1, l) : e;
|
|
435
|
+
}
|
|
436
|
+
var a$1 = ["up", "down", "left", "right", "space", "enter", "cancel"];
|
|
437
|
+
var t = [
|
|
438
|
+
"January",
|
|
439
|
+
"February",
|
|
440
|
+
"March",
|
|
441
|
+
"April",
|
|
442
|
+
"May",
|
|
443
|
+
"June",
|
|
444
|
+
"July",
|
|
445
|
+
"August",
|
|
446
|
+
"September",
|
|
447
|
+
"October",
|
|
448
|
+
"November",
|
|
449
|
+
"December"
|
|
450
|
+
];
|
|
451
|
+
var settings = {
|
|
452
|
+
actions: new Set(a$1),
|
|
453
|
+
aliases: /* @__PURE__ */ new Map([
|
|
454
|
+
// vim support
|
|
455
|
+
["k", "up"],
|
|
456
|
+
["j", "down"],
|
|
457
|
+
["h", "left"],
|
|
458
|
+
["l", "right"],
|
|
459
|
+
["", "cancel"],
|
|
460
|
+
// opinionated defaults!
|
|
461
|
+
["escape", "cancel"]
|
|
462
|
+
]),
|
|
463
|
+
messages: {
|
|
464
|
+
cancel: "Canceled",
|
|
465
|
+
error: "Something went wrong"
|
|
466
|
+
},
|
|
467
|
+
withGuide: true,
|
|
468
|
+
accessible: void 0,
|
|
469
|
+
date: {
|
|
470
|
+
monthNames: [...t],
|
|
471
|
+
messages: {
|
|
472
|
+
required: "Please enter a valid date",
|
|
473
|
+
invalidMonth: "There are only 12 months in a year",
|
|
474
|
+
invalidDay: (n2, e) => `There are only ${n2} days in ${e}`,
|
|
475
|
+
afterMin: (n2) => `Date must be on or after ${n2.toISOString().slice(0, 10)}`,
|
|
476
|
+
beforeMax: (n2) => `Date must be on or before ${n2.toISOString().slice(0, 10)}`
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
function isAccessible(n2) {
|
|
481
|
+
if (n2 !== void 0) return n2;
|
|
482
|
+
if (settings.accessible !== void 0) return settings.accessible;
|
|
483
|
+
const e = process.env.ACCESSIBLE;
|
|
484
|
+
return e !== void 0 && e !== "" && e !== "0" && e !== "false";
|
|
485
|
+
}
|
|
486
|
+
function isActionKey(n2, e) {
|
|
487
|
+
if (typeof n2 == "string")
|
|
488
|
+
return settings.aliases.get(n2) === e;
|
|
489
|
+
for (const s of n2)
|
|
490
|
+
if (s !== void 0 && isActionKey(s, e))
|
|
491
|
+
return true;
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
function diffLines(i2, s) {
|
|
495
|
+
if (i2 === s) return;
|
|
496
|
+
const e = i2.split(`
|
|
497
|
+
`), t2 = s.split(`
|
|
498
|
+
`), r2 = Math.max(e.length, t2.length), f = [];
|
|
499
|
+
for (let n2 = 0; n2 < r2; n2++)
|
|
500
|
+
e[n2] !== t2[n2] && f.push(n2);
|
|
501
|
+
return {
|
|
502
|
+
lines: f,
|
|
503
|
+
numLinesBefore: e.length,
|
|
504
|
+
numLinesAfter: t2.length,
|
|
505
|
+
numLines: r2
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
var R = globalThis.process.platform.startsWith("win");
|
|
509
|
+
var CANCEL_SYMBOL = /* @__PURE__ */ Symbol("clack:cancel");
|
|
510
|
+
function isCancel(e) {
|
|
511
|
+
return e === CANCEL_SYMBOL;
|
|
512
|
+
}
|
|
513
|
+
function setRawMode(e, r2) {
|
|
514
|
+
const o = e;
|
|
515
|
+
o.isTTY && o.setRawMode(r2);
|
|
516
|
+
}
|
|
517
|
+
var getColumns = (e) => "columns" in e && typeof e.columns == "number" ? e.columns : 80;
|
|
518
|
+
var getRows = (e) => "rows" in e && typeof e.rows == "number" ? e.rows : 20;
|
|
519
|
+
function wrapTextWithPrefix(e, r2, o, n2 = o, s = o, t2) {
|
|
520
|
+
const f = getColumns(e ?? stdout);
|
|
521
|
+
return wrapAnsi(r2, f - o.length, {
|
|
522
|
+
hard: true,
|
|
523
|
+
trim: false
|
|
524
|
+
}).split(`
|
|
525
|
+
`).map((c, i2, m2) => {
|
|
526
|
+
const d = t2 ? t2(c, i2) : c;
|
|
527
|
+
return i2 === 0 ? `${n2}${d}` : i2 === m2.length - 1 ? `${s}${d}` : `${o}${d}`;
|
|
528
|
+
}).join(`
|
|
529
|
+
`);
|
|
530
|
+
}
|
|
531
|
+
function runValidation(e, a2) {
|
|
532
|
+
if ("~standard" in e) {
|
|
533
|
+
const n2 = e["~standard"].validate(a2);
|
|
534
|
+
return n2 instanceof Promise ? n2.then((r2) => r2.issues?.at(0)?.message) : n2.issues?.at(0)?.message;
|
|
535
|
+
}
|
|
536
|
+
return e(a2);
|
|
537
|
+
}
|
|
538
|
+
var y = class {
|
|
539
|
+
input;
|
|
540
|
+
output;
|
|
541
|
+
_abortSignal;
|
|
542
|
+
rl;
|
|
543
|
+
opts;
|
|
544
|
+
_render;
|
|
545
|
+
_track = false;
|
|
546
|
+
_prevFrame = "";
|
|
547
|
+
_subscribers = /* @__PURE__ */ new Map();
|
|
548
|
+
_cursor = 0;
|
|
549
|
+
state = "initial";
|
|
550
|
+
error = "";
|
|
551
|
+
value;
|
|
552
|
+
userInput = "";
|
|
553
|
+
/**
|
|
554
|
+
* Whether accessible (static, screen-reader friendly) output is enabled for
|
|
555
|
+
* this prompt, resolved from the `accessible` option, the global setting,
|
|
556
|
+
* and the `ACCESSIBLE` env var.
|
|
557
|
+
*/
|
|
558
|
+
get accessible() {
|
|
559
|
+
return isAccessible(this.opts.accessible);
|
|
560
|
+
}
|
|
561
|
+
constructor(t2, e = true) {
|
|
562
|
+
const { input: i2 = stdin, output: s = stdout, render: r2, signal: n2, ...o } = t2;
|
|
563
|
+
this.opts = o, this.onKeypress = this.onKeypress.bind(this), this.close = this.close.bind(this), this.render = this.render.bind(this), this._render = r2.bind(this), this._track = e, this._abortSignal = n2, this.input = i2, this.output = s;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Unsubscribe all listeners
|
|
567
|
+
*/
|
|
568
|
+
unsubscribe() {
|
|
569
|
+
this._subscribers.clear();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Set a subscriber with opts
|
|
573
|
+
* @param event - The event name
|
|
574
|
+
*/
|
|
575
|
+
setSubscriber(t2, e) {
|
|
576
|
+
const i2 = this._subscribers.get(t2) ?? [];
|
|
577
|
+
i2.push(e), this._subscribers.set(t2, i2);
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* Subscribe to an event
|
|
581
|
+
* @param event - The event name
|
|
582
|
+
* @param cb - The callback
|
|
583
|
+
*/
|
|
584
|
+
on(t2, e) {
|
|
585
|
+
this.setSubscriber(t2, { cb: e });
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Subscribe to an event once
|
|
589
|
+
* @param event - The event name
|
|
590
|
+
* @param cb - The callback
|
|
591
|
+
*/
|
|
592
|
+
once(t2, e) {
|
|
593
|
+
this.setSubscriber(t2, { cb: e, once: true });
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* Emit an event with data
|
|
597
|
+
* @param event - The event name
|
|
598
|
+
* @param data - The data to pass to the callback
|
|
599
|
+
*/
|
|
600
|
+
emit(t2, ...e) {
|
|
601
|
+
const i2 = this._subscribers.get(t2) ?? [], s = [];
|
|
602
|
+
for (const r2 of i2)
|
|
603
|
+
r2.cb(...e), r2.once && s.push(() => i2.splice(i2.indexOf(r2), 1));
|
|
604
|
+
for (const r2 of s)
|
|
605
|
+
r2();
|
|
606
|
+
}
|
|
607
|
+
prompt() {
|
|
608
|
+
return new Promise((t2) => {
|
|
609
|
+
if (this._abortSignal) {
|
|
610
|
+
if (this._abortSignal.aborted)
|
|
611
|
+
return this.state = "cancel", this.close(), t2(CANCEL_SYMBOL);
|
|
612
|
+
this._abortSignal.addEventListener(
|
|
613
|
+
"abort",
|
|
614
|
+
() => {
|
|
615
|
+
this.state = "cancel", this.close();
|
|
616
|
+
},
|
|
617
|
+
{ once: true }
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
this.rl = l__default.createInterface({
|
|
621
|
+
input: this.input,
|
|
622
|
+
tabSize: 2,
|
|
623
|
+
prompt: "",
|
|
624
|
+
escapeCodeTimeout: 50,
|
|
625
|
+
terminal: true
|
|
626
|
+
}), this.rl.prompt(), this.opts.initialUserInput !== void 0 && 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", () => {
|
|
627
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(this.value);
|
|
628
|
+
}), this.once("cancel", () => {
|
|
629
|
+
this.output.write(import_sisteransi.cursor.show), this.output.off("resize", this.render), setRawMode(this.input, false), t2(CANCEL_SYMBOL);
|
|
630
|
+
});
|
|
631
|
+
});
|
|
632
|
+
}
|
|
633
|
+
_isActionKey(t2, e) {
|
|
634
|
+
return t2 === " ";
|
|
635
|
+
}
|
|
636
|
+
_shouldSubmit(t2, e) {
|
|
637
|
+
return true;
|
|
638
|
+
}
|
|
639
|
+
_setValue(t2) {
|
|
640
|
+
this.value = t2, this.emit("value", this.value);
|
|
641
|
+
}
|
|
642
|
+
_setUserInput(t2, e) {
|
|
643
|
+
this.userInput = t2 ?? "", this.emit("userInput", this.userInput), e && this._track && this.rl && (this.rl.write(this.userInput), this._cursor = this.rl.cursor);
|
|
644
|
+
}
|
|
645
|
+
_clearUserInput() {
|
|
646
|
+
this.rl?.write(null, { ctrl: true, name: "u" }), this._setUserInput("");
|
|
647
|
+
}
|
|
648
|
+
async onKeypress(t2, e) {
|
|
649
|
+
if (this.state !== "validating") {
|
|
650
|
+
if (this._track && e.name !== "return" && (e.name && this._isActionKey(t2, 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)), t2 && (t2.toLowerCase() === "y" || t2.toLowerCase() === "n") && this.emit("confirm", t2.toLowerCase() === "y"), this.emit("key", t2, e), e?.name === "return" && this._shouldSubmit(t2, e)) {
|
|
651
|
+
if (this.opts.validate) {
|
|
652
|
+
const i2 = runValidation(this.opts.validate, this.value);
|
|
653
|
+
let s;
|
|
654
|
+
i2 instanceof Promise ? (this.state = "validating", this.render(), s = await i2) : s = i2, s && (this.error = s instanceof Error ? s.message : s, this.state = "error", this.rl?.write(this.userInput));
|
|
655
|
+
}
|
|
656
|
+
this.state !== "error" && (this.state = "submit");
|
|
657
|
+
}
|
|
658
|
+
isActionKey([t2, 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();
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
close() {
|
|
662
|
+
this.input.unpipe(), this.input.removeListener("keypress", this.onKeypress), this.output.write(`
|
|
663
|
+
`), setRawMode(this.input, false), this.rl?.close(), this.rl = void 0, this.emit(`${this.state}`, this.value), this.unsubscribe();
|
|
664
|
+
}
|
|
665
|
+
restoreCursor() {
|
|
666
|
+
const t2 = wrapAnsi(this._prevFrame, process.stdout.columns, { hard: true, trim: false }).split(`
|
|
667
|
+
`).length - 1;
|
|
668
|
+
this.output.write(import_sisteransi.cursor.move(-999, t2 * -1));
|
|
669
|
+
}
|
|
670
|
+
render() {
|
|
671
|
+
const t2 = wrapAnsi(this._render(this) ?? "", process.stdout.columns, {
|
|
672
|
+
hard: true,
|
|
673
|
+
trim: false
|
|
674
|
+
});
|
|
675
|
+
if (t2 !== this._prevFrame) {
|
|
676
|
+
if (this.state === "initial")
|
|
677
|
+
this.output.write(import_sisteransi.cursor.hide);
|
|
678
|
+
else {
|
|
679
|
+
const e = diffLines(this._prevFrame, t2), i2 = getRows(this.output);
|
|
680
|
+
if (this.restoreCursor(), e) {
|
|
681
|
+
const s = Math.max(0, e.numLinesAfter - i2), r2 = Math.max(0, e.numLinesBefore - i2);
|
|
682
|
+
let n2 = e.lines.find((o) => o >= s);
|
|
683
|
+
if (n2 === void 0) {
|
|
684
|
+
this._prevFrame = t2;
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
if (e.lines.length === 1) {
|
|
688
|
+
this.output.write(import_sisteransi.cursor.move(0, n2 - r2)), this.output.write(import_sisteransi.erase.lines(1));
|
|
689
|
+
const o = t2.split(`
|
|
690
|
+
`);
|
|
691
|
+
this.output.write(o[n2]), this._prevFrame = t2, this.output.write(import_sisteransi.cursor.move(0, o.length - n2 - 1));
|
|
692
|
+
return;
|
|
693
|
+
} else if (e.lines.length > 1) {
|
|
694
|
+
if (s < r2)
|
|
695
|
+
n2 = s;
|
|
696
|
+
else {
|
|
697
|
+
const h2 = n2 - r2;
|
|
698
|
+
h2 > 0 && this.output.write(import_sisteransi.cursor.move(0, h2));
|
|
699
|
+
}
|
|
700
|
+
this.output.write(import_sisteransi.erase.down());
|
|
701
|
+
const f = t2.split(`
|
|
702
|
+
`).slice(n2);
|
|
703
|
+
this.output.write(f.join(`
|
|
704
|
+
`)), this._prevFrame = t2;
|
|
705
|
+
return;
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
this.output.write(import_sisteransi.erase.down());
|
|
709
|
+
}
|
|
710
|
+
this.output.write(t2), this.state === "initial" && (this.state = "active"), this._prevFrame = t2;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
var r = class extends y {
|
|
715
|
+
get cursor() {
|
|
716
|
+
return this.value ? 0 : 1;
|
|
717
|
+
}
|
|
718
|
+
get _value() {
|
|
719
|
+
return this.cursor === 0;
|
|
720
|
+
}
|
|
721
|
+
constructor(t2) {
|
|
722
|
+
super(t2, false), this.value = !!t2.initialValue, this.on("userInput", () => {
|
|
723
|
+
this.value = this._value;
|
|
724
|
+
}), this.on("confirm", (i2) => {
|
|
725
|
+
this.output.write(import_sisteransi.cursor.move(0, -1)), this.value = i2, this.state = "submit", this.close();
|
|
726
|
+
}), this.on("cursor", () => {
|
|
727
|
+
this.value = !this.value;
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
};
|
|
731
|
+
var a = class extends y {
|
|
732
|
+
options;
|
|
733
|
+
cursor = 0;
|
|
734
|
+
get _value() {
|
|
735
|
+
return this.options[this.cursor]?.value;
|
|
736
|
+
}
|
|
737
|
+
get _enabledOptions() {
|
|
738
|
+
return this.options.filter((e) => e.disabled !== true);
|
|
739
|
+
}
|
|
740
|
+
toggleAll() {
|
|
741
|
+
const e = this._enabledOptions, i2 = this.value !== void 0 && this.value.length === e.length;
|
|
742
|
+
this.value = i2 ? [] : e.map((t2) => t2.value);
|
|
743
|
+
}
|
|
744
|
+
toggleInvert() {
|
|
745
|
+
const e = this.value;
|
|
746
|
+
if (!e)
|
|
747
|
+
return;
|
|
748
|
+
const i2 = this._enabledOptions.filter((t2) => !e.includes(t2.value));
|
|
749
|
+
this.value = i2.map((t2) => t2.value);
|
|
750
|
+
}
|
|
751
|
+
toggleValue() {
|
|
752
|
+
this.value === void 0 && (this.value = []);
|
|
753
|
+
const e = this.value.includes(this._value);
|
|
754
|
+
this.value = e ? this.value.filter((i2) => i2 !== this._value) : [...this.value, this._value];
|
|
755
|
+
}
|
|
756
|
+
constructor(e) {
|
|
757
|
+
super(e, false), this.options = e.options, this.value = [...e.initialValues ?? []];
|
|
758
|
+
const i2 = Math.max(
|
|
759
|
+
this.options.findIndex(({ value: t2 }) => t2 === e.cursorAt),
|
|
760
|
+
0
|
|
761
|
+
);
|
|
762
|
+
this.cursor = this.options[i2]?.disabled ? findCursor(i2, 1, this.options) : i2, this.on("key", (t2, l) => {
|
|
763
|
+
l.name === "a" && this.toggleAll(), l.name === "i" && this.toggleInvert();
|
|
764
|
+
}), this.on("cursor", (t2) => {
|
|
765
|
+
switch (t2) {
|
|
766
|
+
case "left":
|
|
767
|
+
case "up":
|
|
768
|
+
this.cursor = findCursor(this.cursor, -1, this.options);
|
|
769
|
+
break;
|
|
770
|
+
case "down":
|
|
771
|
+
case "right":
|
|
772
|
+
this.cursor = findCursor(this.cursor, 1, this.options);
|
|
773
|
+
break;
|
|
774
|
+
case "space":
|
|
775
|
+
this.toggleValue();
|
|
776
|
+
break;
|
|
777
|
+
}
|
|
778
|
+
});
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
// ../../node_modules/.pnpm/@clack+prompts@1.8.0/node_modules/@clack/prompts/dist/index.mjs
|
|
783
|
+
import { styleText, stripVTControlCharacters } from "node:util";
|
|
784
|
+
import process$1 from "node:process";
|
|
785
|
+
var import_sisteransi2 = __toESM(require_src(), 1);
|
|
786
|
+
function isUnicodeSupported() {
|
|
787
|
+
if (process$1.platform !== "win32") {
|
|
788
|
+
return process$1.env.TERM !== "linux";
|
|
789
|
+
}
|
|
790
|
+
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";
|
|
791
|
+
}
|
|
792
|
+
var unicode = isUnicodeSupported();
|
|
793
|
+
var unicodeOr = (o, e) => unicode ? o : e;
|
|
794
|
+
var S_STEP_ACTIVE = unicodeOr("\u25C6", "*");
|
|
795
|
+
var S_STEP_CANCEL = unicodeOr("\u25A0", "x");
|
|
796
|
+
var S_STEP_ERROR = unicodeOr("\u25B2", "x");
|
|
797
|
+
var S_STEP_SUBMIT = unicodeOr("\u25C7", "o");
|
|
798
|
+
var S_BAR_START = unicodeOr("\u250C", "T");
|
|
799
|
+
var S_BAR = unicodeOr("\u2502", "|");
|
|
800
|
+
var S_BAR_END = unicodeOr("\u2514", "\u2014");
|
|
801
|
+
var S_BAR_START_RIGHT = unicodeOr("\u2510", "T");
|
|
802
|
+
var S_BAR_END_RIGHT = unicodeOr("\u2518", "\u2014");
|
|
803
|
+
var S_RADIO_ACTIVE = unicodeOr("\u25CF", ">");
|
|
804
|
+
var S_RADIO_INACTIVE = unicodeOr("\u25CB", " ");
|
|
805
|
+
var S_CHECKBOX_ACTIVE = unicodeOr("\u25FB", "[\u2022]");
|
|
806
|
+
var S_CHECKBOX_SELECTED = unicodeOr("\u25FC", "[+]");
|
|
807
|
+
var S_CHECKBOX_INACTIVE = unicodeOr("\u25FB", "[ ]");
|
|
808
|
+
var S_PASSWORD_MASK = unicodeOr("\u25AA", "\u2022");
|
|
809
|
+
var S_BAR_H = unicodeOr("\u2500", "-");
|
|
810
|
+
var S_CORNER_TOP_RIGHT = unicodeOr("\u256E", "+");
|
|
811
|
+
var S_CONNECT_LEFT = unicodeOr("\u251C", "+");
|
|
812
|
+
var S_CORNER_BOTTOM_RIGHT = unicodeOr("\u256F", "+");
|
|
813
|
+
var S_CORNER_BOTTOM_LEFT = unicodeOr("\u2570", "+");
|
|
814
|
+
var S_CORNER_TOP_LEFT = unicodeOr("\u256D", "+");
|
|
815
|
+
var S_INFO = unicodeOr("\u25CF", "\u2022");
|
|
816
|
+
var S_SUCCESS = unicodeOr("\u25C6", "*");
|
|
817
|
+
var S_WARN = unicodeOr("\u25B2", "!");
|
|
818
|
+
var S_ERROR = unicodeOr("\u25A0", "x");
|
|
819
|
+
var symbol = (o) => {
|
|
820
|
+
switch (o) {
|
|
821
|
+
case "initial":
|
|
822
|
+
case "active":
|
|
823
|
+
return styleText("cyan", S_STEP_ACTIVE);
|
|
824
|
+
case "cancel":
|
|
825
|
+
return styleText("red", S_STEP_CANCEL);
|
|
826
|
+
case "error":
|
|
827
|
+
return styleText("yellow", S_STEP_ERROR);
|
|
828
|
+
case "submit":
|
|
829
|
+
return styleText("green", S_STEP_SUBMIT);
|
|
830
|
+
case "validating":
|
|
831
|
+
return styleText("dim", S_STEP_ACTIVE);
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
var symbolBar = (o) => {
|
|
835
|
+
switch (o) {
|
|
836
|
+
case "initial":
|
|
837
|
+
case "active":
|
|
838
|
+
return styleText("cyan", S_BAR);
|
|
839
|
+
case "cancel":
|
|
840
|
+
return styleText("red", S_BAR);
|
|
841
|
+
case "error":
|
|
842
|
+
return styleText("yellow", S_BAR);
|
|
843
|
+
case "submit":
|
|
844
|
+
return styleText("green", S_BAR);
|
|
845
|
+
}
|
|
846
|
+
};
|
|
847
|
+
function formatInstructionFooter(o, e) {
|
|
848
|
+
const r2 = [`${e ? `${styleText("cyan", S_BAR)} ` : ""}${o.join(" \u2022 ")}`];
|
|
849
|
+
return e && r2.push(styleText("cyan", S_BAR_END)), r2;
|
|
850
|
+
}
|
|
851
|
+
var I = (l, e, w, p, b, C2 = false) => {
|
|
852
|
+
let r2 = e, O = 0;
|
|
853
|
+
if (C2)
|
|
854
|
+
for (let i2 = p - 1; i2 >= w; i2--) {
|
|
855
|
+
const m2 = l[i2];
|
|
856
|
+
if (m2 && (r2 -= m2.length), O++, r2 <= b) break;
|
|
857
|
+
}
|
|
858
|
+
else
|
|
859
|
+
for (let i2 = w; i2 < p; i2++) {
|
|
860
|
+
const m2 = l[i2];
|
|
861
|
+
if (m2 && (r2 -= m2.length), O++, r2 <= b) break;
|
|
862
|
+
}
|
|
863
|
+
return { lineCount: r2, removals: O };
|
|
864
|
+
};
|
|
865
|
+
var limitOptions = ({
|
|
866
|
+
cursor: l,
|
|
867
|
+
options: e,
|
|
868
|
+
style: w,
|
|
869
|
+
output: p = process.stdout,
|
|
870
|
+
maxItems: b = Number.POSITIVE_INFINITY,
|
|
871
|
+
columnPadding: C2 = 0,
|
|
872
|
+
rowPadding: r2 = 4
|
|
873
|
+
}) => {
|
|
874
|
+
const i2 = getColumns(p) - C2, m2 = getRows(p), M = styleText("dim", "..."), v = Math.max(m2 - r2, 0), a2 = Math.max(Math.min(b, v), 5);
|
|
875
|
+
let f = 0;
|
|
876
|
+
l >= a2 - 3 && (f = Math.max(
|
|
877
|
+
Math.min(l - a2 + 3, e.length - a2),
|
|
878
|
+
0
|
|
879
|
+
));
|
|
880
|
+
let d = a2 < e.length && f > 0, c = a2 < e.length && f + a2 < e.length;
|
|
881
|
+
const W = Math.min(
|
|
882
|
+
f + a2,
|
|
883
|
+
e.length
|
|
884
|
+
), s = [];
|
|
885
|
+
let g = 0;
|
|
886
|
+
d && g++, c && g++;
|
|
887
|
+
const T = f + (d ? 1 : 0), y2 = W - (c ? 1 : 0);
|
|
888
|
+
for (let t2 = T; t2 < y2; t2++) {
|
|
889
|
+
const n2 = e[t2], o = n2 ? w(n2, t2 === l) : "", h2 = wrapAnsi(o, i2, {
|
|
890
|
+
hard: true,
|
|
891
|
+
trim: false
|
|
892
|
+
}).split(`
|
|
893
|
+
`);
|
|
894
|
+
s.push(h2), g += h2.length;
|
|
895
|
+
}
|
|
896
|
+
if (g > v) {
|
|
897
|
+
let t2 = 0, n2 = 0, o = g;
|
|
898
|
+
const h2 = l - T;
|
|
899
|
+
let u3 = v;
|
|
900
|
+
const L = () => I(s, o, 0, h2, u3), E = () => I(
|
|
901
|
+
s,
|
|
902
|
+
o,
|
|
903
|
+
h2 + 1,
|
|
904
|
+
s.length,
|
|
905
|
+
u3,
|
|
906
|
+
true
|
|
907
|
+
);
|
|
908
|
+
d ? ({ lineCount: o, removals: t2 } = L(), o > u3 && (c || (u3 -= 1), { lineCount: o, removals: n2 } = E())) : (c || (u3 -= 1), { lineCount: o, removals: n2 } = E(), o > u3 && (u3 -= 1, { lineCount: o, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n2 > 0 && (c = true, s.splice(s.length - n2, n2));
|
|
909
|
+
}
|
|
910
|
+
const x = [];
|
|
911
|
+
d && x.push(M);
|
|
912
|
+
for (const t2 of s)
|
|
913
|
+
for (const n2 of t2)
|
|
914
|
+
x.push(n2);
|
|
915
|
+
return c && x.push(M), x;
|
|
916
|
+
};
|
|
917
|
+
var confirm = (i2) => {
|
|
918
|
+
const a2 = i2.active ?? "Yes", s = i2.inactive ?? "No";
|
|
919
|
+
return new r({
|
|
920
|
+
active: a2,
|
|
921
|
+
inactive: s,
|
|
922
|
+
signal: i2.signal,
|
|
923
|
+
input: i2.input,
|
|
924
|
+
output: i2.output,
|
|
925
|
+
initialValue: i2.initialValue ?? true,
|
|
926
|
+
render() {
|
|
927
|
+
const e = i2.withGuide ?? settings.withGuide, u3 = `${symbol(this.state)} `, l = e ? `${styleText("gray", S_BAR)} ` : "", f = wrapTextWithPrefix(
|
|
928
|
+
i2.output,
|
|
929
|
+
i2.message,
|
|
930
|
+
l,
|
|
931
|
+
u3
|
|
932
|
+
), o = `${e ? `${styleText("gray", S_BAR)}
|
|
933
|
+
` : ""}${f}
|
|
934
|
+
`, c = this.value ? a2 : s;
|
|
935
|
+
switch (this.state) {
|
|
936
|
+
case "submit": {
|
|
937
|
+
const r2 = e ? `${styleText("gray", S_BAR)} ` : "";
|
|
938
|
+
return `${o}${r2}${styleText("dim", c)}`;
|
|
939
|
+
}
|
|
940
|
+
case "cancel": {
|
|
941
|
+
const r2 = e ? `${styleText("gray", S_BAR)} ` : "";
|
|
942
|
+
return `${o}${r2}${styleText(["strikethrough", "dim"], c)}${e ? `
|
|
943
|
+
${styleText("gray", S_BAR)}` : ""}`;
|
|
944
|
+
}
|
|
945
|
+
default: {
|
|
946
|
+
const r2 = e ? `${styleText("cyan", S_BAR)} ` : "", g = e ? styleText("cyan", S_BAR_END) : "";
|
|
947
|
+
return `${o}${r2}${this.value ? `${styleText("green", S_RADIO_ACTIVE)} ${a2}` : `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", a2)}`}${i2.vertical ? e ? `
|
|
948
|
+
${styleText("cyan", S_BAR)} ` : `
|
|
949
|
+
` : ` ${styleText("dim", "/")} `}${this.value ? `${styleText("dim", S_RADIO_INACTIVE)} ${styleText("dim", s)}` : `${styleText("green", S_RADIO_ACTIVE)} ${s}`}
|
|
950
|
+
${g}
|
|
951
|
+
`;
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
}).prompt();
|
|
956
|
+
};
|
|
957
|
+
var MULTISELECT_INSTRUCTIONS = [
|
|
958
|
+
`${styleText("dim", "\u2191/\u2193")} to navigate`,
|
|
959
|
+
`${styleText("dim", "Space:")} select`,
|
|
960
|
+
`${styleText("dim", "Enter:")} confirm`
|
|
961
|
+
];
|
|
962
|
+
var m = (i2, u3) => i2.split(`
|
|
963
|
+
`).map((d) => u3(d)).join(`
|
|
964
|
+
`);
|
|
965
|
+
var multiselect = (i2) => {
|
|
966
|
+
const u3 = (t2, a2) => {
|
|
967
|
+
const r2 = t2.label ?? String(t2.value);
|
|
968
|
+
return a2 === "disabled" ? `${styleText("gray", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText(["strikethrough", "gray"], o))}${t2.hint ? ` ${styleText("dim", `(${t2.hint ?? "disabled"})`)}` : ""}` : a2 === "active" ? `${styleText("cyan", S_CHECKBOX_ACTIVE)} ${r2}${t2.hint ? ` ${styleText("dim", `(${t2.hint})`)}` : ""}` : a2 === "selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${m(r2, (o) => styleText("dim", o))}${t2.hint ? ` ${styleText("dim", `(${t2.hint})`)}` : ""}` : a2 === "cancelled" ? `${m(r2, (o) => styleText(["strikethrough", "dim"], o))}` : a2 === "active-selected" ? `${styleText("green", S_CHECKBOX_SELECTED)} ${r2}${t2.hint ? ` ${styleText("dim", `(${t2.hint})`)}` : ""}` : a2 === "submitted" ? `${m(r2, (o) => styleText("dim", o))}` : `${styleText("dim", S_CHECKBOX_INACTIVE)} ${m(r2, (o) => styleText("dim", o))}`;
|
|
969
|
+
}, d = i2.required ?? true, v = i2.showInstructions ?? true;
|
|
970
|
+
return new a({
|
|
971
|
+
options: i2.options,
|
|
972
|
+
signal: i2.signal,
|
|
973
|
+
input: i2.input,
|
|
974
|
+
output: i2.output,
|
|
975
|
+
initialValues: i2.initialValues,
|
|
976
|
+
required: d,
|
|
977
|
+
cursorAt: i2.cursorAt,
|
|
978
|
+
validate(t2) {
|
|
979
|
+
if (d && (t2 === void 0 || t2.length === 0))
|
|
980
|
+
return `Please select at least one option.
|
|
981
|
+
${styleText(
|
|
982
|
+
"reset",
|
|
983
|
+
styleText(
|
|
984
|
+
"dim",
|
|
985
|
+
`Press ${styleText(["gray", "bgWhite", "inverse"], " space ")} to select, ${styleText(
|
|
986
|
+
"gray",
|
|
987
|
+
styleText("bgWhite", styleText("inverse", " enter "))
|
|
988
|
+
)} to submit`
|
|
989
|
+
)
|
|
990
|
+
)}`;
|
|
991
|
+
},
|
|
992
|
+
render() {
|
|
993
|
+
const t2 = i2.withGuide ?? settings.withGuide, a2 = wrapTextWithPrefix(
|
|
994
|
+
i2.output,
|
|
995
|
+
i2.message,
|
|
996
|
+
t2 ? `${symbolBar(this.state)} ` : "",
|
|
997
|
+
`${symbol(this.state)} `
|
|
998
|
+
), r2 = `${t2 ? `${styleText("gray", S_BAR)}
|
|
999
|
+
` : ""}${a2}
|
|
1000
|
+
`, o = this.value ?? [], p = (n2, l) => {
|
|
1001
|
+
if (n2.disabled)
|
|
1002
|
+
return u3(n2, "disabled");
|
|
1003
|
+
const s = o.includes(n2.value);
|
|
1004
|
+
return l && s ? u3(n2, "active-selected") : s ? u3(n2, "selected") : u3(n2, l ? "active" : "inactive");
|
|
1005
|
+
};
|
|
1006
|
+
switch (this.state) {
|
|
1007
|
+
case "submit": {
|
|
1008
|
+
const n2 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u3(s, "submitted")).join(styleText("dim", ", ")) || styleText("dim", "none"), l = wrapTextWithPrefix(
|
|
1009
|
+
i2.output,
|
|
1010
|
+
n2,
|
|
1011
|
+
t2 ? `${styleText("gray", S_BAR)} ` : ""
|
|
1012
|
+
);
|
|
1013
|
+
return `${r2}${l}`;
|
|
1014
|
+
}
|
|
1015
|
+
case "cancel": {
|
|
1016
|
+
const n2 = this.options.filter(({ value: s }) => o.includes(s)).map((s) => u3(s, "cancelled")).join(styleText("dim", ", "));
|
|
1017
|
+
if (n2.trim() === "")
|
|
1018
|
+
return `${r2}${styleText("gray", S_BAR)}`;
|
|
1019
|
+
const l = wrapTextWithPrefix(
|
|
1020
|
+
i2.output,
|
|
1021
|
+
n2,
|
|
1022
|
+
t2 ? `${styleText("gray", S_BAR)} ` : ""
|
|
1023
|
+
);
|
|
1024
|
+
return `${r2}${l}${t2 ? `
|
|
1025
|
+
${styleText("gray", S_BAR)}` : ""}`;
|
|
1026
|
+
}
|
|
1027
|
+
case "error": {
|
|
1028
|
+
const n2 = t2 ? `${styleText("yellow", S_BAR)} ` : "", l = this.error.split(`
|
|
1029
|
+
`).map(
|
|
1030
|
+
($, C2) => C2 === 0 ? `${t2 ? `${styleText("yellow", S_BAR_END)} ` : ""}${styleText("yellow", $)}` : ` ${$}`
|
|
1031
|
+
).join(`
|
|
1032
|
+
`), s = r2.split(`
|
|
1033
|
+
`).length, h2 = l.split(`
|
|
1034
|
+
`).length + 1;
|
|
1035
|
+
return `${r2}${n2}${limitOptions({
|
|
1036
|
+
output: i2.output,
|
|
1037
|
+
options: this.options,
|
|
1038
|
+
cursor: this.cursor,
|
|
1039
|
+
maxItems: i2.maxItems,
|
|
1040
|
+
columnPadding: n2.length,
|
|
1041
|
+
rowPadding: s + h2,
|
|
1042
|
+
style: p
|
|
1043
|
+
}).join(`
|
|
1044
|
+
${n2}`)}
|
|
1045
|
+
${l}
|
|
1046
|
+
`;
|
|
1047
|
+
}
|
|
1048
|
+
default: {
|
|
1049
|
+
const n2 = t2 ? `${styleText("cyan", S_BAR)} ` : "", l = r2.split(`
|
|
1050
|
+
`).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2) : t2 ? [styleText("cyan", S_BAR_END)] : [], h2 = s.join(`
|
|
1051
|
+
`), $ = s.length + 1;
|
|
1052
|
+
return `${r2}${n2}${limitOptions({
|
|
1053
|
+
output: i2.output,
|
|
1054
|
+
options: this.options,
|
|
1055
|
+
cursor: this.cursor,
|
|
1056
|
+
maxItems: i2.maxItems,
|
|
1057
|
+
columnPadding: n2.length,
|
|
1058
|
+
rowPadding: l + $,
|
|
1059
|
+
style: p
|
|
1060
|
+
}).join(`
|
|
1061
|
+
${n2}`)}
|
|
1062
|
+
${h2}
|
|
1063
|
+
`;
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
}).prompt();
|
|
1068
|
+
};
|
|
1069
|
+
var cancel = (o = "", t2) => {
|
|
1070
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_END)} ` : "";
|
|
1071
|
+
i2.write(`${e}${styleText("red", o)}
|
|
1072
|
+
|
|
1073
|
+
`);
|
|
1074
|
+
};
|
|
1075
|
+
var intro = (o = "", t2) => {
|
|
1076
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR_START)} ` : "";
|
|
1077
|
+
i2.write(`${e}${o}
|
|
1078
|
+
`);
|
|
1079
|
+
};
|
|
1080
|
+
var outro = (o = "", t2) => {
|
|
1081
|
+
const i2 = t2?.output ?? process.stdout, e = t2?.withGuide ?? settings.withGuide ? `${styleText("gray", S_BAR)}
|
|
1082
|
+
${styleText("gray", S_BAR_END)} ` : "";
|
|
1083
|
+
i2.write(`${e}${o}
|
|
1084
|
+
|
|
1085
|
+
`);
|
|
1086
|
+
};
|
|
1087
|
+
var W$1 = (o) => o;
|
|
1088
|
+
var C = (o, e, s) => {
|
|
1089
|
+
const a2 = {
|
|
1090
|
+
hard: true,
|
|
1091
|
+
trim: false
|
|
1092
|
+
}, i2 = wrapAnsi(o, e, a2).split(`
|
|
1093
|
+
`), c = i2.reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), u3 = i2.map(s).reduce((n2, t2) => Math.max(dist_default2(t2), n2), 0), g = e - (u3 - c);
|
|
1094
|
+
return wrapAnsi(o, g, a2);
|
|
1095
|
+
};
|
|
1096
|
+
var note = (o = "", e = "", s) => {
|
|
1097
|
+
const a2 = s?.output ?? process$1.stdout, i2 = s?.withGuide ?? settings.withGuide, c = s?.format ?? W$1, g = ["", ...C(o, getColumns(a2) - 6, c).split(`
|
|
1098
|
+
`).map(c), ""], n2 = dist_default2(e), t2 = Math.max(
|
|
1099
|
+
g.reduce((m2, F) => {
|
|
1100
|
+
const O = dist_default2(F);
|
|
1101
|
+
return O > m2 ? O : m2;
|
|
1102
|
+
}, 0),
|
|
1103
|
+
n2
|
|
1104
|
+
) + 2, h2 = g.map(
|
|
1105
|
+
(m2) => `${styleText("gray", S_BAR)} ${m2}${" ".repeat(t2 - dist_default2(m2))}${styleText("gray", S_BAR)}`
|
|
1106
|
+
).join(`
|
|
1107
|
+
`), T = i2 ? `${styleText("gray", S_BAR)}
|
|
1108
|
+
` : "", l$1 = i2 ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
1109
|
+
a2.write(
|
|
1110
|
+
`${T}${styleText("green", S_STEP_SUBMIT)} ${styleText("reset", e)} ${styleText(
|
|
1111
|
+
"gray",
|
|
1112
|
+
S_BAR_H.repeat(Math.max(t2 - n2 - 1, 1)) + S_CORNER_TOP_RIGHT
|
|
1113
|
+
)}
|
|
1114
|
+
${h2}
|
|
1115
|
+
${styleText("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
1116
|
+
`
|
|
1117
|
+
);
|
|
1118
|
+
};
|
|
1119
|
+
var u2 = {
|
|
1120
|
+
light: unicodeOr("\u2500", "-"),
|
|
1121
|
+
heavy: unicodeOr("\u2501", "="),
|
|
1122
|
+
block: unicodeOr("\u2588", "#")
|
|
1123
|
+
};
|
|
1124
|
+
var SELECT_INSTRUCTIONS = [
|
|
1125
|
+
`${styleText("dim", "\u2191/\u2193")} to navigate`,
|
|
1126
|
+
`${styleText("dim", "Enter:")} confirm`
|
|
1127
|
+
];
|
|
1128
|
+
var i = `${styleText("gray", S_BAR)} `;
|
|
1129
|
+
|
|
1130
|
+
// src/native.ts
|
|
1131
|
+
import { spawnSync } from "node:child_process";
|
|
1132
|
+
import { accessSync, constants, realpathSync, statSync } from "node:fs";
|
|
1133
|
+
import { delimiter, isAbsolute, join } from "node:path";
|
|
1134
|
+
import { stripVTControlCharacters as stripVTControlCharacters2 } from "node:util";
|
|
1135
|
+
var agents = ["claude", "codex", "grok"];
|
|
1136
|
+
var labels = {
|
|
1137
|
+
claude: "Claude Code",
|
|
1138
|
+
codex: "Codex",
|
|
1139
|
+
grok: "Grok"
|
|
1140
|
+
};
|
|
1141
|
+
function executable(agent) {
|
|
1142
|
+
for (const directory of (process.env.PATH ?? "").split(delimiter)) {
|
|
1143
|
+
if (!isAbsolute(directory)) continue;
|
|
1144
|
+
for (const extension of [""]) {
|
|
1145
|
+
const path = join(directory, agent + extension);
|
|
1146
|
+
try {
|
|
1147
|
+
accessSync(path, constants.X_OK);
|
|
1148
|
+
if (statSync(path).isFile()) return path;
|
|
1149
|
+
} catch {
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
return void 0;
|
|
1154
|
+
}
|
|
1155
|
+
function native(path, agent, args) {
|
|
1156
|
+
const result = spawnSync(path, args, {
|
|
1157
|
+
encoding: "utf8",
|
|
1158
|
+
timeout: 6e4,
|
|
1159
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
1160
|
+
shell: false
|
|
1161
|
+
});
|
|
1162
|
+
if (result.error || result.status !== 0) {
|
|
1163
|
+
throw new Error(
|
|
1164
|
+
`NATIVE_COMMAND_FAILED: ${agent} ${args.slice(0, 3).join(" ")} failed (${result.status ?? result.error?.code ?? "signal"}). Check '${agent} plugin --help', update the agent CLI, and retry. Its plugin manager may have partially registered Memroot; no success receipt was written.`
|
|
1165
|
+
);
|
|
1166
|
+
}
|
|
1167
|
+
return result.stdout;
|
|
1168
|
+
}
|
|
1169
|
+
function installCommands(agent, marketplace) {
|
|
1170
|
+
if (agent === "claude")
|
|
1171
|
+
return [
|
|
1172
|
+
["plugin", "marketplace", "add", marketplace, "--scope", "user"],
|
|
1173
|
+
["plugin", "install", "memroot@memroot", "--scope", "user"]
|
|
1174
|
+
];
|
|
1175
|
+
if (agent === "codex")
|
|
1176
|
+
return [
|
|
1177
|
+
["plugin", "marketplace", "add", marketplace, "--json"],
|
|
1178
|
+
["plugin", "add", "memroot@memroot", "--json"]
|
|
1179
|
+
];
|
|
1180
|
+
return [
|
|
1181
|
+
["plugin", "install", join(marketplace, "plugins", "memroot"), "--trust"]
|
|
1182
|
+
];
|
|
1183
|
+
}
|
|
1184
|
+
function preflight(path, agent) {
|
|
1185
|
+
native(path, agent, ["plugin", "--help"]);
|
|
1186
|
+
if (agent !== "grok")
|
|
1187
|
+
native(path, agent, ["plugin", "marketplace", "add", "--help"]);
|
|
1188
|
+
native(path, agent, [
|
|
1189
|
+
"plugin",
|
|
1190
|
+
agent === "codex" ? "add" : "install",
|
|
1191
|
+
"--help"
|
|
1192
|
+
]);
|
|
1193
|
+
}
|
|
1194
|
+
function rows(output, field) {
|
|
1195
|
+
let value;
|
|
1196
|
+
try {
|
|
1197
|
+
value = JSON.parse(output);
|
|
1198
|
+
} catch {
|
|
1199
|
+
throw new Error(
|
|
1200
|
+
"NATIVE_STATUS_UNSUPPORTED: Agent plugin status is not valid JSON. Update the agent CLI and retry."
|
|
1201
|
+
);
|
|
1202
|
+
}
|
|
1203
|
+
if (field)
|
|
1204
|
+
value = value && typeof value === "object" ? value[field] : void 0;
|
|
1205
|
+
if (!Array.isArray(value) || value.some((row) => !row || typeof row !== "object" || Array.isArray(row)))
|
|
1206
|
+
throw new Error(
|
|
1207
|
+
"NATIVE_STATUS_UNSUPPORTED: Unrecognized agent plugin status; refusing to change it."
|
|
1208
|
+
);
|
|
1209
|
+
return value;
|
|
1210
|
+
}
|
|
1211
|
+
function samePath(left, right) {
|
|
1212
|
+
if (typeof left !== "string") return false;
|
|
1213
|
+
try {
|
|
1214
|
+
return realpathSync(left) === realpathSync(right);
|
|
1215
|
+
} catch {
|
|
1216
|
+
return left === right;
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1219
|
+
function inspectNative(path, agent, marketplace, previousMarketplace) {
|
|
1220
|
+
if (agent === "grok") {
|
|
1221
|
+
const output = stripVTControlCharacters2(
|
|
1222
|
+
native(path, agent, ["plugin", "list"])
|
|
1223
|
+
);
|
|
1224
|
+
const lines = output.split("\n").filter((line) => line.trim());
|
|
1225
|
+
const empty = output.trim() === "No plugins installed. Run `grok plugin install --help` to get started.";
|
|
1226
|
+
if (!empty && (!lines.length || lines.some(
|
|
1227
|
+
(line) => !/^\s*\S+:\s+[^[]+\[.+\](?:\s+\(disabled\))?\s*$/.test(line)
|
|
1228
|
+
))) {
|
|
1229
|
+
throw new Error(
|
|
1230
|
+
"NATIVE_STATUS_UNSUPPORTED: Unrecognized Grok plugin list format. Update Grok and inspect its native plugin manager before retrying."
|
|
1231
|
+
);
|
|
1232
|
+
}
|
|
1233
|
+
const matching = output.split("\n").filter((line) => /:\s*memroot(?:\s|$)/.test(line));
|
|
1234
|
+
for (const line of matching) {
|
|
1235
|
+
const source = line.match(/\[local: (.*)\]/)?.[1];
|
|
1236
|
+
if (!samePath(source, join(marketplace, "plugins", "memroot")) && !(previousMarketplace && samePath(source, join(previousMarketplace, "plugins", "memroot"))))
|
|
1237
|
+
throw new Error(
|
|
1238
|
+
"PLUGIN_COLLISION: Grok already has a different Memroot plugin. Resolve it with the native plugin manager first."
|
|
1239
|
+
);
|
|
1240
|
+
if (/disabled/i.test(line))
|
|
1241
|
+
throw new Error(
|
|
1242
|
+
"PLUGIN_DISABLED: Memroot is disabled in Grok. Enable it in the native plugin manager when ready."
|
|
1243
|
+
);
|
|
1244
|
+
}
|
|
1245
|
+
return { registered: false, installed: matching.length > 0 };
|
|
1246
|
+
}
|
|
1247
|
+
const markets = rows(
|
|
1248
|
+
native(path, agent, ["plugin", "marketplace", "list", "--json"]),
|
|
1249
|
+
agent === "codex" ? "marketplaces" : void 0
|
|
1250
|
+
);
|
|
1251
|
+
const plugins = rows(
|
|
1252
|
+
native(path, agent, ["plugin", "list", "--json"]),
|
|
1253
|
+
agent === "codex" ? "installed" : void 0
|
|
1254
|
+
);
|
|
1255
|
+
const matchingMarkets = markets.filter((row) => row.name === "memroot");
|
|
1256
|
+
for (const market of matchingMarkets) {
|
|
1257
|
+
const source = agent === "codex" ? market.root : market.path;
|
|
1258
|
+
if (!samePath(source, marketplace) && !(previousMarketplace && samePath(source, previousMarketplace)))
|
|
1259
|
+
throw new Error(
|
|
1260
|
+
"MARKETPLACE_COLLISION: memroot is already registered from a different source. Resolve it with the native plugin manager first."
|
|
1261
|
+
);
|
|
1262
|
+
}
|
|
1263
|
+
const matchingPlugins = plugins.filter(
|
|
1264
|
+
(row) => row.id === "memroot@memroot" || row.pluginId === "memroot@memroot" || row.name === "memroot"
|
|
1265
|
+
);
|
|
1266
|
+
if (matchingPlugins.length && !matchingMarkets.length)
|
|
1267
|
+
throw new Error(
|
|
1268
|
+
"PLUGIN_COLLISION: An existing Memroot plugin has no matching managed marketplace. Resolve it with the native plugin manager first."
|
|
1269
|
+
);
|
|
1270
|
+
for (const plugin of matchingPlugins) {
|
|
1271
|
+
if (plugin.enabled === false)
|
|
1272
|
+
throw new Error(
|
|
1273
|
+
`PLUGIN_DISABLED: Memroot is disabled in ${labels[agent]}. Enable it in the native plugin manager when ready; setup preserves your choice.`
|
|
1274
|
+
);
|
|
1275
|
+
if (plugin.enabled !== true || agent === "claude" && plugin.scope !== "user")
|
|
1276
|
+
throw new Error(
|
|
1277
|
+
"PLUGIN_COLLISION: Existing Memroot plugin status or scope cannot be safely managed. Check the native plugin manager."
|
|
1278
|
+
);
|
|
1279
|
+
}
|
|
1280
|
+
return {
|
|
1281
|
+
registered: matchingMarkets.length > 0,
|
|
1282
|
+
installed: matchingPlugins.length > 0
|
|
1283
|
+
};
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
// src/storage.ts
|
|
1287
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
1288
|
+
import {
|
|
1289
|
+
cp,
|
|
1290
|
+
lstat,
|
|
1291
|
+
mkdir,
|
|
1292
|
+
readdir,
|
|
1293
|
+
readFile,
|
|
1294
|
+
rename,
|
|
1295
|
+
rm,
|
|
1296
|
+
writeFile
|
|
1297
|
+
} from "node:fs/promises";
|
|
1298
|
+
import { homedir } from "node:os";
|
|
1299
|
+
import { dirname, isAbsolute as isAbsolute2, join as join2 } from "node:path";
|
|
1300
|
+
import { fileURLToPath } from "node:url";
|
|
1301
|
+
var version = "0.1.0-alpha.0";
|
|
1302
|
+
function dataDirectory() {
|
|
1303
|
+
const base = process.platform === "win32" ? process.env.LOCALAPPDATA ?? join2(homedir(), "AppData", "Local") : process.env.XDG_DATA_HOME ?? join2(homedir(), ".local", "share");
|
|
1304
|
+
if (!isAbsolute2(base))
|
|
1305
|
+
throw new Error(
|
|
1306
|
+
"INVALID_DATA_DIRECTORY: XDG_DATA_HOME or LOCALAPPDATA must be absolute."
|
|
1307
|
+
);
|
|
1308
|
+
return join2(base, "memroot");
|
|
1309
|
+
}
|
|
1310
|
+
async function exists(path) {
|
|
1311
|
+
try {
|
|
1312
|
+
await lstat(path);
|
|
1313
|
+
return true;
|
|
1314
|
+
} catch (error) {
|
|
1315
|
+
if (error.code === "ENOENT") return false;
|
|
1316
|
+
throw error;
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
async function safeDirectory(path) {
|
|
1320
|
+
const boundary = dataDirectory();
|
|
1321
|
+
if (path !== boundary && path.startsWith(`${boundary}/`))
|
|
1322
|
+
await safeDirectory(dirname(path));
|
|
1323
|
+
await mkdir(path, { recursive: true, mode: 448 });
|
|
1324
|
+
const info = await lstat(path);
|
|
1325
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
1326
|
+
throw new Error(`UNSAFE_PATH: Expected a real directory at ${path}.`);
|
|
1327
|
+
}
|
|
1328
|
+
async function fileEntries(root, prefix = "") {
|
|
1329
|
+
const directory = await lstat(join2(root, prefix));
|
|
1330
|
+
if (!directory.isDirectory() || directory.isSymbolicLink())
|
|
1331
|
+
throw new Error(
|
|
1332
|
+
"INTEGRITY_ERROR: Managed plugin directory is not a real directory."
|
|
1333
|
+
);
|
|
1334
|
+
const result = [];
|
|
1335
|
+
for (const name of (await readdir(join2(root, prefix))).sort()) {
|
|
1336
|
+
const path = join2(root, prefix, name);
|
|
1337
|
+
const info = await lstat(path);
|
|
1338
|
+
const key = join2(prefix, name);
|
|
1339
|
+
if (info.isSymbolicLink())
|
|
1340
|
+
throw new Error(
|
|
1341
|
+
"INTEGRITY_ERROR: Plugin assets must not contain symbolic links."
|
|
1342
|
+
);
|
|
1343
|
+
if (info.isDirectory()) result.push(...await fileEntries(root, key));
|
|
1344
|
+
else if (info.isFile()) result.push([key, await readFile(path)]);
|
|
1345
|
+
else throw new Error("INTEGRITY_ERROR: Unsupported plugin asset.");
|
|
1346
|
+
}
|
|
1347
|
+
return result;
|
|
1348
|
+
}
|
|
1349
|
+
async function integrity(root) {
|
|
1350
|
+
const hash = createHash("sha256");
|
|
1351
|
+
for (const [name, bytes] of await fileEntries(root))
|
|
1352
|
+
hash.update(name).update("\0").update(String(bytes.length)).update("\0").update(bytes);
|
|
1353
|
+
return hash.digest("hex");
|
|
1354
|
+
}
|
|
1355
|
+
async function readReceipt(data, agent) {
|
|
1356
|
+
const path = join2(data, "receipts", `${agent}.json`);
|
|
1357
|
+
if (!await exists(path)) return void 0;
|
|
1358
|
+
if (!(await lstat(path)).isFile() || (await lstat(path)).isSymbolicLink())
|
|
1359
|
+
throw new Error("INVALID_RECEIPT: Expected a regular receipt file.");
|
|
1360
|
+
const value = JSON.parse(await readFile(path, "utf8"));
|
|
1361
|
+
if (!value || typeof value !== "object")
|
|
1362
|
+
throw new Error("INVALID_RECEIPT: Cannot safely read installer state.");
|
|
1363
|
+
const receipt = value;
|
|
1364
|
+
if (receipt.schemaVersion !== 1 || receipt.agent !== agent || typeof receipt.version !== "string" || !/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(
|
|
1365
|
+
receipt.version
|
|
1366
|
+
) || typeof receipt.integrity !== "string" || !/^[a-f0-9]{64}$/.test(receipt.integrity) || receipt.marketplace !== join2(data, "releases", receipt.version, agent))
|
|
1367
|
+
throw new Error("INVALID_RECEIPT: Cannot safely read installer state.");
|
|
1368
|
+
return receipt;
|
|
1369
|
+
}
|
|
1370
|
+
async function verifyReceipt(receipt) {
|
|
1371
|
+
if (await integrity(receipt.marketplace) !== receipt.integrity)
|
|
1372
|
+
throw new Error(
|
|
1373
|
+
"INTEGRITY_ERROR: Managed plugin files were modified. Preserve your changes and reinstall from a clean managed directory."
|
|
1374
|
+
);
|
|
1375
|
+
}
|
|
1376
|
+
async function writeReceipt(data, receipt) {
|
|
1377
|
+
await safeDirectory(join2(data, "receipts"));
|
|
1378
|
+
const path = join2(data, "receipts", `${receipt.agent}.json`);
|
|
1379
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
1380
|
+
try {
|
|
1381
|
+
await writeFile(temporary, `${JSON.stringify(receipt, null, 2)}
|
|
1382
|
+
`, {
|
|
1383
|
+
flag: "wx",
|
|
1384
|
+
mode: 384
|
|
1385
|
+
});
|
|
1386
|
+
await rename(temporary, path);
|
|
1387
|
+
} finally {
|
|
1388
|
+
await rm(temporary, { force: true });
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
function marketplaceMetadata(agent) {
|
|
1392
|
+
if (agent === "codex")
|
|
1393
|
+
return {
|
|
1394
|
+
path: ".agents/plugins/marketplace.json",
|
|
1395
|
+
value: {
|
|
1396
|
+
name: "memroot",
|
|
1397
|
+
interface: { displayName: "Memroot" },
|
|
1398
|
+
plugins: [
|
|
1399
|
+
{
|
|
1400
|
+
name: "memroot",
|
|
1401
|
+
source: { source: "local", path: "./plugins/memroot" },
|
|
1402
|
+
policy: { installation: "AVAILABLE", authentication: "ON_USE" },
|
|
1403
|
+
category: "Productivity"
|
|
1404
|
+
}
|
|
1405
|
+
]
|
|
1406
|
+
}
|
|
1407
|
+
};
|
|
1408
|
+
return {
|
|
1409
|
+
path: ".claude-plugin/marketplace.json",
|
|
1410
|
+
value: {
|
|
1411
|
+
name: "memroot",
|
|
1412
|
+
owner: { name: "Memroot" },
|
|
1413
|
+
plugins: [
|
|
1414
|
+
{
|
|
1415
|
+
name: "memroot",
|
|
1416
|
+
source: "./plugins/memroot",
|
|
1417
|
+
description: "Memroot integration readiness and status",
|
|
1418
|
+
version
|
|
1419
|
+
}
|
|
1420
|
+
]
|
|
1421
|
+
}
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
async function stage(data, agent) {
|
|
1425
|
+
const releases = join2(data, "releases", version);
|
|
1426
|
+
await safeDirectory(releases);
|
|
1427
|
+
const target = join2(releases, agent);
|
|
1428
|
+
const temporary = join2(releases, `.${agent}-${randomUUID()}`);
|
|
1429
|
+
const source = fileURLToPath(new URL(`./plugins/${agent}/`, import.meta.url));
|
|
1430
|
+
await fileEntries(source);
|
|
1431
|
+
try {
|
|
1432
|
+
await mkdir(join2(temporary, "plugins"), { recursive: true, mode: 448 });
|
|
1433
|
+
await cp(source, join2(temporary, "plugins", "memroot"), {
|
|
1434
|
+
recursive: true,
|
|
1435
|
+
dereference: false
|
|
1436
|
+
});
|
|
1437
|
+
if (agent !== "grok") {
|
|
1438
|
+
const metadata = marketplaceMetadata(agent);
|
|
1439
|
+
await mkdir(dirname(join2(temporary, metadata.path)), { recursive: true });
|
|
1440
|
+
await writeFile(
|
|
1441
|
+
join2(temporary, metadata.path),
|
|
1442
|
+
`${JSON.stringify(metadata.value, null, 2)}
|
|
1443
|
+
`
|
|
1444
|
+
);
|
|
1445
|
+
}
|
|
1446
|
+
const digest = await integrity(temporary);
|
|
1447
|
+
if (await exists(target)) {
|
|
1448
|
+
if (await integrity(target) !== digest)
|
|
1449
|
+
throw new Error(
|
|
1450
|
+
"INTEGRITY_ERROR: Existing versioned plugin files differ from this package; refusing to overwrite."
|
|
1451
|
+
);
|
|
1452
|
+
} else await rename(temporary, target);
|
|
1453
|
+
return {
|
|
1454
|
+
schemaVersion: 1,
|
|
1455
|
+
agent,
|
|
1456
|
+
version,
|
|
1457
|
+
marketplace: target,
|
|
1458
|
+
integrity: digest
|
|
1459
|
+
};
|
|
1460
|
+
} finally {
|
|
1461
|
+
await rm(temporary, { recursive: true, force: true });
|
|
1462
|
+
}
|
|
1463
|
+
}
|
|
1464
|
+
async function acquireLock(data) {
|
|
1465
|
+
await safeDirectory(data);
|
|
1466
|
+
const lock = join2(data, ".setup-lock");
|
|
1467
|
+
try {
|
|
1468
|
+
await mkdir(lock, { mode: 448 });
|
|
1469
|
+
} catch (error) {
|
|
1470
|
+
if (error.code === "EEXIST")
|
|
1471
|
+
throw new Error(
|
|
1472
|
+
`SETUP_BUSY: Another setup owns ${lock}. Wait for it to finish. If it was interrupted, verify no memroot setup process remains before removing that lock directory.`
|
|
1473
|
+
);
|
|
1474
|
+
throw error;
|
|
1475
|
+
}
|
|
1476
|
+
await writeFile(
|
|
1477
|
+
join2(lock, "owner.json"),
|
|
1478
|
+
JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }),
|
|
1479
|
+
{ mode: 384 }
|
|
1480
|
+
);
|
|
1481
|
+
return async () => {
|
|
1482
|
+
await rm(lock, { recursive: true });
|
|
1483
|
+
};
|
|
1484
|
+
}
|
|
1485
|
+
|
|
1486
|
+
// src/index.ts
|
|
1487
|
+
var installationDocs = {
|
|
1488
|
+
claude: "https://code.claude.com/docs/en/quickstart",
|
|
1489
|
+
codex: "https://developers.openai.com/codex/cli",
|
|
1490
|
+
grok: "https://docs.x.ai/build/overview"
|
|
1491
|
+
};
|
|
1492
|
+
var setupComplete = "Plugins ready. Cloud memory is not connected.";
|
|
1493
|
+
var cloudStatus = "Cloud memory: not connected. This installer alpha does not provide cloud authentication, memory retrieval, or session upload.";
|
|
1494
|
+
var help = `Memroot ${version} \u2014 native agent plugin installer
|
|
1495
|
+
|
|
1496
|
+
Usage:
|
|
1497
|
+
npx memroot setup
|
|
1498
|
+
memroot setup --agent codex --yes
|
|
1499
|
+
memroot setup --agent claude --agent grok --yes --dry-run
|
|
1500
|
+
memroot doctor
|
|
1501
|
+
|
|
1502
|
+
Commands:
|
|
1503
|
+
setup Install native plugins for your user account
|
|
1504
|
+
doctor Check installer receipts and plugin file integrity
|
|
1505
|
+
|
|
1506
|
+
Options:
|
|
1507
|
+
--agent claude, codex, or grok; repeat to select more than one
|
|
1508
|
+
--yes Use the explicitly selected agents without interactive prompts
|
|
1509
|
+
--dry-run Show planned changes without running agent CLIs or writing files
|
|
1510
|
+
--help Show help
|
|
1511
|
+
--version Show version
|
|
1512
|
+
|
|
1513
|
+
${cloudStatus}
|
|
1514
|
+
Grok setup trusts the selected local plugin via its native --trust option.
|
|
1515
|
+
Hook execution trust remains controlled by each agent.
|
|
1516
|
+
`;
|
|
1517
|
+
function parse(args) {
|
|
1518
|
+
const command = args.shift();
|
|
1519
|
+
if (command !== "setup" && command !== "doctor")
|
|
1520
|
+
throw new Error(
|
|
1521
|
+
"INVALID_ARGUMENT: Choose setup or doctor. Run memroot --help."
|
|
1522
|
+
);
|
|
1523
|
+
const options = { command, selected: [], yes: false, dryRun: false };
|
|
1524
|
+
while (args.length) {
|
|
1525
|
+
const flag = args.shift();
|
|
1526
|
+
if (flag === "--yes") options.yes = true;
|
|
1527
|
+
else if (flag === "--dry-run") options.dryRun = true;
|
|
1528
|
+
else if (flag === "--agent") {
|
|
1529
|
+
const value = args.shift();
|
|
1530
|
+
if (!agents.includes(value))
|
|
1531
|
+
throw new Error("INVALID_AGENT: Use claude, codex, or grok.");
|
|
1532
|
+
if (!options.selected.includes(value))
|
|
1533
|
+
options.selected.push(value);
|
|
1534
|
+
} else
|
|
1535
|
+
throw new Error(
|
|
1536
|
+
`INVALID_ARGUMENT: Unknown option ${flag}. Run memroot --help.`
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
if (command === "doctor" && (options.yes || options.dryRun))
|
|
1540
|
+
throw new Error("INVALID_ARGUMENT: doctor supports only --agent.");
|
|
1541
|
+
return options;
|
|
1542
|
+
}
|
|
1543
|
+
async function doctor(selected) {
|
|
1544
|
+
const data = dataDirectory();
|
|
1545
|
+
let failures = 0;
|
|
1546
|
+
for (const agent of selected.length ? selected : agents) {
|
|
1547
|
+
const path = executable(agent);
|
|
1548
|
+
try {
|
|
1549
|
+
const receipt = await readReceipt(data, agent);
|
|
1550
|
+
if (!receipt) {
|
|
1551
|
+
console.log(
|
|
1552
|
+
`${labels[agent]}: no installation receipt; CLI ${path ? "detected" : "not found"}.`
|
|
1553
|
+
);
|
|
1554
|
+
continue;
|
|
1555
|
+
}
|
|
1556
|
+
await verifyReceipt(receipt);
|
|
1557
|
+
if (path) {
|
|
1558
|
+
const state = inspectNative(path, agent, receipt.marketplace);
|
|
1559
|
+
if (!state.installed)
|
|
1560
|
+
throw new Error(
|
|
1561
|
+
"PLUGIN_MISSING: Native plugin installation is absent. Run memroot setup again."
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
console.log(
|
|
1565
|
+
`${labels[agent]}: plugin files verified (${receipt.version}); CLI ${path ? "detected" : "not found"}. ${path ? "Native plugin present" : "Native presence not verified"}; hook execution trust remains controlled by the agent.`
|
|
1566
|
+
);
|
|
1567
|
+
if (!path) failures++;
|
|
1568
|
+
} catch (error) {
|
|
1569
|
+
failures++;
|
|
1570
|
+
console.error(
|
|
1571
|
+
`${labels[agent]}: ${error instanceof Error ? error.message : "check failed"}`
|
|
1572
|
+
);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
console.log(cloudStatus);
|
|
1576
|
+
if (failures) process.exitCode = 1;
|
|
1577
|
+
}
|
|
1578
|
+
async function setup(options) {
|
|
1579
|
+
if (process.platform !== "darwin" && process.platform !== "linux")
|
|
1580
|
+
throw new Error(
|
|
1581
|
+
"UNSUPPORTED_PLATFORM: This installer alpha supports macOS and Linux. Windows support is not available yet."
|
|
1582
|
+
);
|
|
1583
|
+
const found = new Map(agents.map((agent) => [agent, executable(agent)]));
|
|
1584
|
+
const interactive = Boolean(
|
|
1585
|
+
process.stdin.isTTY && process.stdout.isTTY && !options.yes && !options.dryRun
|
|
1586
|
+
);
|
|
1587
|
+
if (interactive) {
|
|
1588
|
+
intro(`Memroot ${version}`);
|
|
1589
|
+
note(
|
|
1590
|
+
"Install Memroot plugins for your coding agents.\nCloud memory connection is not available in this alpha.",
|
|
1591
|
+
"Set up your agents"
|
|
1592
|
+
);
|
|
1593
|
+
if (!options.selected.length) {
|
|
1594
|
+
const result = await multiselect({
|
|
1595
|
+
message: "Choose agents (Space to select, Enter to continue)",
|
|
1596
|
+
required: true,
|
|
1597
|
+
options: agents.map((agent) => ({
|
|
1598
|
+
value: agent,
|
|
1599
|
+
label: labels[agent],
|
|
1600
|
+
hint: found.get(agent) ? "CLI detected" : "CLI not found"
|
|
1601
|
+
})),
|
|
1602
|
+
initialValues: agents.filter((agent) => found.get(agent))
|
|
1603
|
+
});
|
|
1604
|
+
if (isCancel(result)) {
|
|
1605
|
+
cancel("Setup cancelled. No changes made.");
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
options.selected = result;
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
if (!options.selected.length)
|
|
1612
|
+
throw new Error(
|
|
1613
|
+
"AGENT_REQUIRED: Choose an agent with --agent codex (repeat for multiple agents). Use --yes for noninteractive setup."
|
|
1614
|
+
);
|
|
1615
|
+
for (const agent of options.selected)
|
|
1616
|
+
if (!found.get(agent))
|
|
1617
|
+
throw new Error(
|
|
1618
|
+
`AGENT_NOT_FOUND: ${labels[agent]} CLI is not on PATH. Install it from ${installationDocs[agent]}, then retry memroot setup --agent ${agent} --yes.`
|
|
1619
|
+
);
|
|
1620
|
+
if (!interactive && !options.yes && !options.dryRun)
|
|
1621
|
+
throw new Error(
|
|
1622
|
+
"CONFIRMATION_REQUIRED: Noninteractive setup requires --yes with explicit --agent selections."
|
|
1623
|
+
);
|
|
1624
|
+
const data = dataDirectory();
|
|
1625
|
+
const summary = `${options.selected.map((agent) => labels[agent]).join(", ")}
|
|
1626
|
+
User scope \xB7 ${data}
|
|
1627
|
+
${options.selected.includes("grok") ? "Grok: trust this local Memroot plugin using native --trust.\n" : ""}${cloudStatus}`;
|
|
1628
|
+
if (options.dryRun) {
|
|
1629
|
+
console.log(`Dry run \u2014 no changes
|
|
1630
|
+
${summary}`);
|
|
1631
|
+
for (const agent of options.selected)
|
|
1632
|
+
console.log(
|
|
1633
|
+
`${agent}: ${JSON.stringify(installCommands(agent, `${data}/releases/${version}/${agent}`))}`
|
|
1634
|
+
);
|
|
1635
|
+
return;
|
|
1636
|
+
}
|
|
1637
|
+
if (interactive) {
|
|
1638
|
+
note(summary, "Installation");
|
|
1639
|
+
const confirmed = await confirm({
|
|
1640
|
+
message: "Install these plugins?",
|
|
1641
|
+
initialValue: true
|
|
1642
|
+
});
|
|
1643
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
1644
|
+
cancel("Setup cancelled. No changes made.");
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
} else console.log(summary);
|
|
1648
|
+
for (const agent of options.selected)
|
|
1649
|
+
preflight(found.get(agent), agent);
|
|
1650
|
+
const release = await acquireLock(data);
|
|
1651
|
+
try {
|
|
1652
|
+
for (const agent of options.selected) {
|
|
1653
|
+
const receipt = await readReceipt(data, agent);
|
|
1654
|
+
if (receipt) await verifyReceipt(receipt);
|
|
1655
|
+
const candidate = await stage(data, agent);
|
|
1656
|
+
const state = inspectNative(
|
|
1657
|
+
found.get(agent),
|
|
1658
|
+
agent,
|
|
1659
|
+
candidate.marketplace,
|
|
1660
|
+
receipt?.marketplace
|
|
1661
|
+
);
|
|
1662
|
+
if (state.installed && receipt?.version === candidate.version && receipt.integrity === candidate.integrity) {
|
|
1663
|
+
console.log(
|
|
1664
|
+
`${labels[agent]}: already installed; plugin files verified. Check native enablement in the agent.`
|
|
1665
|
+
);
|
|
1666
|
+
continue;
|
|
1667
|
+
}
|
|
1668
|
+
const commands = installCommands(agent, candidate.marketplace);
|
|
1669
|
+
if (state.registered && (!receipt || receipt.marketplace === candidate.marketplace))
|
|
1670
|
+
commands.shift();
|
|
1671
|
+
for (const args of commands)
|
|
1672
|
+
native(found.get(agent), agent, args);
|
|
1673
|
+
await writeReceipt(data, candidate);
|
|
1674
|
+
console.log(
|
|
1675
|
+
`${labels[agent]}: plugin installed. Restart the agent to load it.`
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
} finally {
|
|
1679
|
+
await release();
|
|
1680
|
+
}
|
|
1681
|
+
if (interactive) outro(setupComplete);
|
|
1682
|
+
else console.log(setupComplete);
|
|
1683
|
+
}
|
|
1684
|
+
async function main() {
|
|
1685
|
+
const args = process.argv.slice(2);
|
|
1686
|
+
if (args.includes("--help") || args.length === 0) {
|
|
1687
|
+
console.log(help);
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
if (args.length === 1 && args[0] === "--version") {
|
|
1691
|
+
console.log(version);
|
|
1692
|
+
return;
|
|
1693
|
+
}
|
|
1694
|
+
const options = parse(args);
|
|
1695
|
+
if (options.command === "doctor") await doctor(options.selected);
|
|
1696
|
+
else await setup(options);
|
|
1697
|
+
}
|
|
1698
|
+
main().catch((error) => {
|
|
1699
|
+
console.error(
|
|
1700
|
+
error instanceof Error ? error.message : "SETUP_FAILED: Unexpected installer failure."
|
|
1701
|
+
);
|
|
1702
|
+
process.exitCode = 1;
|
|
1703
|
+
});
|