@bitfun-vsl/plugin 0.0.0-stage → 0.0.1
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/LICENSE +21 -0
- package/README.md +62 -3
- package/assets/bitfun/command/vsl/cr-health.md +5 -0
- package/assets/bitfun/command/vsl/review.md +5 -0
- package/assets/bitfun/command/vsl/trajectory.md +8 -0
- package/assets/build.json +4 -0
- package/assets/claude-code/.claude-plugin/plugin.json +5 -0
- package/assets/claude-code/.mcp.json +10 -0
- package/assets/claude-code/agents/vsl-trajectory.md +6 -0
- package/assets/claude-code/commands/cr-health.md +7 -0
- package/assets/claude-code/commands/review.md +7 -0
- package/assets/claude-code/commands/trajectory.md +10 -0
- package/assets/claude-code/scripts/mcp-server.js +741 -0
- package/assets/claude-code/skills/vsl-trajectory-analysis/SKILL.md +7 -0
- package/assets/deveco/skills/vsl-trajectory-analysis/SKILL.md +7 -0
- package/assets/install-manifest.json +58 -0
- package/assets/skills/vsl-trajectory-analysis/SKILL.md +7 -0
- package/dist/cli/index.d.ts +17 -0
- package/dist/cli/index.js +4576 -0
- package/dist/hosts/bitfun-kernel/commands.d.ts +26 -0
- package/dist/hosts/bitfun-kernel/plugin.d.ts +2 -0
- package/dist/hosts/bitfun-kernel/plugin.js +661 -0
- package/dist/hosts/claude-code/index.d.ts +1 -0
- package/dist/hosts/claude-code/index.js +680 -0
- package/dist/hosts/claude-code/mcp-server.d.ts +45 -0
- package/dist/hosts/deveco/plugin.d.ts +2 -0
- package/dist/hosts/deveco/plugin.js +659 -0
- package/dist/hosts/shared/opencode.d.ts +12 -0
- package/dist/hosts/shared/schema.d.ts +8 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +663 -0
- package/dist/install/config.d.ts +50 -0
- package/dist/install/index.d.ts +182 -0
- package/dist/install/resources.d.ts +7 -0
- package/dist/install/resources.js +590 -0
- package/dist/plugin/contracts.d.ts +63 -0
- package/dist/plugin/index.d.ts +19 -0
- package/dist/plugin/index.js +539 -0
- package/dist/plugin/modules/code-review/index.d.ts +4 -0
- package/dist/plugin/modules/code-review/runtime.d.ts +42 -0
- package/dist/plugin/modules/trajectory-analysis.d.ts +2 -0
- package/dist/plugin/registry.d.ts +16 -0
- package/dist/plugin/schema.d.ts +2 -0
- package/dist/runtime.d.ts +22 -0
- package/docs/code-review-integration.md +182 -0
- package/docs/init-installation.md +97 -0
- package/docs/plugin-design.md +391 -0
- package/package.json +74 -6
|
@@ -0,0 +1,4576 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
// @bun
|
|
3
|
+
var __create = Object.create;
|
|
4
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
|
+
var __defProp = Object.defineProperty;
|
|
6
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
function __accessProp(key) {
|
|
9
|
+
return this[key];
|
|
10
|
+
}
|
|
11
|
+
var __toESMCache_node;
|
|
12
|
+
var __toESMCache_esm;
|
|
13
|
+
var __toESM = (mod, isNodeMode, target) => {
|
|
14
|
+
var canCache = mod != null && typeof mod === "object";
|
|
15
|
+
if (canCache) {
|
|
16
|
+
var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
|
|
17
|
+
var cached = cache.get(mod);
|
|
18
|
+
if (cached)
|
|
19
|
+
return cached;
|
|
20
|
+
}
|
|
21
|
+
target = mod != null ? __create(__getProtoOf(mod)) : {};
|
|
22
|
+
const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
|
|
23
|
+
if (mod && typeof mod === "object" || typeof mod === "function") {
|
|
24
|
+
for (let key of __getOwnPropNames(mod))
|
|
25
|
+
if (!__hasOwnProp.call(to, key))
|
|
26
|
+
__defProp(to, key, {
|
|
27
|
+
get: __accessProp.bind(mod, key),
|
|
28
|
+
enumerable: true
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
if (canCache)
|
|
32
|
+
cache.set(mod, to);
|
|
33
|
+
return to;
|
|
34
|
+
};
|
|
35
|
+
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
|
|
36
|
+
var __returnValue = (v) => v;
|
|
37
|
+
function __exportSetter(name, newValue) {
|
|
38
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
39
|
+
}
|
|
40
|
+
var __export = (target, all) => {
|
|
41
|
+
for (var name in all)
|
|
42
|
+
__defProp(target, name, {
|
|
43
|
+
get: all[name],
|
|
44
|
+
enumerable: true,
|
|
45
|
+
configurable: true,
|
|
46
|
+
set: __exportSetter.bind(all, name)
|
|
47
|
+
});
|
|
48
|
+
};
|
|
49
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
50
|
+
var __require = import.meta.require;
|
|
51
|
+
|
|
52
|
+
// node_modules/cli-width/index.js
|
|
53
|
+
var require_cli_width = __commonJS(function(exports, module) {
|
|
54
|
+
module.exports = cliWidth;
|
|
55
|
+
function normalizeOpts(options) {
|
|
56
|
+
const defaultOpts = {
|
|
57
|
+
defaultWidth: 0,
|
|
58
|
+
output: process.stdout,
|
|
59
|
+
tty: __require("tty")
|
|
60
|
+
};
|
|
61
|
+
if (!options) {
|
|
62
|
+
return defaultOpts;
|
|
63
|
+
}
|
|
64
|
+
Object.keys(defaultOpts).forEach(function(key) {
|
|
65
|
+
if (!options[key]) {
|
|
66
|
+
options[key] = defaultOpts[key];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
return options;
|
|
70
|
+
}
|
|
71
|
+
function cliWidth(options) {
|
|
72
|
+
const opts = normalizeOpts(options);
|
|
73
|
+
if (opts.output.getWindowSize) {
|
|
74
|
+
return opts.output.getWindowSize()[0] || opts.defaultWidth;
|
|
75
|
+
}
|
|
76
|
+
if (opts.tty.getWindowSize) {
|
|
77
|
+
return opts.tty.getWindowSize()[1] || opts.defaultWidth;
|
|
78
|
+
}
|
|
79
|
+
if (opts.output.columns) {
|
|
80
|
+
return opts.output.columns;
|
|
81
|
+
}
|
|
82
|
+
if (process.env.CLI_WIDTH) {
|
|
83
|
+
const width = parseInt(process.env.CLI_WIDTH, 10);
|
|
84
|
+
if (!isNaN(width) && width !== 0) {
|
|
85
|
+
return width;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return opts.defaultWidth;
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
// node_modules/mute-stream/lib/index.js
|
|
93
|
+
var require_lib = __commonJS(function(exports, module) {
|
|
94
|
+
var Stream = __require("stream");
|
|
95
|
+
|
|
96
|
+
class MuteStream extends Stream {
|
|
97
|
+
#isTTY = null;
|
|
98
|
+
constructor(opts = {}) {
|
|
99
|
+
super(opts);
|
|
100
|
+
this.writable = this.readable = true;
|
|
101
|
+
this.muted = false;
|
|
102
|
+
this.on("pipe", this._onpipe);
|
|
103
|
+
this.replace = opts.replace;
|
|
104
|
+
this._prompt = opts.prompt || null;
|
|
105
|
+
this._hadControl = false;
|
|
106
|
+
}
|
|
107
|
+
#destSrc(key, def) {
|
|
108
|
+
if (this._dest) {
|
|
109
|
+
return this._dest[key];
|
|
110
|
+
}
|
|
111
|
+
if (this._src) {
|
|
112
|
+
return this._src[key];
|
|
113
|
+
}
|
|
114
|
+
return def;
|
|
115
|
+
}
|
|
116
|
+
#proxy(method, ...args) {
|
|
117
|
+
if (typeof this._dest?.[method] === "function") {
|
|
118
|
+
this._dest[method](...args);
|
|
119
|
+
}
|
|
120
|
+
if (typeof this._src?.[method] === "function") {
|
|
121
|
+
this._src[method](...args);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
get isTTY() {
|
|
125
|
+
if (this.#isTTY !== null) {
|
|
126
|
+
return this.#isTTY;
|
|
127
|
+
}
|
|
128
|
+
return this.#destSrc("isTTY", false);
|
|
129
|
+
}
|
|
130
|
+
set isTTY(val) {
|
|
131
|
+
this.#isTTY = val;
|
|
132
|
+
}
|
|
133
|
+
get rows() {
|
|
134
|
+
return this.#destSrc("rows");
|
|
135
|
+
}
|
|
136
|
+
get columns() {
|
|
137
|
+
return this.#destSrc("columns");
|
|
138
|
+
}
|
|
139
|
+
mute() {
|
|
140
|
+
this.muted = true;
|
|
141
|
+
}
|
|
142
|
+
unmute() {
|
|
143
|
+
this.muted = false;
|
|
144
|
+
}
|
|
145
|
+
_onpipe(src) {
|
|
146
|
+
this._src = src;
|
|
147
|
+
}
|
|
148
|
+
pipe(dest, options) {
|
|
149
|
+
this._dest = dest;
|
|
150
|
+
return super.pipe(dest, options);
|
|
151
|
+
}
|
|
152
|
+
pause() {
|
|
153
|
+
if (this._src) {
|
|
154
|
+
return this._src.pause();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
resume() {
|
|
158
|
+
if (this._src) {
|
|
159
|
+
return this._src.resume();
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
write(c) {
|
|
163
|
+
if (this.muted) {
|
|
164
|
+
if (!this.replace) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
if (c.match(/^\u001b/)) {
|
|
168
|
+
if (c.indexOf(this._prompt) === 0) {
|
|
169
|
+
c = c.slice(this._prompt.length);
|
|
170
|
+
c = c.replace(/./g, this.replace);
|
|
171
|
+
c = this._prompt + c;
|
|
172
|
+
}
|
|
173
|
+
this._hadControl = true;
|
|
174
|
+
return this.emit("data", c);
|
|
175
|
+
} else {
|
|
176
|
+
if (this._prompt && this._hadControl && c.indexOf(this._prompt) === 0) {
|
|
177
|
+
this._hadControl = false;
|
|
178
|
+
this.emit("data", this._prompt);
|
|
179
|
+
c = c.slice(this._prompt.length);
|
|
180
|
+
}
|
|
181
|
+
c = c.toString().replace(/./g, this.replace);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
this.emit("data", c);
|
|
185
|
+
}
|
|
186
|
+
end(c) {
|
|
187
|
+
if (this.muted) {
|
|
188
|
+
if (c && this.replace) {
|
|
189
|
+
c = c.toString().replace(/./g, this.replace);
|
|
190
|
+
} else {
|
|
191
|
+
c = null;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
if (c) {
|
|
195
|
+
this.emit("data", c);
|
|
196
|
+
}
|
|
197
|
+
this.emit("end");
|
|
198
|
+
}
|
|
199
|
+
destroy(...args) {
|
|
200
|
+
return this.#proxy("destroy", ...args);
|
|
201
|
+
}
|
|
202
|
+
destroySoon(...args) {
|
|
203
|
+
return this.#proxy("destroySoon", ...args);
|
|
204
|
+
}
|
|
205
|
+
close(...args) {
|
|
206
|
+
return this.#proxy("close", ...args);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
module.exports = MuteStream;
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// src/plugin/modules/code-review/runtime.ts
|
|
213
|
+
var exports_runtime = {};
|
|
214
|
+
__export(exports_runtime, {
|
|
215
|
+
runCr: () => runCr,
|
|
216
|
+
reviewResult: () => reviewResult,
|
|
217
|
+
review: () => review,
|
|
218
|
+
resolveCr: () => resolveCr,
|
|
219
|
+
health: () => health
|
|
220
|
+
});
|
|
221
|
+
import { spawn } from "child_process";
|
|
222
|
+
import { createWriteStream } from "fs";
|
|
223
|
+
import { access, mkdir, readFile, realpath, stat } from "fs/promises";
|
|
224
|
+
import { homedir } from "os";
|
|
225
|
+
import { delimiter, isAbsolute, join as join2, resolve as resolve2 } from "path";
|
|
226
|
+
import { pipeline } from "stream/promises";
|
|
227
|
+
async function review(input, context, options) {
|
|
228
|
+
if (Boolean(input.from) !== Boolean(input.to))
|
|
229
|
+
throw new Error("from and to must be provided together");
|
|
230
|
+
if (input.commit && (input.from || input.to))
|
|
231
|
+
throw new Error("commit cannot be combined with from/to");
|
|
232
|
+
if (input.preview && input.resume)
|
|
233
|
+
throw new Error("preview cannot be combined with resume");
|
|
234
|
+
if (input.resume && !input.commit && !input.from)
|
|
235
|
+
throw new Error("resume requires commit or from/to; workspace resume is not supported");
|
|
236
|
+
const directory = await realpath(resolve2(context.directory, input.repo ?? "."));
|
|
237
|
+
const args = ["review", "--repo", directory, "--audience", "agent", "--format", "json"];
|
|
238
|
+
const flags = {
|
|
239
|
+
commit: "commit",
|
|
240
|
+
from: "from",
|
|
241
|
+
to: "to",
|
|
242
|
+
resume: "resume",
|
|
243
|
+
background: "background",
|
|
244
|
+
backgroundFile: "background-file",
|
|
245
|
+
rule: "rule",
|
|
246
|
+
provider: "provider",
|
|
247
|
+
model: "model",
|
|
248
|
+
effort: "effort",
|
|
249
|
+
concurrency: "concurrency",
|
|
250
|
+
taskTimeoutMinutes: "timeout",
|
|
251
|
+
maxTokensBudget: "max-tokens-budget"
|
|
252
|
+
};
|
|
253
|
+
Object.entries(flags).forEach(([key, flag]) => {
|
|
254
|
+
const value = input[key];
|
|
255
|
+
if (value !== undefined)
|
|
256
|
+
args.push(`--${flag}`, String(value));
|
|
257
|
+
});
|
|
258
|
+
if (input.preview)
|
|
259
|
+
args.push("--preview");
|
|
260
|
+
if (input.exclude?.length)
|
|
261
|
+
args.push("--exclude", input.exclude.join(","));
|
|
262
|
+
context.report(input.preview ? "Previewing CR review scope" : "Running CR review");
|
|
263
|
+
const result = await runCr(await resolveCr(options.binary), args, {
|
|
264
|
+
directory,
|
|
265
|
+
signal: context.signal,
|
|
266
|
+
timeoutMs: (input.overallTimeoutMinutes ?? 60) * 60000,
|
|
267
|
+
cacheDirectory: options.cacheDirectory
|
|
268
|
+
});
|
|
269
|
+
return reviewResult(result, directory, input.preview);
|
|
270
|
+
}
|
|
271
|
+
async function reviewResult(result, directory, preview = false) {
|
|
272
|
+
const text = await readFile(result.resultFile, "utf8");
|
|
273
|
+
const parsed = await Promise.resolve().then(() => JSON.parse(text)).catch(() => {
|
|
274
|
+
return;
|
|
275
|
+
});
|
|
276
|
+
const payload = record(parsed);
|
|
277
|
+
const manifest = record(payload?.manifest);
|
|
278
|
+
const coverage = record(manifest?.coverage);
|
|
279
|
+
const terminal = manifest?.terminal_state;
|
|
280
|
+
const knownState = typeof terminal === "string" && ["complete", "partial", "failed", "skipped"].includes(terminal);
|
|
281
|
+
const validCoverage = ["selected", "completed", "reused", "failed", "waived"].every((key) => Array.isArray(coverage?.[key]));
|
|
282
|
+
const validReview = knownState && manifest?.schema_version === "cr.run-manifest/v1" && validCoverage && Array.isArray(payload?.comments);
|
|
283
|
+
const noFiles = !manifest && payload?.status === "skipped" && Array.isArray(payload.comments) && payload.comments.length === 0 && typeof payload.message === "string";
|
|
284
|
+
const validPreview = preview && typeof payload?.total_files === "number" && typeof payload.reviewable_count === "number" && Array.isArray(payload.files);
|
|
285
|
+
const diagnostic = (await readFile(result.stderrFile, "utf8")).slice(-4000);
|
|
286
|
+
const error = result.error || (result.exitCode !== 0 ? `CR exited with code ${result.exitCode}` : undefined) || (!(preview ? validPreview : validReview || noFiles) ? "CR returned empty, invalid, or incompatible JSON; review completion is unknown" : undefined);
|
|
287
|
+
const comments = Array.isArray(payload?.comments) ? payload.comments : [];
|
|
288
|
+
const metadata = {
|
|
289
|
+
repository: directory,
|
|
290
|
+
executable: result.executable,
|
|
291
|
+
exitCode: result.exitCode,
|
|
292
|
+
state: validReview ? terminal : !error && validPreview ? "preview" : !error && noFiles ? "skipped" : "error",
|
|
293
|
+
terminalState: knownState ? terminal : undefined,
|
|
294
|
+
message: typeof payload?.message === "string" ? payload.message.slice(0, 1000) : undefined,
|
|
295
|
+
sessionId: payload?.session_id,
|
|
296
|
+
resultFile: result.resultFile,
|
|
297
|
+
stderrFile: result.stderrFile
|
|
298
|
+
};
|
|
299
|
+
const output = JSON.stringify({
|
|
300
|
+
...metadata,
|
|
301
|
+
error,
|
|
302
|
+
...error ? { diagnostic } : {},
|
|
303
|
+
manifest,
|
|
304
|
+
summary: payload?.summary,
|
|
305
|
+
warnings: payload?.warnings,
|
|
306
|
+
resume: payload?.resume,
|
|
307
|
+
...preview ? { preview: payload } : {
|
|
308
|
+
findingsCount: comments.length,
|
|
309
|
+
comments: text.length > 48000 ? [] : comments.slice(0, 30),
|
|
310
|
+
findingsTruncated: comments.length > 30 || text.length > 48000
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
return {
|
|
314
|
+
title: error ? "CR execution failed" : preview ? "CR preview ready" : `CR review: ${metadata.state}`,
|
|
315
|
+
isError: Boolean(error || terminal === "failed"),
|
|
316
|
+
metadata,
|
|
317
|
+
output: output.length <= 64000 ? output : JSON.stringify({
|
|
318
|
+
...metadata,
|
|
319
|
+
error,
|
|
320
|
+
diagnostic: error ? diagnostic : undefined,
|
|
321
|
+
findingsCount: comments.length,
|
|
322
|
+
coverageCounts: Object.fromEntries(Object.entries(coverage ?? {}).filter(([, value]) => Array.isArray(value)).map(([key, value]) => [key, value.length])),
|
|
323
|
+
detailsTruncated: true,
|
|
324
|
+
findingsTruncated: !preview,
|
|
325
|
+
instruction: "Read resultFile in bounded batches for the complete review/preview, findings, warnings and coverage."
|
|
326
|
+
})
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
async function health(input, context, options) {
|
|
330
|
+
const executable = await resolveCr(options.binary);
|
|
331
|
+
const version = await runCr(executable, ["version"], { directory: context.directory, signal: context.signal, timeoutMs: 30000, cacheDirectory: options.cacheDirectory });
|
|
332
|
+
const help = await runCr(executable, ["review", "--help"], { directory: context.directory, signal: context.signal, timeoutMs: 30000, cacheDirectory: options.cacheDirectory });
|
|
333
|
+
const helpText = await readFile(help.resultFile, "utf8");
|
|
334
|
+
const compatible = ["--format", "--audience", "--preview", "--resume", "--max-tokens-budget"].every((flag) => helpText.includes(flag));
|
|
335
|
+
const connection = input.checkConnection ? await runCr(executable, ["llm", "test"], {
|
|
336
|
+
directory: context.directory,
|
|
337
|
+
signal: context.signal,
|
|
338
|
+
timeoutMs: 120000,
|
|
339
|
+
cacheDirectory: options.cacheDirectory
|
|
340
|
+
}) : undefined;
|
|
341
|
+
const isError = !compatible || [version, help, ...connection ? [connection] : []].some((item) => item.error || item.exitCode !== 0);
|
|
342
|
+
return {
|
|
343
|
+
title: isError ? "CR health check failed" : "CR is available",
|
|
344
|
+
isError,
|
|
345
|
+
output: JSON.stringify({
|
|
346
|
+
executable,
|
|
347
|
+
version: (await readFile(version.resultFile, "utf8")).trim(),
|
|
348
|
+
cliFlagsCompatible: compatible,
|
|
349
|
+
manifestCompatibility: "Validated against cr.run-manifest/v1 when an actual review runs",
|
|
350
|
+
modelConnection: connection ? { exitCode: connection.exitCode, error: connection.error, output: (await readFile(connection.resultFile, "utf8")).trim(), stderrFile: connection.stderrFile } : "not checked",
|
|
351
|
+
diagnostics: [version, help]
|
|
352
|
+
})
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
async function resolveCr(binary = process.env.VSL_CR_BIN) {
|
|
356
|
+
if (binary) {
|
|
357
|
+
if (!isAbsolute(binary))
|
|
358
|
+
throw new Error("VSL_CR_BIN must be an absolute path to the native CR executable");
|
|
359
|
+
if (/\.(cmd|bat|ps1|js)$/i.test(binary))
|
|
360
|
+
throw new Error("VSL_CR_BIN must point to the native executable, not a shell or npm shim");
|
|
361
|
+
await access(binary);
|
|
362
|
+
return realpath(binary);
|
|
363
|
+
}
|
|
364
|
+
const names = process.platform === "win32" ? ["cr.exe"] : ["cr"];
|
|
365
|
+
const candidates = (process.env.PATH ?? "").split(delimiter).filter(Boolean).flatMap((directory) => names.map((name) => join2(directory, name)));
|
|
366
|
+
const found = await Promise.all(candidates.map(async (path2) => await access(path2).then(() => path2, () => {
|
|
367
|
+
return;
|
|
368
|
+
})));
|
|
369
|
+
const executable = found.find((path2) => path2 !== undefined);
|
|
370
|
+
if (!executable)
|
|
371
|
+
throw new Error("CR native executable not found. Install/build the review CLI and set VSL_CR_BIN to its absolute executable path.");
|
|
372
|
+
return realpath(executable);
|
|
373
|
+
}
|
|
374
|
+
async function runCr(executable, args, options) {
|
|
375
|
+
options.signal.throwIfAborted();
|
|
376
|
+
const directory = join2(options.cacheDirectory ?? process.env.VSL_CR_CACHE_DIR ?? join2(process.env.LOCALAPPDATA ?? process.env.XDG_CACHE_HOME ?? join2(homedir(), ".cache"), "vsl", "cr"), crypto.randomUUID());
|
|
377
|
+
await mkdir(directory, { recursive: true, mode: 448 });
|
|
378
|
+
const resultFile = join2(directory, "result.json");
|
|
379
|
+
const stderrFile = join2(directory, "stderr.log");
|
|
380
|
+
const child = spawn(executable, args, {
|
|
381
|
+
cwd: options.directory,
|
|
382
|
+
env: { ...process.env, CR_NO_UPDATE: "1" },
|
|
383
|
+
shell: false,
|
|
384
|
+
detached: process.platform !== "win32",
|
|
385
|
+
windowsHide: true,
|
|
386
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
387
|
+
});
|
|
388
|
+
let error;
|
|
389
|
+
let closed = false;
|
|
390
|
+
let forceTimer;
|
|
391
|
+
const kill = () => {
|
|
392
|
+
if (closed || !child.pid)
|
|
393
|
+
return;
|
|
394
|
+
if (process.platform === "win32") {
|
|
395
|
+
spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { windowsHide: true, stdio: "ignore" }).on("error", () => child.kill("SIGKILL"));
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
process.kill(-child.pid, "SIGTERM");
|
|
400
|
+
} catch {
|
|
401
|
+
child.kill("SIGTERM");
|
|
402
|
+
}
|
|
403
|
+
forceTimer = setTimeout(() => {
|
|
404
|
+
if (!closed && child.pid) {
|
|
405
|
+
try {
|
|
406
|
+
process.kill(-child.pid, "SIGKILL");
|
|
407
|
+
} catch {
|
|
408
|
+
child.kill("SIGKILL");
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}, 3000);
|
|
412
|
+
};
|
|
413
|
+
const stop = (message) => {
|
|
414
|
+
if (error)
|
|
415
|
+
return;
|
|
416
|
+
error = message;
|
|
417
|
+
kill();
|
|
418
|
+
};
|
|
419
|
+
const abort = () => stop("CR execution cancelled");
|
|
420
|
+
const timer = setTimeout(() => stop("CR overall execution deadline exceeded"), options.timeoutMs);
|
|
421
|
+
options.signal.addEventListener("abort", abort, { once: true });
|
|
422
|
+
if (options.signal.aborted)
|
|
423
|
+
abort();
|
|
424
|
+
child.on("error", (cause) => {
|
|
425
|
+
error ??= `Cannot start CR: ${cause.message}`;
|
|
426
|
+
});
|
|
427
|
+
const streams = Promise.all([
|
|
428
|
+
pipeline(child.stdout, createWriteStream(resultFile, { mode: 384 })),
|
|
429
|
+
pipeline(child.stderr, createWriteStream(stderrFile, { mode: 384 }))
|
|
430
|
+
]).catch((cause) => stop(`Cannot save CR output: ${cause instanceof Error ? cause.message : String(cause)}`));
|
|
431
|
+
let outputBytes = 0;
|
|
432
|
+
[child.stdout, child.stderr].forEach((stream) => stream.on("data", (chunk) => {
|
|
433
|
+
outputBytes += chunk.length;
|
|
434
|
+
if (outputBytes > 32 * 1024 * 1024)
|
|
435
|
+
stop("CR output exceeds 32 MiB; partial evidence retained on disk");
|
|
436
|
+
}));
|
|
437
|
+
const exitCode = await new Promise((done) => child.once("close", (code) => {
|
|
438
|
+
closed = true;
|
|
439
|
+
clearTimeout(timer);
|
|
440
|
+
clearTimeout(forceTimer);
|
|
441
|
+
options.signal.removeEventListener("abort", abort);
|
|
442
|
+
done(code);
|
|
443
|
+
}));
|
|
444
|
+
await streams;
|
|
445
|
+
const size = (await stat(resultFile)).size;
|
|
446
|
+
if (size > 32 * 1024 * 1024)
|
|
447
|
+
throw new Error(`CR JSON exceeds the 32 MiB parsing limit; full output: ${resultFile}; stderr: ${stderrFile}`);
|
|
448
|
+
return { executable, exitCode, resultFile, stderrFile, error };
|
|
449
|
+
}
|
|
450
|
+
function record(value) {
|
|
451
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : undefined;
|
|
452
|
+
}
|
|
453
|
+
var init_runtime = () => {};
|
|
454
|
+
|
|
455
|
+
// node_modules/@inquirer/core/dist/lib/key.js
|
|
456
|
+
var keybindings = ["emacs", "vim"];
|
|
457
|
+
var keybindingLookup = new Set(keybindings);
|
|
458
|
+
function isKeybinding(value) {
|
|
459
|
+
return keybindingLookup.has(value);
|
|
460
|
+
}
|
|
461
|
+
function getDefaultKeybindings() {
|
|
462
|
+
const env = process.env["INQUIRER_KEYBINDINGS"];
|
|
463
|
+
if (!env)
|
|
464
|
+
return [];
|
|
465
|
+
return Array.from(new Set(env.toLowerCase().split(/[\s,]+/).filter(isKeybinding)));
|
|
466
|
+
}
|
|
467
|
+
var isUpKey = (key, keybindings2 = []) => key.name === "up" || keybindings2.includes("vim") && key.name === "k" || keybindings2.includes("emacs") && key.ctrl && key.name === "p";
|
|
468
|
+
var isDownKey = (key, keybindings2 = []) => key.name === "down" || keybindings2.includes("vim") && key.name === "j" || keybindings2.includes("emacs") && key.ctrl && key.name === "n";
|
|
469
|
+
var isSpaceKey = (key) => key.name === "space";
|
|
470
|
+
var isTabKey = (key) => key.name === "tab";
|
|
471
|
+
var isNumberKey = (key) => "1234567890".includes(key.name);
|
|
472
|
+
var isEnterKey = (key) => key.name === "enter" || key.name === "return";
|
|
473
|
+
// node_modules/@inquirer/core/dist/lib/errors.js
|
|
474
|
+
class AbortPromptError extends Error {
|
|
475
|
+
name = "AbortPromptError";
|
|
476
|
+
message = "Prompt was aborted";
|
|
477
|
+
constructor(options) {
|
|
478
|
+
super();
|
|
479
|
+
this.cause = options?.cause;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
class CancelPromptError extends Error {
|
|
484
|
+
name = "CancelPromptError";
|
|
485
|
+
message = "Prompt was canceled";
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
class ExitPromptError extends Error {
|
|
489
|
+
name = "ExitPromptError";
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
class HookError extends Error {
|
|
493
|
+
name = "HookError";
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
class ValidationError extends Error {
|
|
497
|
+
name = "ValidationError";
|
|
498
|
+
}
|
|
499
|
+
// node_modules/@inquirer/core/dist/lib/use-state.js
|
|
500
|
+
import { AsyncResource as AsyncResource2 } from "async_hooks";
|
|
501
|
+
|
|
502
|
+
// node_modules/@inquirer/core/dist/lib/hook-engine.js
|
|
503
|
+
import { AsyncLocalStorage, AsyncResource } from "async_hooks";
|
|
504
|
+
var hookStorage = new AsyncLocalStorage;
|
|
505
|
+
function createStore(rl) {
|
|
506
|
+
const store = {
|
|
507
|
+
rl,
|
|
508
|
+
hooks: [],
|
|
509
|
+
hooksCleanup: [],
|
|
510
|
+
hooksEffect: [],
|
|
511
|
+
index: 0,
|
|
512
|
+
handleChange() {}
|
|
513
|
+
};
|
|
514
|
+
return store;
|
|
515
|
+
}
|
|
516
|
+
function withHooks(rl, cb) {
|
|
517
|
+
const store = createStore(rl);
|
|
518
|
+
function cycle(render) {
|
|
519
|
+
store.handleChange = () => {
|
|
520
|
+
store.index = 0;
|
|
521
|
+
render();
|
|
522
|
+
};
|
|
523
|
+
store.handleChange();
|
|
524
|
+
}
|
|
525
|
+
return hookStorage.run(store, () => cb(cycle));
|
|
526
|
+
}
|
|
527
|
+
function getStore() {
|
|
528
|
+
const store = hookStorage.getStore();
|
|
529
|
+
if (!store) {
|
|
530
|
+
throw new HookError("[Inquirer] Hook functions can only be called from within a prompt");
|
|
531
|
+
}
|
|
532
|
+
return store;
|
|
533
|
+
}
|
|
534
|
+
function readline() {
|
|
535
|
+
return getStore().rl;
|
|
536
|
+
}
|
|
537
|
+
function withUpdates(fn) {
|
|
538
|
+
const wrapped = (...args) => {
|
|
539
|
+
const store = getStore();
|
|
540
|
+
let shouldUpdate = false;
|
|
541
|
+
const oldHandleChange = store.handleChange;
|
|
542
|
+
store.handleChange = () => {
|
|
543
|
+
shouldUpdate = true;
|
|
544
|
+
};
|
|
545
|
+
const returnValue = fn(...args);
|
|
546
|
+
if (shouldUpdate) {
|
|
547
|
+
oldHandleChange();
|
|
548
|
+
}
|
|
549
|
+
store.handleChange = oldHandleChange;
|
|
550
|
+
return returnValue;
|
|
551
|
+
};
|
|
552
|
+
return AsyncResource.bind(wrapped);
|
|
553
|
+
}
|
|
554
|
+
function withPointer(cb) {
|
|
555
|
+
const store = getStore();
|
|
556
|
+
const { index } = store;
|
|
557
|
+
const pointer = {
|
|
558
|
+
get() {
|
|
559
|
+
return store.hooks[index];
|
|
560
|
+
},
|
|
561
|
+
set(value) {
|
|
562
|
+
store.hooks[index] = value;
|
|
563
|
+
},
|
|
564
|
+
initialized: index in store.hooks
|
|
565
|
+
};
|
|
566
|
+
const returnValue = cb(pointer);
|
|
567
|
+
store.index++;
|
|
568
|
+
return returnValue;
|
|
569
|
+
}
|
|
570
|
+
function handleChange() {
|
|
571
|
+
getStore().handleChange();
|
|
572
|
+
}
|
|
573
|
+
var effectScheduler = {
|
|
574
|
+
queue(cb) {
|
|
575
|
+
const store = getStore();
|
|
576
|
+
const { index } = store;
|
|
577
|
+
store.hooksEffect.push(() => {
|
|
578
|
+
store.hooksCleanup[index]?.();
|
|
579
|
+
const cleanFn = cb(readline());
|
|
580
|
+
if (cleanFn != null && typeof cleanFn !== "function") {
|
|
581
|
+
throw new ValidationError("useEffect return value must be a cleanup function or nothing.");
|
|
582
|
+
}
|
|
583
|
+
store.hooksCleanup[index] = cleanFn;
|
|
584
|
+
});
|
|
585
|
+
},
|
|
586
|
+
run() {
|
|
587
|
+
const store = getStore();
|
|
588
|
+
withUpdates(() => {
|
|
589
|
+
store.hooksEffect.forEach((effect) => {
|
|
590
|
+
effect();
|
|
591
|
+
});
|
|
592
|
+
store.hooksEffect.length = 0;
|
|
593
|
+
})();
|
|
594
|
+
},
|
|
595
|
+
clearAll() {
|
|
596
|
+
const store = getStore();
|
|
597
|
+
store.hooksCleanup.forEach((cleanFn) => {
|
|
598
|
+
cleanFn?.();
|
|
599
|
+
});
|
|
600
|
+
store.hooksEffect.length = 0;
|
|
601
|
+
store.hooksCleanup.length = 0;
|
|
602
|
+
}
|
|
603
|
+
};
|
|
604
|
+
|
|
605
|
+
// node_modules/@inquirer/core/dist/lib/use-state.js
|
|
606
|
+
function isFactory(value) {
|
|
607
|
+
return typeof value === "function";
|
|
608
|
+
}
|
|
609
|
+
function isReducer(value) {
|
|
610
|
+
return typeof value === "function";
|
|
611
|
+
}
|
|
612
|
+
function useState(defaultValue) {
|
|
613
|
+
return withPointer((pointer) => {
|
|
614
|
+
const setState = AsyncResource2.bind(function setState2(newValue) {
|
|
615
|
+
const currentValue = pointer.get();
|
|
616
|
+
const nextValue = isReducer(newValue) ? newValue(currentValue) : newValue;
|
|
617
|
+
if (!Object.is(currentValue, nextValue)) {
|
|
618
|
+
pointer.set(nextValue);
|
|
619
|
+
handleChange();
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
if (pointer.initialized) {
|
|
623
|
+
return [pointer.get(), setState];
|
|
624
|
+
}
|
|
625
|
+
const value = isFactory(defaultValue) ? defaultValue() : defaultValue;
|
|
626
|
+
pointer.set(value);
|
|
627
|
+
return [value, setState];
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
// node_modules/@inquirer/core/dist/lib/use-effect.js
|
|
632
|
+
function useEffect(cb, depArray) {
|
|
633
|
+
withPointer((pointer) => {
|
|
634
|
+
const oldDeps = pointer.get();
|
|
635
|
+
const hasChanged = !Array.isArray(oldDeps) || depArray.some((dep, i) => !Object.is(dep, oldDeps[i]));
|
|
636
|
+
if (hasChanged) {
|
|
637
|
+
effectScheduler.queue(cb);
|
|
638
|
+
}
|
|
639
|
+
pointer.set(depArray);
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// node_modules/@inquirer/core/dist/lib/theme.js
|
|
644
|
+
import { styleText } from "util";
|
|
645
|
+
|
|
646
|
+
// node_modules/@inquirer/figures/dist/index.js
|
|
647
|
+
import process2 from "process";
|
|
648
|
+
function isUnicodeSupported() {
|
|
649
|
+
if (!process2.platform.startsWith("win")) {
|
|
650
|
+
return process2.env["TERM"] !== "linux";
|
|
651
|
+
}
|
|
652
|
+
return Boolean(process2.env["CI"]) || Boolean(process2.env["WT_SESSION"]) || Boolean(process2.env["TERMINUS_SUBLIME"]) || process2.env["ConEmuTask"] === "{cmd::Cmder}" || process2.env["TERM_PROGRAM"] === "Terminus-Sublime" || process2.env["TERM_PROGRAM"] === "vscode" || process2.env["TERM"] === "xterm-256color" || process2.env["TERM"] === "alacritty" || process2.env["TERMINAL_EMULATOR"] === "JetBrains-JediTerm";
|
|
653
|
+
}
|
|
654
|
+
var common = {
|
|
655
|
+
circleQuestionMark: "(?)",
|
|
656
|
+
questionMarkPrefix: "(?)",
|
|
657
|
+
square: "\u2588",
|
|
658
|
+
squareDarkShade: "\u2593",
|
|
659
|
+
squareMediumShade: "\u2592",
|
|
660
|
+
squareLightShade: "\u2591",
|
|
661
|
+
squareTop: "\u2580",
|
|
662
|
+
squareBottom: "\u2584",
|
|
663
|
+
squareLeft: "\u258C",
|
|
664
|
+
squareRight: "\u2590",
|
|
665
|
+
squareCenter: "\u25A0",
|
|
666
|
+
bullet: "\u25CF",
|
|
667
|
+
dot: "\u2024",
|
|
668
|
+
ellipsis: "\u2026",
|
|
669
|
+
pointerSmall: "\u203A",
|
|
670
|
+
triangleUp: "\u25B2",
|
|
671
|
+
triangleUpSmall: "\u25B4",
|
|
672
|
+
triangleDown: "\u25BC",
|
|
673
|
+
triangleDownSmall: "\u25BE",
|
|
674
|
+
triangleLeftSmall: "\u25C2",
|
|
675
|
+
triangleRightSmall: "\u25B8",
|
|
676
|
+
home: "\u2302",
|
|
677
|
+
heart: "\u2665",
|
|
678
|
+
musicNote: "\u266A",
|
|
679
|
+
musicNoteBeamed: "\u266B",
|
|
680
|
+
arrowUp: "\u2191",
|
|
681
|
+
arrowDown: "\u2193",
|
|
682
|
+
arrowLeft: "\u2190",
|
|
683
|
+
arrowRight: "\u2192",
|
|
684
|
+
arrowLeftRight: "\u2194",
|
|
685
|
+
arrowUpDown: "\u2195",
|
|
686
|
+
almostEqual: "\u2248",
|
|
687
|
+
notEqual: "\u2260",
|
|
688
|
+
lessOrEqual: "\u2264",
|
|
689
|
+
greaterOrEqual: "\u2265",
|
|
690
|
+
identical: "\u2261",
|
|
691
|
+
infinity: "\u221E",
|
|
692
|
+
subscriptZero: "\u2080",
|
|
693
|
+
subscriptOne: "\u2081",
|
|
694
|
+
subscriptTwo: "\u2082",
|
|
695
|
+
subscriptThree: "\u2083",
|
|
696
|
+
subscriptFour: "\u2084",
|
|
697
|
+
subscriptFive: "\u2085",
|
|
698
|
+
subscriptSix: "\u2086",
|
|
699
|
+
subscriptSeven: "\u2087",
|
|
700
|
+
subscriptEight: "\u2088",
|
|
701
|
+
subscriptNine: "\u2089",
|
|
702
|
+
oneHalf: "\xBD",
|
|
703
|
+
oneThird: "\u2153",
|
|
704
|
+
oneQuarter: "\xBC",
|
|
705
|
+
oneFifth: "\u2155",
|
|
706
|
+
oneSixth: "\u2159",
|
|
707
|
+
oneEighth: "\u215B",
|
|
708
|
+
twoThirds: "\u2154",
|
|
709
|
+
twoFifths: "\u2156",
|
|
710
|
+
threeQuarters: "\xBE",
|
|
711
|
+
threeFifths: "\u2157",
|
|
712
|
+
threeEighths: "\u215C",
|
|
713
|
+
fourFifths: "\u2158",
|
|
714
|
+
fiveSixths: "\u215A",
|
|
715
|
+
fiveEighths: "\u215D",
|
|
716
|
+
sevenEighths: "\u215E",
|
|
717
|
+
line: "\u2500",
|
|
718
|
+
lineBold: "\u2501",
|
|
719
|
+
lineDouble: "\u2550",
|
|
720
|
+
lineDashed0: "\u2504",
|
|
721
|
+
lineDashed1: "\u2505",
|
|
722
|
+
lineDashed2: "\u2508",
|
|
723
|
+
lineDashed3: "\u2509",
|
|
724
|
+
lineDashed4: "\u254C",
|
|
725
|
+
lineDashed5: "\u254D",
|
|
726
|
+
lineDashed6: "\u2574",
|
|
727
|
+
lineDashed7: "\u2576",
|
|
728
|
+
lineDashed8: "\u2578",
|
|
729
|
+
lineDashed9: "\u257A",
|
|
730
|
+
lineDashed10: "\u257C",
|
|
731
|
+
lineDashed11: "\u257E",
|
|
732
|
+
lineDashed12: "\u2212",
|
|
733
|
+
lineDashed13: "\u2013",
|
|
734
|
+
lineDashed14: "\u2010",
|
|
735
|
+
lineDashed15: "\u2043",
|
|
736
|
+
lineVertical: "\u2502",
|
|
737
|
+
lineVerticalBold: "\u2503",
|
|
738
|
+
lineVerticalDouble: "\u2551",
|
|
739
|
+
lineVerticalDashed0: "\u2506",
|
|
740
|
+
lineVerticalDashed1: "\u2507",
|
|
741
|
+
lineVerticalDashed2: "\u250A",
|
|
742
|
+
lineVerticalDashed3: "\u250B",
|
|
743
|
+
lineVerticalDashed4: "\u254E",
|
|
744
|
+
lineVerticalDashed5: "\u254F",
|
|
745
|
+
lineVerticalDashed6: "\u2575",
|
|
746
|
+
lineVerticalDashed7: "\u2577",
|
|
747
|
+
lineVerticalDashed8: "\u2579",
|
|
748
|
+
lineVerticalDashed9: "\u257B",
|
|
749
|
+
lineVerticalDashed10: "\u257D",
|
|
750
|
+
lineVerticalDashed11: "\u257F",
|
|
751
|
+
lineDownLeft: "\u2510",
|
|
752
|
+
lineDownLeftArc: "\u256E",
|
|
753
|
+
lineDownBoldLeftBold: "\u2513",
|
|
754
|
+
lineDownBoldLeft: "\u2512",
|
|
755
|
+
lineDownLeftBold: "\u2511",
|
|
756
|
+
lineDownDoubleLeftDouble: "\u2557",
|
|
757
|
+
lineDownDoubleLeft: "\u2556",
|
|
758
|
+
lineDownLeftDouble: "\u2555",
|
|
759
|
+
lineDownRight: "\u250C",
|
|
760
|
+
lineDownRightArc: "\u256D",
|
|
761
|
+
lineDownBoldRightBold: "\u250F",
|
|
762
|
+
lineDownBoldRight: "\u250E",
|
|
763
|
+
lineDownRightBold: "\u250D",
|
|
764
|
+
lineDownDoubleRightDouble: "\u2554",
|
|
765
|
+
lineDownDoubleRight: "\u2553",
|
|
766
|
+
lineDownRightDouble: "\u2552",
|
|
767
|
+
lineUpLeft: "\u2518",
|
|
768
|
+
lineUpLeftArc: "\u256F",
|
|
769
|
+
lineUpBoldLeftBold: "\u251B",
|
|
770
|
+
lineUpBoldLeft: "\u251A",
|
|
771
|
+
lineUpLeftBold: "\u2519",
|
|
772
|
+
lineUpDoubleLeftDouble: "\u255D",
|
|
773
|
+
lineUpDoubleLeft: "\u255C",
|
|
774
|
+
lineUpLeftDouble: "\u255B",
|
|
775
|
+
lineUpRight: "\u2514",
|
|
776
|
+
lineUpRightArc: "\u2570",
|
|
777
|
+
lineUpBoldRightBold: "\u2517",
|
|
778
|
+
lineUpBoldRight: "\u2516",
|
|
779
|
+
lineUpRightBold: "\u2515",
|
|
780
|
+
lineUpDoubleRightDouble: "\u255A",
|
|
781
|
+
lineUpDoubleRight: "\u2559",
|
|
782
|
+
lineUpRightDouble: "\u2558",
|
|
783
|
+
lineUpDownLeft: "\u2524",
|
|
784
|
+
lineUpBoldDownBoldLeftBold: "\u252B",
|
|
785
|
+
lineUpBoldDownBoldLeft: "\u2528",
|
|
786
|
+
lineUpDownLeftBold: "\u2525",
|
|
787
|
+
lineUpBoldDownLeftBold: "\u2529",
|
|
788
|
+
lineUpDownBoldLeftBold: "\u252A",
|
|
789
|
+
lineUpDownBoldLeft: "\u2527",
|
|
790
|
+
lineUpBoldDownLeft: "\u2526",
|
|
791
|
+
lineUpDoubleDownDoubleLeftDouble: "\u2563",
|
|
792
|
+
lineUpDoubleDownDoubleLeft: "\u2562",
|
|
793
|
+
lineUpDownLeftDouble: "\u2561",
|
|
794
|
+
lineUpDownRight: "\u251C",
|
|
795
|
+
lineUpBoldDownBoldRightBold: "\u2523",
|
|
796
|
+
lineUpBoldDownBoldRight: "\u2520",
|
|
797
|
+
lineUpDownRightBold: "\u251D",
|
|
798
|
+
lineUpBoldDownRightBold: "\u2521",
|
|
799
|
+
lineUpDownBoldRightBold: "\u2522",
|
|
800
|
+
lineUpDownBoldRight: "\u251F",
|
|
801
|
+
lineUpBoldDownRight: "\u251E",
|
|
802
|
+
lineUpDoubleDownDoubleRightDouble: "\u2560",
|
|
803
|
+
lineUpDoubleDownDoubleRight: "\u255F",
|
|
804
|
+
lineUpDownRightDouble: "\u255E",
|
|
805
|
+
lineDownLeftRight: "\u252C",
|
|
806
|
+
lineDownBoldLeftBoldRightBold: "\u2533",
|
|
807
|
+
lineDownLeftBoldRightBold: "\u252F",
|
|
808
|
+
lineDownBoldLeftRight: "\u2530",
|
|
809
|
+
lineDownBoldLeftBoldRight: "\u2531",
|
|
810
|
+
lineDownBoldLeftRightBold: "\u2532",
|
|
811
|
+
lineDownLeftRightBold: "\u252E",
|
|
812
|
+
lineDownLeftBoldRight: "\u252D",
|
|
813
|
+
lineDownDoubleLeftDoubleRightDouble: "\u2566",
|
|
814
|
+
lineDownDoubleLeftRight: "\u2565",
|
|
815
|
+
lineDownLeftDoubleRightDouble: "\u2564",
|
|
816
|
+
lineUpLeftRight: "\u2534",
|
|
817
|
+
lineUpBoldLeftBoldRightBold: "\u253B",
|
|
818
|
+
lineUpLeftBoldRightBold: "\u2537",
|
|
819
|
+
lineUpBoldLeftRight: "\u2538",
|
|
820
|
+
lineUpBoldLeftBoldRight: "\u2539",
|
|
821
|
+
lineUpBoldLeftRightBold: "\u253A",
|
|
822
|
+
lineUpLeftRightBold: "\u2536",
|
|
823
|
+
lineUpLeftBoldRight: "\u2535",
|
|
824
|
+
lineUpDoubleLeftDoubleRightDouble: "\u2569",
|
|
825
|
+
lineUpDoubleLeftRight: "\u2568",
|
|
826
|
+
lineUpLeftDoubleRightDouble: "\u2567",
|
|
827
|
+
lineUpDownLeftRight: "\u253C",
|
|
828
|
+
lineUpBoldDownBoldLeftBoldRightBold: "\u254B",
|
|
829
|
+
lineUpDownBoldLeftBoldRightBold: "\u2548",
|
|
830
|
+
lineUpBoldDownLeftBoldRightBold: "\u2547",
|
|
831
|
+
lineUpBoldDownBoldLeftRightBold: "\u254A",
|
|
832
|
+
lineUpBoldDownBoldLeftBoldRight: "\u2549",
|
|
833
|
+
lineUpBoldDownLeftRight: "\u2540",
|
|
834
|
+
lineUpDownBoldLeftRight: "\u2541",
|
|
835
|
+
lineUpDownLeftBoldRight: "\u253D",
|
|
836
|
+
lineUpDownLeftRightBold: "\u253E",
|
|
837
|
+
lineUpBoldDownBoldLeftRight: "\u2542",
|
|
838
|
+
lineUpDownLeftBoldRightBold: "\u253F",
|
|
839
|
+
lineUpBoldDownLeftBoldRight: "\u2543",
|
|
840
|
+
lineUpBoldDownLeftRightBold: "\u2544",
|
|
841
|
+
lineUpDownBoldLeftBoldRight: "\u2545",
|
|
842
|
+
lineUpDownBoldLeftRightBold: "\u2546",
|
|
843
|
+
lineUpDoubleDownDoubleLeftDoubleRightDouble: "\u256C",
|
|
844
|
+
lineUpDoubleDownDoubleLeftRight: "\u256B",
|
|
845
|
+
lineUpDownLeftDoubleRightDouble: "\u256A",
|
|
846
|
+
lineCross: "\u2573",
|
|
847
|
+
lineBackslash: "\u2572",
|
|
848
|
+
lineSlash: "\u2571"
|
|
849
|
+
};
|
|
850
|
+
var specialMainSymbols = {
|
|
851
|
+
tick: "\u2714",
|
|
852
|
+
info: "\u2139",
|
|
853
|
+
warning: "\u26A0",
|
|
854
|
+
cross: "\u2718",
|
|
855
|
+
squareSmall: "\u25FB",
|
|
856
|
+
squareSmallFilled: "\u25FC",
|
|
857
|
+
circle: "\u25EF",
|
|
858
|
+
circleFilled: "\u25C9",
|
|
859
|
+
circleDotted: "\u25CC",
|
|
860
|
+
circleDouble: "\u25CE",
|
|
861
|
+
circleCircle: "\u24DE",
|
|
862
|
+
circleCross: "\u24E7",
|
|
863
|
+
circlePipe: "\u24BE",
|
|
864
|
+
radioOn: "\u25C9",
|
|
865
|
+
radioOff: "\u25EF",
|
|
866
|
+
checkboxOn: "\u2612",
|
|
867
|
+
checkboxOff: "\u2610",
|
|
868
|
+
checkboxCircleOn: "\u24E7",
|
|
869
|
+
checkboxCircleOff: "\u24BE",
|
|
870
|
+
pointer: "\u276F",
|
|
871
|
+
triangleUpOutline: "\u25B3",
|
|
872
|
+
triangleLeft: "\u25C0",
|
|
873
|
+
triangleRight: "\u25B6",
|
|
874
|
+
lozenge: "\u25C6",
|
|
875
|
+
lozengeOutline: "\u25C7",
|
|
876
|
+
hamburger: "\u2630",
|
|
877
|
+
smiley: "\u32E1",
|
|
878
|
+
mustache: "\u0DF4",
|
|
879
|
+
star: "\u2605",
|
|
880
|
+
play: "\u25B6",
|
|
881
|
+
nodejs: "\u2B22",
|
|
882
|
+
oneSeventh: "\u2150",
|
|
883
|
+
oneNinth: "\u2151",
|
|
884
|
+
oneTenth: "\u2152"
|
|
885
|
+
};
|
|
886
|
+
var specialFallbackSymbols = {
|
|
887
|
+
tick: "\u221A",
|
|
888
|
+
info: "i",
|
|
889
|
+
warning: "\u203C",
|
|
890
|
+
cross: "\xD7",
|
|
891
|
+
squareSmall: "\u25A1",
|
|
892
|
+
squareSmallFilled: "\u25A0",
|
|
893
|
+
circle: "( )",
|
|
894
|
+
circleFilled: "(*)",
|
|
895
|
+
circleDotted: "( )",
|
|
896
|
+
circleDouble: "( )",
|
|
897
|
+
circleCircle: "(\u25CB)",
|
|
898
|
+
circleCross: "(\xD7)",
|
|
899
|
+
circlePipe: "(\u2502)",
|
|
900
|
+
radioOn: "(*)",
|
|
901
|
+
radioOff: "( )",
|
|
902
|
+
checkboxOn: "[\xD7]",
|
|
903
|
+
checkboxOff: "[ ]",
|
|
904
|
+
checkboxCircleOn: "(\xD7)",
|
|
905
|
+
checkboxCircleOff: "( )",
|
|
906
|
+
pointer: ">",
|
|
907
|
+
triangleUpOutline: "\u2206",
|
|
908
|
+
triangleLeft: "\u25C4",
|
|
909
|
+
triangleRight: "\u25BA",
|
|
910
|
+
lozenge: "\u2666",
|
|
911
|
+
lozengeOutline: "\u25CA",
|
|
912
|
+
hamburger: "\u2261",
|
|
913
|
+
smiley: "\u263A",
|
|
914
|
+
mustache: "\u250C\u2500\u2510",
|
|
915
|
+
star: "\u2736",
|
|
916
|
+
play: "\u25BA",
|
|
917
|
+
nodejs: "\u2666",
|
|
918
|
+
oneSeventh: "1/7",
|
|
919
|
+
oneNinth: "1/9",
|
|
920
|
+
oneTenth: "1/10"
|
|
921
|
+
};
|
|
922
|
+
var mainSymbols = {
|
|
923
|
+
...common,
|
|
924
|
+
...specialMainSymbols
|
|
925
|
+
};
|
|
926
|
+
var fallbackSymbols = {
|
|
927
|
+
...common,
|
|
928
|
+
...specialFallbackSymbols
|
|
929
|
+
};
|
|
930
|
+
var shouldUseMain = isUnicodeSupported();
|
|
931
|
+
var figures = shouldUseMain ? mainSymbols : fallbackSymbols;
|
|
932
|
+
var dist_default = figures;
|
|
933
|
+
var replacements = Object.entries(specialMainSymbols);
|
|
934
|
+
|
|
935
|
+
// node_modules/@inquirer/core/dist/lib/theme.js
|
|
936
|
+
var defaultTheme = {
|
|
937
|
+
prefix: {
|
|
938
|
+
idle: styleText("blue", "?"),
|
|
939
|
+
done: styleText("green", dist_default.tick)
|
|
940
|
+
},
|
|
941
|
+
spinner: {
|
|
942
|
+
interval: 80,
|
|
943
|
+
frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"].map((frame) => styleText("yellow", frame))
|
|
944
|
+
},
|
|
945
|
+
keybindings: [],
|
|
946
|
+
style: {
|
|
947
|
+
answer: (text) => styleText("cyan", text),
|
|
948
|
+
message: (text) => styleText("bold", text),
|
|
949
|
+
error: (text) => styleText("red", `> ${text}`),
|
|
950
|
+
defaultAnswer: (text) => styleText("dim", `(${text})`),
|
|
951
|
+
help: (text) => styleText("dim", text),
|
|
952
|
+
highlight: (text) => styleText("cyan", text),
|
|
953
|
+
key: (text) => styleText("cyan", styleText("bold", `<${text}>`))
|
|
954
|
+
}
|
|
955
|
+
};
|
|
956
|
+
function getDefaultTheme() {
|
|
957
|
+
return {
|
|
958
|
+
...defaultTheme,
|
|
959
|
+
keybindings: getDefaultKeybindings()
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
// node_modules/@inquirer/core/dist/lib/make-theme.js
|
|
964
|
+
function isPlainObject(value) {
|
|
965
|
+
if (typeof value !== "object" || value === null)
|
|
966
|
+
return false;
|
|
967
|
+
let proto = value;
|
|
968
|
+
while (Object.getPrototypeOf(proto) !== null) {
|
|
969
|
+
proto = Object.getPrototypeOf(proto);
|
|
970
|
+
}
|
|
971
|
+
return Object.getPrototypeOf(value) === proto;
|
|
972
|
+
}
|
|
973
|
+
function deepMerge(...objects) {
|
|
974
|
+
const output = {};
|
|
975
|
+
for (const obj of objects) {
|
|
976
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
977
|
+
const prevValue = output[key];
|
|
978
|
+
output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
return output;
|
|
982
|
+
}
|
|
983
|
+
function makeTheme(...themes) {
|
|
984
|
+
const themesToMerge = [
|
|
985
|
+
getDefaultTheme(),
|
|
986
|
+
...themes.filter((theme) => theme != null)
|
|
987
|
+
];
|
|
988
|
+
return deepMerge(...themesToMerge);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// node_modules/@inquirer/core/dist/lib/use-prefix.js
|
|
992
|
+
function usePrefix({ status = "idle", theme }) {
|
|
993
|
+
const [showLoader, setShowLoader] = useState(false);
|
|
994
|
+
const [tick, setTick] = useState(0);
|
|
995
|
+
const { prefix, spinner } = makeTheme(theme);
|
|
996
|
+
useEffect(() => {
|
|
997
|
+
if (status === "loading") {
|
|
998
|
+
let tickInterval;
|
|
999
|
+
let inc = -1;
|
|
1000
|
+
const delayTimeout = setTimeout(() => {
|
|
1001
|
+
setShowLoader(true);
|
|
1002
|
+
tickInterval = setInterval(() => {
|
|
1003
|
+
inc = inc + 1;
|
|
1004
|
+
setTick(inc % spinner.frames.length);
|
|
1005
|
+
}, spinner.interval);
|
|
1006
|
+
}, 300);
|
|
1007
|
+
return () => {
|
|
1008
|
+
clearTimeout(delayTimeout);
|
|
1009
|
+
clearInterval(tickInterval);
|
|
1010
|
+
};
|
|
1011
|
+
} else {
|
|
1012
|
+
setShowLoader(false);
|
|
1013
|
+
}
|
|
1014
|
+
}, [status]);
|
|
1015
|
+
if (showLoader) {
|
|
1016
|
+
return spinner.frames[tick];
|
|
1017
|
+
}
|
|
1018
|
+
const iconName = status === "loading" ? "idle" : status;
|
|
1019
|
+
return typeof prefix === "string" ? prefix : prefix[iconName] ?? prefix["idle"];
|
|
1020
|
+
}
|
|
1021
|
+
// node_modules/@inquirer/core/dist/lib/use-memo.js
|
|
1022
|
+
function useMemo(fn, dependencies) {
|
|
1023
|
+
return withPointer((pointer) => {
|
|
1024
|
+
const prev = pointer.get();
|
|
1025
|
+
if (!pointer.initialized || prev.dependencies.length !== dependencies.length || prev.dependencies.some((dep, i) => dep !== dependencies[i])) {
|
|
1026
|
+
const value = fn();
|
|
1027
|
+
pointer.set({ value, dependencies });
|
|
1028
|
+
return value;
|
|
1029
|
+
}
|
|
1030
|
+
return prev.value;
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
// node_modules/@inquirer/core/dist/lib/use-ref.js
|
|
1034
|
+
function useRef(val) {
|
|
1035
|
+
return useState({ current: val })[0];
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// node_modules/@inquirer/core/dist/lib/use-keypress.js
|
|
1039
|
+
function useKeypress(userHandler) {
|
|
1040
|
+
const signal = useRef(userHandler);
|
|
1041
|
+
signal.current = userHandler;
|
|
1042
|
+
useEffect((rl) => {
|
|
1043
|
+
let ignore = false;
|
|
1044
|
+
const handler = withUpdates((_input, event) => {
|
|
1045
|
+
if (ignore)
|
|
1046
|
+
return;
|
|
1047
|
+
signal.current(event, rl);
|
|
1048
|
+
});
|
|
1049
|
+
rl.input.on("keypress", handler);
|
|
1050
|
+
return () => {
|
|
1051
|
+
ignore = true;
|
|
1052
|
+
rl.input.removeListener("keypress", handler);
|
|
1053
|
+
};
|
|
1054
|
+
}, []);
|
|
1055
|
+
}
|
|
1056
|
+
// node_modules/@inquirer/core/dist/lib/utils.js
|
|
1057
|
+
var import_cli_width = __toESM(require_cli_width(), 1);
|
|
1058
|
+
|
|
1059
|
+
// node_modules/fast-string-truncated-width/dist/utils.js
|
|
1060
|
+
var getCodePointsLength = (() => {
|
|
1061
|
+
const SURROGATE_PAIR_RE = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
|
|
1062
|
+
return (input) => {
|
|
1063
|
+
let surrogatePairsNr = 0;
|
|
1064
|
+
SURROGATE_PAIR_RE.lastIndex = 0;
|
|
1065
|
+
while (SURROGATE_PAIR_RE.test(input)) {
|
|
1066
|
+
surrogatePairsNr += 1;
|
|
1067
|
+
}
|
|
1068
|
+
return input.length - surrogatePairsNr;
|
|
1069
|
+
};
|
|
1070
|
+
})();
|
|
1071
|
+
var isFullWidth = (x) => {
|
|
1072
|
+
return x === 12288 || x >= 65281 && x <= 65376 || x >= 65504 && x <= 65510;
|
|
1073
|
+
};
|
|
1074
|
+
var isWideNotCJKTNotEmoji = (x) => {
|
|
1075
|
+
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;
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
// node_modules/fast-string-truncated-width/dist/index.js
|
|
1079
|
+
var ANSI_RE = /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y;
|
|
1080
|
+
var CONTROL_RE = /[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y;
|
|
1081
|
+
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;
|
|
1082
|
+
var TAB_RE = /\t{1,1000}/y;
|
|
1083
|
+
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;
|
|
1084
|
+
var LATIN_RE = /(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y;
|
|
1085
|
+
var MODIFIER_RE = /\p{M}+/gu;
|
|
1086
|
+
var NO_TRUNCATION = { limit: Infinity, ellipsis: "" };
|
|
1087
|
+
var getStringTruncatedWidth = (input, truncationOptions = {}, widthOptions = {}) => {
|
|
1088
|
+
const LIMIT = truncationOptions.limit ?? Infinity;
|
|
1089
|
+
const ELLIPSIS = truncationOptions.ellipsis ?? "";
|
|
1090
|
+
const ELLIPSIS_WIDTH = truncationOptions?.ellipsisWidth ?? (ELLIPSIS ? getStringTruncatedWidth(ELLIPSIS, NO_TRUNCATION, widthOptions).width : 0);
|
|
1091
|
+
const ANSI_WIDTH = 0;
|
|
1092
|
+
const CONTROL_WIDTH = widthOptions.controlWidth ?? 0;
|
|
1093
|
+
const TAB_WIDTH = widthOptions.tabWidth ?? 8;
|
|
1094
|
+
const EMOJI_WIDTH = widthOptions.emojiWidth ?? 2;
|
|
1095
|
+
const FULL_WIDTH_WIDTH = 2;
|
|
1096
|
+
const REGULAR_WIDTH = widthOptions.regularWidth ?? 1;
|
|
1097
|
+
const WIDE_WIDTH = widthOptions.wideWidth ?? FULL_WIDTH_WIDTH;
|
|
1098
|
+
const PARSE_BLOCKS = [
|
|
1099
|
+
[LATIN_RE, REGULAR_WIDTH],
|
|
1100
|
+
[ANSI_RE, ANSI_WIDTH],
|
|
1101
|
+
[CONTROL_RE, CONTROL_WIDTH],
|
|
1102
|
+
[TAB_RE, TAB_WIDTH],
|
|
1103
|
+
[EMOJI_RE, EMOJI_WIDTH],
|
|
1104
|
+
[CJKT_WIDE_RE, WIDE_WIDTH]
|
|
1105
|
+
];
|
|
1106
|
+
let indexPrev = 0;
|
|
1107
|
+
let index = 0;
|
|
1108
|
+
let length = input.length;
|
|
1109
|
+
let lengthExtra = 0;
|
|
1110
|
+
let truncationEnabled = false;
|
|
1111
|
+
let truncationIndex = length;
|
|
1112
|
+
let truncationLimit = Math.max(0, LIMIT - ELLIPSIS_WIDTH);
|
|
1113
|
+
let unmatchedStart = 0;
|
|
1114
|
+
let unmatchedEnd = 0;
|
|
1115
|
+
let width = 0;
|
|
1116
|
+
let widthExtra = 0;
|
|
1117
|
+
outer:
|
|
1118
|
+
while (true) {
|
|
1119
|
+
if (unmatchedEnd > unmatchedStart || index >= length && index > indexPrev) {
|
|
1120
|
+
const unmatched = input.slice(unmatchedStart, unmatchedEnd) || input.slice(indexPrev, index);
|
|
1121
|
+
lengthExtra = 0;
|
|
1122
|
+
for (const char of unmatched.replaceAll(MODIFIER_RE, "")) {
|
|
1123
|
+
const codePoint = char.codePointAt(0) || 0;
|
|
1124
|
+
if (isFullWidth(codePoint)) {
|
|
1125
|
+
widthExtra = FULL_WIDTH_WIDTH;
|
|
1126
|
+
} else if (isWideNotCJKTNotEmoji(codePoint)) {
|
|
1127
|
+
widthExtra = WIDE_WIDTH;
|
|
1128
|
+
} else {
|
|
1129
|
+
widthExtra = REGULAR_WIDTH;
|
|
1130
|
+
}
|
|
1131
|
+
if (width + widthExtra > truncationLimit) {
|
|
1132
|
+
truncationIndex = Math.min(truncationIndex, Math.max(unmatchedStart, indexPrev) + lengthExtra);
|
|
1133
|
+
}
|
|
1134
|
+
if (width + widthExtra > LIMIT) {
|
|
1135
|
+
truncationEnabled = true;
|
|
1136
|
+
break outer;
|
|
1137
|
+
}
|
|
1138
|
+
lengthExtra += char.length;
|
|
1139
|
+
width += widthExtra;
|
|
1140
|
+
}
|
|
1141
|
+
unmatchedStart = unmatchedEnd = 0;
|
|
1142
|
+
}
|
|
1143
|
+
if (index >= length) {
|
|
1144
|
+
break outer;
|
|
1145
|
+
}
|
|
1146
|
+
for (let i = 0, l = PARSE_BLOCKS.length;i < l; i++) {
|
|
1147
|
+
const [BLOCK_RE, BLOCK_WIDTH] = PARSE_BLOCKS[i];
|
|
1148
|
+
BLOCK_RE.lastIndex = index;
|
|
1149
|
+
if (BLOCK_RE.test(input)) {
|
|
1150
|
+
lengthExtra = BLOCK_RE === CJKT_WIDE_RE ? getCodePointsLength(input.slice(index, BLOCK_RE.lastIndex)) : BLOCK_RE === EMOJI_RE ? 1 : BLOCK_RE.lastIndex - index;
|
|
1151
|
+
widthExtra = lengthExtra * BLOCK_WIDTH;
|
|
1152
|
+
if (width + widthExtra > truncationLimit) {
|
|
1153
|
+
truncationIndex = Math.min(truncationIndex, index + Math.floor((truncationLimit - width) / BLOCK_WIDTH));
|
|
1154
|
+
}
|
|
1155
|
+
if (width + widthExtra > LIMIT) {
|
|
1156
|
+
truncationEnabled = true;
|
|
1157
|
+
break outer;
|
|
1158
|
+
}
|
|
1159
|
+
width += widthExtra;
|
|
1160
|
+
unmatchedStart = indexPrev;
|
|
1161
|
+
unmatchedEnd = index;
|
|
1162
|
+
index = indexPrev = BLOCK_RE.lastIndex;
|
|
1163
|
+
continue outer;
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
index += 1;
|
|
1167
|
+
}
|
|
1168
|
+
return {
|
|
1169
|
+
width: truncationEnabled ? truncationLimit : width,
|
|
1170
|
+
index: truncationEnabled ? truncationIndex : length,
|
|
1171
|
+
truncated: truncationEnabled,
|
|
1172
|
+
ellipsed: truncationEnabled && LIMIT >= ELLIPSIS_WIDTH
|
|
1173
|
+
};
|
|
1174
|
+
};
|
|
1175
|
+
var dist_default2 = getStringTruncatedWidth;
|
|
1176
|
+
|
|
1177
|
+
// node_modules/fast-string-width/dist/index.js
|
|
1178
|
+
var NO_TRUNCATION2 = {
|
|
1179
|
+
limit: Infinity,
|
|
1180
|
+
ellipsis: "",
|
|
1181
|
+
ellipsisWidth: 0
|
|
1182
|
+
};
|
|
1183
|
+
var fastStringWidth = (input, options = {}) => {
|
|
1184
|
+
return dist_default2(input, NO_TRUNCATION2, options).width;
|
|
1185
|
+
};
|
|
1186
|
+
var dist_default3 = fastStringWidth;
|
|
1187
|
+
|
|
1188
|
+
// node_modules/fast-wrap-ansi/lib/main.js
|
|
1189
|
+
var ESC = "\x1B";
|
|
1190
|
+
var CSI = "\x9B";
|
|
1191
|
+
var END_CODE = 39;
|
|
1192
|
+
var ANSI_ESCAPE_BELL = "\x07";
|
|
1193
|
+
var ANSI_CSI = "[";
|
|
1194
|
+
var ANSI_OSC = "]";
|
|
1195
|
+
var ANSI_SGR_TERMINATOR = "m";
|
|
1196
|
+
var ANSI_ESCAPE_LINK = `${ANSI_OSC}8;;`;
|
|
1197
|
+
var GROUP_REGEX = new RegExp(`(?:\\${ANSI_CSI}(?<code>\\d+)m|\\${ANSI_ESCAPE_LINK}(?<uri>.*)${ANSI_ESCAPE_BELL})`, "y");
|
|
1198
|
+
var getClosingCode = (openingCode) => {
|
|
1199
|
+
if (openingCode >= 30 && openingCode <= 37)
|
|
1200
|
+
return 39;
|
|
1201
|
+
if (openingCode >= 90 && openingCode <= 97)
|
|
1202
|
+
return 39;
|
|
1203
|
+
if (openingCode >= 40 && openingCode <= 47)
|
|
1204
|
+
return 49;
|
|
1205
|
+
if (openingCode >= 100 && openingCode <= 107)
|
|
1206
|
+
return 49;
|
|
1207
|
+
if (openingCode === 1 || openingCode === 2)
|
|
1208
|
+
return 22;
|
|
1209
|
+
if (openingCode === 3)
|
|
1210
|
+
return 23;
|
|
1211
|
+
if (openingCode === 4)
|
|
1212
|
+
return 24;
|
|
1213
|
+
if (openingCode === 7)
|
|
1214
|
+
return 27;
|
|
1215
|
+
if (openingCode === 8)
|
|
1216
|
+
return 28;
|
|
1217
|
+
if (openingCode === 9)
|
|
1218
|
+
return 29;
|
|
1219
|
+
if (openingCode === 0)
|
|
1220
|
+
return 0;
|
|
1221
|
+
return;
|
|
1222
|
+
};
|
|
1223
|
+
var wrapAnsiCode = (code) => `${ESC}${ANSI_CSI}${code}${ANSI_SGR_TERMINATOR}`;
|
|
1224
|
+
var wrapAnsiHyperlink = (url) => `${ESC}${ANSI_ESCAPE_LINK}${url}${ANSI_ESCAPE_BELL}`;
|
|
1225
|
+
var wrapWord = (rows, word, columns) => {
|
|
1226
|
+
const characters = word[Symbol.iterator]();
|
|
1227
|
+
let isInsideEscape = false;
|
|
1228
|
+
let isInsideLinkEscape = false;
|
|
1229
|
+
let lastRow = rows.at(-1);
|
|
1230
|
+
let visible = lastRow === undefined ? 0 : dist_default3(lastRow);
|
|
1231
|
+
let currentCharacter = characters.next();
|
|
1232
|
+
let nextCharacter = characters.next();
|
|
1233
|
+
let rawCharacterIndex = 0;
|
|
1234
|
+
while (!currentCharacter.done) {
|
|
1235
|
+
const character = currentCharacter.value;
|
|
1236
|
+
const characterLength = dist_default3(character);
|
|
1237
|
+
if (visible + characterLength <= columns) {
|
|
1238
|
+
rows[rows.length - 1] += character;
|
|
1239
|
+
} else {
|
|
1240
|
+
rows.push(character);
|
|
1241
|
+
visible = 0;
|
|
1242
|
+
}
|
|
1243
|
+
if (character === ESC || character === CSI) {
|
|
1244
|
+
isInsideEscape = true;
|
|
1245
|
+
isInsideLinkEscape = word.startsWith(ANSI_ESCAPE_LINK, rawCharacterIndex + 1);
|
|
1246
|
+
}
|
|
1247
|
+
if (isInsideEscape) {
|
|
1248
|
+
if (isInsideLinkEscape) {
|
|
1249
|
+
if (character === ANSI_ESCAPE_BELL) {
|
|
1250
|
+
isInsideEscape = false;
|
|
1251
|
+
isInsideLinkEscape = false;
|
|
1252
|
+
}
|
|
1253
|
+
} else if (character === ANSI_SGR_TERMINATOR) {
|
|
1254
|
+
isInsideEscape = false;
|
|
1255
|
+
}
|
|
1256
|
+
} else {
|
|
1257
|
+
visible += characterLength;
|
|
1258
|
+
if (visible === columns && !nextCharacter.done) {
|
|
1259
|
+
rows.push("");
|
|
1260
|
+
visible = 0;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
currentCharacter = nextCharacter;
|
|
1264
|
+
nextCharacter = characters.next();
|
|
1265
|
+
rawCharacterIndex += character.length;
|
|
1266
|
+
}
|
|
1267
|
+
lastRow = rows.at(-1);
|
|
1268
|
+
if (!visible && lastRow !== undefined && lastRow.length && rows.length > 1) {
|
|
1269
|
+
rows[rows.length - 2] += rows.pop();
|
|
1270
|
+
}
|
|
1271
|
+
};
|
|
1272
|
+
var stringVisibleTrimSpacesRight = (string) => {
|
|
1273
|
+
const words = string.split(" ");
|
|
1274
|
+
let last = words.length;
|
|
1275
|
+
while (last) {
|
|
1276
|
+
if (dist_default3(words[last - 1])) {
|
|
1277
|
+
break;
|
|
1278
|
+
}
|
|
1279
|
+
last--;
|
|
1280
|
+
}
|
|
1281
|
+
if (last === words.length) {
|
|
1282
|
+
return string;
|
|
1283
|
+
}
|
|
1284
|
+
return words.slice(0, last).join(" ") + words.slice(last).join("");
|
|
1285
|
+
};
|
|
1286
|
+
var exec = (string, columns, options = {}) => {
|
|
1287
|
+
if (options.trim !== false && string.trim() === "") {
|
|
1288
|
+
return "";
|
|
1289
|
+
}
|
|
1290
|
+
let returnValue = "";
|
|
1291
|
+
let escapeCode;
|
|
1292
|
+
let escapeUrl;
|
|
1293
|
+
const words = string.split(" ");
|
|
1294
|
+
let rows = [""];
|
|
1295
|
+
let rowLength = 0;
|
|
1296
|
+
for (let index = 0;index < words.length; index++) {
|
|
1297
|
+
const word = words[index];
|
|
1298
|
+
if (options.trim !== false) {
|
|
1299
|
+
const row = rows.at(-1) ?? "";
|
|
1300
|
+
const trimmed = row.trimStart();
|
|
1301
|
+
if (row.length !== trimmed.length) {
|
|
1302
|
+
rows[rows.length - 1] = trimmed;
|
|
1303
|
+
rowLength = dist_default3(trimmed);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
if (index !== 0) {
|
|
1307
|
+
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
|
|
1308
|
+
rows.push("");
|
|
1309
|
+
rowLength = 0;
|
|
1310
|
+
}
|
|
1311
|
+
if (rowLength || options.trim === false) {
|
|
1312
|
+
rows[rows.length - 1] += " ";
|
|
1313
|
+
rowLength++;
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
const wordLength = dist_default3(word);
|
|
1317
|
+
if (options.hard && wordLength > columns) {
|
|
1318
|
+
const remainingColumns = columns - rowLength;
|
|
1319
|
+
const breaksStartingThisLine = 1 + Math.floor((wordLength - remainingColumns - 1) / columns);
|
|
1320
|
+
const breaksStartingNextLine = Math.floor((wordLength - 1) / columns);
|
|
1321
|
+
if (breaksStartingNextLine < breaksStartingThisLine) {
|
|
1322
|
+
rows.push("");
|
|
1323
|
+
}
|
|
1324
|
+
wrapWord(rows, word, columns);
|
|
1325
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
1326
|
+
continue;
|
|
1327
|
+
}
|
|
1328
|
+
if (rowLength + wordLength > columns && rowLength && wordLength) {
|
|
1329
|
+
if (options.wordWrap === false && rowLength < columns) {
|
|
1330
|
+
wrapWord(rows, word, columns);
|
|
1331
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
1332
|
+
continue;
|
|
1333
|
+
}
|
|
1334
|
+
rows.push("");
|
|
1335
|
+
rowLength = 0;
|
|
1336
|
+
}
|
|
1337
|
+
if (rowLength + wordLength > columns && options.wordWrap === false) {
|
|
1338
|
+
wrapWord(rows, word, columns);
|
|
1339
|
+
rowLength = dist_default3(rows.at(-1) ?? "");
|
|
1340
|
+
continue;
|
|
1341
|
+
}
|
|
1342
|
+
rows[rows.length - 1] += word;
|
|
1343
|
+
rowLength += wordLength;
|
|
1344
|
+
}
|
|
1345
|
+
if (options.trim !== false) {
|
|
1346
|
+
rows = rows.map((row) => stringVisibleTrimSpacesRight(row));
|
|
1347
|
+
}
|
|
1348
|
+
const preString = rows.join(`
|
|
1349
|
+
`);
|
|
1350
|
+
let inSurrogate = false;
|
|
1351
|
+
for (let i = 0;i < preString.length; i++) {
|
|
1352
|
+
const character = preString[i];
|
|
1353
|
+
returnValue += character;
|
|
1354
|
+
if (!inSurrogate) {
|
|
1355
|
+
inSurrogate = character >= "\uD800" && character <= "\uDBFF";
|
|
1356
|
+
if (inSurrogate) {
|
|
1357
|
+
continue;
|
|
1358
|
+
}
|
|
1359
|
+
} else {
|
|
1360
|
+
inSurrogate = false;
|
|
1361
|
+
}
|
|
1362
|
+
if (character === ESC || character === CSI) {
|
|
1363
|
+
GROUP_REGEX.lastIndex = i + 1;
|
|
1364
|
+
const groupsResult = GROUP_REGEX.exec(preString);
|
|
1365
|
+
const groups = groupsResult?.groups;
|
|
1366
|
+
if (groups?.code !== undefined) {
|
|
1367
|
+
const code = Number.parseFloat(groups.code);
|
|
1368
|
+
escapeCode = code === END_CODE ? undefined : code;
|
|
1369
|
+
} else if (groups?.uri !== undefined) {
|
|
1370
|
+
escapeUrl = groups.uri.length === 0 ? undefined : groups.uri;
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
if (preString[i + 1] === `
|
|
1374
|
+
`) {
|
|
1375
|
+
if (escapeUrl) {
|
|
1376
|
+
returnValue += wrapAnsiHyperlink("");
|
|
1377
|
+
}
|
|
1378
|
+
const closingCode = escapeCode ? getClosingCode(escapeCode) : undefined;
|
|
1379
|
+
if (escapeCode && closingCode) {
|
|
1380
|
+
returnValue += wrapAnsiCode(closingCode);
|
|
1381
|
+
}
|
|
1382
|
+
} else if (character === `
|
|
1383
|
+
`) {
|
|
1384
|
+
if (escapeCode && getClosingCode(escapeCode)) {
|
|
1385
|
+
returnValue += wrapAnsiCode(escapeCode);
|
|
1386
|
+
}
|
|
1387
|
+
if (escapeUrl) {
|
|
1388
|
+
returnValue += wrapAnsiHyperlink(escapeUrl);
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
return returnValue;
|
|
1393
|
+
};
|
|
1394
|
+
var CRLF_OR_LF = /\r?\n/;
|
|
1395
|
+
function wrapAnsi(string, columns, options) {
|
|
1396
|
+
return String(string).normalize().split(CRLF_OR_LF).map((line) => exec(line, columns, options)).join(`
|
|
1397
|
+
`);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
// node_modules/@inquirer/core/dist/lib/utils.js
|
|
1401
|
+
function breakLines(content, width) {
|
|
1402
|
+
return content.split(`
|
|
1403
|
+
`).flatMap((line) => wrapAnsi(line, width, { trim: false, wordWrap: false }).split(`
|
|
1404
|
+
`).map((str) => str.trimEnd())).join(`
|
|
1405
|
+
`);
|
|
1406
|
+
}
|
|
1407
|
+
function readlineWidth() {
|
|
1408
|
+
return import_cli_width.default({ defaultWidth: 80, output: readline().output });
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// node_modules/@inquirer/core/dist/lib/pagination/use-pagination.js
|
|
1412
|
+
function usePointerPosition({ active, renderedItems, pageSize, loop }) {
|
|
1413
|
+
const state = useRef({
|
|
1414
|
+
lastPointer: active,
|
|
1415
|
+
lastActive: undefined
|
|
1416
|
+
});
|
|
1417
|
+
const { lastPointer, lastActive } = state.current;
|
|
1418
|
+
const middle = Math.floor(pageSize / 2);
|
|
1419
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
1420
|
+
const defaultPointerPosition = renderedItems.slice(0, active).reduce((acc, item) => acc + item.length, 0);
|
|
1421
|
+
let pointer = defaultPointerPosition;
|
|
1422
|
+
if (renderedLength > pageSize) {
|
|
1423
|
+
if (loop) {
|
|
1424
|
+
pointer = lastPointer;
|
|
1425
|
+
if (lastActive != null && lastActive < active && active - lastActive < pageSize) {
|
|
1426
|
+
pointer = Math.min(middle, Math.abs(active - lastActive) === 1 ? Math.min(lastPointer + (renderedItems[lastActive]?.length ?? 0), Math.max(defaultPointerPosition, lastPointer)) : lastPointer + active - lastActive);
|
|
1427
|
+
}
|
|
1428
|
+
} else {
|
|
1429
|
+
const spaceUnderActive = renderedItems.slice(active).reduce((acc, item) => acc + item.length, 0);
|
|
1430
|
+
pointer = spaceUnderActive < pageSize - middle ? pageSize - spaceUnderActive : Math.min(defaultPointerPosition, middle);
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
state.current.lastPointer = pointer;
|
|
1434
|
+
state.current.lastActive = active;
|
|
1435
|
+
return pointer;
|
|
1436
|
+
}
|
|
1437
|
+
function usePagination({ items, active, renderItem, pageSize, loop = true }) {
|
|
1438
|
+
const width = readlineWidth();
|
|
1439
|
+
const bound = (num) => (num % items.length + items.length) % items.length;
|
|
1440
|
+
const renderedItems = items.map((item, index) => {
|
|
1441
|
+
if (item == null)
|
|
1442
|
+
return [];
|
|
1443
|
+
return breakLines(renderItem({ item, index, isActive: index === active }), width).split(`
|
|
1444
|
+
`);
|
|
1445
|
+
});
|
|
1446
|
+
const renderedLength = renderedItems.reduce((acc, item) => acc + item.length, 0);
|
|
1447
|
+
const renderItemAtIndex = (index) => renderedItems[index] ?? [];
|
|
1448
|
+
const pointer = usePointerPosition({ active, renderedItems, pageSize, loop });
|
|
1449
|
+
const activeItem = renderItemAtIndex(active).slice(0, pageSize);
|
|
1450
|
+
const activeItemPosition = pointer + activeItem.length <= pageSize ? pointer : pageSize - activeItem.length;
|
|
1451
|
+
const pageBuffer = Array.from({ length: pageSize });
|
|
1452
|
+
pageBuffer.splice(activeItemPosition, activeItem.length, ...activeItem);
|
|
1453
|
+
const itemVisited = new Set([active]);
|
|
1454
|
+
let bufferPointer = activeItemPosition + activeItem.length;
|
|
1455
|
+
let itemPointer = bound(active + 1);
|
|
1456
|
+
while (bufferPointer < pageSize && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer > active)) {
|
|
1457
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
1458
|
+
const linesToAdd = lines.slice(0, pageSize - bufferPointer);
|
|
1459
|
+
pageBuffer.splice(bufferPointer, linesToAdd.length, ...linesToAdd);
|
|
1460
|
+
itemVisited.add(itemPointer);
|
|
1461
|
+
bufferPointer += linesToAdd.length;
|
|
1462
|
+
itemPointer = bound(itemPointer + 1);
|
|
1463
|
+
}
|
|
1464
|
+
bufferPointer = activeItemPosition - 1;
|
|
1465
|
+
itemPointer = bound(active - 1);
|
|
1466
|
+
while (bufferPointer >= 0 && !itemVisited.has(itemPointer) && (loop && renderedLength > pageSize ? itemPointer !== active : itemPointer < active)) {
|
|
1467
|
+
const lines = renderItemAtIndex(itemPointer);
|
|
1468
|
+
const linesToAdd = lines.slice(Math.max(0, lines.length - bufferPointer - 1));
|
|
1469
|
+
pageBuffer.splice(bufferPointer - linesToAdd.length + 1, linesToAdd.length, ...linesToAdd);
|
|
1470
|
+
itemVisited.add(itemPointer);
|
|
1471
|
+
bufferPointer -= linesToAdd.length;
|
|
1472
|
+
itemPointer = bound(itemPointer - 1);
|
|
1473
|
+
}
|
|
1474
|
+
return pageBuffer.filter((line) => typeof line === "string").join(`
|
|
1475
|
+
`);
|
|
1476
|
+
}
|
|
1477
|
+
// node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
1478
|
+
import * as readline2 from "readline";
|
|
1479
|
+
import { AsyncResource as AsyncResource3 } from "async_hooks";
|
|
1480
|
+
|
|
1481
|
+
// node_modules/@inquirer/type/dist/utils.js
|
|
1482
|
+
function withResolver() {
|
|
1483
|
+
let resolve;
|
|
1484
|
+
let reject;
|
|
1485
|
+
const promise = new Promise((res, rej) => {
|
|
1486
|
+
resolve = res;
|
|
1487
|
+
reject = rej;
|
|
1488
|
+
});
|
|
1489
|
+
return { promise, resolve, reject };
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
// node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
1493
|
+
var import_mute_stream = __toESM(require_lib(), 1);
|
|
1494
|
+
|
|
1495
|
+
// node_modules/signal-exit/dist/mjs/signals.js
|
|
1496
|
+
var signals = [];
|
|
1497
|
+
signals.push("SIGHUP", "SIGINT", "SIGTERM");
|
|
1498
|
+
if (process.platform !== "win32") {
|
|
1499
|
+
signals.push("SIGALRM", "SIGABRT", "SIGVTALRM", "SIGXCPU", "SIGXFSZ", "SIGUSR2", "SIGTRAP", "SIGSYS", "SIGQUIT", "SIGIOT");
|
|
1500
|
+
}
|
|
1501
|
+
if (process.platform === "linux") {
|
|
1502
|
+
signals.push("SIGIO", "SIGPOLL", "SIGPWR", "SIGSTKFLT");
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
// node_modules/signal-exit/dist/mjs/index.js
|
|
1506
|
+
var processOk = (process3) => !!process3 && typeof process3 === "object" && typeof process3.removeListener === "function" && typeof process3.emit === "function" && typeof process3.reallyExit === "function" && typeof process3.listeners === "function" && typeof process3.kill === "function" && typeof process3.pid === "number" && typeof process3.on === "function";
|
|
1507
|
+
var kExitEmitter = Symbol.for("signal-exit emitter");
|
|
1508
|
+
var global = globalThis;
|
|
1509
|
+
var ObjectDefineProperty = Object.defineProperty.bind(Object);
|
|
1510
|
+
|
|
1511
|
+
class Emitter {
|
|
1512
|
+
emitted = {
|
|
1513
|
+
afterExit: false,
|
|
1514
|
+
exit: false
|
|
1515
|
+
};
|
|
1516
|
+
listeners = {
|
|
1517
|
+
afterExit: [],
|
|
1518
|
+
exit: []
|
|
1519
|
+
};
|
|
1520
|
+
count = 0;
|
|
1521
|
+
id = Math.random();
|
|
1522
|
+
constructor() {
|
|
1523
|
+
if (global[kExitEmitter]) {
|
|
1524
|
+
return global[kExitEmitter];
|
|
1525
|
+
}
|
|
1526
|
+
ObjectDefineProperty(global, kExitEmitter, {
|
|
1527
|
+
value: this,
|
|
1528
|
+
writable: false,
|
|
1529
|
+
enumerable: false,
|
|
1530
|
+
configurable: false
|
|
1531
|
+
});
|
|
1532
|
+
}
|
|
1533
|
+
on(ev, fn) {
|
|
1534
|
+
this.listeners[ev].push(fn);
|
|
1535
|
+
}
|
|
1536
|
+
removeListener(ev, fn) {
|
|
1537
|
+
const list = this.listeners[ev];
|
|
1538
|
+
const i = list.indexOf(fn);
|
|
1539
|
+
if (i === -1) {
|
|
1540
|
+
return;
|
|
1541
|
+
}
|
|
1542
|
+
if (i === 0 && list.length === 1) {
|
|
1543
|
+
list.length = 0;
|
|
1544
|
+
} else {
|
|
1545
|
+
list.splice(i, 1);
|
|
1546
|
+
}
|
|
1547
|
+
}
|
|
1548
|
+
emit(ev, code, signal) {
|
|
1549
|
+
if (this.emitted[ev]) {
|
|
1550
|
+
return false;
|
|
1551
|
+
}
|
|
1552
|
+
this.emitted[ev] = true;
|
|
1553
|
+
let ret = false;
|
|
1554
|
+
for (const fn of this.listeners[ev]) {
|
|
1555
|
+
ret = fn(code, signal) === true || ret;
|
|
1556
|
+
}
|
|
1557
|
+
if (ev === "exit") {
|
|
1558
|
+
ret = this.emit("afterExit", code, signal) || ret;
|
|
1559
|
+
}
|
|
1560
|
+
return ret;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
class SignalExitBase {
|
|
1565
|
+
}
|
|
1566
|
+
var signalExitWrap = (handler) => {
|
|
1567
|
+
return {
|
|
1568
|
+
onExit(cb, opts) {
|
|
1569
|
+
return handler.onExit(cb, opts);
|
|
1570
|
+
},
|
|
1571
|
+
load() {
|
|
1572
|
+
return handler.load();
|
|
1573
|
+
},
|
|
1574
|
+
unload() {
|
|
1575
|
+
return handler.unload();
|
|
1576
|
+
}
|
|
1577
|
+
};
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1580
|
+
class SignalExitFallback extends SignalExitBase {
|
|
1581
|
+
onExit() {
|
|
1582
|
+
return () => {};
|
|
1583
|
+
}
|
|
1584
|
+
load() {}
|
|
1585
|
+
unload() {}
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
class SignalExit extends SignalExitBase {
|
|
1589
|
+
#hupSig = process3.platform === "win32" ? "SIGINT" : "SIGHUP";
|
|
1590
|
+
#emitter = new Emitter;
|
|
1591
|
+
#process;
|
|
1592
|
+
#originalProcessEmit;
|
|
1593
|
+
#originalProcessReallyExit;
|
|
1594
|
+
#sigListeners = {};
|
|
1595
|
+
#loaded = false;
|
|
1596
|
+
constructor(process3) {
|
|
1597
|
+
super();
|
|
1598
|
+
this.#process = process3;
|
|
1599
|
+
this.#sigListeners = {};
|
|
1600
|
+
for (const sig of signals) {
|
|
1601
|
+
this.#sigListeners[sig] = () => {
|
|
1602
|
+
const listeners = this.#process.listeners(sig);
|
|
1603
|
+
let { count } = this.#emitter;
|
|
1604
|
+
const p = process3;
|
|
1605
|
+
if (typeof p.__signal_exit_emitter__ === "object" && typeof p.__signal_exit_emitter__.count === "number") {
|
|
1606
|
+
count += p.__signal_exit_emitter__.count;
|
|
1607
|
+
}
|
|
1608
|
+
if (listeners.length === count) {
|
|
1609
|
+
this.unload();
|
|
1610
|
+
const ret = this.#emitter.emit("exit", null, sig);
|
|
1611
|
+
const s = sig === "SIGHUP" ? this.#hupSig : sig;
|
|
1612
|
+
if (!ret)
|
|
1613
|
+
process3.kill(process3.pid, s);
|
|
1614
|
+
}
|
|
1615
|
+
};
|
|
1616
|
+
}
|
|
1617
|
+
this.#originalProcessReallyExit = process3.reallyExit;
|
|
1618
|
+
this.#originalProcessEmit = process3.emit;
|
|
1619
|
+
}
|
|
1620
|
+
onExit(cb, opts) {
|
|
1621
|
+
if (!processOk(this.#process)) {
|
|
1622
|
+
return () => {};
|
|
1623
|
+
}
|
|
1624
|
+
if (this.#loaded === false) {
|
|
1625
|
+
this.load();
|
|
1626
|
+
}
|
|
1627
|
+
const ev = opts?.alwaysLast ? "afterExit" : "exit";
|
|
1628
|
+
this.#emitter.on(ev, cb);
|
|
1629
|
+
return () => {
|
|
1630
|
+
this.#emitter.removeListener(ev, cb);
|
|
1631
|
+
if (this.#emitter.listeners["exit"].length === 0 && this.#emitter.listeners["afterExit"].length === 0) {
|
|
1632
|
+
this.unload();
|
|
1633
|
+
}
|
|
1634
|
+
};
|
|
1635
|
+
}
|
|
1636
|
+
load() {
|
|
1637
|
+
if (this.#loaded) {
|
|
1638
|
+
return;
|
|
1639
|
+
}
|
|
1640
|
+
this.#loaded = true;
|
|
1641
|
+
this.#emitter.count += 1;
|
|
1642
|
+
for (const sig of signals) {
|
|
1643
|
+
try {
|
|
1644
|
+
const fn = this.#sigListeners[sig];
|
|
1645
|
+
if (fn)
|
|
1646
|
+
this.#process.on(sig, fn);
|
|
1647
|
+
} catch (_) {}
|
|
1648
|
+
}
|
|
1649
|
+
this.#process.emit = (ev, ...a) => {
|
|
1650
|
+
return this.#processEmit(ev, ...a);
|
|
1651
|
+
};
|
|
1652
|
+
this.#process.reallyExit = (code) => {
|
|
1653
|
+
return this.#processReallyExit(code);
|
|
1654
|
+
};
|
|
1655
|
+
}
|
|
1656
|
+
unload() {
|
|
1657
|
+
if (!this.#loaded) {
|
|
1658
|
+
return;
|
|
1659
|
+
}
|
|
1660
|
+
this.#loaded = false;
|
|
1661
|
+
signals.forEach((sig) => {
|
|
1662
|
+
const listener = this.#sigListeners[sig];
|
|
1663
|
+
if (!listener) {
|
|
1664
|
+
throw new Error("Listener not defined for signal: " + sig);
|
|
1665
|
+
}
|
|
1666
|
+
try {
|
|
1667
|
+
this.#process.removeListener(sig, listener);
|
|
1668
|
+
} catch (_) {}
|
|
1669
|
+
});
|
|
1670
|
+
this.#process.emit = this.#originalProcessEmit;
|
|
1671
|
+
this.#process.reallyExit = this.#originalProcessReallyExit;
|
|
1672
|
+
this.#emitter.count -= 1;
|
|
1673
|
+
}
|
|
1674
|
+
#processReallyExit(code) {
|
|
1675
|
+
if (!processOk(this.#process)) {
|
|
1676
|
+
return 0;
|
|
1677
|
+
}
|
|
1678
|
+
this.#process.exitCode = code || 0;
|
|
1679
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
1680
|
+
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
|
|
1681
|
+
}
|
|
1682
|
+
#processEmit(ev, ...args) {
|
|
1683
|
+
const og = this.#originalProcessEmit;
|
|
1684
|
+
if (ev === "exit" && processOk(this.#process)) {
|
|
1685
|
+
if (typeof args[0] === "number") {
|
|
1686
|
+
this.#process.exitCode = args[0];
|
|
1687
|
+
}
|
|
1688
|
+
const ret = og.call(this.#process, ev, ...args);
|
|
1689
|
+
this.#emitter.emit("exit", this.#process.exitCode, null);
|
|
1690
|
+
return ret;
|
|
1691
|
+
} else {
|
|
1692
|
+
return og.call(this.#process, ev, ...args);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
}
|
|
1696
|
+
var process3 = globalThis.process;
|
|
1697
|
+
var {
|
|
1698
|
+
onExit,
|
|
1699
|
+
load,
|
|
1700
|
+
unload
|
|
1701
|
+
} = signalExitWrap(processOk(process3) ? new SignalExit(process3) : new SignalExitFallback);
|
|
1702
|
+
|
|
1703
|
+
// node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
1704
|
+
import { stripVTControlCharacters } from "util";
|
|
1705
|
+
|
|
1706
|
+
// node_modules/@inquirer/ansi/dist/index.js
|
|
1707
|
+
var ESC2 = "\x1B[";
|
|
1708
|
+
var cursorLeft = ESC2 + "G";
|
|
1709
|
+
var cursorHide = ESC2 + "?25l";
|
|
1710
|
+
var cursorShow = ESC2 + "?25h";
|
|
1711
|
+
var cursorUp = (rows = 1) => rows > 0 ? `${ESC2}${rows}A` : "";
|
|
1712
|
+
var cursorDown = (rows = 1) => rows > 0 ? `${ESC2}${rows}B` : "";
|
|
1713
|
+
var cursorTo = (x, y) => {
|
|
1714
|
+
if (typeof y === "number" && !Number.isNaN(y)) {
|
|
1715
|
+
return `${ESC2}${y + 1};${x + 1}H`;
|
|
1716
|
+
}
|
|
1717
|
+
return `${ESC2}${x + 1}G`;
|
|
1718
|
+
};
|
|
1719
|
+
var eraseLine = ESC2 + "2K";
|
|
1720
|
+
var eraseLines = (lines) => lines > 0 ? (eraseLine + cursorUp(1)).repeat(lines - 1) + eraseLine + cursorLeft : "";
|
|
1721
|
+
|
|
1722
|
+
// node_modules/@inquirer/core/dist/lib/screen-manager.js
|
|
1723
|
+
var height = (content) => content.split(`
|
|
1724
|
+
`).length;
|
|
1725
|
+
var lastLine = (content) => content.split(`
|
|
1726
|
+
`).pop() ?? "";
|
|
1727
|
+
|
|
1728
|
+
class ScreenManager {
|
|
1729
|
+
height = 0;
|
|
1730
|
+
extraLinesUnderPrompt = 0;
|
|
1731
|
+
cursorPos;
|
|
1732
|
+
rl;
|
|
1733
|
+
constructor(rl) {
|
|
1734
|
+
this.rl = rl;
|
|
1735
|
+
this.cursorPos = rl.getCursorPos();
|
|
1736
|
+
}
|
|
1737
|
+
write(content) {
|
|
1738
|
+
this.rl.output.unmute();
|
|
1739
|
+
this.rl.output.write(content);
|
|
1740
|
+
this.rl.output.mute();
|
|
1741
|
+
}
|
|
1742
|
+
render(content, bottomContent = "") {
|
|
1743
|
+
const promptLine = lastLine(content);
|
|
1744
|
+
const rawPromptLine = stripVTControlCharacters(promptLine);
|
|
1745
|
+
let prompt = rawPromptLine;
|
|
1746
|
+
if (this.rl.line.length > 0) {
|
|
1747
|
+
prompt = prompt.slice(0, -this.rl.line.length);
|
|
1748
|
+
}
|
|
1749
|
+
this.rl.setPrompt(prompt);
|
|
1750
|
+
this.cursorPos = this.rl.getCursorPos();
|
|
1751
|
+
const width = readlineWidth();
|
|
1752
|
+
content = breakLines(content, width);
|
|
1753
|
+
bottomContent = breakLines(bottomContent, width);
|
|
1754
|
+
if (rawPromptLine.length % width === 0) {
|
|
1755
|
+
content += `
|
|
1756
|
+
`;
|
|
1757
|
+
}
|
|
1758
|
+
let output = content + (bottomContent ? `
|
|
1759
|
+
` + bottomContent : "");
|
|
1760
|
+
const promptLineUpDiff = Math.floor(rawPromptLine.length / width) - this.cursorPos.rows;
|
|
1761
|
+
const bottomContentHeight = promptLineUpDiff + (bottomContent ? height(bottomContent) : 0);
|
|
1762
|
+
if (bottomContentHeight > 0)
|
|
1763
|
+
output += cursorUp(bottomContentHeight);
|
|
1764
|
+
output += cursorTo(this.cursorPos.cols);
|
|
1765
|
+
this.write(cursorDown(this.extraLinesUnderPrompt) + eraseLines(this.height) + output);
|
|
1766
|
+
this.extraLinesUnderPrompt = bottomContentHeight;
|
|
1767
|
+
this.height = height(output);
|
|
1768
|
+
}
|
|
1769
|
+
checkCursorPos() {
|
|
1770
|
+
const cursorPos = this.rl.getCursorPos();
|
|
1771
|
+
if (cursorPos.cols !== this.cursorPos.cols) {
|
|
1772
|
+
this.write(cursorTo(cursorPos.cols));
|
|
1773
|
+
this.cursorPos = cursorPos;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
done({ clearContent }) {
|
|
1777
|
+
this.rl.setPrompt("");
|
|
1778
|
+
let output = cursorDown(this.extraLinesUnderPrompt);
|
|
1779
|
+
output += clearContent ? eraseLines(this.height) : `
|
|
1780
|
+
`;
|
|
1781
|
+
output += cursorLeft;
|
|
1782
|
+
output += cursorShow;
|
|
1783
|
+
this.write(output);
|
|
1784
|
+
this.rl.close();
|
|
1785
|
+
}
|
|
1786
|
+
}
|
|
1787
|
+
|
|
1788
|
+
// node_modules/@inquirer/core/dist/lib/create-prompt.js
|
|
1789
|
+
import path from "path";
|
|
1790
|
+
var nativeSetImmediate = globalThis.setImmediate;
|
|
1791
|
+
var nativeClearImmediate = globalThis.clearImmediate;
|
|
1792
|
+
function listenTo(target, event, listener) {
|
|
1793
|
+
if ("on" in target) {
|
|
1794
|
+
target.on(event, listener);
|
|
1795
|
+
return () => target.removeListener(event, listener);
|
|
1796
|
+
}
|
|
1797
|
+
target.addEventListener(event, listener);
|
|
1798
|
+
return () => target.removeEventListener(event, listener);
|
|
1799
|
+
}
|
|
1800
|
+
function getCallSites() {
|
|
1801
|
+
const savedPrepareStackTrace = Error.prepareStackTrace;
|
|
1802
|
+
let result = [];
|
|
1803
|
+
try {
|
|
1804
|
+
Error.prepareStackTrace = (_, callSites) => {
|
|
1805
|
+
const callSitesWithoutCurrent = callSites.slice(1);
|
|
1806
|
+
result = callSitesWithoutCurrent;
|
|
1807
|
+
return callSitesWithoutCurrent;
|
|
1808
|
+
};
|
|
1809
|
+
new Error().stack;
|
|
1810
|
+
} catch {
|
|
1811
|
+
return result;
|
|
1812
|
+
}
|
|
1813
|
+
Error.prepareStackTrace = savedPrepareStackTrace;
|
|
1814
|
+
return result;
|
|
1815
|
+
}
|
|
1816
|
+
function createPrompt(view) {
|
|
1817
|
+
const callSites = getCallSites();
|
|
1818
|
+
const prompt = (config, context = {}) => {
|
|
1819
|
+
const { input = process.stdin, signal } = context;
|
|
1820
|
+
const cleanups = new Set;
|
|
1821
|
+
const output = new import_mute_stream.default;
|
|
1822
|
+
output.pipe(context.output ?? process.stdout);
|
|
1823
|
+
const rl = readline2.createInterface({
|
|
1824
|
+
terminal: true,
|
|
1825
|
+
input,
|
|
1826
|
+
output
|
|
1827
|
+
});
|
|
1828
|
+
output.mute();
|
|
1829
|
+
const screen = new ScreenManager(rl);
|
|
1830
|
+
const { promise, resolve, reject } = withResolver();
|
|
1831
|
+
return withHooks(rl, (cycle) => {
|
|
1832
|
+
const clearEffects = AsyncResource3.bind(() => effectScheduler.clearAll());
|
|
1833
|
+
const settlePrompt = (settle) => {
|
|
1834
|
+
try {
|
|
1835
|
+
clearEffects();
|
|
1836
|
+
settle();
|
|
1837
|
+
} catch (error) {
|
|
1838
|
+
reject(error);
|
|
1839
|
+
}
|
|
1840
|
+
};
|
|
1841
|
+
const resolvePrompt = (value) => settlePrompt(() => resolve(value));
|
|
1842
|
+
const rejectPrompt = (error) => settlePrompt(() => reject(error));
|
|
1843
|
+
const promptPromise = Object.assign(promise.finally(() => {
|
|
1844
|
+
cleanups.forEach((cleanup) => cleanup());
|
|
1845
|
+
screen.done({ clearContent: Boolean(context.clearPromptOnDone) });
|
|
1846
|
+
output.end();
|
|
1847
|
+
}).then(() => promise), { cancel: () => rejectPrompt(new CancelPromptError) });
|
|
1848
|
+
if (signal) {
|
|
1849
|
+
const abort = () => rejectPrompt(new AbortPromptError({ cause: signal.reason }));
|
|
1850
|
+
if (signal.aborted) {
|
|
1851
|
+
abort();
|
|
1852
|
+
return promptPromise;
|
|
1853
|
+
}
|
|
1854
|
+
cleanups.add(listenTo(signal, "abort", abort));
|
|
1855
|
+
}
|
|
1856
|
+
cleanups.add(onExit((code, signal2) => {
|
|
1857
|
+
rejectPrompt(new ExitPromptError(`User force closed the prompt with ${code} ${signal2}`));
|
|
1858
|
+
}));
|
|
1859
|
+
cleanups.add(listenTo(rl, "SIGINT", () => rejectPrompt(new ExitPromptError(`User force closed the prompt with SIGINT`))));
|
|
1860
|
+
cleanups.add(listenTo(rl, "close", clearEffects));
|
|
1861
|
+
const startCycle = () => {
|
|
1862
|
+
cleanups.add(listenTo(rl.input, "keypress", () => screen.checkCursorPos()));
|
|
1863
|
+
let pendingDone = null;
|
|
1864
|
+
cycle(() => {
|
|
1865
|
+
let effectsSettled = false;
|
|
1866
|
+
try {
|
|
1867
|
+
const nextView = view(config, (value) => {
|
|
1868
|
+
if (effectsSettled) {
|
|
1869
|
+
resolvePrompt(value);
|
|
1870
|
+
} else {
|
|
1871
|
+
pendingDone = { value };
|
|
1872
|
+
}
|
|
1873
|
+
});
|
|
1874
|
+
if (nextView === undefined) {
|
|
1875
|
+
let callerFilename = callSites[1]?.getFileName();
|
|
1876
|
+
if (callerFilename && !callerFilename.startsWith("file://")) {
|
|
1877
|
+
callerFilename = path.resolve(callerFilename);
|
|
1878
|
+
}
|
|
1879
|
+
throw new Error(`Prompt functions must return a string.
|
|
1880
|
+
at ${callerFilename}`);
|
|
1881
|
+
}
|
|
1882
|
+
const [content, bottomContent] = typeof nextView === "string" ? [nextView] : nextView;
|
|
1883
|
+
screen.render(content, bottomContent);
|
|
1884
|
+
effectScheduler.run();
|
|
1885
|
+
} catch (error) {
|
|
1886
|
+
rejectPrompt(error);
|
|
1887
|
+
}
|
|
1888
|
+
effectsSettled = true;
|
|
1889
|
+
if (pendingDone !== null) {
|
|
1890
|
+
const { value } = pendingDone;
|
|
1891
|
+
pendingDone = null;
|
|
1892
|
+
resolvePrompt(value);
|
|
1893
|
+
}
|
|
1894
|
+
});
|
|
1895
|
+
};
|
|
1896
|
+
if ("readableFlowing" in input && input.isTTY) {
|
|
1897
|
+
const immediate = nativeSetImmediate(startCycle);
|
|
1898
|
+
cleanups.add(() => nativeClearImmediate(immediate));
|
|
1899
|
+
} else {
|
|
1900
|
+
startCycle();
|
|
1901
|
+
}
|
|
1902
|
+
return promptPromise;
|
|
1903
|
+
});
|
|
1904
|
+
};
|
|
1905
|
+
return prompt;
|
|
1906
|
+
}
|
|
1907
|
+
// node_modules/@inquirer/core/dist/lib/Separator.js
|
|
1908
|
+
import { styleText as styleText2 } from "util";
|
|
1909
|
+
class Separator {
|
|
1910
|
+
separator = styleText2("dim", Array.from({ length: 15 }).join(dist_default.line));
|
|
1911
|
+
type = "separator";
|
|
1912
|
+
constructor(separator) {
|
|
1913
|
+
if (separator) {
|
|
1914
|
+
this.separator = separator;
|
|
1915
|
+
}
|
|
1916
|
+
}
|
|
1917
|
+
static isSeparator(choice) {
|
|
1918
|
+
return Boolean(choice && typeof choice === "object" && "type" in choice && choice.type === "separator");
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
// node_modules/@inquirer/checkbox/dist/index.js
|
|
1922
|
+
import { styleText as styleText3 } from "util";
|
|
1923
|
+
var checkboxTheme = {
|
|
1924
|
+
icon: {
|
|
1925
|
+
checked: styleText3("green", dist_default.circleFilled),
|
|
1926
|
+
unchecked: dist_default.circle,
|
|
1927
|
+
cursor: dist_default.pointer,
|
|
1928
|
+
disabledChecked: styleText3("green", dist_default.circleDouble),
|
|
1929
|
+
disabledUnchecked: "-"
|
|
1930
|
+
},
|
|
1931
|
+
style: {
|
|
1932
|
+
disabled: (text) => styleText3("dim", text),
|
|
1933
|
+
renderSelectedChoices: (selectedChoices) => selectedChoices.map((choice) => choice.short).join(", "),
|
|
1934
|
+
description: (text) => styleText3("cyan", text),
|
|
1935
|
+
keysHelpTip: (keys) => keys.map(([key, action]) => `${styleText3("bold", key)} ${styleText3("dim", action)}`).join(styleText3("dim", " \u2022 "))
|
|
1936
|
+
},
|
|
1937
|
+
i18n: { disabledError: "This option is disabled and cannot be toggled." }
|
|
1938
|
+
};
|
|
1939
|
+
function isSelectable(item) {
|
|
1940
|
+
return !Separator.isSeparator(item) && !item.disabled;
|
|
1941
|
+
}
|
|
1942
|
+
function isNavigable(item) {
|
|
1943
|
+
return !Separator.isSeparator(item);
|
|
1944
|
+
}
|
|
1945
|
+
function isChecked(item) {
|
|
1946
|
+
return !Separator.isSeparator(item) && item.checked;
|
|
1947
|
+
}
|
|
1948
|
+
function toggle(item) {
|
|
1949
|
+
return isSelectable(item) ? { ...item, checked: !item.checked } : item;
|
|
1950
|
+
}
|
|
1951
|
+
function check(checked) {
|
|
1952
|
+
return function(item) {
|
|
1953
|
+
return isSelectable(item) ? { ...item, checked } : item;
|
|
1954
|
+
};
|
|
1955
|
+
}
|
|
1956
|
+
function normalizeChoices(choices) {
|
|
1957
|
+
return choices.map((choice) => {
|
|
1958
|
+
if (Separator.isSeparator(choice))
|
|
1959
|
+
return choice;
|
|
1960
|
+
if (typeof choice !== "object" || choice === null || !("value" in choice)) {
|
|
1961
|
+
const name2 = String(choice);
|
|
1962
|
+
return {
|
|
1963
|
+
value: choice,
|
|
1964
|
+
name: name2,
|
|
1965
|
+
short: name2,
|
|
1966
|
+
checkedName: name2,
|
|
1967
|
+
disabled: false,
|
|
1968
|
+
checked: false
|
|
1969
|
+
};
|
|
1970
|
+
}
|
|
1971
|
+
const name = choice.name ?? String(choice.value);
|
|
1972
|
+
const normalizedChoice = {
|
|
1973
|
+
value: choice.value,
|
|
1974
|
+
name,
|
|
1975
|
+
short: choice.short ?? name,
|
|
1976
|
+
checkedName: choice.checkedName ?? name,
|
|
1977
|
+
disabled: choice.disabled ?? false,
|
|
1978
|
+
checked: choice.checked ?? false
|
|
1979
|
+
};
|
|
1980
|
+
if (choice.description) {
|
|
1981
|
+
normalizedChoice.description = choice.description;
|
|
1982
|
+
}
|
|
1983
|
+
return normalizedChoice;
|
|
1984
|
+
});
|
|
1985
|
+
}
|
|
1986
|
+
var dist_default4 = createPrompt((config, done) => {
|
|
1987
|
+
const { pageSize = 7, loop = true, required, validate = () => true } = config;
|
|
1988
|
+
const shortcuts = { all: "a", invert: "i", ...config.shortcuts };
|
|
1989
|
+
const theme = makeTheme(checkboxTheme, config.theme);
|
|
1990
|
+
const { keybindings: keybindings2 } = theme;
|
|
1991
|
+
const [status, setStatus] = useState("idle");
|
|
1992
|
+
const prefix = usePrefix({ status, theme });
|
|
1993
|
+
const [items, setItems] = useState(normalizeChoices(config.choices));
|
|
1994
|
+
const bounds = useMemo(() => {
|
|
1995
|
+
const first = items.findIndex(isNavigable);
|
|
1996
|
+
const last = items.findLastIndex(isNavigable);
|
|
1997
|
+
if (first === -1) {
|
|
1998
|
+
throw new ValidationError("[checkbox prompt] No selectable choices. All choices are disabled.");
|
|
1999
|
+
}
|
|
2000
|
+
return { first, last };
|
|
2001
|
+
}, [items]);
|
|
2002
|
+
const [active, setActive] = useState(bounds.first);
|
|
2003
|
+
const [errorMsg, setError] = useState();
|
|
2004
|
+
useKeypress(async (key) => {
|
|
2005
|
+
if (status !== "idle")
|
|
2006
|
+
return;
|
|
2007
|
+
if (isEnterKey(key)) {
|
|
2008
|
+
setStatus("loading");
|
|
2009
|
+
const selection = items.filter(isChecked);
|
|
2010
|
+
const isValid = await validate([...selection]);
|
|
2011
|
+
setStatus("idle");
|
|
2012
|
+
if (required && !selection.length) {
|
|
2013
|
+
setError("At least one choice must be selected");
|
|
2014
|
+
} else if (isValid === true) {
|
|
2015
|
+
setStatus("done");
|
|
2016
|
+
done(selection.map((choice) => choice.value));
|
|
2017
|
+
} else {
|
|
2018
|
+
setError(isValid || "You must select a valid value");
|
|
2019
|
+
}
|
|
2020
|
+
} else if (isUpKey(key, keybindings2) || isDownKey(key, keybindings2)) {
|
|
2021
|
+
if (errorMsg) {
|
|
2022
|
+
setError(undefined);
|
|
2023
|
+
}
|
|
2024
|
+
if (loop || isUpKey(key, keybindings2) && active !== bounds.first || isDownKey(key, keybindings2) && active !== bounds.last) {
|
|
2025
|
+
const offset = isUpKey(key, keybindings2) ? -1 : 1;
|
|
2026
|
+
let next = active;
|
|
2027
|
+
do {
|
|
2028
|
+
next = (next + offset + items.length) % items.length;
|
|
2029
|
+
} while (!isNavigable(items[next]));
|
|
2030
|
+
setActive(next);
|
|
2031
|
+
}
|
|
2032
|
+
} else if (isSpaceKey(key)) {
|
|
2033
|
+
const activeItem = items[active];
|
|
2034
|
+
if (activeItem && !Separator.isSeparator(activeItem)) {
|
|
2035
|
+
if (activeItem.disabled) {
|
|
2036
|
+
setError(theme.i18n.disabledError);
|
|
2037
|
+
} else {
|
|
2038
|
+
setError(undefined);
|
|
2039
|
+
setItems(items.map((choice, i) => i === active ? toggle(choice) : choice));
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
} else if (key.name === shortcuts.all) {
|
|
2043
|
+
const selectAll = items.some((choice) => isSelectable(choice) && !choice.checked);
|
|
2044
|
+
setItems(items.map(check(selectAll)));
|
|
2045
|
+
} else if (key.name === shortcuts.invert) {
|
|
2046
|
+
setItems(items.map(toggle));
|
|
2047
|
+
} else if (isNumberKey(key)) {
|
|
2048
|
+
const selectedIndex = Number(key.name) - 1;
|
|
2049
|
+
let selectableIndex = -1;
|
|
2050
|
+
const position = items.findIndex((item) => {
|
|
2051
|
+
if (Separator.isSeparator(item))
|
|
2052
|
+
return false;
|
|
2053
|
+
selectableIndex++;
|
|
2054
|
+
return selectableIndex === selectedIndex;
|
|
2055
|
+
});
|
|
2056
|
+
const selectedItem = items[position];
|
|
2057
|
+
if (selectedItem && isSelectable(selectedItem)) {
|
|
2058
|
+
setActive(position);
|
|
2059
|
+
setItems(items.map((choice, i) => i === position ? toggle(choice) : choice));
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
});
|
|
2063
|
+
const message = theme.style.message(config.message, status);
|
|
2064
|
+
let description;
|
|
2065
|
+
const page = usePagination({
|
|
2066
|
+
items,
|
|
2067
|
+
active,
|
|
2068
|
+
renderItem({ item, isActive }) {
|
|
2069
|
+
if (Separator.isSeparator(item)) {
|
|
2070
|
+
return ` ${item.separator}`;
|
|
2071
|
+
}
|
|
2072
|
+
const cursor = isActive ? theme.icon.cursor : " ";
|
|
2073
|
+
if (item.disabled) {
|
|
2074
|
+
const disabledLabel = typeof item.disabled === "string" ? item.disabled : "(disabled)";
|
|
2075
|
+
const checkbox2 = item.checked ? theme.icon.disabledChecked : theme.icon.disabledUnchecked;
|
|
2076
|
+
return theme.style.disabled(`${cursor}${checkbox2} ${item.name} ${disabledLabel}`);
|
|
2077
|
+
}
|
|
2078
|
+
if (isActive) {
|
|
2079
|
+
description = item.description;
|
|
2080
|
+
}
|
|
2081
|
+
const checkbox = item.checked ? theme.icon.checked : theme.icon.unchecked;
|
|
2082
|
+
const name = item.checked ? item.checkedName : item.name;
|
|
2083
|
+
const color = isActive ? theme.style.highlight : (x) => x;
|
|
2084
|
+
return color(`${cursor}${checkbox} ${name}`);
|
|
2085
|
+
},
|
|
2086
|
+
pageSize,
|
|
2087
|
+
loop
|
|
2088
|
+
});
|
|
2089
|
+
if (status === "done") {
|
|
2090
|
+
const selection = items.filter(isChecked);
|
|
2091
|
+
const answer = theme.style.answer(theme.style.renderSelectedChoices(selection, items));
|
|
2092
|
+
return [prefix, message, answer].filter(Boolean).join(" ");
|
|
2093
|
+
}
|
|
2094
|
+
const keys = [
|
|
2095
|
+
["\u2191\u2193", "navigate"],
|
|
2096
|
+
["space", "select"]
|
|
2097
|
+
];
|
|
2098
|
+
if (shortcuts.all)
|
|
2099
|
+
keys.push([shortcuts.all, "all"]);
|
|
2100
|
+
if (shortcuts.invert)
|
|
2101
|
+
keys.push([shortcuts.invert, "invert"]);
|
|
2102
|
+
keys.push(["\u23CE", "submit"]);
|
|
2103
|
+
const helpLine = theme.style.keysHelpTip(keys);
|
|
2104
|
+
const lines = [
|
|
2105
|
+
[prefix, message].filter(Boolean).join(" "),
|
|
2106
|
+
page,
|
|
2107
|
+
" ",
|
|
2108
|
+
description ? theme.style.description(description) : "",
|
|
2109
|
+
errorMsg ? theme.style.error(errorMsg) : "",
|
|
2110
|
+
helpLine
|
|
2111
|
+
].filter(Boolean).join(`
|
|
2112
|
+
`).trimEnd();
|
|
2113
|
+
return `${lines}${cursorHide}`;
|
|
2114
|
+
});
|
|
2115
|
+
// node_modules/@inquirer/confirm/dist/index.js
|
|
2116
|
+
import { styleText as styleText4 } from "util";
|
|
2117
|
+
var confirmTheme = {
|
|
2118
|
+
keywords: {
|
|
2119
|
+
yes: "Yes",
|
|
2120
|
+
no: "No",
|
|
2121
|
+
error: ({ yes, no }) => `You must answer with "${yes}" or "${no}"`
|
|
2122
|
+
},
|
|
2123
|
+
style: {
|
|
2124
|
+
confirmDefault: (text) => {
|
|
2125
|
+
const first = text[0] ?? "";
|
|
2126
|
+
if (first.toLowerCase() === first.toUpperCase()) {
|
|
2127
|
+
return styleText4("cyan", text);
|
|
2128
|
+
}
|
|
2129
|
+
return first.toUpperCase() + text.slice(1);
|
|
2130
|
+
}
|
|
2131
|
+
}
|
|
2132
|
+
};
|
|
2133
|
+
var dist_default5 = createPrompt((config, done) => {
|
|
2134
|
+
const [status, setStatus] = useState("idle");
|
|
2135
|
+
const [value, setValue] = useState("");
|
|
2136
|
+
const [errorMsg, setError] = useState();
|
|
2137
|
+
const theme = makeTheme(confirmTheme, config.theme);
|
|
2138
|
+
const prefix = usePrefix({ status, theme });
|
|
2139
|
+
const { yes, no } = theme.keywords;
|
|
2140
|
+
const yesHint = (yes[0] ?? "").toLowerCase();
|
|
2141
|
+
const noHint = (no[0] ?? "").toLowerCase();
|
|
2142
|
+
const hint = config.default === false ? `${yesHint}/${theme.style.confirmDefault(noHint)}` : `${theme.style.confirmDefault(yesHint)}/${noHint}`;
|
|
2143
|
+
function boolToString(value2) {
|
|
2144
|
+
return value2 ? yes : no;
|
|
2145
|
+
}
|
|
2146
|
+
const { transformer = boolToString } = config;
|
|
2147
|
+
function getBooleanValue(value2) {
|
|
2148
|
+
const v = value2.trim().toLowerCase();
|
|
2149
|
+
if (v === "")
|
|
2150
|
+
return config.default !== false;
|
|
2151
|
+
if (yes.toLowerCase().startsWith(v))
|
|
2152
|
+
return true;
|
|
2153
|
+
if (no.toLowerCase().startsWith(v))
|
|
2154
|
+
return false;
|
|
2155
|
+
if ("yes".startsWith(v))
|
|
2156
|
+
return true;
|
|
2157
|
+
if ("no".startsWith(v))
|
|
2158
|
+
return false;
|
|
2159
|
+
return;
|
|
2160
|
+
}
|
|
2161
|
+
useKeypress((key, rl) => {
|
|
2162
|
+
if (status !== "idle")
|
|
2163
|
+
return;
|
|
2164
|
+
if (isEnterKey(key)) {
|
|
2165
|
+
const answer = getBooleanValue(value);
|
|
2166
|
+
if (answer === undefined) {
|
|
2167
|
+
rl.write(value);
|
|
2168
|
+
setError(theme.keywords.error({ yes, no }));
|
|
2169
|
+
return;
|
|
2170
|
+
}
|
|
2171
|
+
setValue(transformer(answer));
|
|
2172
|
+
setStatus("done");
|
|
2173
|
+
done(answer);
|
|
2174
|
+
} else if (isTabKey(key)) {
|
|
2175
|
+
const answer = boolToString(!(getBooleanValue(value) ?? config.default !== false));
|
|
2176
|
+
rl.clearLine(0);
|
|
2177
|
+
rl.write(answer);
|
|
2178
|
+
setValue(answer);
|
|
2179
|
+
} else {
|
|
2180
|
+
setValue(rl.line);
|
|
2181
|
+
setError(undefined);
|
|
2182
|
+
}
|
|
2183
|
+
});
|
|
2184
|
+
let formattedValue = value;
|
|
2185
|
+
let defaultValue = "";
|
|
2186
|
+
if (status === "done") {
|
|
2187
|
+
formattedValue = theme.style.answer(value);
|
|
2188
|
+
} else {
|
|
2189
|
+
defaultValue = ` ${theme.style.defaultAnswer(hint)}`;
|
|
2190
|
+
}
|
|
2191
|
+
const message = theme.style.message(config.message, status);
|
|
2192
|
+
let error = "";
|
|
2193
|
+
if (errorMsg) {
|
|
2194
|
+
error = theme.style.error(errorMsg);
|
|
2195
|
+
}
|
|
2196
|
+
return [`${prefix} ${message}${defaultValue} ${formattedValue}`, error];
|
|
2197
|
+
});
|
|
2198
|
+
// src/install/index.ts
|
|
2199
|
+
import { mkdir as mkdir3, rm, rename, lstat, open } from "fs/promises";
|
|
2200
|
+
import { dirname as dirname3, join as join5, resolve as resolve5, isAbsolute as isAbsolute3 } from "path";
|
|
2201
|
+
import { pathToFileURL } from "url";
|
|
2202
|
+
|
|
2203
|
+
// node_modules/jsonc-parser/lib/esm/impl/scanner.js
|
|
2204
|
+
function createScanner(text, ignoreTrivia = false) {
|
|
2205
|
+
const len = text.length;
|
|
2206
|
+
let pos = 0, value = "", tokenOffset = 0, token = 16, lineNumber = 0, lineStartOffset = 0, tokenLineStartOffset = 0, prevTokenLineStartOffset = 0, scanError = 0;
|
|
2207
|
+
function scanHexDigits(count, exact) {
|
|
2208
|
+
let digits = 0;
|
|
2209
|
+
let value2 = 0;
|
|
2210
|
+
while (digits < count || !exact) {
|
|
2211
|
+
let ch = text.charCodeAt(pos);
|
|
2212
|
+
if (ch >= 48 && ch <= 57) {
|
|
2213
|
+
value2 = value2 * 16 + ch - 48;
|
|
2214
|
+
} else if (ch >= 65 && ch <= 70) {
|
|
2215
|
+
value2 = value2 * 16 + ch - 65 + 10;
|
|
2216
|
+
} else if (ch >= 97 && ch <= 102) {
|
|
2217
|
+
value2 = value2 * 16 + ch - 97 + 10;
|
|
2218
|
+
} else {
|
|
2219
|
+
break;
|
|
2220
|
+
}
|
|
2221
|
+
pos++;
|
|
2222
|
+
digits++;
|
|
2223
|
+
}
|
|
2224
|
+
if (digits < count) {
|
|
2225
|
+
value2 = -1;
|
|
2226
|
+
}
|
|
2227
|
+
return value2;
|
|
2228
|
+
}
|
|
2229
|
+
function setPosition(newPosition) {
|
|
2230
|
+
pos = newPosition;
|
|
2231
|
+
value = "";
|
|
2232
|
+
tokenOffset = 0;
|
|
2233
|
+
token = 16;
|
|
2234
|
+
scanError = 0;
|
|
2235
|
+
}
|
|
2236
|
+
function scanNumber() {
|
|
2237
|
+
let start = pos;
|
|
2238
|
+
if (text.charCodeAt(pos) === 48) {
|
|
2239
|
+
pos++;
|
|
2240
|
+
} else {
|
|
2241
|
+
pos++;
|
|
2242
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
2243
|
+
pos++;
|
|
2244
|
+
}
|
|
2245
|
+
}
|
|
2246
|
+
if (pos < text.length && text.charCodeAt(pos) === 46) {
|
|
2247
|
+
pos++;
|
|
2248
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
2249
|
+
pos++;
|
|
2250
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
2251
|
+
pos++;
|
|
2252
|
+
}
|
|
2253
|
+
} else {
|
|
2254
|
+
scanError = 3;
|
|
2255
|
+
return text.substring(start, pos);
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
let end = pos;
|
|
2259
|
+
if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
|
|
2260
|
+
pos++;
|
|
2261
|
+
if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) {
|
|
2262
|
+
pos++;
|
|
2263
|
+
}
|
|
2264
|
+
if (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
2265
|
+
pos++;
|
|
2266
|
+
while (pos < text.length && isDigit(text.charCodeAt(pos))) {
|
|
2267
|
+
pos++;
|
|
2268
|
+
}
|
|
2269
|
+
end = pos;
|
|
2270
|
+
} else {
|
|
2271
|
+
scanError = 3;
|
|
2272
|
+
}
|
|
2273
|
+
}
|
|
2274
|
+
return text.substring(start, end);
|
|
2275
|
+
}
|
|
2276
|
+
function scanString() {
|
|
2277
|
+
let result = "", start = pos;
|
|
2278
|
+
while (true) {
|
|
2279
|
+
if (pos >= len) {
|
|
2280
|
+
result += text.substring(start, pos);
|
|
2281
|
+
scanError = 2;
|
|
2282
|
+
break;
|
|
2283
|
+
}
|
|
2284
|
+
const ch = text.charCodeAt(pos);
|
|
2285
|
+
if (ch === 34) {
|
|
2286
|
+
result += text.substring(start, pos);
|
|
2287
|
+
pos++;
|
|
2288
|
+
break;
|
|
2289
|
+
}
|
|
2290
|
+
if (ch === 92) {
|
|
2291
|
+
result += text.substring(start, pos);
|
|
2292
|
+
pos++;
|
|
2293
|
+
if (pos >= len) {
|
|
2294
|
+
scanError = 2;
|
|
2295
|
+
break;
|
|
2296
|
+
}
|
|
2297
|
+
const ch2 = text.charCodeAt(pos++);
|
|
2298
|
+
switch (ch2) {
|
|
2299
|
+
case 34:
|
|
2300
|
+
result += '"';
|
|
2301
|
+
break;
|
|
2302
|
+
case 92:
|
|
2303
|
+
result += "\\";
|
|
2304
|
+
break;
|
|
2305
|
+
case 47:
|
|
2306
|
+
result += "/";
|
|
2307
|
+
break;
|
|
2308
|
+
case 98:
|
|
2309
|
+
result += "\b";
|
|
2310
|
+
break;
|
|
2311
|
+
case 102:
|
|
2312
|
+
result += "\f";
|
|
2313
|
+
break;
|
|
2314
|
+
case 110:
|
|
2315
|
+
result += `
|
|
2316
|
+
`;
|
|
2317
|
+
break;
|
|
2318
|
+
case 114:
|
|
2319
|
+
result += "\r";
|
|
2320
|
+
break;
|
|
2321
|
+
case 116:
|
|
2322
|
+
result += "\t";
|
|
2323
|
+
break;
|
|
2324
|
+
case 117:
|
|
2325
|
+
const ch3 = scanHexDigits(4, true);
|
|
2326
|
+
if (ch3 >= 0) {
|
|
2327
|
+
result += String.fromCharCode(ch3);
|
|
2328
|
+
} else {
|
|
2329
|
+
scanError = 4;
|
|
2330
|
+
}
|
|
2331
|
+
break;
|
|
2332
|
+
default:
|
|
2333
|
+
scanError = 5;
|
|
2334
|
+
}
|
|
2335
|
+
start = pos;
|
|
2336
|
+
continue;
|
|
2337
|
+
}
|
|
2338
|
+
if (ch >= 0 && ch <= 31) {
|
|
2339
|
+
if (isLineBreak(ch)) {
|
|
2340
|
+
result += text.substring(start, pos);
|
|
2341
|
+
scanError = 2;
|
|
2342
|
+
break;
|
|
2343
|
+
} else {
|
|
2344
|
+
scanError = 6;
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
pos++;
|
|
2348
|
+
}
|
|
2349
|
+
return result;
|
|
2350
|
+
}
|
|
2351
|
+
function scanNext() {
|
|
2352
|
+
value = "";
|
|
2353
|
+
scanError = 0;
|
|
2354
|
+
tokenOffset = pos;
|
|
2355
|
+
lineStartOffset = lineNumber;
|
|
2356
|
+
prevTokenLineStartOffset = tokenLineStartOffset;
|
|
2357
|
+
if (pos >= len) {
|
|
2358
|
+
tokenOffset = len;
|
|
2359
|
+
return token = 17;
|
|
2360
|
+
}
|
|
2361
|
+
let code = text.charCodeAt(pos);
|
|
2362
|
+
if (isWhiteSpace(code)) {
|
|
2363
|
+
do {
|
|
2364
|
+
pos++;
|
|
2365
|
+
value += String.fromCharCode(code);
|
|
2366
|
+
code = text.charCodeAt(pos);
|
|
2367
|
+
} while (isWhiteSpace(code));
|
|
2368
|
+
return token = 15;
|
|
2369
|
+
}
|
|
2370
|
+
if (isLineBreak(code)) {
|
|
2371
|
+
pos++;
|
|
2372
|
+
value += String.fromCharCode(code);
|
|
2373
|
+
if (code === 13 && text.charCodeAt(pos) === 10) {
|
|
2374
|
+
pos++;
|
|
2375
|
+
value += `
|
|
2376
|
+
`;
|
|
2377
|
+
}
|
|
2378
|
+
lineNumber++;
|
|
2379
|
+
tokenLineStartOffset = pos;
|
|
2380
|
+
return token = 14;
|
|
2381
|
+
}
|
|
2382
|
+
switch (code) {
|
|
2383
|
+
case 123:
|
|
2384
|
+
pos++;
|
|
2385
|
+
return token = 1;
|
|
2386
|
+
case 125:
|
|
2387
|
+
pos++;
|
|
2388
|
+
return token = 2;
|
|
2389
|
+
case 91:
|
|
2390
|
+
pos++;
|
|
2391
|
+
return token = 3;
|
|
2392
|
+
case 93:
|
|
2393
|
+
pos++;
|
|
2394
|
+
return token = 4;
|
|
2395
|
+
case 58:
|
|
2396
|
+
pos++;
|
|
2397
|
+
return token = 6;
|
|
2398
|
+
case 44:
|
|
2399
|
+
pos++;
|
|
2400
|
+
return token = 5;
|
|
2401
|
+
case 34:
|
|
2402
|
+
pos++;
|
|
2403
|
+
value = scanString();
|
|
2404
|
+
return token = 10;
|
|
2405
|
+
case 47:
|
|
2406
|
+
const start = pos - 1;
|
|
2407
|
+
if (text.charCodeAt(pos + 1) === 47) {
|
|
2408
|
+
pos += 2;
|
|
2409
|
+
while (pos < len) {
|
|
2410
|
+
if (isLineBreak(text.charCodeAt(pos))) {
|
|
2411
|
+
break;
|
|
2412
|
+
}
|
|
2413
|
+
pos++;
|
|
2414
|
+
}
|
|
2415
|
+
value = text.substring(start, pos);
|
|
2416
|
+
return token = 12;
|
|
2417
|
+
}
|
|
2418
|
+
if (text.charCodeAt(pos + 1) === 42) {
|
|
2419
|
+
pos += 2;
|
|
2420
|
+
const safeLength = len - 1;
|
|
2421
|
+
let commentClosed = false;
|
|
2422
|
+
while (pos < safeLength) {
|
|
2423
|
+
const ch = text.charCodeAt(pos);
|
|
2424
|
+
if (ch === 42 && text.charCodeAt(pos + 1) === 47) {
|
|
2425
|
+
pos += 2;
|
|
2426
|
+
commentClosed = true;
|
|
2427
|
+
break;
|
|
2428
|
+
}
|
|
2429
|
+
pos++;
|
|
2430
|
+
if (isLineBreak(ch)) {
|
|
2431
|
+
if (ch === 13 && text.charCodeAt(pos) === 10) {
|
|
2432
|
+
pos++;
|
|
2433
|
+
}
|
|
2434
|
+
lineNumber++;
|
|
2435
|
+
tokenLineStartOffset = pos;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
if (!commentClosed) {
|
|
2439
|
+
pos++;
|
|
2440
|
+
scanError = 1;
|
|
2441
|
+
}
|
|
2442
|
+
value = text.substring(start, pos);
|
|
2443
|
+
return token = 13;
|
|
2444
|
+
}
|
|
2445
|
+
value += String.fromCharCode(code);
|
|
2446
|
+
pos++;
|
|
2447
|
+
return token = 16;
|
|
2448
|
+
case 45:
|
|
2449
|
+
value += String.fromCharCode(code);
|
|
2450
|
+
pos++;
|
|
2451
|
+
if (pos === len || !isDigit(text.charCodeAt(pos))) {
|
|
2452
|
+
return token = 16;
|
|
2453
|
+
}
|
|
2454
|
+
case 48:
|
|
2455
|
+
case 49:
|
|
2456
|
+
case 50:
|
|
2457
|
+
case 51:
|
|
2458
|
+
case 52:
|
|
2459
|
+
case 53:
|
|
2460
|
+
case 54:
|
|
2461
|
+
case 55:
|
|
2462
|
+
case 56:
|
|
2463
|
+
case 57:
|
|
2464
|
+
value += scanNumber();
|
|
2465
|
+
return token = 11;
|
|
2466
|
+
default:
|
|
2467
|
+
while (pos < len && isUnknownContentCharacter(code)) {
|
|
2468
|
+
pos++;
|
|
2469
|
+
code = text.charCodeAt(pos);
|
|
2470
|
+
}
|
|
2471
|
+
if (tokenOffset !== pos) {
|
|
2472
|
+
value = text.substring(tokenOffset, pos);
|
|
2473
|
+
switch (value) {
|
|
2474
|
+
case "true":
|
|
2475
|
+
return token = 8;
|
|
2476
|
+
case "false":
|
|
2477
|
+
return token = 9;
|
|
2478
|
+
case "null":
|
|
2479
|
+
return token = 7;
|
|
2480
|
+
}
|
|
2481
|
+
return token = 16;
|
|
2482
|
+
}
|
|
2483
|
+
value += String.fromCharCode(code);
|
|
2484
|
+
pos++;
|
|
2485
|
+
return token = 16;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
function isUnknownContentCharacter(code) {
|
|
2489
|
+
if (isWhiteSpace(code) || isLineBreak(code)) {
|
|
2490
|
+
return false;
|
|
2491
|
+
}
|
|
2492
|
+
switch (code) {
|
|
2493
|
+
case 125:
|
|
2494
|
+
case 93:
|
|
2495
|
+
case 123:
|
|
2496
|
+
case 91:
|
|
2497
|
+
case 34:
|
|
2498
|
+
case 58:
|
|
2499
|
+
case 44:
|
|
2500
|
+
case 47:
|
|
2501
|
+
return false;
|
|
2502
|
+
}
|
|
2503
|
+
return true;
|
|
2504
|
+
}
|
|
2505
|
+
function scanNextNonTrivia() {
|
|
2506
|
+
let result;
|
|
2507
|
+
do {
|
|
2508
|
+
result = scanNext();
|
|
2509
|
+
} while (result >= 12 && result <= 15);
|
|
2510
|
+
return result;
|
|
2511
|
+
}
|
|
2512
|
+
return {
|
|
2513
|
+
setPosition,
|
|
2514
|
+
getPosition: () => pos,
|
|
2515
|
+
scan: ignoreTrivia ? scanNextNonTrivia : scanNext,
|
|
2516
|
+
getToken: () => token,
|
|
2517
|
+
getTokenValue: () => value,
|
|
2518
|
+
getTokenOffset: () => tokenOffset,
|
|
2519
|
+
getTokenLength: () => pos - tokenOffset,
|
|
2520
|
+
getTokenStartLine: () => lineStartOffset,
|
|
2521
|
+
getTokenStartCharacter: () => tokenOffset - prevTokenLineStartOffset,
|
|
2522
|
+
getTokenError: () => scanError
|
|
2523
|
+
};
|
|
2524
|
+
}
|
|
2525
|
+
function isWhiteSpace(ch) {
|
|
2526
|
+
return ch === 32 || ch === 9;
|
|
2527
|
+
}
|
|
2528
|
+
function isLineBreak(ch) {
|
|
2529
|
+
return ch === 10 || ch === 13;
|
|
2530
|
+
}
|
|
2531
|
+
function isDigit(ch) {
|
|
2532
|
+
return ch >= 48 && ch <= 57;
|
|
2533
|
+
}
|
|
2534
|
+
var CharacterCodes;
|
|
2535
|
+
(function(CharacterCodes2) {
|
|
2536
|
+
CharacterCodes2[CharacterCodes2["lineFeed"] = 10] = "lineFeed";
|
|
2537
|
+
CharacterCodes2[CharacterCodes2["carriageReturn"] = 13] = "carriageReturn";
|
|
2538
|
+
CharacterCodes2[CharacterCodes2["space"] = 32] = "space";
|
|
2539
|
+
CharacterCodes2[CharacterCodes2["_0"] = 48] = "_0";
|
|
2540
|
+
CharacterCodes2[CharacterCodes2["_1"] = 49] = "_1";
|
|
2541
|
+
CharacterCodes2[CharacterCodes2["_2"] = 50] = "_2";
|
|
2542
|
+
CharacterCodes2[CharacterCodes2["_3"] = 51] = "_3";
|
|
2543
|
+
CharacterCodes2[CharacterCodes2["_4"] = 52] = "_4";
|
|
2544
|
+
CharacterCodes2[CharacterCodes2["_5"] = 53] = "_5";
|
|
2545
|
+
CharacterCodes2[CharacterCodes2["_6"] = 54] = "_6";
|
|
2546
|
+
CharacterCodes2[CharacterCodes2["_7"] = 55] = "_7";
|
|
2547
|
+
CharacterCodes2[CharacterCodes2["_8"] = 56] = "_8";
|
|
2548
|
+
CharacterCodes2[CharacterCodes2["_9"] = 57] = "_9";
|
|
2549
|
+
CharacterCodes2[CharacterCodes2["a"] = 97] = "a";
|
|
2550
|
+
CharacterCodes2[CharacterCodes2["b"] = 98] = "b";
|
|
2551
|
+
CharacterCodes2[CharacterCodes2["c"] = 99] = "c";
|
|
2552
|
+
CharacterCodes2[CharacterCodes2["d"] = 100] = "d";
|
|
2553
|
+
CharacterCodes2[CharacterCodes2["e"] = 101] = "e";
|
|
2554
|
+
CharacterCodes2[CharacterCodes2["f"] = 102] = "f";
|
|
2555
|
+
CharacterCodes2[CharacterCodes2["g"] = 103] = "g";
|
|
2556
|
+
CharacterCodes2[CharacterCodes2["h"] = 104] = "h";
|
|
2557
|
+
CharacterCodes2[CharacterCodes2["i"] = 105] = "i";
|
|
2558
|
+
CharacterCodes2[CharacterCodes2["j"] = 106] = "j";
|
|
2559
|
+
CharacterCodes2[CharacterCodes2["k"] = 107] = "k";
|
|
2560
|
+
CharacterCodes2[CharacterCodes2["l"] = 108] = "l";
|
|
2561
|
+
CharacterCodes2[CharacterCodes2["m"] = 109] = "m";
|
|
2562
|
+
CharacterCodes2[CharacterCodes2["n"] = 110] = "n";
|
|
2563
|
+
CharacterCodes2[CharacterCodes2["o"] = 111] = "o";
|
|
2564
|
+
CharacterCodes2[CharacterCodes2["p"] = 112] = "p";
|
|
2565
|
+
CharacterCodes2[CharacterCodes2["q"] = 113] = "q";
|
|
2566
|
+
CharacterCodes2[CharacterCodes2["r"] = 114] = "r";
|
|
2567
|
+
CharacterCodes2[CharacterCodes2["s"] = 115] = "s";
|
|
2568
|
+
CharacterCodes2[CharacterCodes2["t"] = 116] = "t";
|
|
2569
|
+
CharacterCodes2[CharacterCodes2["u"] = 117] = "u";
|
|
2570
|
+
CharacterCodes2[CharacterCodes2["v"] = 118] = "v";
|
|
2571
|
+
CharacterCodes2[CharacterCodes2["w"] = 119] = "w";
|
|
2572
|
+
CharacterCodes2[CharacterCodes2["x"] = 120] = "x";
|
|
2573
|
+
CharacterCodes2[CharacterCodes2["y"] = 121] = "y";
|
|
2574
|
+
CharacterCodes2[CharacterCodes2["z"] = 122] = "z";
|
|
2575
|
+
CharacterCodes2[CharacterCodes2["A"] = 65] = "A";
|
|
2576
|
+
CharacterCodes2[CharacterCodes2["B"] = 66] = "B";
|
|
2577
|
+
CharacterCodes2[CharacterCodes2["C"] = 67] = "C";
|
|
2578
|
+
CharacterCodes2[CharacterCodes2["D"] = 68] = "D";
|
|
2579
|
+
CharacterCodes2[CharacterCodes2["E"] = 69] = "E";
|
|
2580
|
+
CharacterCodes2[CharacterCodes2["F"] = 70] = "F";
|
|
2581
|
+
CharacterCodes2[CharacterCodes2["G"] = 71] = "G";
|
|
2582
|
+
CharacterCodes2[CharacterCodes2["H"] = 72] = "H";
|
|
2583
|
+
CharacterCodes2[CharacterCodes2["I"] = 73] = "I";
|
|
2584
|
+
CharacterCodes2[CharacterCodes2["J"] = 74] = "J";
|
|
2585
|
+
CharacterCodes2[CharacterCodes2["K"] = 75] = "K";
|
|
2586
|
+
CharacterCodes2[CharacterCodes2["L"] = 76] = "L";
|
|
2587
|
+
CharacterCodes2[CharacterCodes2["M"] = 77] = "M";
|
|
2588
|
+
CharacterCodes2[CharacterCodes2["N"] = 78] = "N";
|
|
2589
|
+
CharacterCodes2[CharacterCodes2["O"] = 79] = "O";
|
|
2590
|
+
CharacterCodes2[CharacterCodes2["P"] = 80] = "P";
|
|
2591
|
+
CharacterCodes2[CharacterCodes2["Q"] = 81] = "Q";
|
|
2592
|
+
CharacterCodes2[CharacterCodes2["R"] = 82] = "R";
|
|
2593
|
+
CharacterCodes2[CharacterCodes2["S"] = 83] = "S";
|
|
2594
|
+
CharacterCodes2[CharacterCodes2["T"] = 84] = "T";
|
|
2595
|
+
CharacterCodes2[CharacterCodes2["U"] = 85] = "U";
|
|
2596
|
+
CharacterCodes2[CharacterCodes2["V"] = 86] = "V";
|
|
2597
|
+
CharacterCodes2[CharacterCodes2["W"] = 87] = "W";
|
|
2598
|
+
CharacterCodes2[CharacterCodes2["X"] = 88] = "X";
|
|
2599
|
+
CharacterCodes2[CharacterCodes2["Y"] = 89] = "Y";
|
|
2600
|
+
CharacterCodes2[CharacterCodes2["Z"] = 90] = "Z";
|
|
2601
|
+
CharacterCodes2[CharacterCodes2["asterisk"] = 42] = "asterisk";
|
|
2602
|
+
CharacterCodes2[CharacterCodes2["backslash"] = 92] = "backslash";
|
|
2603
|
+
CharacterCodes2[CharacterCodes2["closeBrace"] = 125] = "closeBrace";
|
|
2604
|
+
CharacterCodes2[CharacterCodes2["closeBracket"] = 93] = "closeBracket";
|
|
2605
|
+
CharacterCodes2[CharacterCodes2["colon"] = 58] = "colon";
|
|
2606
|
+
CharacterCodes2[CharacterCodes2["comma"] = 44] = "comma";
|
|
2607
|
+
CharacterCodes2[CharacterCodes2["dot"] = 46] = "dot";
|
|
2608
|
+
CharacterCodes2[CharacterCodes2["doubleQuote"] = 34] = "doubleQuote";
|
|
2609
|
+
CharacterCodes2[CharacterCodes2["minus"] = 45] = "minus";
|
|
2610
|
+
CharacterCodes2[CharacterCodes2["openBrace"] = 123] = "openBrace";
|
|
2611
|
+
CharacterCodes2[CharacterCodes2["openBracket"] = 91] = "openBracket";
|
|
2612
|
+
CharacterCodes2[CharacterCodes2["plus"] = 43] = "plus";
|
|
2613
|
+
CharacterCodes2[CharacterCodes2["slash"] = 47] = "slash";
|
|
2614
|
+
CharacterCodes2[CharacterCodes2["formFeed"] = 12] = "formFeed";
|
|
2615
|
+
CharacterCodes2[CharacterCodes2["tab"] = 9] = "tab";
|
|
2616
|
+
})(CharacterCodes || (CharacterCodes = {}));
|
|
2617
|
+
|
|
2618
|
+
// node_modules/jsonc-parser/lib/esm/impl/string-intern.js
|
|
2619
|
+
var cachedSpaces = new Array(20).fill(0).map((_, index) => {
|
|
2620
|
+
return " ".repeat(index);
|
|
2621
|
+
});
|
|
2622
|
+
var maxCachedValues = 200;
|
|
2623
|
+
var cachedBreakLinesWithSpaces = {
|
|
2624
|
+
" ": {
|
|
2625
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2626
|
+
return `
|
|
2627
|
+
` + " ".repeat(index);
|
|
2628
|
+
}),
|
|
2629
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2630
|
+
return "\r" + " ".repeat(index);
|
|
2631
|
+
}),
|
|
2632
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2633
|
+
return `\r
|
|
2634
|
+
` + " ".repeat(index);
|
|
2635
|
+
})
|
|
2636
|
+
},
|
|
2637
|
+
"\t": {
|
|
2638
|
+
"\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2639
|
+
return `
|
|
2640
|
+
` + "\t".repeat(index);
|
|
2641
|
+
}),
|
|
2642
|
+
"\r": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2643
|
+
return "\r" + "\t".repeat(index);
|
|
2644
|
+
}),
|
|
2645
|
+
"\r\n": new Array(maxCachedValues).fill(0).map((_, index) => {
|
|
2646
|
+
return `\r
|
|
2647
|
+
` + "\t".repeat(index);
|
|
2648
|
+
})
|
|
2649
|
+
}
|
|
2650
|
+
};
|
|
2651
|
+
var supportedEols = [`
|
|
2652
|
+
`, "\r", `\r
|
|
2653
|
+
`];
|
|
2654
|
+
|
|
2655
|
+
// node_modules/jsonc-parser/lib/esm/impl/format.js
|
|
2656
|
+
function format(documentText, range, options) {
|
|
2657
|
+
let initialIndentLevel;
|
|
2658
|
+
let formatText;
|
|
2659
|
+
let formatTextStart;
|
|
2660
|
+
let rangeStart;
|
|
2661
|
+
let rangeEnd;
|
|
2662
|
+
if (range) {
|
|
2663
|
+
rangeStart = range.offset;
|
|
2664
|
+
rangeEnd = rangeStart + range.length;
|
|
2665
|
+
formatTextStart = rangeStart;
|
|
2666
|
+
while (formatTextStart > 0 && !isEOL(documentText, formatTextStart - 1)) {
|
|
2667
|
+
formatTextStart--;
|
|
2668
|
+
}
|
|
2669
|
+
let endOffset = rangeEnd;
|
|
2670
|
+
while (endOffset < documentText.length && !isEOL(documentText, endOffset)) {
|
|
2671
|
+
endOffset++;
|
|
2672
|
+
}
|
|
2673
|
+
formatText = documentText.substring(formatTextStart, endOffset);
|
|
2674
|
+
initialIndentLevel = computeIndentLevel(formatText, options);
|
|
2675
|
+
} else {
|
|
2676
|
+
formatText = documentText;
|
|
2677
|
+
initialIndentLevel = 0;
|
|
2678
|
+
formatTextStart = 0;
|
|
2679
|
+
rangeStart = 0;
|
|
2680
|
+
rangeEnd = documentText.length;
|
|
2681
|
+
}
|
|
2682
|
+
const eol = getEOL(options, documentText);
|
|
2683
|
+
const eolFastPathSupported = supportedEols.includes(eol);
|
|
2684
|
+
let numberLineBreaks = 0;
|
|
2685
|
+
let indentLevel = 0;
|
|
2686
|
+
let indentValue;
|
|
2687
|
+
if (options.insertSpaces) {
|
|
2688
|
+
indentValue = cachedSpaces[options.tabSize || 4] ?? repeat(cachedSpaces[1], options.tabSize || 4);
|
|
2689
|
+
} else {
|
|
2690
|
+
indentValue = "\t";
|
|
2691
|
+
}
|
|
2692
|
+
const indentType = indentValue === "\t" ? "\t" : " ";
|
|
2693
|
+
let scanner = createScanner(formatText, false);
|
|
2694
|
+
let hasError = false;
|
|
2695
|
+
function newLinesAndIndent() {
|
|
2696
|
+
if (numberLineBreaks > 1) {
|
|
2697
|
+
return repeat(eol, numberLineBreaks) + repeat(indentValue, initialIndentLevel + indentLevel);
|
|
2698
|
+
}
|
|
2699
|
+
const amountOfSpaces = indentValue.length * (initialIndentLevel + indentLevel);
|
|
2700
|
+
if (!eolFastPathSupported || amountOfSpaces > cachedBreakLinesWithSpaces[indentType][eol].length) {
|
|
2701
|
+
return eol + repeat(indentValue, initialIndentLevel + indentLevel);
|
|
2702
|
+
}
|
|
2703
|
+
if (amountOfSpaces <= 0) {
|
|
2704
|
+
return eol;
|
|
2705
|
+
}
|
|
2706
|
+
return cachedBreakLinesWithSpaces[indentType][eol][amountOfSpaces];
|
|
2707
|
+
}
|
|
2708
|
+
function scanNext() {
|
|
2709
|
+
let token = scanner.scan();
|
|
2710
|
+
numberLineBreaks = 0;
|
|
2711
|
+
while (token === 15 || token === 14) {
|
|
2712
|
+
if (token === 14 && options.keepLines) {
|
|
2713
|
+
numberLineBreaks += 1;
|
|
2714
|
+
} else if (token === 14) {
|
|
2715
|
+
numberLineBreaks = 1;
|
|
2716
|
+
}
|
|
2717
|
+
token = scanner.scan();
|
|
2718
|
+
}
|
|
2719
|
+
hasError = token === 16 || scanner.getTokenError() !== 0;
|
|
2720
|
+
return token;
|
|
2721
|
+
}
|
|
2722
|
+
const editOperations = [];
|
|
2723
|
+
function addEdit(text, startOffset, endOffset) {
|
|
2724
|
+
if (!hasError && (!range || startOffset < rangeEnd && endOffset > rangeStart) && documentText.substring(startOffset, endOffset) !== text) {
|
|
2725
|
+
editOperations.push({ offset: startOffset, length: endOffset - startOffset, content: text });
|
|
2726
|
+
}
|
|
2727
|
+
}
|
|
2728
|
+
let firstToken = scanNext();
|
|
2729
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
2730
|
+
addEdit(repeat(eol, numberLineBreaks), 0, 0);
|
|
2731
|
+
}
|
|
2732
|
+
if (firstToken !== 17) {
|
|
2733
|
+
let firstTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
2734
|
+
let initialIndent = indentValue.length * initialIndentLevel < 20 && options.insertSpaces ? cachedSpaces[indentValue.length * initialIndentLevel] : repeat(indentValue, initialIndentLevel);
|
|
2735
|
+
addEdit(initialIndent, formatTextStart, firstTokenStart);
|
|
2736
|
+
}
|
|
2737
|
+
while (firstToken !== 17) {
|
|
2738
|
+
let firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
2739
|
+
let secondToken = scanNext();
|
|
2740
|
+
let replaceContent = "";
|
|
2741
|
+
let needsLineBreak = false;
|
|
2742
|
+
while (numberLineBreaks === 0 && (secondToken === 12 || secondToken === 13)) {
|
|
2743
|
+
let commentTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
2744
|
+
addEdit(cachedSpaces[1], firstTokenEnd, commentTokenStart);
|
|
2745
|
+
firstTokenEnd = scanner.getTokenOffset() + scanner.getTokenLength() + formatTextStart;
|
|
2746
|
+
needsLineBreak = secondToken === 12;
|
|
2747
|
+
replaceContent = needsLineBreak ? newLinesAndIndent() : "";
|
|
2748
|
+
secondToken = scanNext();
|
|
2749
|
+
}
|
|
2750
|
+
if (secondToken === 2) {
|
|
2751
|
+
if (firstToken !== 1) {
|
|
2752
|
+
indentLevel--;
|
|
2753
|
+
}
|
|
2754
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 1) {
|
|
2755
|
+
replaceContent = newLinesAndIndent();
|
|
2756
|
+
} else if (options.keepLines) {
|
|
2757
|
+
replaceContent = cachedSpaces[1];
|
|
2758
|
+
}
|
|
2759
|
+
} else if (secondToken === 4) {
|
|
2760
|
+
if (firstToken !== 3) {
|
|
2761
|
+
indentLevel--;
|
|
2762
|
+
}
|
|
2763
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines && firstToken !== 3) {
|
|
2764
|
+
replaceContent = newLinesAndIndent();
|
|
2765
|
+
} else if (options.keepLines) {
|
|
2766
|
+
replaceContent = cachedSpaces[1];
|
|
2767
|
+
}
|
|
2768
|
+
} else {
|
|
2769
|
+
switch (firstToken) {
|
|
2770
|
+
case 3:
|
|
2771
|
+
case 1:
|
|
2772
|
+
indentLevel++;
|
|
2773
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
|
|
2774
|
+
replaceContent = newLinesAndIndent();
|
|
2775
|
+
} else {
|
|
2776
|
+
replaceContent = cachedSpaces[1];
|
|
2777
|
+
}
|
|
2778
|
+
break;
|
|
2779
|
+
case 5:
|
|
2780
|
+
if (options.keepLines && numberLineBreaks > 0 || !options.keepLines) {
|
|
2781
|
+
replaceContent = newLinesAndIndent();
|
|
2782
|
+
} else {
|
|
2783
|
+
replaceContent = cachedSpaces[1];
|
|
2784
|
+
}
|
|
2785
|
+
break;
|
|
2786
|
+
case 12:
|
|
2787
|
+
replaceContent = newLinesAndIndent();
|
|
2788
|
+
break;
|
|
2789
|
+
case 13:
|
|
2790
|
+
if (numberLineBreaks > 0) {
|
|
2791
|
+
replaceContent = newLinesAndIndent();
|
|
2792
|
+
} else if (!needsLineBreak) {
|
|
2793
|
+
replaceContent = cachedSpaces[1];
|
|
2794
|
+
}
|
|
2795
|
+
break;
|
|
2796
|
+
case 6:
|
|
2797
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
2798
|
+
replaceContent = newLinesAndIndent();
|
|
2799
|
+
} else if (!needsLineBreak) {
|
|
2800
|
+
replaceContent = cachedSpaces[1];
|
|
2801
|
+
}
|
|
2802
|
+
break;
|
|
2803
|
+
case 10:
|
|
2804
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
2805
|
+
replaceContent = newLinesAndIndent();
|
|
2806
|
+
} else if (secondToken === 6 && !needsLineBreak) {
|
|
2807
|
+
replaceContent = "";
|
|
2808
|
+
}
|
|
2809
|
+
break;
|
|
2810
|
+
case 7:
|
|
2811
|
+
case 8:
|
|
2812
|
+
case 9:
|
|
2813
|
+
case 11:
|
|
2814
|
+
case 2:
|
|
2815
|
+
case 4:
|
|
2816
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
2817
|
+
replaceContent = newLinesAndIndent();
|
|
2818
|
+
} else {
|
|
2819
|
+
if ((secondToken === 12 || secondToken === 13) && !needsLineBreak) {
|
|
2820
|
+
replaceContent = cachedSpaces[1];
|
|
2821
|
+
} else if (secondToken !== 5 && secondToken !== 17) {
|
|
2822
|
+
hasError = true;
|
|
2823
|
+
}
|
|
2824
|
+
}
|
|
2825
|
+
break;
|
|
2826
|
+
case 16:
|
|
2827
|
+
hasError = true;
|
|
2828
|
+
break;
|
|
2829
|
+
}
|
|
2830
|
+
if (numberLineBreaks > 0 && (secondToken === 12 || secondToken === 13)) {
|
|
2831
|
+
replaceContent = newLinesAndIndent();
|
|
2832
|
+
}
|
|
2833
|
+
}
|
|
2834
|
+
if (secondToken === 17) {
|
|
2835
|
+
if (options.keepLines && numberLineBreaks > 0) {
|
|
2836
|
+
replaceContent = newLinesAndIndent();
|
|
2837
|
+
} else {
|
|
2838
|
+
replaceContent = options.insertFinalNewline ? eol : "";
|
|
2839
|
+
}
|
|
2840
|
+
}
|
|
2841
|
+
const secondTokenStart = scanner.getTokenOffset() + formatTextStart;
|
|
2842
|
+
addEdit(replaceContent, firstTokenEnd, secondTokenStart);
|
|
2843
|
+
firstToken = secondToken;
|
|
2844
|
+
}
|
|
2845
|
+
return editOperations;
|
|
2846
|
+
}
|
|
2847
|
+
function repeat(s, count) {
|
|
2848
|
+
let result = "";
|
|
2849
|
+
for (let i = 0;i < count; i++) {
|
|
2850
|
+
result += s;
|
|
2851
|
+
}
|
|
2852
|
+
return result;
|
|
2853
|
+
}
|
|
2854
|
+
function computeIndentLevel(content, options) {
|
|
2855
|
+
let i = 0;
|
|
2856
|
+
let nChars = 0;
|
|
2857
|
+
const tabSize = options.tabSize || 4;
|
|
2858
|
+
while (i < content.length) {
|
|
2859
|
+
let ch = content.charAt(i);
|
|
2860
|
+
if (ch === cachedSpaces[1]) {
|
|
2861
|
+
nChars++;
|
|
2862
|
+
} else if (ch === "\t") {
|
|
2863
|
+
nChars += tabSize;
|
|
2864
|
+
} else {
|
|
2865
|
+
break;
|
|
2866
|
+
}
|
|
2867
|
+
i++;
|
|
2868
|
+
}
|
|
2869
|
+
return Math.floor(nChars / tabSize);
|
|
2870
|
+
}
|
|
2871
|
+
function getEOL(options, text) {
|
|
2872
|
+
for (let i = 0;i < text.length; i++) {
|
|
2873
|
+
const ch = text.charAt(i);
|
|
2874
|
+
if (ch === "\r") {
|
|
2875
|
+
if (i + 1 < text.length && text.charAt(i + 1) === `
|
|
2876
|
+
`) {
|
|
2877
|
+
return `\r
|
|
2878
|
+
`;
|
|
2879
|
+
}
|
|
2880
|
+
return "\r";
|
|
2881
|
+
} else if (ch === `
|
|
2882
|
+
`) {
|
|
2883
|
+
return `
|
|
2884
|
+
`;
|
|
2885
|
+
}
|
|
2886
|
+
}
|
|
2887
|
+
return options && options.eol || `
|
|
2888
|
+
`;
|
|
2889
|
+
}
|
|
2890
|
+
function isEOL(text, offset) {
|
|
2891
|
+
return `\r
|
|
2892
|
+
`.indexOf(text.charAt(offset)) !== -1;
|
|
2893
|
+
}
|
|
2894
|
+
|
|
2895
|
+
// node_modules/jsonc-parser/lib/esm/impl/parser.js
|
|
2896
|
+
var ParseOptions;
|
|
2897
|
+
(function(ParseOptions2) {
|
|
2898
|
+
ParseOptions2.DEFAULT = {
|
|
2899
|
+
allowTrailingComma: false
|
|
2900
|
+
};
|
|
2901
|
+
})(ParseOptions || (ParseOptions = {}));
|
|
2902
|
+
function parse(text, errors2 = [], options = ParseOptions.DEFAULT) {
|
|
2903
|
+
let currentProperty = null;
|
|
2904
|
+
let currentParent = [];
|
|
2905
|
+
const previousParents = [];
|
|
2906
|
+
function onValue(value) {
|
|
2907
|
+
if (Array.isArray(currentParent)) {
|
|
2908
|
+
currentParent.push(value);
|
|
2909
|
+
} else if (currentProperty !== null) {
|
|
2910
|
+
currentParent[currentProperty] = value;
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
const visitor = {
|
|
2914
|
+
onObjectBegin: () => {
|
|
2915
|
+
const object = {};
|
|
2916
|
+
onValue(object);
|
|
2917
|
+
previousParents.push(currentParent);
|
|
2918
|
+
currentParent = object;
|
|
2919
|
+
currentProperty = null;
|
|
2920
|
+
},
|
|
2921
|
+
onObjectProperty: (name) => {
|
|
2922
|
+
currentProperty = name;
|
|
2923
|
+
},
|
|
2924
|
+
onObjectEnd: () => {
|
|
2925
|
+
currentParent = previousParents.pop();
|
|
2926
|
+
},
|
|
2927
|
+
onArrayBegin: () => {
|
|
2928
|
+
const array = [];
|
|
2929
|
+
onValue(array);
|
|
2930
|
+
previousParents.push(currentParent);
|
|
2931
|
+
currentParent = array;
|
|
2932
|
+
currentProperty = null;
|
|
2933
|
+
},
|
|
2934
|
+
onArrayEnd: () => {
|
|
2935
|
+
currentParent = previousParents.pop();
|
|
2936
|
+
},
|
|
2937
|
+
onLiteralValue: onValue,
|
|
2938
|
+
onError: (error, offset, length) => {
|
|
2939
|
+
errors2.push({ error, offset, length });
|
|
2940
|
+
}
|
|
2941
|
+
};
|
|
2942
|
+
visit(text, visitor, options);
|
|
2943
|
+
return currentParent[0];
|
|
2944
|
+
}
|
|
2945
|
+
function parseTree(text, errors2 = [], options = ParseOptions.DEFAULT) {
|
|
2946
|
+
let currentParent = { type: "array", offset: -1, length: -1, children: [], parent: undefined };
|
|
2947
|
+
function ensurePropertyComplete(endOffset) {
|
|
2948
|
+
if (currentParent.type === "property") {
|
|
2949
|
+
currentParent.length = endOffset - currentParent.offset;
|
|
2950
|
+
currentParent = currentParent.parent;
|
|
2951
|
+
}
|
|
2952
|
+
}
|
|
2953
|
+
function onValue(valueNode) {
|
|
2954
|
+
currentParent.children.push(valueNode);
|
|
2955
|
+
return valueNode;
|
|
2956
|
+
}
|
|
2957
|
+
const visitor = {
|
|
2958
|
+
onObjectBegin: (offset) => {
|
|
2959
|
+
currentParent = onValue({ type: "object", offset, length: -1, parent: currentParent, children: [] });
|
|
2960
|
+
},
|
|
2961
|
+
onObjectProperty: (name, offset, length) => {
|
|
2962
|
+
currentParent = onValue({ type: "property", offset, length: -1, parent: currentParent, children: [] });
|
|
2963
|
+
currentParent.children.push({ type: "string", value: name, offset, length, parent: currentParent });
|
|
2964
|
+
},
|
|
2965
|
+
onObjectEnd: (offset, length) => {
|
|
2966
|
+
ensurePropertyComplete(offset + length);
|
|
2967
|
+
currentParent.length = offset + length - currentParent.offset;
|
|
2968
|
+
currentParent = currentParent.parent;
|
|
2969
|
+
ensurePropertyComplete(offset + length);
|
|
2970
|
+
},
|
|
2971
|
+
onArrayBegin: (offset, length) => {
|
|
2972
|
+
currentParent = onValue({ type: "array", offset, length: -1, parent: currentParent, children: [] });
|
|
2973
|
+
},
|
|
2974
|
+
onArrayEnd: (offset, length) => {
|
|
2975
|
+
currentParent.length = offset + length - currentParent.offset;
|
|
2976
|
+
currentParent = currentParent.parent;
|
|
2977
|
+
ensurePropertyComplete(offset + length);
|
|
2978
|
+
},
|
|
2979
|
+
onLiteralValue: (value, offset, length) => {
|
|
2980
|
+
onValue({ type: getNodeType(value), offset, length, parent: currentParent, value });
|
|
2981
|
+
ensurePropertyComplete(offset + length);
|
|
2982
|
+
},
|
|
2983
|
+
onSeparator: (sep, offset, length) => {
|
|
2984
|
+
if (currentParent.type === "property") {
|
|
2985
|
+
if (sep === ":") {
|
|
2986
|
+
currentParent.colonOffset = offset;
|
|
2987
|
+
} else if (sep === ",") {
|
|
2988
|
+
ensurePropertyComplete(offset);
|
|
2989
|
+
}
|
|
2990
|
+
}
|
|
2991
|
+
},
|
|
2992
|
+
onError: (error, offset, length) => {
|
|
2993
|
+
errors2.push({ error, offset, length });
|
|
2994
|
+
}
|
|
2995
|
+
};
|
|
2996
|
+
visit(text, visitor, options);
|
|
2997
|
+
const result = currentParent.children[0];
|
|
2998
|
+
if (result) {
|
|
2999
|
+
delete result.parent;
|
|
3000
|
+
}
|
|
3001
|
+
return result;
|
|
3002
|
+
}
|
|
3003
|
+
function findNodeAtLocation(root, path2) {
|
|
3004
|
+
if (!root) {
|
|
3005
|
+
return;
|
|
3006
|
+
}
|
|
3007
|
+
let node = root;
|
|
3008
|
+
for (let segment of path2) {
|
|
3009
|
+
if (typeof segment === "string") {
|
|
3010
|
+
if (node.type !== "object" || !Array.isArray(node.children)) {
|
|
3011
|
+
return;
|
|
3012
|
+
}
|
|
3013
|
+
let found = false;
|
|
3014
|
+
for (const propertyNode of node.children) {
|
|
3015
|
+
if (Array.isArray(propertyNode.children) && propertyNode.children[0].value === segment && propertyNode.children.length === 2) {
|
|
3016
|
+
node = propertyNode.children[1];
|
|
3017
|
+
found = true;
|
|
3018
|
+
break;
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
if (!found) {
|
|
3022
|
+
return;
|
|
3023
|
+
}
|
|
3024
|
+
} else {
|
|
3025
|
+
const index = segment;
|
|
3026
|
+
if (node.type !== "array" || index < 0 || !Array.isArray(node.children) || index >= node.children.length) {
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
node = node.children[index];
|
|
3030
|
+
}
|
|
3031
|
+
}
|
|
3032
|
+
return node;
|
|
3033
|
+
}
|
|
3034
|
+
function visit(text, visitor, options = ParseOptions.DEFAULT) {
|
|
3035
|
+
const _scanner = createScanner(text, false);
|
|
3036
|
+
const _jsonPath = [];
|
|
3037
|
+
let suppressedCallbacks = 0;
|
|
3038
|
+
function toNoArgVisit(visitFunction) {
|
|
3039
|
+
return visitFunction ? () => suppressedCallbacks === 0 && visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
3040
|
+
}
|
|
3041
|
+
function toOneArgVisit(visitFunction) {
|
|
3042
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter()) : () => true;
|
|
3043
|
+
}
|
|
3044
|
+
function toOneArgVisitWithPath(visitFunction) {
|
|
3045
|
+
return visitFunction ? (arg) => suppressedCallbacks === 0 && visitFunction(arg, _scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice()) : () => true;
|
|
3046
|
+
}
|
|
3047
|
+
function toBeginVisit(visitFunction) {
|
|
3048
|
+
return visitFunction ? () => {
|
|
3049
|
+
if (suppressedCallbacks > 0) {
|
|
3050
|
+
suppressedCallbacks++;
|
|
3051
|
+
} else {
|
|
3052
|
+
let cbReturn = visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter(), () => _jsonPath.slice());
|
|
3053
|
+
if (cbReturn === false) {
|
|
3054
|
+
suppressedCallbacks = 1;
|
|
3055
|
+
}
|
|
3056
|
+
}
|
|
3057
|
+
} : () => true;
|
|
3058
|
+
}
|
|
3059
|
+
function toEndVisit(visitFunction) {
|
|
3060
|
+
return visitFunction ? () => {
|
|
3061
|
+
if (suppressedCallbacks > 0) {
|
|
3062
|
+
suppressedCallbacks--;
|
|
3063
|
+
}
|
|
3064
|
+
if (suppressedCallbacks === 0) {
|
|
3065
|
+
visitFunction(_scanner.getTokenOffset(), _scanner.getTokenLength(), _scanner.getTokenStartLine(), _scanner.getTokenStartCharacter());
|
|
3066
|
+
}
|
|
3067
|
+
} : () => true;
|
|
3068
|
+
}
|
|
3069
|
+
const onObjectBegin = toBeginVisit(visitor.onObjectBegin), onObjectProperty = toOneArgVisitWithPath(visitor.onObjectProperty), onObjectEnd = toEndVisit(visitor.onObjectEnd), onArrayBegin = toBeginVisit(visitor.onArrayBegin), onArrayEnd = toEndVisit(visitor.onArrayEnd), onLiteralValue = toOneArgVisitWithPath(visitor.onLiteralValue), onSeparator = toOneArgVisit(visitor.onSeparator), onComment = toNoArgVisit(visitor.onComment), onError = toOneArgVisit(visitor.onError);
|
|
3070
|
+
const disallowComments = options && options.disallowComments;
|
|
3071
|
+
const allowTrailingComma = options && options.allowTrailingComma;
|
|
3072
|
+
function scanNext() {
|
|
3073
|
+
while (true) {
|
|
3074
|
+
const token = _scanner.scan();
|
|
3075
|
+
switch (_scanner.getTokenError()) {
|
|
3076
|
+
case 4:
|
|
3077
|
+
handleError(14);
|
|
3078
|
+
break;
|
|
3079
|
+
case 5:
|
|
3080
|
+
handleError(15);
|
|
3081
|
+
break;
|
|
3082
|
+
case 3:
|
|
3083
|
+
handleError(13);
|
|
3084
|
+
break;
|
|
3085
|
+
case 1:
|
|
3086
|
+
if (!disallowComments) {
|
|
3087
|
+
handleError(11);
|
|
3088
|
+
}
|
|
3089
|
+
break;
|
|
3090
|
+
case 2:
|
|
3091
|
+
handleError(12);
|
|
3092
|
+
break;
|
|
3093
|
+
case 6:
|
|
3094
|
+
handleError(16);
|
|
3095
|
+
break;
|
|
3096
|
+
}
|
|
3097
|
+
switch (token) {
|
|
3098
|
+
case 12:
|
|
3099
|
+
case 13:
|
|
3100
|
+
if (disallowComments) {
|
|
3101
|
+
handleError(10);
|
|
3102
|
+
} else {
|
|
3103
|
+
onComment();
|
|
3104
|
+
}
|
|
3105
|
+
break;
|
|
3106
|
+
case 16:
|
|
3107
|
+
handleError(1);
|
|
3108
|
+
break;
|
|
3109
|
+
case 15:
|
|
3110
|
+
case 14:
|
|
3111
|
+
break;
|
|
3112
|
+
default:
|
|
3113
|
+
return token;
|
|
3114
|
+
}
|
|
3115
|
+
}
|
|
3116
|
+
}
|
|
3117
|
+
function handleError(error, skipUntilAfter = [], skipUntil = []) {
|
|
3118
|
+
onError(error);
|
|
3119
|
+
if (skipUntilAfter.length + skipUntil.length > 0) {
|
|
3120
|
+
let token = _scanner.getToken();
|
|
3121
|
+
while (token !== 17) {
|
|
3122
|
+
if (skipUntilAfter.indexOf(token) !== -1) {
|
|
3123
|
+
scanNext();
|
|
3124
|
+
break;
|
|
3125
|
+
} else if (skipUntil.indexOf(token) !== -1) {
|
|
3126
|
+
break;
|
|
3127
|
+
}
|
|
3128
|
+
token = scanNext();
|
|
3129
|
+
}
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
function parseString(isValue) {
|
|
3133
|
+
const value = _scanner.getTokenValue();
|
|
3134
|
+
if (isValue) {
|
|
3135
|
+
onLiteralValue(value);
|
|
3136
|
+
} else {
|
|
3137
|
+
onObjectProperty(value);
|
|
3138
|
+
_jsonPath.push(value);
|
|
3139
|
+
}
|
|
3140
|
+
scanNext();
|
|
3141
|
+
return true;
|
|
3142
|
+
}
|
|
3143
|
+
function parseLiteral() {
|
|
3144
|
+
switch (_scanner.getToken()) {
|
|
3145
|
+
case 11:
|
|
3146
|
+
const tokenValue = _scanner.getTokenValue();
|
|
3147
|
+
let value = Number(tokenValue);
|
|
3148
|
+
if (isNaN(value)) {
|
|
3149
|
+
handleError(2);
|
|
3150
|
+
value = 0;
|
|
3151
|
+
}
|
|
3152
|
+
onLiteralValue(value);
|
|
3153
|
+
break;
|
|
3154
|
+
case 7:
|
|
3155
|
+
onLiteralValue(null);
|
|
3156
|
+
break;
|
|
3157
|
+
case 8:
|
|
3158
|
+
onLiteralValue(true);
|
|
3159
|
+
break;
|
|
3160
|
+
case 9:
|
|
3161
|
+
onLiteralValue(false);
|
|
3162
|
+
break;
|
|
3163
|
+
default:
|
|
3164
|
+
return false;
|
|
3165
|
+
}
|
|
3166
|
+
scanNext();
|
|
3167
|
+
return true;
|
|
3168
|
+
}
|
|
3169
|
+
function parseProperty() {
|
|
3170
|
+
if (_scanner.getToken() !== 10) {
|
|
3171
|
+
handleError(3, [], [2, 5]);
|
|
3172
|
+
return false;
|
|
3173
|
+
}
|
|
3174
|
+
parseString(false);
|
|
3175
|
+
if (_scanner.getToken() === 6) {
|
|
3176
|
+
onSeparator(":");
|
|
3177
|
+
scanNext();
|
|
3178
|
+
if (!parseValue()) {
|
|
3179
|
+
handleError(4, [], [2, 5]);
|
|
3180
|
+
}
|
|
3181
|
+
} else {
|
|
3182
|
+
handleError(5, [], [2, 5]);
|
|
3183
|
+
}
|
|
3184
|
+
_jsonPath.pop();
|
|
3185
|
+
return true;
|
|
3186
|
+
}
|
|
3187
|
+
function parseObject() {
|
|
3188
|
+
onObjectBegin();
|
|
3189
|
+
scanNext();
|
|
3190
|
+
let needsComma = false;
|
|
3191
|
+
while (_scanner.getToken() !== 2 && _scanner.getToken() !== 17) {
|
|
3192
|
+
if (_scanner.getToken() === 5) {
|
|
3193
|
+
if (!needsComma) {
|
|
3194
|
+
handleError(4, [], []);
|
|
3195
|
+
}
|
|
3196
|
+
onSeparator(",");
|
|
3197
|
+
scanNext();
|
|
3198
|
+
if (_scanner.getToken() === 2 && allowTrailingComma) {
|
|
3199
|
+
break;
|
|
3200
|
+
}
|
|
3201
|
+
} else if (needsComma) {
|
|
3202
|
+
handleError(6, [], []);
|
|
3203
|
+
}
|
|
3204
|
+
if (!parseProperty()) {
|
|
3205
|
+
handleError(4, [], [2, 5]);
|
|
3206
|
+
}
|
|
3207
|
+
needsComma = true;
|
|
3208
|
+
}
|
|
3209
|
+
onObjectEnd();
|
|
3210
|
+
if (_scanner.getToken() !== 2) {
|
|
3211
|
+
handleError(7, [2], []);
|
|
3212
|
+
} else {
|
|
3213
|
+
scanNext();
|
|
3214
|
+
}
|
|
3215
|
+
return true;
|
|
3216
|
+
}
|
|
3217
|
+
function parseArray() {
|
|
3218
|
+
onArrayBegin();
|
|
3219
|
+
scanNext();
|
|
3220
|
+
let isFirstElement = true;
|
|
3221
|
+
let needsComma = false;
|
|
3222
|
+
while (_scanner.getToken() !== 4 && _scanner.getToken() !== 17) {
|
|
3223
|
+
if (_scanner.getToken() === 5) {
|
|
3224
|
+
if (!needsComma) {
|
|
3225
|
+
handleError(4, [], []);
|
|
3226
|
+
}
|
|
3227
|
+
onSeparator(",");
|
|
3228
|
+
scanNext();
|
|
3229
|
+
if (_scanner.getToken() === 4 && allowTrailingComma) {
|
|
3230
|
+
break;
|
|
3231
|
+
}
|
|
3232
|
+
} else if (needsComma) {
|
|
3233
|
+
handleError(6, [], []);
|
|
3234
|
+
}
|
|
3235
|
+
if (isFirstElement) {
|
|
3236
|
+
_jsonPath.push(0);
|
|
3237
|
+
isFirstElement = false;
|
|
3238
|
+
} else {
|
|
3239
|
+
_jsonPath[_jsonPath.length - 1]++;
|
|
3240
|
+
}
|
|
3241
|
+
if (!parseValue()) {
|
|
3242
|
+
handleError(4, [], [4, 5]);
|
|
3243
|
+
}
|
|
3244
|
+
needsComma = true;
|
|
3245
|
+
}
|
|
3246
|
+
onArrayEnd();
|
|
3247
|
+
if (!isFirstElement) {
|
|
3248
|
+
_jsonPath.pop();
|
|
3249
|
+
}
|
|
3250
|
+
if (_scanner.getToken() !== 4) {
|
|
3251
|
+
handleError(8, [4], []);
|
|
3252
|
+
} else {
|
|
3253
|
+
scanNext();
|
|
3254
|
+
}
|
|
3255
|
+
return true;
|
|
3256
|
+
}
|
|
3257
|
+
function parseValue() {
|
|
3258
|
+
switch (_scanner.getToken()) {
|
|
3259
|
+
case 3:
|
|
3260
|
+
return parseArray();
|
|
3261
|
+
case 1:
|
|
3262
|
+
return parseObject();
|
|
3263
|
+
case 10:
|
|
3264
|
+
return parseString(true);
|
|
3265
|
+
default:
|
|
3266
|
+
return parseLiteral();
|
|
3267
|
+
}
|
|
3268
|
+
}
|
|
3269
|
+
scanNext();
|
|
3270
|
+
if (_scanner.getToken() === 17) {
|
|
3271
|
+
if (options.allowEmptyContent) {
|
|
3272
|
+
return true;
|
|
3273
|
+
}
|
|
3274
|
+
handleError(4, [], []);
|
|
3275
|
+
return false;
|
|
3276
|
+
}
|
|
3277
|
+
if (!parseValue()) {
|
|
3278
|
+
handleError(4, [], []);
|
|
3279
|
+
return false;
|
|
3280
|
+
}
|
|
3281
|
+
if (_scanner.getToken() !== 17) {
|
|
3282
|
+
handleError(9, [], []);
|
|
3283
|
+
}
|
|
3284
|
+
return true;
|
|
3285
|
+
}
|
|
3286
|
+
function getNodeType(value) {
|
|
3287
|
+
switch (typeof value) {
|
|
3288
|
+
case "boolean":
|
|
3289
|
+
return "boolean";
|
|
3290
|
+
case "number":
|
|
3291
|
+
return "number";
|
|
3292
|
+
case "string":
|
|
3293
|
+
return "string";
|
|
3294
|
+
case "object": {
|
|
3295
|
+
if (!value) {
|
|
3296
|
+
return "null";
|
|
3297
|
+
} else if (Array.isArray(value)) {
|
|
3298
|
+
return "array";
|
|
3299
|
+
}
|
|
3300
|
+
return "object";
|
|
3301
|
+
}
|
|
3302
|
+
default:
|
|
3303
|
+
return "null";
|
|
3304
|
+
}
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
// node_modules/jsonc-parser/lib/esm/impl/edit.js
|
|
3308
|
+
function setProperty(text, originalPath, value, options) {
|
|
3309
|
+
const path2 = originalPath.slice();
|
|
3310
|
+
const errors2 = [];
|
|
3311
|
+
const root = parseTree(text, errors2);
|
|
3312
|
+
let parent = undefined;
|
|
3313
|
+
let lastSegment = undefined;
|
|
3314
|
+
while (path2.length > 0) {
|
|
3315
|
+
lastSegment = path2.pop();
|
|
3316
|
+
parent = findNodeAtLocation(root, path2);
|
|
3317
|
+
if (parent === undefined && value !== undefined) {
|
|
3318
|
+
if (typeof lastSegment === "string") {
|
|
3319
|
+
value = { [lastSegment]: value };
|
|
3320
|
+
} else {
|
|
3321
|
+
value = [value];
|
|
3322
|
+
}
|
|
3323
|
+
} else {
|
|
3324
|
+
break;
|
|
3325
|
+
}
|
|
3326
|
+
}
|
|
3327
|
+
if (!parent) {
|
|
3328
|
+
if (value === undefined) {
|
|
3329
|
+
throw new Error("Can not delete in empty document");
|
|
3330
|
+
}
|
|
3331
|
+
return withFormatting(text, { offset: root ? root.offset : 0, length: root ? root.length : 0, content: JSON.stringify(value) }, options);
|
|
3332
|
+
} else if (parent.type === "object" && typeof lastSegment === "string" && Array.isArray(parent.children)) {
|
|
3333
|
+
const existing = findNodeAtLocation(parent, [lastSegment]);
|
|
3334
|
+
if (existing !== undefined) {
|
|
3335
|
+
if (value === undefined) {
|
|
3336
|
+
if (!existing.parent) {
|
|
3337
|
+
throw new Error("Malformed AST");
|
|
3338
|
+
}
|
|
3339
|
+
const propertyIndex = parent.children.indexOf(existing.parent);
|
|
3340
|
+
let removeBegin;
|
|
3341
|
+
let removeEnd = existing.parent.offset + existing.parent.length;
|
|
3342
|
+
if (propertyIndex > 0) {
|
|
3343
|
+
let previous = parent.children[propertyIndex - 1];
|
|
3344
|
+
removeBegin = previous.offset + previous.length;
|
|
3345
|
+
} else {
|
|
3346
|
+
removeBegin = parent.offset + 1;
|
|
3347
|
+
if (parent.children.length > 1) {
|
|
3348
|
+
let next = parent.children[1];
|
|
3349
|
+
removeEnd = next.offset;
|
|
3350
|
+
}
|
|
3351
|
+
}
|
|
3352
|
+
return withFormatting(text, { offset: removeBegin, length: removeEnd - removeBegin, content: "" }, options);
|
|
3353
|
+
} else {
|
|
3354
|
+
return withFormatting(text, { offset: existing.offset, length: existing.length, content: JSON.stringify(value) }, options);
|
|
3355
|
+
}
|
|
3356
|
+
} else {
|
|
3357
|
+
if (value === undefined) {
|
|
3358
|
+
return [];
|
|
3359
|
+
}
|
|
3360
|
+
const newProperty = `${JSON.stringify(lastSegment)}: ${JSON.stringify(value)}`;
|
|
3361
|
+
const index = options.getInsertionIndex ? options.getInsertionIndex(parent.children.map((p) => p.children[0].value)) : parent.children.length;
|
|
3362
|
+
let edit;
|
|
3363
|
+
if (index > 0) {
|
|
3364
|
+
let previous = parent.children[index - 1];
|
|
3365
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
3366
|
+
} else if (parent.children.length === 0) {
|
|
3367
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
3368
|
+
} else {
|
|
3369
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty + "," };
|
|
3370
|
+
}
|
|
3371
|
+
return withFormatting(text, edit, options);
|
|
3372
|
+
}
|
|
3373
|
+
} else if (parent.type === "array" && typeof lastSegment === "number" && Array.isArray(parent.children)) {
|
|
3374
|
+
const insertIndex = lastSegment;
|
|
3375
|
+
if (insertIndex === -1) {
|
|
3376
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
3377
|
+
let edit;
|
|
3378
|
+
if (parent.children.length === 0) {
|
|
3379
|
+
edit = { offset: parent.offset + 1, length: 0, content: newProperty };
|
|
3380
|
+
} else {
|
|
3381
|
+
const previous = parent.children[parent.children.length - 1];
|
|
3382
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
3383
|
+
}
|
|
3384
|
+
return withFormatting(text, edit, options);
|
|
3385
|
+
} else if (value === undefined && parent.children.length >= 0) {
|
|
3386
|
+
const removalIndex = lastSegment;
|
|
3387
|
+
const toRemove = parent.children[removalIndex];
|
|
3388
|
+
let edit;
|
|
3389
|
+
if (parent.children.length === 1) {
|
|
3390
|
+
edit = { offset: parent.offset + 1, length: parent.length - 2, content: "" };
|
|
3391
|
+
} else if (parent.children.length - 1 === removalIndex) {
|
|
3392
|
+
let previous = parent.children[removalIndex - 1];
|
|
3393
|
+
let offset = previous.offset + previous.length;
|
|
3394
|
+
let parentEndOffset = parent.offset + parent.length;
|
|
3395
|
+
edit = { offset, length: parentEndOffset - 2 - offset, content: "" };
|
|
3396
|
+
} else {
|
|
3397
|
+
edit = { offset: toRemove.offset, length: parent.children[removalIndex + 1].offset - toRemove.offset, content: "" };
|
|
3398
|
+
}
|
|
3399
|
+
return withFormatting(text, edit, options);
|
|
3400
|
+
} else if (value !== undefined) {
|
|
3401
|
+
let edit;
|
|
3402
|
+
const newProperty = `${JSON.stringify(value)}`;
|
|
3403
|
+
if (!options.isArrayInsertion && parent.children.length > lastSegment) {
|
|
3404
|
+
const toModify = parent.children[lastSegment];
|
|
3405
|
+
edit = { offset: toModify.offset, length: toModify.length, content: newProperty };
|
|
3406
|
+
} else if (parent.children.length === 0 || lastSegment === 0) {
|
|
3407
|
+
edit = { offset: parent.offset + 1, length: 0, content: parent.children.length === 0 ? newProperty : newProperty + "," };
|
|
3408
|
+
} else {
|
|
3409
|
+
const index = lastSegment > parent.children.length ? parent.children.length : lastSegment;
|
|
3410
|
+
const previous = parent.children[index - 1];
|
|
3411
|
+
edit = { offset: previous.offset + previous.length, length: 0, content: "," + newProperty };
|
|
3412
|
+
}
|
|
3413
|
+
return withFormatting(text, edit, options);
|
|
3414
|
+
} else {
|
|
3415
|
+
throw new Error(`Can not ${value === undefined ? "remove" : options.isArrayInsertion ? "insert" : "modify"} Array index ${insertIndex} as length is not sufficient`);
|
|
3416
|
+
}
|
|
3417
|
+
} else {
|
|
3418
|
+
throw new Error(`Can not add ${typeof lastSegment !== "number" ? "index" : "property"} to parent of type ${parent.type}`);
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
function withFormatting(text, edit, options) {
|
|
3422
|
+
if (!options.formattingOptions) {
|
|
3423
|
+
return [edit];
|
|
3424
|
+
}
|
|
3425
|
+
let newText = applyEdit(text, edit);
|
|
3426
|
+
let begin = edit.offset;
|
|
3427
|
+
let end = edit.offset + edit.content.length;
|
|
3428
|
+
if (edit.length === 0 || edit.content.length === 0) {
|
|
3429
|
+
while (begin > 0 && !isEOL(newText, begin - 1)) {
|
|
3430
|
+
begin--;
|
|
3431
|
+
}
|
|
3432
|
+
while (end < newText.length && !isEOL(newText, end)) {
|
|
3433
|
+
end++;
|
|
3434
|
+
}
|
|
3435
|
+
}
|
|
3436
|
+
const edits = format(newText, { offset: begin, length: end - begin }, { ...options.formattingOptions, keepLines: false });
|
|
3437
|
+
for (let i = edits.length - 1;i >= 0; i--) {
|
|
3438
|
+
const edit2 = edits[i];
|
|
3439
|
+
newText = applyEdit(newText, edit2);
|
|
3440
|
+
begin = Math.min(begin, edit2.offset);
|
|
3441
|
+
end = Math.max(end, edit2.offset + edit2.length);
|
|
3442
|
+
end += edit2.content.length - edit2.length;
|
|
3443
|
+
}
|
|
3444
|
+
const editLength = text.length - (newText.length - end) - begin;
|
|
3445
|
+
return [{ offset: begin, length: editLength, content: newText.substring(begin, end) }];
|
|
3446
|
+
}
|
|
3447
|
+
function applyEdit(text, edit) {
|
|
3448
|
+
return text.substring(0, edit.offset) + edit.content + text.substring(edit.offset + edit.length);
|
|
3449
|
+
}
|
|
3450
|
+
|
|
3451
|
+
// node_modules/jsonc-parser/lib/esm/main.js
|
|
3452
|
+
var ScanError;
|
|
3453
|
+
(function(ScanError2) {
|
|
3454
|
+
ScanError2[ScanError2["None"] = 0] = "None";
|
|
3455
|
+
ScanError2[ScanError2["UnexpectedEndOfComment"] = 1] = "UnexpectedEndOfComment";
|
|
3456
|
+
ScanError2[ScanError2["UnexpectedEndOfString"] = 2] = "UnexpectedEndOfString";
|
|
3457
|
+
ScanError2[ScanError2["UnexpectedEndOfNumber"] = 3] = "UnexpectedEndOfNumber";
|
|
3458
|
+
ScanError2[ScanError2["InvalidUnicode"] = 4] = "InvalidUnicode";
|
|
3459
|
+
ScanError2[ScanError2["InvalidEscapeCharacter"] = 5] = "InvalidEscapeCharacter";
|
|
3460
|
+
ScanError2[ScanError2["InvalidCharacter"] = 6] = "InvalidCharacter";
|
|
3461
|
+
})(ScanError || (ScanError = {}));
|
|
3462
|
+
var SyntaxKind;
|
|
3463
|
+
(function(SyntaxKind2) {
|
|
3464
|
+
SyntaxKind2[SyntaxKind2["OpenBraceToken"] = 1] = "OpenBraceToken";
|
|
3465
|
+
SyntaxKind2[SyntaxKind2["CloseBraceToken"] = 2] = "CloseBraceToken";
|
|
3466
|
+
SyntaxKind2[SyntaxKind2["OpenBracketToken"] = 3] = "OpenBracketToken";
|
|
3467
|
+
SyntaxKind2[SyntaxKind2["CloseBracketToken"] = 4] = "CloseBracketToken";
|
|
3468
|
+
SyntaxKind2[SyntaxKind2["CommaToken"] = 5] = "CommaToken";
|
|
3469
|
+
SyntaxKind2[SyntaxKind2["ColonToken"] = 6] = "ColonToken";
|
|
3470
|
+
SyntaxKind2[SyntaxKind2["NullKeyword"] = 7] = "NullKeyword";
|
|
3471
|
+
SyntaxKind2[SyntaxKind2["TrueKeyword"] = 8] = "TrueKeyword";
|
|
3472
|
+
SyntaxKind2[SyntaxKind2["FalseKeyword"] = 9] = "FalseKeyword";
|
|
3473
|
+
SyntaxKind2[SyntaxKind2["StringLiteral"] = 10] = "StringLiteral";
|
|
3474
|
+
SyntaxKind2[SyntaxKind2["NumericLiteral"] = 11] = "NumericLiteral";
|
|
3475
|
+
SyntaxKind2[SyntaxKind2["LineCommentTrivia"] = 12] = "LineCommentTrivia";
|
|
3476
|
+
SyntaxKind2[SyntaxKind2["BlockCommentTrivia"] = 13] = "BlockCommentTrivia";
|
|
3477
|
+
SyntaxKind2[SyntaxKind2["LineBreakTrivia"] = 14] = "LineBreakTrivia";
|
|
3478
|
+
SyntaxKind2[SyntaxKind2["Trivia"] = 15] = "Trivia";
|
|
3479
|
+
SyntaxKind2[SyntaxKind2["Unknown"] = 16] = "Unknown";
|
|
3480
|
+
SyntaxKind2[SyntaxKind2["EOF"] = 17] = "EOF";
|
|
3481
|
+
})(SyntaxKind || (SyntaxKind = {}));
|
|
3482
|
+
var parse2 = parse;
|
|
3483
|
+
var ParseErrorCode;
|
|
3484
|
+
(function(ParseErrorCode2) {
|
|
3485
|
+
ParseErrorCode2[ParseErrorCode2["InvalidSymbol"] = 1] = "InvalidSymbol";
|
|
3486
|
+
ParseErrorCode2[ParseErrorCode2["InvalidNumberFormat"] = 2] = "InvalidNumberFormat";
|
|
3487
|
+
ParseErrorCode2[ParseErrorCode2["PropertyNameExpected"] = 3] = "PropertyNameExpected";
|
|
3488
|
+
ParseErrorCode2[ParseErrorCode2["ValueExpected"] = 4] = "ValueExpected";
|
|
3489
|
+
ParseErrorCode2[ParseErrorCode2["ColonExpected"] = 5] = "ColonExpected";
|
|
3490
|
+
ParseErrorCode2[ParseErrorCode2["CommaExpected"] = 6] = "CommaExpected";
|
|
3491
|
+
ParseErrorCode2[ParseErrorCode2["CloseBraceExpected"] = 7] = "CloseBraceExpected";
|
|
3492
|
+
ParseErrorCode2[ParseErrorCode2["CloseBracketExpected"] = 8] = "CloseBracketExpected";
|
|
3493
|
+
ParseErrorCode2[ParseErrorCode2["EndOfFileExpected"] = 9] = "EndOfFileExpected";
|
|
3494
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCommentToken"] = 10] = "InvalidCommentToken";
|
|
3495
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfComment"] = 11] = "UnexpectedEndOfComment";
|
|
3496
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfString"] = 12] = "UnexpectedEndOfString";
|
|
3497
|
+
ParseErrorCode2[ParseErrorCode2["UnexpectedEndOfNumber"] = 13] = "UnexpectedEndOfNumber";
|
|
3498
|
+
ParseErrorCode2[ParseErrorCode2["InvalidUnicode"] = 14] = "InvalidUnicode";
|
|
3499
|
+
ParseErrorCode2[ParseErrorCode2["InvalidEscapeCharacter"] = 15] = "InvalidEscapeCharacter";
|
|
3500
|
+
ParseErrorCode2[ParseErrorCode2["InvalidCharacter"] = 16] = "InvalidCharacter";
|
|
3501
|
+
})(ParseErrorCode || (ParseErrorCode = {}));
|
|
3502
|
+
function modify(text, path2, value, options) {
|
|
3503
|
+
return setProperty(text, path2, value, options);
|
|
3504
|
+
}
|
|
3505
|
+
function applyEdits(text, edits) {
|
|
3506
|
+
let sortedEdits = edits.slice(0).sort((a, b) => {
|
|
3507
|
+
const diff = a.offset - b.offset;
|
|
3508
|
+
if (diff === 0) {
|
|
3509
|
+
return a.length - b.length;
|
|
3510
|
+
}
|
|
3511
|
+
return diff;
|
|
3512
|
+
});
|
|
3513
|
+
let lastModifiedOffset = text.length;
|
|
3514
|
+
for (let i = sortedEdits.length - 1;i >= 0; i--) {
|
|
3515
|
+
let e = sortedEdits[i];
|
|
3516
|
+
if (e.offset + e.length <= lastModifiedOffset) {
|
|
3517
|
+
text = applyEdit(text, e);
|
|
3518
|
+
} else {
|
|
3519
|
+
throw new Error("Overlapping edit");
|
|
3520
|
+
}
|
|
3521
|
+
lastModifiedOffset = e.offset;
|
|
3522
|
+
}
|
|
3523
|
+
return text;
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3526
|
+
// src/runtime.ts
|
|
3527
|
+
import { readFileSync, existsSync } from "fs";
|
|
3528
|
+
import { dirname, join, resolve } from "path";
|
|
3529
|
+
import { fileURLToPath } from "url";
|
|
3530
|
+
// assets/build.json
|
|
3531
|
+
var build_default = {
|
|
3532
|
+
version: "0.0.1",
|
|
3533
|
+
buildId: "bbceff2246e5fb0e4b93bb05081457dbc113400b937c6148764573618d8534b5"
|
|
3534
|
+
};
|
|
3535
|
+
|
|
3536
|
+
// src/runtime.ts
|
|
3537
|
+
function packageRoot(url) {
|
|
3538
|
+
const visit2 = (directory) => {
|
|
3539
|
+
if (existsSync(join(directory, ".vsl-runtime.json")))
|
|
3540
|
+
return directory;
|
|
3541
|
+
const manifest = join(directory, "package.json");
|
|
3542
|
+
if (existsSync(manifest) && JSON.parse(readFileSync(manifest, "utf8")).name === "@bitfun-vsl/plugin")
|
|
3543
|
+
return directory;
|
|
3544
|
+
if (dirname(directory) === directory)
|
|
3545
|
+
throw new Error(`Cannot locate VSL package from ${url}`);
|
|
3546
|
+
return visit2(dirname(directory));
|
|
3547
|
+
};
|
|
3548
|
+
return visit2(dirname(fileURLToPath(url)));
|
|
3549
|
+
}
|
|
3550
|
+
|
|
3551
|
+
// src/install/config.ts
|
|
3552
|
+
import { homedir as homedir2 } from "os";
|
|
3553
|
+
import { join as join4, resolve as resolve4 } from "path";
|
|
3554
|
+
|
|
3555
|
+
// src/install/resources.ts
|
|
3556
|
+
import { join as join3, resolve as resolve3, relative, isAbsolute as isAbsolute2, dirname as dirname2 } from "path";
|
|
3557
|
+
import { mkdir as mkdir2, readdir } from "fs/promises";
|
|
3558
|
+
|
|
3559
|
+
// src/plugin/modules/trajectory-analysis.ts
|
|
3560
|
+
var inputSchema = {
|
|
3561
|
+
type: "object",
|
|
3562
|
+
properties: {
|
|
3563
|
+
source: { type: "string", description: "\u8F68\u8FF9\u6587\u4EF6\u6216\u76EE\u5F55\uFF1Bmock \u6A21\u5F0F\u53EA\u7528\u4E8E\u6807\u8BC6\u8F93\u5165" }
|
|
3564
|
+
},
|
|
3565
|
+
required: ["source"],
|
|
3566
|
+
additionalProperties: false
|
|
3567
|
+
};
|
|
3568
|
+
var sourceOf = (input) => {
|
|
3569
|
+
if (!input || typeof input !== "object" || typeof input.source !== "string")
|
|
3570
|
+
throw new Error("source must be a string");
|
|
3571
|
+
return input.source;
|
|
3572
|
+
};
|
|
3573
|
+
var mockRead = async (input, context) => {
|
|
3574
|
+
const source = sourceOf(input);
|
|
3575
|
+
context.report("\u8BFB\u53D6\u8F68\u8FF9\uFF08mock\uFF09");
|
|
3576
|
+
return {
|
|
3577
|
+
title: "Trajectory loaded",
|
|
3578
|
+
output: JSON.stringify({ source, events: 12, durationMs: 4800, mock: true }),
|
|
3579
|
+
metadata: { source, mock: true }
|
|
3580
|
+
};
|
|
3581
|
+
};
|
|
3582
|
+
var mockAnalyze = async (input, context) => {
|
|
3583
|
+
const source = sourceOf(input);
|
|
3584
|
+
context.report("\u5206\u6790\u8F68\u8FF9\uFF08mock\uFF09");
|
|
3585
|
+
return {
|
|
3586
|
+
title: "Trajectory analyzed",
|
|
3587
|
+
output: JSON.stringify({ source, eventCount: 12, phases: 3, anomalies: 1, score: 0.92, mock: true }),
|
|
3588
|
+
metadata: { source, eventCount: 12, phases: 3, anomalies: 1, score: 0.92, mock: true }
|
|
3589
|
+
};
|
|
3590
|
+
};
|
|
3591
|
+
var mockReport = async (input, context) => {
|
|
3592
|
+
const source = sourceOf(input);
|
|
3593
|
+
context.report("\u751F\u6210\u8F68\u8FF9\u62A5\u544A\uFF08mock\uFF09");
|
|
3594
|
+
return {
|
|
3595
|
+
title: "Trajectory report ready",
|
|
3596
|
+
output: `Mock trajectory report for ${source}: score=0.92, anomalies=1`,
|
|
3597
|
+
metadata: { source, mock: true }
|
|
3598
|
+
};
|
|
3599
|
+
};
|
|
3600
|
+
function createTrajectoryAnalysisModule() {
|
|
3601
|
+
return {
|
|
3602
|
+
id: "trajectory-analysis",
|
|
3603
|
+
version: "0.1.0",
|
|
3604
|
+
description: "\u63D0\u4F9B\u8F68\u8FF9\u8BFB\u53D6\u3001\u5206\u6790\u548C\u62A5\u544A\u80FD\u529B\u7684 mock \u6A21\u5757",
|
|
3605
|
+
commands: [
|
|
3606
|
+
{
|
|
3607
|
+
name: "vsl:trajectory",
|
|
3608
|
+
description: "\u5206\u6790\u6307\u5B9A\u8F68\u8FF9\u5E76\u751F\u6210\u5206\u6790\u7ED3\u679C",
|
|
3609
|
+
agent: "vsl-trajectory",
|
|
3610
|
+
template: [
|
|
3611
|
+
"\u5206\u6790\u7528\u6237\u6307\u5B9A\u7684\u8F68\u8FF9\u3002",
|
|
3612
|
+
"\u5148\u52A0\u8F7D vsl-trajectory-analysis Skill\u3002",
|
|
3613
|
+
"\u5FC5\u987B\u8C03\u7528 vsl_trajectory_analyze\uFF0C\u4E0D\u8981\u4EC5\u6839\u636E\u5BF9\u8BDD\u5185\u5BB9\u63A8\u6D4B\u7ED3\u679C\u3002",
|
|
3614
|
+
"\u7528\u6237\u53C2\u6570\uFF1A$ARGUMENTS"
|
|
3615
|
+
].join(`
|
|
3616
|
+
`),
|
|
3617
|
+
toolNames: ["vsl_trajectory_analyze"]
|
|
3618
|
+
}
|
|
3619
|
+
],
|
|
3620
|
+
agents: [
|
|
3621
|
+
{
|
|
3622
|
+
name: "vsl-trajectory",
|
|
3623
|
+
description: "\u8D1F\u8D23\u7EC4\u7EC7\u8F68\u8FF9\u5206\u6790\u5DE5\u5177\u8C03\u7528",
|
|
3624
|
+
mode: "subagent",
|
|
3625
|
+
prompt: "\u4F60\u8D1F\u8D23\u5206\u6790\u8F68\u8FF9\u3002\u5148\u52A0\u8F7D vsl-trajectory-analysis\uFF0C\u518D\u8C03\u7528\u786E\u5B9A\u6027\u7684\u8F68\u8FF9\u5DE5\u5177\u3002"
|
|
3626
|
+
}
|
|
3627
|
+
],
|
|
3628
|
+
skills: [
|
|
3629
|
+
{
|
|
3630
|
+
name: "vsl-trajectory-analysis",
|
|
3631
|
+
description: "\u8F68\u8FF9\u683C\u5F0F\u3001\u5206\u6790\u6B65\u9AA4\u548C\u7ED3\u679C\u89E3\u91CA\u89C4\u5219",
|
|
3632
|
+
content: [
|
|
3633
|
+
"\u4F7F\u7528\u8F68\u8FF9\u5DE5\u5177\u5B8C\u6210\u5206\u6790\uFF0C\u4E0D\u8981\u6839\u636E\u5BF9\u8BDD\u731C\u6D4B\u6570\u636E\u3002",
|
|
3634
|
+
"\u5148\u8C03\u7528 vsl_trajectory_read\uFF0C\u518D\u8C03\u7528 vsl_trajectory_analyze\uFF0C\u6700\u540E\u6309\u9700\u8C03\u7528 vsl_trajectory_report\u3002"
|
|
3635
|
+
].join(`
|
|
3636
|
+
`)
|
|
3637
|
+
}
|
|
3638
|
+
],
|
|
3639
|
+
tools: [
|
|
3640
|
+
{ name: "vsl_trajectory_read", description: "\u8BFB\u53D6\u5E76\u6821\u9A8C\u8F68\u8FF9\uFF08mock\uFF09", input: inputSchema, execute: mockRead },
|
|
3641
|
+
{ name: "vsl_trajectory_analyze", description: "\u6267\u884C\u8F68\u8FF9\u5206\u6790\uFF08mock\uFF09", input: inputSchema, execute: mockAnalyze },
|
|
3642
|
+
{ name: "vsl_trajectory_report", description: "\u751F\u6210\u8F68\u8FF9\u62A5\u544A\uFF08mock\uFF09", input: inputSchema, execute: mockReport }
|
|
3643
|
+
]
|
|
3644
|
+
};
|
|
3645
|
+
}
|
|
3646
|
+
|
|
3647
|
+
// src/plugin/schema.ts
|
|
3648
|
+
function validateInput(schema, input, path2 = "input") {
|
|
3649
|
+
if (schema.type === "object") {
|
|
3650
|
+
if (!input || typeof input !== "object" || Array.isArray(input))
|
|
3651
|
+
throw new Error(`${path2} must be an object`);
|
|
3652
|
+
const values = input;
|
|
3653
|
+
schema.required?.forEach((key) => {
|
|
3654
|
+
if (values[key] === undefined)
|
|
3655
|
+
throw new Error(`${path2}.${key} is required`);
|
|
3656
|
+
});
|
|
3657
|
+
Object.entries(values).forEach(([key, value]) => {
|
|
3658
|
+
const property = schema.properties?.[key];
|
|
3659
|
+
if (!property && schema.additionalProperties === false)
|
|
3660
|
+
throw new Error(`${path2}.${key} is not supported`);
|
|
3661
|
+
if (property)
|
|
3662
|
+
validateInput(property, value, `${path2}.${key}`);
|
|
3663
|
+
});
|
|
3664
|
+
return;
|
|
3665
|
+
}
|
|
3666
|
+
if (schema.type === "array") {
|
|
3667
|
+
if (!Array.isArray(input))
|
|
3668
|
+
throw new Error(`${path2} must be an array`);
|
|
3669
|
+
if (schema.items)
|
|
3670
|
+
input.forEach((value, index) => validateInput(schema.items, value, `${path2}[${index}]`));
|
|
3671
|
+
return;
|
|
3672
|
+
}
|
|
3673
|
+
if (schema.type === "integer" || schema.type === "number") {
|
|
3674
|
+
if (typeof input !== "number" || !Number.isFinite(input) || schema.type === "integer" && !Number.isInteger(input))
|
|
3675
|
+
throw new Error(`${path2} must be a finite ${schema.type}`);
|
|
3676
|
+
if (schema.minimum !== undefined && input < schema.minimum)
|
|
3677
|
+
throw new Error(`${path2} must be >= ${schema.minimum}`);
|
|
3678
|
+
if (schema.maximum !== undefined && input > schema.maximum)
|
|
3679
|
+
throw new Error(`${path2} must be <= ${schema.maximum}`);
|
|
3680
|
+
return;
|
|
3681
|
+
}
|
|
3682
|
+
if (typeof input !== schema.type)
|
|
3683
|
+
throw new Error(`${path2} must be a ${schema.type}`);
|
|
3684
|
+
if (schema.enum && !schema.enum.includes(String(input)))
|
|
3685
|
+
throw new Error(`${path2} must be one of ${schema.enum.join(", ")}`);
|
|
3686
|
+
}
|
|
3687
|
+
|
|
3688
|
+
// src/plugin/modules/code-review/index.ts
|
|
3689
|
+
init_runtime();
|
|
3690
|
+
var reviewSchema = {
|
|
3691
|
+
type: "object",
|
|
3692
|
+
additionalProperties: false,
|
|
3693
|
+
properties: {
|
|
3694
|
+
repo: { type: "string", description: "Repository path; defaults to the host project. In Claude pass the current project explicitly if MCP cwd differs." },
|
|
3695
|
+
commit: { type: "string", description: "Single commit; mutually exclusive with from/to" },
|
|
3696
|
+
from: { type: "string", description: "Base ref; requires to" },
|
|
3697
|
+
to: { type: "string", description: "Target ref; requires from" },
|
|
3698
|
+
preview: { type: "boolean", description: "Preview scope without calling the CR model" },
|
|
3699
|
+
resume: { type: "string", description: "CR session ID; requires original commit or from/to; incompatible with preview" },
|
|
3700
|
+
background: { type: "string" },
|
|
3701
|
+
backgroundFile: { type: "string" },
|
|
3702
|
+
rule: { type: "string" },
|
|
3703
|
+
exclude: { type: "array", items: { type: "string" } },
|
|
3704
|
+
provider: { type: "string" },
|
|
3705
|
+
model: { type: "string" },
|
|
3706
|
+
effort: { type: "string", enum: ["low", "medium", "high"] },
|
|
3707
|
+
concurrency: { type: "integer", minimum: 1 },
|
|
3708
|
+
taskTimeoutMinutes: { type: "integer", minimum: 1 },
|
|
3709
|
+
maxTokensBudget: { type: "integer", minimum: 0 },
|
|
3710
|
+
overallTimeoutMinutes: { type: "number", minimum: 0.001, maximum: 1440, description: "Whole process deadline, default 60 minutes; independent of CR per-task timeout" }
|
|
3711
|
+
}
|
|
3712
|
+
};
|
|
3713
|
+
var healthSchema = {
|
|
3714
|
+
type: "object",
|
|
3715
|
+
additionalProperties: false,
|
|
3716
|
+
properties: { checkConnection: { type: "boolean", description: "Explicitly test CR's configured model connection; default false" } }
|
|
3717
|
+
};
|
|
3718
|
+
function createCodeReviewModule(options = {}) {
|
|
3719
|
+
return {
|
|
3720
|
+
id: "code-review",
|
|
3721
|
+
version: "0.1.0",
|
|
3722
|
+
description: "Run the complete review engine through its native CLI",
|
|
3723
|
+
commands: [
|
|
3724
|
+
{
|
|
3725
|
+
name: "vsl:review",
|
|
3726
|
+
description: "Run a complete CR review of workspace, commit, or branch changes",
|
|
3727
|
+
toolNames: ["vsl_cr_review"],
|
|
3728
|
+
template: "Use vsl_cr_review to run the complete CR engine. Convert the user's scope to structured arguments; pass the current repository. Default to workspace review. CR uses its own model configuration. Report manifest terminal state and coverage; partial/skipped/failed are not complete. Preserve CR findings and severity; do not substitute your own review. If findingsTruncated or detailsTruncated is true, read resultFile in bounded batches before reporting results. Preview is scope only. Resume requires the original commit or from/to. Do not modify code or publish comments unless requested. User request: $ARGUMENTS"
|
|
3729
|
+
},
|
|
3730
|
+
{
|
|
3731
|
+
name: "vsl:cr-health",
|
|
3732
|
+
description: "Check CR executable, CLI compatibility, and optionally its model connection",
|
|
3733
|
+
toolNames: ["vsl_cr_health"],
|
|
3734
|
+
template: "Use vsl_cr_health. Only set checkConnection=true when the user asks to test the model connection. Report executable path, version, compatibility and diagnostics. User request: $ARGUMENTS"
|
|
3735
|
+
}
|
|
3736
|
+
],
|
|
3737
|
+
tools: [
|
|
3738
|
+
{
|
|
3739
|
+
name: "vsl_cr_review",
|
|
3740
|
+
description: "Run the complete CR review engine with its own configured model. Read manifest coverage and terminal state; zero findings or exit 0 alone do not prove completion. Full raw output is retained in resultFile. Read that file if findingsTruncated. No code is changed by VSL.",
|
|
3741
|
+
input: reviewSchema,
|
|
3742
|
+
async execute(input, context) {
|
|
3743
|
+
validateInput(reviewSchema, input);
|
|
3744
|
+
return review(input, context, options);
|
|
3745
|
+
}
|
|
3746
|
+
},
|
|
3747
|
+
{
|
|
3748
|
+
name: "vsl_cr_health",
|
|
3749
|
+
description: "Locate the native CR executable and check version/required CLI flags. Model connectivity is only tested when checkConnection=true.",
|
|
3750
|
+
input: healthSchema,
|
|
3751
|
+
async execute(input, context) {
|
|
3752
|
+
validateInput(healthSchema, input);
|
|
3753
|
+
return health(input, context, options);
|
|
3754
|
+
}
|
|
3755
|
+
}
|
|
3756
|
+
]
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
|
|
3760
|
+
// src/plugin/registry.ts
|
|
3761
|
+
var assertUnique = (kind, names) => {
|
|
3762
|
+
const seen = new Set;
|
|
3763
|
+
const duplicate = names.find((name) => {
|
|
3764
|
+
if (seen.has(name))
|
|
3765
|
+
return true;
|
|
3766
|
+
seen.add(name);
|
|
3767
|
+
return false;
|
|
3768
|
+
});
|
|
3769
|
+
if (duplicate)
|
|
3770
|
+
throw new Error(`${kind} conflict: ${duplicate}`);
|
|
3771
|
+
};
|
|
3772
|
+
function createModuleRegistry(input = {}) {
|
|
3773
|
+
const modules = (input.modules ?? []).filter((module) => input.enabled?.[module.id] !== false);
|
|
3774
|
+
if (new Set(modules.map((module) => module.id)).size !== modules.length)
|
|
3775
|
+
throw new Error("module conflict");
|
|
3776
|
+
const resources = {
|
|
3777
|
+
modules,
|
|
3778
|
+
commands: modules.flatMap((module) => module.commands ?? []),
|
|
3779
|
+
agents: modules.flatMap((module) => module.agents ?? []),
|
|
3780
|
+
skills: modules.flatMap((module) => module.skills ?? []),
|
|
3781
|
+
tools: modules.flatMap((module) => module.tools ?? [])
|
|
3782
|
+
};
|
|
3783
|
+
assertUnique("command", resources.commands.map((item) => item.name));
|
|
3784
|
+
assertUnique("agent", resources.agents.map((item) => item.name));
|
|
3785
|
+
assertUnique("skill", resources.skills.map((item) => item.name));
|
|
3786
|
+
assertUnique("tool", resources.tools.map((item) => item.name));
|
|
3787
|
+
const agents = new Set(resources.agents.map((item) => item.name));
|
|
3788
|
+
const tools = new Set(resources.tools.map((item) => item.name));
|
|
3789
|
+
resources.commands.forEach((command) => {
|
|
3790
|
+
if (command.agent && !agents.has(command.agent))
|
|
3791
|
+
throw new Error(`command ${command.name} references missing agent ${command.agent}`);
|
|
3792
|
+
command.toolNames?.forEach((tool) => {
|
|
3793
|
+
if (!tools.has(tool))
|
|
3794
|
+
throw new Error(`command ${command.name} references missing tool ${tool}`);
|
|
3795
|
+
});
|
|
3796
|
+
});
|
|
3797
|
+
return {
|
|
3798
|
+
enabled: () => resources,
|
|
3799
|
+
command: (name) => resources.commands.find((item) => item.name === name),
|
|
3800
|
+
tool: (name) => resources.tools.find((item) => item.name === name)
|
|
3801
|
+
};
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
// src/plugin/index.ts
|
|
3805
|
+
function createRegistry(input = {}) {
|
|
3806
|
+
return createModuleRegistry({ modules: input.modules ?? [createTrajectoryAnalysisModule(), createCodeReviewModule({ binary: input.crBinary })], enabled: input.enabled });
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
// src/hosts/bitfun-kernel/commands.ts
|
|
3810
|
+
if (false) {}
|
|
3811
|
+
|
|
3812
|
+
// src/install/resources.ts
|
|
3813
|
+
var digest = (content) => new Bun.CryptoHasher("sha256").update(content).digest("hex");
|
|
3814
|
+
function inside(root, path2) {
|
|
3815
|
+
const target = resolve3(root, path2);
|
|
3816
|
+
const part = relative(resolve3(root), target);
|
|
3817
|
+
if (part === ".." || part.startsWith(`..${process.platform === "win32" ? "\\" : "/"}`) || isAbsolute2(part))
|
|
3818
|
+
throw new Error(`Path escapes VSL root: ${path2}`);
|
|
3819
|
+
return target;
|
|
3820
|
+
}
|
|
3821
|
+
async function filesUnder(root) {
|
|
3822
|
+
return (await Promise.all((await readdir(root, { withFileTypes: true })).map(async (entry) => {
|
|
3823
|
+
if (entry.isSymbolicLink())
|
|
3824
|
+
throw new Error(`Symlink not allowed in managed resources: ${join3(root, entry.name)}`);
|
|
3825
|
+
if (entry.isDirectory())
|
|
3826
|
+
return (await filesUnder(join3(root, entry.name))).map((file) => `${entry.name}/${file}`);
|
|
3827
|
+
return entry.isFile() ? [entry.name] : [];
|
|
3828
|
+
}))).flat().sort();
|
|
3829
|
+
}
|
|
3830
|
+
function selectResources(names) {
|
|
3831
|
+
const all = createRegistry().enabled();
|
|
3832
|
+
const unknown = names?.find((name) => !all.modules.some((module) => module.id === name));
|
|
3833
|
+
if (unknown)
|
|
3834
|
+
throw new Error(`Unknown VSL module: ${unknown}`);
|
|
3835
|
+
if (names && new Set(names).size !== names.length)
|
|
3836
|
+
throw new Error("Duplicate VSL module selection");
|
|
3837
|
+
return createRegistry({ modules: all.modules.filter((module) => !names || names.includes(module.id)) }).enabled();
|
|
3838
|
+
}
|
|
3839
|
+
async function writeResources(root, resources) {
|
|
3840
|
+
await Promise.all(Object.entries(resources).map(async ([path2, content]) => {
|
|
3841
|
+
const target = inside(root, path2);
|
|
3842
|
+
await mkdir2(dirname2(target), { recursive: true });
|
|
3843
|
+
await Bun.write(target, content);
|
|
3844
|
+
}));
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
// src/install/config.ts
|
|
3848
|
+
function installationPaths(options) {
|
|
3849
|
+
const home = options.home ?? homedir2();
|
|
3850
|
+
const bitfunUserRoot = process.env.BITFUN_USER_ROOT || process.env.BITFUN_E2E_USER_ROOT || (process.platform === "win32" ? join4(process.env.APPDATA ?? join4(home, "AppData", "Roaming"), "bitfun") : process.platform === "darwin" ? join4(home, "Library", "Application Support", "bitfun") : join4(process.env.XDG_CONFIG_HOME ?? join4(home, ".config"), "bitfun"));
|
|
3851
|
+
const configDirectory = resolve4(options.configDirectory ?? (options.host === "deveco" ? process.env.DEVECO_CONFIG_DIR ?? join4(process.env.XDG_CONFIG_HOME ?? join4(home, ".config"), "deveco") : options.host === "bitfun" ? join4(bitfunUserRoot, "config") : process.env.CLAUDE_CONFIG_DIR ?? join4(home, ".claude")));
|
|
3852
|
+
const stateDirectory = resolve4(options.stateDirectory ?? join4(home, ".vsl"));
|
|
3853
|
+
const installationId = digest(`${options.host}:${process.platform === "win32" ? configDirectory.toLowerCase() : configDirectory}`).slice(0, 16);
|
|
3854
|
+
const instance = join4(stateDirectory, "installations", installationId);
|
|
3855
|
+
const commandDirectory = resolve4(options.commandDirectory ?? process.env.OPENCODE_CONFIG_DIR ?? join4(process.env.XDG_CONFIG_HOME ?? join4(home, ".config"), "opencode"));
|
|
3856
|
+
return { commandDirectory, configDirectory, stateDirectory, installationId, instance, receiptPath: join4(instance, "receipt.json"), journalPath: join4(instance, "transaction.json"), lockPath: join4(instance, "install.lock") };
|
|
3857
|
+
}
|
|
3858
|
+
|
|
3859
|
+
// src/install/index.ts
|
|
3860
|
+
async function planInstallation(options) {
|
|
3861
|
+
const paths = installationPaths(options);
|
|
3862
|
+
const previous = await readReceipt(paths.receiptPath);
|
|
3863
|
+
const modules = options.modules ?? previous?.modules ?? selectResources().modules.map((module) => module.id);
|
|
3864
|
+
selectResources(modules);
|
|
3865
|
+
if (!modules.length)
|
|
3866
|
+
throw new Error("Select at least one module");
|
|
3867
|
+
if (previous?.commandDirectory && paths.commandDirectory !== previous.commandDirectory)
|
|
3868
|
+
throw new Error("BitFun command directory changed; use the original --command-dir or uninstall first");
|
|
3869
|
+
if (options.crBinary && !isAbsolute3(options.crBinary))
|
|
3870
|
+
throw new Error("CR binary must be an absolute native executable path");
|
|
3871
|
+
const source = options.source ? resolve5(options.source) : packageRoot(import.meta.url);
|
|
3872
|
+
if (!await Bun.file(source).exists() && !await lstat(source).then((value) => value.isDirectory()).catch(() => false))
|
|
3873
|
+
throw new Error(`Package source not found: ${source}`);
|
|
3874
|
+
const configPath = options.host === "deveco" ? await devecoConfigPath(paths.configDirectory) : join5(paths.configDirectory, options.host === "bitfun" ? "app.json" : "settings.json");
|
|
3875
|
+
if (options.host !== "claude-code")
|
|
3876
|
+
validatePluginConfig(await readObject(configPath), previous);
|
|
3877
|
+
const sourceIdentity = await Bun.file(source).exists() ? { sha256: digest(await Bun.file(source).bytes()) } : await verifyPackage(source).then((manifest) => ({ version: manifest.version, buildId: manifest.buildId }));
|
|
3878
|
+
return {
|
|
3879
|
+
action: previous ? "update" : "install",
|
|
3880
|
+
host: options.host,
|
|
3881
|
+
source,
|
|
3882
|
+
modules,
|
|
3883
|
+
configDirectory: paths.configDirectory,
|
|
3884
|
+
sourceIdentity,
|
|
3885
|
+
commandDirectory: options.host === "bitfun" ? paths.commandDirectory : undefined,
|
|
3886
|
+
configPath,
|
|
3887
|
+
installationId: paths.installationId,
|
|
3888
|
+
receiptPath: paths.receiptPath,
|
|
3889
|
+
previousVersion: previous?.version,
|
|
3890
|
+
operations: options.host !== "claude-code" ? ["validate package manifest", "install actual host npm dependency", "register one native plugin", ...options.host === "bitfun" ? ["install selected BitFun command files"] : [], "verify package resources"] : ["validate package manifest", "materialize selected native plugin resources", "register local marketplace through Claude CLI", "verify installed plugin cache"],
|
|
3891
|
+
restartRequired: true,
|
|
3892
|
+
loaded: "not checked",
|
|
3893
|
+
verified: false
|
|
3894
|
+
};
|
|
3895
|
+
}
|
|
3896
|
+
async function install(options) {
|
|
3897
|
+
const plan = await planInstallation(options);
|
|
3898
|
+
const paths = installationPaths(options);
|
|
3899
|
+
await mkdir3(paths.instance, { recursive: true });
|
|
3900
|
+
const lock = await acquireLock(paths.lockPath);
|
|
3901
|
+
try {
|
|
3902
|
+
if (await Bun.file(paths.journalPath).exists())
|
|
3903
|
+
throw new Error(`Unfinished installation: inspect ${paths.journalPath}; run vsl recover for this host`);
|
|
3904
|
+
const previous = await readReceipt(paths.receiptPath);
|
|
3905
|
+
if (previous)
|
|
3906
|
+
await assertOwnedFiles(previous);
|
|
3907
|
+
if (previous && !(await doctor(options)).configured)
|
|
3908
|
+
throw new Error("Managed host registration changed; resolve doctor diagnostics before update");
|
|
3909
|
+
const packageJsonPath = join5(paths.configDirectory, "package.json");
|
|
3910
|
+
const configBefore = await textOrUndefined(plan.configPath);
|
|
3911
|
+
const packageBefore = await textOrUndefined(packageJsonPath);
|
|
3912
|
+
const dependencyBefore = dependencyOf(await readObject(packageJsonPath));
|
|
3913
|
+
const originalEntries = options.host !== "claude-code" ? validatePluginConfig(await readObject(plan.configPath), previous) : [];
|
|
3914
|
+
const currentRoot = join5(paths.configDirectory, "node_modules/@bitfun-vsl/plugin");
|
|
3915
|
+
if (!previous && options.host !== "claude-code" && await Bun.file(join5(currentRoot, "package.json")).exists()) {
|
|
3916
|
+
if (!await Bun.file(join5(currentRoot, "assets/install-manifest.json")).exists())
|
|
3917
|
+
throw new Error("Existing host VSL package has no ownership manifest. Back up and remove the legacy installation before init can take ownership.");
|
|
3918
|
+
await verifyPackage(currentRoot);
|
|
3919
|
+
const existing = await inventory(currentRoot);
|
|
3920
|
+
const manifest2 = await Bun.file(join5(currentRoot, "assets/install-manifest.json")).json();
|
|
3921
|
+
const pkg = await Bun.file(join5(currentRoot, "package.json")).json();
|
|
3922
|
+
const unowned = Object.keys(existing).filter((path2) => !["package.json", "README.md", "LICENSE", "assets/install-manifest.json", "assets/runtime.json"].includes(path2) && !(path2 in manifest2.files) && !(pkg.files ?? []).some((file) => file.startsWith("docs/") && path2 === file));
|
|
3923
|
+
if (unowned.length)
|
|
3924
|
+
throw new Error(`Unowned files in existing VSL package: ${unowned.join(", ")}`);
|
|
3925
|
+
}
|
|
3926
|
+
const originalRuntime = options.host !== "claude-code" ? await textOrUndefined(join5(currentRoot, "assets/runtime.json")) : undefined;
|
|
3927
|
+
const releaseRoot = join5(paths.instance, "releases", crypto.randomUUID());
|
|
3928
|
+
const marketplaceBefore = await textOrUndefined(join5(paths.instance, "marketplace/.claude-plugin/marketplace.json"));
|
|
3929
|
+
const state = {
|
|
3930
|
+
phase: "staging",
|
|
3931
|
+
host: options.host,
|
|
3932
|
+
configDirectory: paths.configDirectory,
|
|
3933
|
+
releaseRoot,
|
|
3934
|
+
marketplaceBefore,
|
|
3935
|
+
configPath: plan.configPath,
|
|
3936
|
+
configBefore,
|
|
3937
|
+
packageBefore,
|
|
3938
|
+
previous,
|
|
3939
|
+
dependencyBefore,
|
|
3940
|
+
originalEntries,
|
|
3941
|
+
originalRuntime
|
|
3942
|
+
};
|
|
3943
|
+
await writeJson(paths.journalPath, state);
|
|
3944
|
+
await mkdir3(releaseRoot, { recursive: true });
|
|
3945
|
+
await command(["npm", "install", "--prefix", releaseRoot, "--ignore-scripts", "--install-links", "--no-audit", "--no-fund", plan.source]);
|
|
3946
|
+
const stagedRoot = join5(releaseRoot, "node_modules/@bitfun-vsl/plugin");
|
|
3947
|
+
const manifest = await verifyPackage(stagedRoot);
|
|
3948
|
+
if (plan.modules.some((name) => !manifest.modules.some((module) => module.id === name)))
|
|
3949
|
+
throw new Error("Selected module is absent from source package");
|
|
3950
|
+
const { resolveCr: resolveCr2 } = await Promise.resolve().then(() => (init_runtime(), exports_runtime));
|
|
3951
|
+
const requestedCr = options.crBinary ?? previous?.crBinary ?? process.env.VSL_CR_BIN;
|
|
3952
|
+
const crBinary = requestedCr ? await resolveCr2(requestedCr) : plan.modules.includes("code-review") ? await resolveCr2().catch(() => {
|
|
3953
|
+
return;
|
|
3954
|
+
}) : undefined;
|
|
3955
|
+
const runtime = { schemaVersion: 1, host: options.host, modules: plan.modules, crBinary, installationId: paths.installationId };
|
|
3956
|
+
if (previous && previous.buildId === manifest.buildId && JSON.stringify(previous.modules) === JSON.stringify(plan.modules) && previous.crBinary === runtime.crBinary) {
|
|
3957
|
+
const report2 = await doctor(options);
|
|
3958
|
+
if (report2.configured) {
|
|
3959
|
+
await safeRemove(paths.instance, releaseRoot);
|
|
3960
|
+
await rm(paths.journalPath);
|
|
3961
|
+
return { ...report2, recoveryRequired: false, unchanged: true };
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
await writeJson(join5(stagedRoot, "assets/runtime.json"), runtime);
|
|
3965
|
+
const marketplace = `vsl-${paths.installationId}`;
|
|
3966
|
+
const marketplacePath = join5(paths.instance, "marketplace");
|
|
3967
|
+
const pluginVersion = `${manifest.version}+vsl.${manifest.buildId.slice(0, 8)}.${digest(JSON.stringify(runtime)).slice(0, 8)}.${crypto.randomUUID().slice(0, 8)}`;
|
|
3968
|
+
const pluginRoot = join5(marketplacePath, "releases", pluginVersion, "plugin");
|
|
3969
|
+
if (options.host === "claude-code") {
|
|
3970
|
+
const existing = await command(["claude", "plugin", "list", "--json"], claudeEnvironment(paths.configDirectory));
|
|
3971
|
+
const plugins = JSON.parse(existing);
|
|
3972
|
+
if (!Array.isArray(plugins))
|
|
3973
|
+
throw new Error("Invalid Claude plugin inventory");
|
|
3974
|
+
if (plugins.some((item) => item && typeof item === "object" && ("id" in item) && typeof item.id === "string" && (item.id === "vsl" || item.id.startsWith("vsl@")) && item.id !== `vsl@${marketplace}`))
|
|
3975
|
+
throw new Error("Another VSL Claude plugin is registered; resolve it before adopting this installation");
|
|
3976
|
+
const existingPlugin = await Bun.file(join5(pluginRoot, ".claude-plugin/plugin.json")).exists();
|
|
3977
|
+
if (existingPlugin)
|
|
3978
|
+
throw new Error(`Unowned Claude release already exists: ${pluginRoot}`);
|
|
3979
|
+
const renderer2 = await import(pathToFileURL(join5(stagedRoot, "dist/install/resources.js")).href);
|
|
3980
|
+
await writeResources(pluginRoot, Object.fromEntries(Object.entries(renderer2.renderResources(renderer2.selectResources(plan.modules), pluginVersion)).filter(([path2]) => path2.startsWith("claude-code/")).map(([path2, content]) => [path2.slice("claude-code/".length), content])));
|
|
3981
|
+
await writeJson(join5(pluginRoot, ".vsl-runtime.json"), runtime);
|
|
3982
|
+
await mkdir3(join5(pluginRoot, "scripts"), { recursive: true });
|
|
3983
|
+
await Bun.write(join5(pluginRoot, "scripts/mcp-server.js"), Bun.file(join5(stagedRoot, "assets/claude-code/scripts/mcp-server.js")));
|
|
3984
|
+
await command(["claude", "plugin", "validate", pluginRoot], claudeEnvironment(paths.configDirectory));
|
|
3985
|
+
}
|
|
3986
|
+
const renderer = options.host === "bitfun" ? await import(pathToFileURL(join5(stagedRoot, "dist/install/resources.js")).href) : undefined;
|
|
3987
|
+
const selectedCommandFiles = renderer ? Object.fromEntries(Object.entries(renderer.renderResources(renderer.selectResources(plan.modules), manifest.version)).filter(([path2]) => path2.startsWith("bitfun/command/")).map(([path2, content]) => [path2.slice("bitfun/".length), String(content)])) : undefined;
|
|
3988
|
+
const commandFilesBefore = selectedCommandFiles ? Object.fromEntries(await Promise.all([...new Set([
|
|
3989
|
+
...Object.keys(previous?.commandFiles ?? {}),
|
|
3990
|
+
...Object.keys(selectedCommandFiles)
|
|
3991
|
+
])].map(async (path2) => [path2, await textOrUndefined(inside(paths.commandDirectory, path2)) ?? null]))) : undefined;
|
|
3992
|
+
if (selectedCommandFiles && commandFilesBefore) {
|
|
3993
|
+
for (const [path2, before] of Object.entries(commandFilesBefore)) {
|
|
3994
|
+
if (before !== null && !(path2 in (previous?.commandFiles ?? {})) && before !== selectedCommandFiles[path2])
|
|
3995
|
+
throw new Error(`Unmanaged BitFun command would be overwritten: ${path2}`);
|
|
3996
|
+
}
|
|
3997
|
+
}
|
|
3998
|
+
if (await textOrUndefined(plan.configPath) !== configBefore || await textOrUndefined(packageJsonPath) !== packageBefore)
|
|
3999
|
+
throw new Error("Host configuration changed during planning; retry installation");
|
|
4000
|
+
await writeJson(paths.journalPath, { ...state, phase: "registering", marketplace, marketplacePath, pluginRoot, commandFilesBefore, commandDirectory: paths.commandDirectory });
|
|
4001
|
+
if (options.host !== "claude-code") {
|
|
4002
|
+
await mkdir3(paths.configDirectory, { recursive: true });
|
|
4003
|
+
await command(["npm", "install", "--prefix", paths.configDirectory, "--ignore-scripts", "--install-links", "--no-audit", "--no-fund", stagedRoot]);
|
|
4004
|
+
await verifyPackage(currentRoot);
|
|
4005
|
+
if (await textOrUndefined(plan.configPath) !== configBefore)
|
|
4006
|
+
throw new Error("Host configuration changed during dependency installation");
|
|
4007
|
+
const parsed = await readObject(plan.configPath);
|
|
4008
|
+
const entries = Array.isArray(parsed.plugin) ? parsed.plugin : [];
|
|
4009
|
+
const entry = pathToFileURL(join5(currentRoot, hostEntry(options.host))).href;
|
|
4010
|
+
await patchJson(plan.configPath, ["plugin"], [...entries.filter((item) => !isVslEntry(entrySpec(item))), entry]);
|
|
4011
|
+
}
|
|
4012
|
+
if (options.host === "claude-code") {
|
|
4013
|
+
await writeJson(join5(marketplacePath, ".claude-plugin/marketplace.json"), {
|
|
4014
|
+
name: marketplace,
|
|
4015
|
+
owner: { name: "VSL" },
|
|
4016
|
+
plugins: [{
|
|
4017
|
+
name: "vsl",
|
|
4018
|
+
version: pluginVersion,
|
|
4019
|
+
source: `./releases/${pluginVersion}/plugin`,
|
|
4020
|
+
description: "VSL shared modules and tools"
|
|
4021
|
+
}]
|
|
4022
|
+
});
|
|
4023
|
+
if (previous) {
|
|
4024
|
+
await command(["claude", "plugin", "marketplace", "update", marketplace], claudeEnvironment(paths.configDirectory));
|
|
4025
|
+
await command(["claude", "plugin", "update", `vsl@${marketplace}`, "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4026
|
+
}
|
|
4027
|
+
if (!previous) {
|
|
4028
|
+
await command(["claude", "plugin", "marketplace", "add", marketplacePath, "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4029
|
+
await command(["claude", "plugin", "install", `vsl@${marketplace}`, "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
if (selectedCommandFiles && commandFilesBefore) {
|
|
4033
|
+
for (const [path2, before] of Object.entries(commandFilesBefore)) {
|
|
4034
|
+
if ((await textOrUndefined(inside(paths.commandDirectory, path2)) ?? null) !== before)
|
|
4035
|
+
throw new Error(`BitFun command changed during installation: ${path2}`);
|
|
4036
|
+
}
|
|
4037
|
+
await restoreCommands(paths.commandDirectory, Object.fromEntries(Object.keys(commandFilesBefore).map((path2) => [path2, selectedCommandFiles[path2] ?? previous?.originalCommandFiles?.[path2] ?? null])));
|
|
4038
|
+
}
|
|
4039
|
+
const installedRoot = options.host !== "claude-code" ? currentRoot : await claudeInstalledRoot(paths.configDirectory, `vsl@${marketplace}`, pluginVersion);
|
|
4040
|
+
const receipt = {
|
|
4041
|
+
schemaVersion: 1,
|
|
4042
|
+
installationId: paths.installationId,
|
|
4043
|
+
host: options.host,
|
|
4044
|
+
configDirectory: paths.configDirectory,
|
|
4045
|
+
packageRoot: installedRoot,
|
|
4046
|
+
releaseRoot,
|
|
4047
|
+
version: manifest.version,
|
|
4048
|
+
buildId: manifest.buildId,
|
|
4049
|
+
modules: plan.modules,
|
|
4050
|
+
crBinary: runtime.crBinary,
|
|
4051
|
+
files: await inventory(installedRoot),
|
|
4052
|
+
configPath: plan.configPath,
|
|
4053
|
+
entry: options.host !== "claude-code" ? pathToFileURL(join5(currentRoot, hostEntry(options.host))).href : `vsl@${marketplace}`,
|
|
4054
|
+
marketplace: options.host === "claude-code" ? marketplace : undefined,
|
|
4055
|
+
marketplacePath: options.host === "claude-code" ? marketplacePath : undefined,
|
|
4056
|
+
sourceFiles: await inventory(stagedRoot),
|
|
4057
|
+
dependency: options.host !== "claude-code" ? dependencyOf(await readObject(packageJsonPath)) : undefined,
|
|
4058
|
+
pluginVersion: options.host === "claude-code" ? pluginVersion : undefined,
|
|
4059
|
+
commandDirectory: options.host === "bitfun" ? paths.commandDirectory : undefined,
|
|
4060
|
+
commandFiles: selectedCommandFiles ? Object.fromEntries(Object.entries(selectedCommandFiles).map(([path2, content]) => [path2, digest(content)])) : undefined,
|
|
4061
|
+
originalCommandFiles: commandFilesBefore ? { ...commandFilesBefore, ...previous?.originalCommandFiles } : undefined,
|
|
4062
|
+
originalPluginEntries: previous?.originalPluginEntries ?? originalEntries,
|
|
4063
|
+
originalDependency: previous ? previous.originalDependency : dependencyBefore,
|
|
4064
|
+
originalRuntime: previous ? previous.originalRuntime : originalRuntime,
|
|
4065
|
+
installedAt: new Date().toISOString(),
|
|
4066
|
+
status: "configured",
|
|
4067
|
+
restartRequired: true
|
|
4068
|
+
};
|
|
4069
|
+
await writeJson(paths.receiptPath, receipt);
|
|
4070
|
+
const report = await doctor(options);
|
|
4071
|
+
if (!report.configured)
|
|
4072
|
+
throw new Error("Installed host registration failed verification");
|
|
4073
|
+
await rm(paths.journalPath);
|
|
4074
|
+
return { ...report, recoveryRequired: false };
|
|
4075
|
+
} finally {
|
|
4076
|
+
await lock.close();
|
|
4077
|
+
await rm(paths.lockPath);
|
|
4078
|
+
}
|
|
4079
|
+
}
|
|
4080
|
+
async function doctor(options) {
|
|
4081
|
+
const paths = installationPaths(options);
|
|
4082
|
+
const receipt = await readReceipt(paths.receiptPath);
|
|
4083
|
+
if (!receipt)
|
|
4084
|
+
return {
|
|
4085
|
+
installed: false,
|
|
4086
|
+
configured: false,
|
|
4087
|
+
loaded: "not checked",
|
|
4088
|
+
verified: false,
|
|
4089
|
+
configDirectory: paths.configDirectory,
|
|
4090
|
+
recoveryRequired: await Bun.file(paths.journalPath).exists()
|
|
4091
|
+
};
|
|
4092
|
+
const changed = await changedFiles(receipt);
|
|
4093
|
+
const config = await readObject(receipt.configPath);
|
|
4094
|
+
const dependency = options.host !== "claude-code" ? dependencyOf(await readObject(join5(paths.configDirectory, "package.json"))) : undefined;
|
|
4095
|
+
const commandChanges = receipt.commandDirectory ? (await Promise.all(Object.entries(receipt.commandFiles ?? {}).map(async ([path2, hash]) => digest(await textOrUndefined(inside(receipt.commandDirectory, path2)) ?? "") === hash ? undefined : `commands/${path2}`))).filter((path2) => !!path2) : [];
|
|
4096
|
+
changed.push(...commandChanges);
|
|
4097
|
+
const registration = options.host !== "claude-code" ? Array.isArray(config.plugin) && config.plugin.filter((item) => isVslEntry(entrySpec(item))).length === 1 && config.plugin.includes(receipt.entry) && dependency === receipt.dependency : await claudeInstalledRoot(paths.configDirectory, receipt.entry, receipt.pluginVersion).then((root) => root === receipt.packageRoot).catch(() => false);
|
|
4098
|
+
return {
|
|
4099
|
+
host: receipt.host,
|
|
4100
|
+
version: receipt.version,
|
|
4101
|
+
buildId: receipt.buildId,
|
|
4102
|
+
modules: receipt.modules,
|
|
4103
|
+
installationId: receipt.installationId,
|
|
4104
|
+
crBinary: receipt.crBinary,
|
|
4105
|
+
packageRoot: receipt.packageRoot,
|
|
4106
|
+
configDirectory: receipt.configDirectory,
|
|
4107
|
+
changedFiles: changed,
|
|
4108
|
+
installed: changed.length === 0,
|
|
4109
|
+
configured: changed.length === 0 && registration,
|
|
4110
|
+
recoveryRequired: await Bun.file(paths.journalPath).exists(),
|
|
4111
|
+
restartRequired: true,
|
|
4112
|
+
loaded: "not checked",
|
|
4113
|
+
verified: false,
|
|
4114
|
+
runtimeProof: "After restarting the host, call vsl_runtime_info there and compare buildId, installationId and modules with this report."
|
|
4115
|
+
};
|
|
4116
|
+
}
|
|
4117
|
+
async function uninstall(options, dryRun = false) {
|
|
4118
|
+
const paths = installationPaths(options);
|
|
4119
|
+
const receipt = await readReceipt(paths.receiptPath);
|
|
4120
|
+
if (!receipt)
|
|
4121
|
+
return { removed: false, reason: "No managed installation" };
|
|
4122
|
+
await assertOwnedFiles(receipt);
|
|
4123
|
+
const report = await doctor(options);
|
|
4124
|
+
if (!report.configured)
|
|
4125
|
+
throw new Error("Host registration changed; resolve doctor diagnostics before uninstalling");
|
|
4126
|
+
if (dryRun)
|
|
4127
|
+
return {
|
|
4128
|
+
host: receipt.host,
|
|
4129
|
+
action: "uninstall",
|
|
4130
|
+
entry: receipt.entry,
|
|
4131
|
+
restoreDependency: receipt.originalDependency,
|
|
4132
|
+
preserve: ["user files", "external tools", "historical release evidence"],
|
|
4133
|
+
dryRun: true
|
|
4134
|
+
};
|
|
4135
|
+
const lock = await acquireLock(paths.lockPath);
|
|
4136
|
+
try {
|
|
4137
|
+
if (await Bun.file(paths.journalPath).exists())
|
|
4138
|
+
throw new Error("Recover the unfinished installation before uninstalling");
|
|
4139
|
+
await assertOwnedFiles(receipt);
|
|
4140
|
+
if (!(await doctor(options)).configured)
|
|
4141
|
+
throw new Error("Registration changed during uninstall planning");
|
|
4142
|
+
await writeJson(paths.journalPath, {
|
|
4143
|
+
phase: "uninstalling",
|
|
4144
|
+
previous: receipt,
|
|
4145
|
+
configPath: receipt.configPath,
|
|
4146
|
+
commandDirectory: receipt.commandDirectory,
|
|
4147
|
+
commandFilesBefore: receipt.commandDirectory ? Object.fromEntries(await Promise.all(Object.keys(receipt.commandFiles ?? {}).map(async (path2) => [path2, await textOrUndefined(inside(receipt.commandDirectory, path2)) ?? null]))) : undefined,
|
|
4148
|
+
marketplaceBefore: receipt.marketplacePath ? await textOrUndefined(join5(receipt.marketplacePath, ".claude-plugin/marketplace.json")) : undefined
|
|
4149
|
+
});
|
|
4150
|
+
if (receipt.host !== "claude-code") {
|
|
4151
|
+
const config = await readObject(receipt.configPath);
|
|
4152
|
+
await patchJson(receipt.configPath, ["plugin"], [...config.plugin.filter((entry) => entry !== receipt.entry), ...receipt.originalPluginEntries]);
|
|
4153
|
+
if (receipt.originalDependency) {
|
|
4154
|
+
await command([
|
|
4155
|
+
"npm",
|
|
4156
|
+
"install",
|
|
4157
|
+
"--prefix",
|
|
4158
|
+
receipt.configDirectory,
|
|
4159
|
+
"--ignore-scripts",
|
|
4160
|
+
"--install-links",
|
|
4161
|
+
"--no-audit",
|
|
4162
|
+
"--no-fund",
|
|
4163
|
+
receipt.originalDependency.startsWith("file:") ? resolve5(receipt.configDirectory, receipt.originalDependency.slice(5)) : `@bitfun-vsl/plugin@${receipt.originalDependency}`
|
|
4164
|
+
]);
|
|
4165
|
+
await patchJson(join5(receipt.configDirectory, "package.json"), ["dependencies", "@bitfun-vsl/plugin"], receipt.originalDependency);
|
|
4166
|
+
if (receipt.originalRuntime)
|
|
4167
|
+
await Bun.write(join5(receipt.packageRoot, "assets/runtime.json"), receipt.originalRuntime);
|
|
4168
|
+
}
|
|
4169
|
+
if (!receipt.originalDependency)
|
|
4170
|
+
await command(["npm", "uninstall", "--prefix", receipt.configDirectory, "--ignore-scripts", "--no-audit", "--no-fund", "@bitfun-vsl/plugin"]);
|
|
4171
|
+
}
|
|
4172
|
+
if (receipt.host === "claude-code") {
|
|
4173
|
+
await command(["claude", "plugin", "uninstall", receipt.entry, "--scope", "user", "--keep-data"], claudeEnvironment(receipt.configDirectory));
|
|
4174
|
+
await command(["claude", "plugin", "marketplace", "remove", receipt.marketplace, "--scope", "user"], claudeEnvironment(receipt.configDirectory));
|
|
4175
|
+
}
|
|
4176
|
+
if (receipt.commandDirectory)
|
|
4177
|
+
await restoreCommands(receipt.commandDirectory, Object.fromEntries(Object.keys(receipt.commandFiles ?? {}).map((path2) => [path2, receipt.originalCommandFiles?.[path2] ?? null])));
|
|
4178
|
+
await rename(paths.receiptPath, join5(paths.instance, `uninstalled-${Date.now()}.json`));
|
|
4179
|
+
await rm(paths.journalPath);
|
|
4180
|
+
return { removed: true, host: receipt.host, restartRequired: true };
|
|
4181
|
+
} finally {
|
|
4182
|
+
await lock.close();
|
|
4183
|
+
await rm(paths.lockPath);
|
|
4184
|
+
}
|
|
4185
|
+
}
|
|
4186
|
+
async function recover(options) {
|
|
4187
|
+
const paths = installationPaths(options);
|
|
4188
|
+
const journal = await readObject(paths.journalPath);
|
|
4189
|
+
if (!Object.keys(journal).length)
|
|
4190
|
+
return { recovered: false, reason: "No unfinished transaction" };
|
|
4191
|
+
const lock = await acquireLock(paths.lockPath);
|
|
4192
|
+
try {
|
|
4193
|
+
if (journal.phase !== "staging") {
|
|
4194
|
+
const previous = journal.previous;
|
|
4195
|
+
if (options.host !== "claude-code") {
|
|
4196
|
+
const configPath = String(journal.configPath);
|
|
4197
|
+
const current = await readObject(configPath);
|
|
4198
|
+
const entries = current.plugin ?? [];
|
|
4199
|
+
if (!Array.isArray(entries))
|
|
4200
|
+
throw new Error("Invalid host plugin configuration; manual recovery required");
|
|
4201
|
+
const restoredEntries = previous ? [previous.entry] : Array.isArray(journal.originalEntries) ? journal.originalEntries : [];
|
|
4202
|
+
const foreign = entries.filter((entry) => isVslEntry(entrySpec(entry)) && !restoredEntries.includes(entry) && entry !== pathToFileURL(join5(paths.configDirectory, "node_modules/@bitfun-vsl/plugin", hostEntry(options.host))).href);
|
|
4203
|
+
if (foreign.length)
|
|
4204
|
+
throw new Error("VSL registration changed externally; preserving recovery evidence");
|
|
4205
|
+
const dependency = previous?.dependency ?? (typeof journal.dependencyBefore === "string" ? journal.dependencyBefore : undefined);
|
|
4206
|
+
if (dependency) {
|
|
4207
|
+
await command(["npm", "install", "--prefix", paths.configDirectory, "--ignore-scripts", "--install-links", "--no-audit", "--no-fund", dependency.startsWith("file:") ? resolve5(paths.configDirectory, dependency.slice(5)) : `@bitfun-vsl/plugin@${dependency}`]);
|
|
4208
|
+
await patchJson(join5(paths.configDirectory, "package.json"), ["dependencies", "@bitfun-vsl/plugin"], dependency);
|
|
4209
|
+
if (!previous && typeof journal.originalRuntime === "string")
|
|
4210
|
+
await Bun.write(join5(paths.configDirectory, "node_modules/@bitfun-vsl/plugin/assets/runtime.json"), journal.originalRuntime);
|
|
4211
|
+
}
|
|
4212
|
+
if (!dependency)
|
|
4213
|
+
await command(["npm", "uninstall", "--prefix", paths.configDirectory, "--ignore-scripts", "--no-audit", "--no-fund", "@bitfun-vsl/plugin"]);
|
|
4214
|
+
await patchJson(configPath, ["plugin"], [...entries.filter((entry) => !isVslEntry(entrySpec(entry))), ...restoredEntries]);
|
|
4215
|
+
}
|
|
4216
|
+
if (options.host === "claude-code") {
|
|
4217
|
+
const marketplace = typeof journal.marketplace === "string" ? journal.marketplace : previous?.marketplace;
|
|
4218
|
+
if (!marketplace)
|
|
4219
|
+
throw new Error("Missing marketplace recovery identity");
|
|
4220
|
+
const entry = `vsl@${marketplace}`;
|
|
4221
|
+
if (typeof journal.marketplaceBefore === "string") {
|
|
4222
|
+
await Bun.write(join5(paths.instance, "marketplace/.claude-plugin/marketplace.json"), journal.marketplaceBefore);
|
|
4223
|
+
if (journal.phase === "uninstalling")
|
|
4224
|
+
await command(["claude", "plugin", "marketplace", "add", join5(paths.instance, "marketplace"), "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4225
|
+
await command(["claude", "plugin", "marketplace", "update", marketplace], claudeEnvironment(paths.configDirectory));
|
|
4226
|
+
await command(["claude", "plugin", journal.phase === "uninstalling" ? "install" : "update", entry, "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4227
|
+
}
|
|
4228
|
+
if (!previous) {
|
|
4229
|
+
const inventory = JSON.parse(await command(["claude", "plugin", "list", "--json"], claudeEnvironment(paths.configDirectory)));
|
|
4230
|
+
if (Array.isArray(inventory) && inventory.some((item) => item?.id === entry))
|
|
4231
|
+
await command(["claude", "plugin", "uninstall", entry, "--scope", "user", "--keep-data"], claudeEnvironment(paths.configDirectory));
|
|
4232
|
+
await command(["claude", "plugin", "marketplace", "remove", marketplace, "--scope", "user"], claudeEnvironment(paths.configDirectory));
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
if (options.host === "bitfun" && journal.commandFilesBefore && typeof journal.commandDirectory === "string")
|
|
4236
|
+
await restoreCommands(journal.commandDirectory, journal.commandFilesBefore);
|
|
4237
|
+
if (previous)
|
|
4238
|
+
await writeJson(paths.receiptPath, previous);
|
|
4239
|
+
if (!previous)
|
|
4240
|
+
await rm(paths.receiptPath, { force: true });
|
|
4241
|
+
}
|
|
4242
|
+
await rm(paths.journalPath);
|
|
4243
|
+
return { recovered: true, retainedRelease: journal.releaseRoot };
|
|
4244
|
+
} finally {
|
|
4245
|
+
await lock.close();
|
|
4246
|
+
await rm(paths.lockPath);
|
|
4247
|
+
}
|
|
4248
|
+
}
|
|
4249
|
+
async function verifyPackage(root) {
|
|
4250
|
+
const manifest = await Bun.file(join5(root, "assets/install-manifest.json")).json();
|
|
4251
|
+
if (manifest.schemaVersion !== 1 || !manifest.buildId || !manifest.files || !Array.isArray(manifest.modules))
|
|
4252
|
+
throw new Error("Invalid VSL install manifest");
|
|
4253
|
+
const pkg = await Bun.file(join5(root, "package.json")).json();
|
|
4254
|
+
if (pkg.name !== "@bitfun-vsl/plugin" || pkg.version !== manifest.version)
|
|
4255
|
+
throw new Error("VSL package identity differs from install manifest");
|
|
4256
|
+
for (const required of ["dist/hosts/deveco/plugin.js", "dist/hosts/bitfun-kernel/plugin.js", "dist/index.js", "dist/install/resources.js", "assets/claude-code/scripts/mcp-server.js", "assets/claude-code/.mcp.json", "assets/build.json"]) {
|
|
4257
|
+
if (!(required in manifest.files))
|
|
4258
|
+
throw new Error(`Missing required manifest entry: ${required}`);
|
|
4259
|
+
}
|
|
4260
|
+
const invalid = (await Promise.all(Object.entries(manifest.files).map(async ([path2, hash]) => await Bun.file(inside(root, path2)).bytes().then((content) => digest(content) === hash ? undefined : path2).catch(() => path2)))).filter(Boolean);
|
|
4261
|
+
if (invalid.length)
|
|
4262
|
+
throw new Error(`Package files failed verification: ${invalid.join(", ")}`);
|
|
4263
|
+
return manifest;
|
|
4264
|
+
}
|
|
4265
|
+
async function command(args, env = process.env) {
|
|
4266
|
+
const executable = Bun.which(args[0], { PATH: env.PATH });
|
|
4267
|
+
if (!executable)
|
|
4268
|
+
throw new Error(`Required command not found: ${args[0]}`);
|
|
4269
|
+
const nativeClaude = join5(dirname3(executable), "node_modules/@anthropic-ai/claude-code/bin/claude.exe");
|
|
4270
|
+
const npmCli = join5(dirname3(executable), "node_modules/npm/bin/npm-cli.js");
|
|
4271
|
+
const invocation = process.platform === "win32" && /\.(cmd|bat)$/i.test(executable) ? args[0] === "npm" && await Bun.file(npmCli).exists() ? [Bun.which("node") ?? process.execPath, npmCli] : args[0] === "claude" && await Bun.file(nativeClaude).exists() ? [nativeClaude] : undefined : [executable];
|
|
4272
|
+
if (!invocation)
|
|
4273
|
+
throw new Error(`Cannot safely resolve command shim: ${executable}; use a native CLI installation`);
|
|
4274
|
+
const child = Bun.spawn([...invocation, ...args.slice(1)], { env, stdout: "pipe", stderr: "pipe", stdin: "ignore", timeout: 180000 });
|
|
4275
|
+
const [stdout, stderr, code] = await Promise.all([new Response(child.stdout).text(), new Response(child.stderr).text(), child.exited]);
|
|
4276
|
+
if (code !== 0)
|
|
4277
|
+
throw new Error(`${args.slice(0, 3).join(" ")} failed (${code}): ${stderr || stdout}`);
|
|
4278
|
+
return stdout;
|
|
4279
|
+
}
|
|
4280
|
+
async function readObject(path2) {
|
|
4281
|
+
const text = await textOrUndefined(path2);
|
|
4282
|
+
if (text === undefined)
|
|
4283
|
+
return {};
|
|
4284
|
+
const errors2 = [];
|
|
4285
|
+
const value = parse2(text, errors2, { allowTrailingComma: true });
|
|
4286
|
+
if (errors2.length || !value || typeof value !== "object" || Array.isArray(value))
|
|
4287
|
+
throw new Error(`Invalid JSON/JSONC: ${path2}`);
|
|
4288
|
+
return value;
|
|
4289
|
+
}
|
|
4290
|
+
async function readReceipt(path2) {
|
|
4291
|
+
const value = await readObject(path2);
|
|
4292
|
+
if (!Object.keys(value).length)
|
|
4293
|
+
return;
|
|
4294
|
+
if (value.schemaVersion !== 1 || !value.files || typeof value.packageRoot !== "string")
|
|
4295
|
+
throw new Error(`Invalid installation receipt: ${path2}`);
|
|
4296
|
+
return value;
|
|
4297
|
+
}
|
|
4298
|
+
async function devecoConfigPath(root) {
|
|
4299
|
+
const candidates = await Promise.all(["deveco.jsonc", "deveco.json"].map(async (name) => await Bun.file(join5(root, name)).exists() ? join5(root, name) : undefined));
|
|
4300
|
+
const found = candidates.filter((path2) => !!path2);
|
|
4301
|
+
if (found.length > 1)
|
|
4302
|
+
throw new Error("Both deveco.json and deveco.jsonc exist; choose one effective configuration before installing");
|
|
4303
|
+
return found[0] ?? join5(root, "deveco.jsonc");
|
|
4304
|
+
}
|
|
4305
|
+
function isVslEntry(value) {
|
|
4306
|
+
return value === "@bitfun-vsl/plugin" || value.startsWith("@bitfun-vsl/plugin/") || value.startsWith("@bitfun-vsl/plugin@") || value.startsWith("file:") && /\/@bitfun-vsl\/plugin\/dist\/(?:index\.js|hosts\/(?:deveco|bitfun-kernel)\/plugin\.js)$/.test(decodeURI(value).replaceAll("\\", "/"));
|
|
4307
|
+
}
|
|
4308
|
+
function entrySpec(value) {
|
|
4309
|
+
if (typeof value === "string")
|
|
4310
|
+
return value;
|
|
4311
|
+
if (Array.isArray(value) && typeof value[0] === "string")
|
|
4312
|
+
return value[0];
|
|
4313
|
+
if (value && typeof value === "object" && "spec" in value && typeof value.spec === "string")
|
|
4314
|
+
return value.spec;
|
|
4315
|
+
throw new Error("Invalid host plugin declaration");
|
|
4316
|
+
}
|
|
4317
|
+
function hostEntry(host) {
|
|
4318
|
+
return `dist/hosts/${host === "bitfun" ? "bitfun-kernel" : "deveco"}/plugin.js`;
|
|
4319
|
+
}
|
|
4320
|
+
function validatePluginConfig(config, previous) {
|
|
4321
|
+
if (config.plugin !== undefined && !Array.isArray(config.plugin))
|
|
4322
|
+
throw new Error("Host plugin configuration must be an array");
|
|
4323
|
+
const entries = config.plugin ?? [];
|
|
4324
|
+
const own = entries.filter((entry) => isVslEntry(entrySpec(entry)));
|
|
4325
|
+
if (own.some((entry) => entrySpec(entry).startsWith("file:") && entrySpec(entry) !== previous?.entry))
|
|
4326
|
+
throw new Error("Unmanaged VSL file URL requires explicit removal before installation");
|
|
4327
|
+
return own;
|
|
4328
|
+
}
|
|
4329
|
+
async function restoreCommands(root, files) {
|
|
4330
|
+
for (const [path2, content] of Object.entries(files)) {
|
|
4331
|
+
const target = inside(root, path2);
|
|
4332
|
+
if (content === null) {
|
|
4333
|
+
await rm(target, { force: true });
|
|
4334
|
+
continue;
|
|
4335
|
+
}
|
|
4336
|
+
await mkdir3(dirname3(target), { recursive: true });
|
|
4337
|
+
await Bun.write(target, content);
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
function dependencyOf(config) {
|
|
4341
|
+
const deps = config.dependencies;
|
|
4342
|
+
if (deps === undefined)
|
|
4343
|
+
return;
|
|
4344
|
+
if (!deps || typeof deps !== "object" || Array.isArray(deps))
|
|
4345
|
+
throw new Error("Invalid host dependencies");
|
|
4346
|
+
const value = deps["@bitfun-vsl/plugin"];
|
|
4347
|
+
if (value !== undefined && typeof value !== "string")
|
|
4348
|
+
throw new Error("Invalid VSL dependency");
|
|
4349
|
+
return value;
|
|
4350
|
+
}
|
|
4351
|
+
async function inventory(root) {
|
|
4352
|
+
return Object.fromEntries(await Promise.all((await filesUnder(root)).map(async (path2) => [path2, digest(await Bun.file(join5(root, path2)).bytes())])));
|
|
4353
|
+
}
|
|
4354
|
+
async function changedFiles(receipt) {
|
|
4355
|
+
const current = await inventory(receipt.packageRoot).catch(() => ({}));
|
|
4356
|
+
return [...new Set([...Object.keys(receipt.files), ...Object.keys(current)])].filter((path2) => current[path2] !== receipt.files[path2]);
|
|
4357
|
+
}
|
|
4358
|
+
async function assertOwnedFiles(receipt) {
|
|
4359
|
+
const changed = await changedFiles(receipt);
|
|
4360
|
+
if (changed.length)
|
|
4361
|
+
throw new Error(`Managed files were modified; preserving them: ${changed.join(", ")}`);
|
|
4362
|
+
if (receipt.commandDirectory) {
|
|
4363
|
+
for (const [path2, hash] of Object.entries(receipt.commandFiles ?? {})) {
|
|
4364
|
+
if (digest(await textOrUndefined(inside(receipt.commandDirectory, path2)) ?? "") !== hash)
|
|
4365
|
+
throw new Error(`Managed files were modified; preserving them: ${path2}`);
|
|
4366
|
+
}
|
|
4367
|
+
}
|
|
4368
|
+
const sourceRoot = join5(receipt.releaseRoot, "node_modules/@bitfun-vsl/plugin");
|
|
4369
|
+
const current = await inventory(sourceRoot);
|
|
4370
|
+
if (JSON.stringify(current) !== JSON.stringify(receipt.sourceFiles))
|
|
4371
|
+
throw new Error("Staged release was modified; preserving installation");
|
|
4372
|
+
}
|
|
4373
|
+
async function claudeInstalledRoot(configDirectory, entry, version) {
|
|
4374
|
+
const plugins = JSON.parse(await command(["claude", "plugin", "list", "--json"], claudeEnvironment(configDirectory)));
|
|
4375
|
+
if (!Array.isArray(plugins))
|
|
4376
|
+
throw new Error("Invalid Claude inventory");
|
|
4377
|
+
const item = plugins.find((item2) => item2 && typeof item2 === "object" && item2.id === entry && item2.scope === "user");
|
|
4378
|
+
if (!item || typeof item !== "object" || !("installPath" in item) || typeof item.installPath !== "string" || !("version" in item) || item.version !== version || !("enabled" in item) || item.enabled !== true)
|
|
4379
|
+
throw new Error("Claude did not activate the expected plugin version");
|
|
4380
|
+
return item.installPath;
|
|
4381
|
+
}
|
|
4382
|
+
function claudeEnvironment(configDirectory) {
|
|
4383
|
+
return { ...process.env, CLAUDE_CONFIG_DIR: configDirectory };
|
|
4384
|
+
}
|
|
4385
|
+
async function textOrUndefined(path2) {
|
|
4386
|
+
return await Bun.file(path2).exists() ? Bun.file(path2).text() : undefined;
|
|
4387
|
+
}
|
|
4388
|
+
async function writeJson(path2, value) {
|
|
4389
|
+
await mkdir3(dirname3(path2), { recursive: true });
|
|
4390
|
+
const temporary = `${path2}.${crypto.randomUUID()}.tmp`;
|
|
4391
|
+
await Bun.write(temporary, `${JSON.stringify(value, null, 2)}
|
|
4392
|
+
`);
|
|
4393
|
+
await rename(temporary, path2);
|
|
4394
|
+
}
|
|
4395
|
+
async function patchJson(path2, keys, value) {
|
|
4396
|
+
const raw = await textOrUndefined(path2) ?? `{}
|
|
4397
|
+
`;
|
|
4398
|
+
await readObject(path2);
|
|
4399
|
+
await mkdir3(dirname3(path2), { recursive: true });
|
|
4400
|
+
await Bun.write(path2, applyEdits(raw, modify(raw, keys, value, { formattingOptions: { insertSpaces: true, tabSize: 2 } })));
|
|
4401
|
+
}
|
|
4402
|
+
async function acquireLock(path2) {
|
|
4403
|
+
if (await Bun.file(path2).exists()) {
|
|
4404
|
+
const value = await Bun.file(path2).json();
|
|
4405
|
+
if (!value || typeof value !== "object" || !("pid" in value) || typeof value.pid !== "number" || !Number.isInteger(value.pid) || value.pid <= 0)
|
|
4406
|
+
throw new Error(`Invalid installation lock: ${path2}`);
|
|
4407
|
+
const owner = value.pid;
|
|
4408
|
+
const exited = await Promise.resolve().then(() => {
|
|
4409
|
+
process.kill(owner, 0);
|
|
4410
|
+
return false;
|
|
4411
|
+
}).catch((error) => error instanceof Error && ("code" in error) && error.code === "ESRCH");
|
|
4412
|
+
if (!exited)
|
|
4413
|
+
throw new Error(`Another installer owns ${path2} (PID ${owner})`);
|
|
4414
|
+
await rm(path2);
|
|
4415
|
+
}
|
|
4416
|
+
const handle = await open(path2, "wx").catch(() => {
|
|
4417
|
+
throw new Error(`Installation is locked: ${path2}`);
|
|
4418
|
+
});
|
|
4419
|
+
await handle.writeFile(JSON.stringify({ pid: process.pid, createdAt: new Date().toISOString() }));
|
|
4420
|
+
return handle;
|
|
4421
|
+
}
|
|
4422
|
+
async function safeRemove(root, target) {
|
|
4423
|
+
const checked = inside(root, target);
|
|
4424
|
+
if (checked === resolve5(root))
|
|
4425
|
+
throw new Error("Refusing to remove installation root");
|
|
4426
|
+
await rm(checked, { recursive: true, force: true });
|
|
4427
|
+
}
|
|
4428
|
+
|
|
4429
|
+
// src/cli/index.ts
|
|
4430
|
+
var hostChoices = [
|
|
4431
|
+
{ name: "DevEco Code", value: "deveco" },
|
|
4432
|
+
{ name: "Claude Code", value: "claude-code" },
|
|
4433
|
+
{ name: "BitFun", value: "bitfun" }
|
|
4434
|
+
];
|
|
4435
|
+
var moduleChoices = () => selectResources().modules.map((module) => ({
|
|
4436
|
+
name: `${module.id} \u2014 ${module.description}`,
|
|
4437
|
+
value: module.id,
|
|
4438
|
+
checked: true
|
|
4439
|
+
}));
|
|
4440
|
+
async function main(args = process.argv.slice(2)) {
|
|
4441
|
+
if (args.includes("--version")) {
|
|
4442
|
+
console.log(build_default.version);
|
|
4443
|
+
return;
|
|
4444
|
+
}
|
|
4445
|
+
if (!args.length || args.includes("--help")) {
|
|
4446
|
+
console.log(`vsl <init|update|doctor|uninstall|recover> [--host deveco|claude-code|bitfun] [--modules id,id] [--package path] [--config-dir path] [--command-dir path] [--state-dir path] [--cr-bin path] [--dry-run] [--yes] [--json]
|
|
4447
|
+
|
|
4448
|
+
vsl init: \u9009\u62E9\u5BBF\u4E3B \u2192 \u9009\u62E9\u6A21\u5757\uFF08\u9ED8\u8BA4\u5168\u9009\uFF09\u2192 \u786E\u8BA4\u5B89\u88C5\u3002
|
|
4449
|
+
\u5BBF\u4E3B\u652F\u6301\u591A\u9009\uFF0C\u4E5F\u53EF\u91CD\u590D\u4F20\u5165 --host\u3002\u9700\u8981 Bun\u3001npm\uFF1BClaude \u5B89\u88C5\u8FD8\u9700\u8981 Claude CLI\u3002`);
|
|
4450
|
+
return;
|
|
4451
|
+
}
|
|
4452
|
+
const action = args[0];
|
|
4453
|
+
if (!["init", "update", "doctor", "uninstall", "recover"].includes(action))
|
|
4454
|
+
throw new Error(`Unknown command: ${action}`);
|
|
4455
|
+
const values = new Map;
|
|
4456
|
+
const flags = new Set;
|
|
4457
|
+
const parseArgs = (index) => {
|
|
4458
|
+
if (index >= args.length)
|
|
4459
|
+
return;
|
|
4460
|
+
const key = args[index];
|
|
4461
|
+
if (["--dry-run", "--yes", "--json"].includes(key)) {
|
|
4462
|
+
flags.add(key);
|
|
4463
|
+
return parseArgs(index + 1);
|
|
4464
|
+
}
|
|
4465
|
+
if (!["--host", "--modules", "--package", "--config-dir", "--command-dir", "--state-dir", "--cr-bin", "--scope"].includes(key))
|
|
4466
|
+
throw new Error(`Unknown option: ${key}`);
|
|
4467
|
+
const value = args[index + 1];
|
|
4468
|
+
if (!value || value.startsWith("--"))
|
|
4469
|
+
throw new Error(`Missing value: ${key}`);
|
|
4470
|
+
values.set(key, [...values.get(key) ?? [], value]);
|
|
4471
|
+
parseArgs(index + 2);
|
|
4472
|
+
};
|
|
4473
|
+
parseArgs(1);
|
|
4474
|
+
const repeated = [...values].find(([key, items]) => key !== "--host" && items.length > 1);
|
|
4475
|
+
if (repeated)
|
|
4476
|
+
throw new Error(`Option cannot be repeated: ${repeated[0]}`);
|
|
4477
|
+
if (values.has("--scope") && values.get("--scope")?.[0] !== "user")
|
|
4478
|
+
throw new Error("Only user scope is supported");
|
|
4479
|
+
const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY && !flags.has("--yes") && !flags.has("--json"));
|
|
4480
|
+
const installing = action === "init" || action === "update";
|
|
4481
|
+
if (interactive && installing)
|
|
4482
|
+
console.log(`
|
|
4483
|
+
VSL v${build_default.version} \u5B89\u88C5\u5411\u5BFC
|
|
4484
|
+
`);
|
|
4485
|
+
const hosts = values.get("--host")?.flatMap((value) => value.split(",")) ?? (interactive ? await dist_default4({ message: "\u7B2C\u4E00\u6B65\uFF1A\u9009\u62E9\u5BBF\u4E3B\uFF08\u7A7A\u683C\u52FE\u9009\uFF0C\u56DE\u8F66\u7EE7\u7EED\uFF09", choices: hostChoices, required: true }) : []);
|
|
4486
|
+
if (!hosts.length || hosts.some((host) => !hostChoices.some((choice) => choice.value === host)))
|
|
4487
|
+
throw new Error("Specify --host deveco, --host claude-code or --host bitfun");
|
|
4488
|
+
if (new Set(hosts).size !== hosts.length)
|
|
4489
|
+
throw new Error("Duplicate host selection");
|
|
4490
|
+
if (hosts.length > 1 && values.has("--config-dir"))
|
|
4491
|
+
throw new Error("--config-dir requires exactly one host");
|
|
4492
|
+
if (values.has("--command-dir") && !hosts.includes("bitfun"))
|
|
4493
|
+
throw new Error("--command-dir requires the BitFun host");
|
|
4494
|
+
const modules = values.get("--modules")?.[0]?.split(",") ?? (installing && interactive ? await dist_default4({ message: "\u7B2C\u4E8C\u6B65\uFF1A\u9009\u62E9\u6A21\u5757\uFF08\u9ED8\u8BA4\u5168\u9009\uFF0C\u7A7A\u683C\u5207\u6362\uFF0C\u56DE\u8F66\u7EE7\u7EED\uFF09", choices: moduleChoices(), required: true }) : undefined);
|
|
4495
|
+
if (modules?.some((name) => !name.trim()) || modules?.length === 0)
|
|
4496
|
+
throw new Error("Select at least one module");
|
|
4497
|
+
selectResources(modules);
|
|
4498
|
+
const options = hosts.map((host) => ({
|
|
4499
|
+
host,
|
|
4500
|
+
configDirectory: values.get("--config-dir")?.[0],
|
|
4501
|
+
commandDirectory: values.get("--command-dir")?.[0],
|
|
4502
|
+
stateDirectory: values.get("--state-dir")?.[0],
|
|
4503
|
+
source: values.get("--package")?.[0],
|
|
4504
|
+
modules,
|
|
4505
|
+
crBinary: values.get("--cr-bin")?.[0]
|
|
4506
|
+
}));
|
|
4507
|
+
const plans = await Promise.all(options.map((option) => action === "uninstall" ? uninstall(option, true) : installing ? planInstallation(option) : Promise.resolve(undefined)));
|
|
4508
|
+
if (flags.has("--dry-run")) {
|
|
4509
|
+
console.log(JSON.stringify(plans, null, 2));
|
|
4510
|
+
return;
|
|
4511
|
+
}
|
|
4512
|
+
if (installing || action === "uninstall" || action === "recover") {
|
|
4513
|
+
if (interactive) {
|
|
4514
|
+
console.log(`
|
|
4515
|
+
\u5BBF\u4E3B\uFF1A${hosts.map((host) => hostChoices.find((choice) => choice.value === host).name).join("\u3001")}`);
|
|
4516
|
+
if (installing)
|
|
4517
|
+
console.log(`\u6A21\u5757\uFF1A${(modules ?? selectResources().modules.map((module) => module.id)).join("\u3001")}
|
|
4518
|
+
\u5B89\u88C5\u6765\u6E90\uFF1A${values.get("--package")?.[0] ?? "\u5F53\u524D VSL \u5305"}`);
|
|
4519
|
+
}
|
|
4520
|
+
if (!flags.has("--yes") && !interactive)
|
|
4521
|
+
throw new Error("Non-interactive changes require --yes");
|
|
4522
|
+
if (!flags.has("--yes") && !await dist_default5({ message: installing ? "\u662F\u5426\u6267\u884C\u5B89\u88C5\uFF1F" : action === "uninstall" ? "\u662F\u5426\u6267\u884C\u5378\u8F7D\uFF1F" : "\u662F\u5426\u6062\u590D\u5B89\u88C5\uFF1F", default: true })) {
|
|
4523
|
+
console.log("\u5DF2\u53D6\u6D88\uFF0C\u672A\u4FEE\u6539\u5BBF\u4E3B\u914D\u7F6E\u3002");
|
|
4524
|
+
return;
|
|
4525
|
+
}
|
|
4526
|
+
}
|
|
4527
|
+
const results = [];
|
|
4528
|
+
for (const option of options) {
|
|
4529
|
+
try {
|
|
4530
|
+
if (!flags.has("--json"))
|
|
4531
|
+
console.log(`
|
|
4532
|
+
\u6B63\u5728\u5904\u7406 ${hostChoices.find((choice) => choice.value === option.host).name}\u2026`);
|
|
4533
|
+
const result = action === "doctor" ? await doctor(option) : action === "recover" ? await recover(option) : action === "uninstall" ? await uninstall(option) : await install(option);
|
|
4534
|
+
results.push(result);
|
|
4535
|
+
if ("configured" in result && !result.configured || "recoveryRequired" in result && result.recoveryRequired)
|
|
4536
|
+
process.exitCode = 1;
|
|
4537
|
+
if (!flags.has("--json")) {
|
|
4538
|
+
console.log("configured" in result ? result.configured ? "\u5B89\u88C5\u914D\u7F6E\u68C0\u67E5\u901A\u8FC7\u3002" : "\u5C1A\u672A\u6B63\u786E\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u72B6\u6001\u3002" : JSON.stringify(result));
|
|
4539
|
+
if ("packageRoot" in result)
|
|
4540
|
+
console.log(`\u63D2\u4EF6\u4F4D\u7F6E\uFF1A${result.packageRoot}`);
|
|
4541
|
+
if ("buildId" in result)
|
|
4542
|
+
console.log(`\u7248\u672C\uFF1A${result.version}
|
|
4543
|
+
\u6784\u5EFA\uFF1A${result.buildId}`);
|
|
4544
|
+
if ("modules" in result && result.modules?.includes("code-review"))
|
|
4545
|
+
console.log(result.crBinary ? `CR \u7A0B\u5E8F\uFF1A${result.crBinary}` : "\u672A\u68C0\u6D4B\u5230 CR \u539F\u751F\u7A0B\u5E8F\uFF1B\u8BF7\u5B89\u88C5\u540E\u91CD\u65B0\u8FD0\u884C init\uFF0C\u6216\u4F7F\u7528 --cr-bin \u6307\u5B9A\u5176\u7EDD\u5BF9\u8DEF\u5F84\u3002");
|
|
4546
|
+
if ("configured" in result && result.configured)
|
|
4547
|
+
console.log("\u8BF7\u91CD\u542F\u5BBF\u4E3B\uFF0C\u5728\u5BBF\u4E3B\u4E2D\u8C03\u7528 vsl_runtime_info \u6838\u5BF9\u6784\u5EFA\u4E0E\u6A21\u5757\uFF0C\u518D\u89E6\u53D1\u5BF9\u5E94 command\u3002");
|
|
4548
|
+
if (option.host === "bitfun" && "configured" in result && result.configured)
|
|
4549
|
+
console.log("BitFun \u8FD8\u9700\u542F\u7528 OpenCode \u517C\u5BB9\uFF1Abitfun config external set-enabled true --scope global\uFF1Bbitfun config external set-mode recommended --ecosystem opencode --scope global\u3002\u5728\u4F1A\u8BDD\u4E2D\u7528 /extensions \u68C0\u67E5\u6765\u6E90\u72B6\u6001\u3002");
|
|
4550
|
+
}
|
|
4551
|
+
} catch (error) {
|
|
4552
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
4553
|
+
results.push({ host: option.host, failed: true, error: message });
|
|
4554
|
+
process.exitCode = 1;
|
|
4555
|
+
if (!flags.has("--json"))
|
|
4556
|
+
console.error(`${option.host} \u5931\u8D25\uFF1A${message}`);
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
if (flags.has("--json"))
|
|
4560
|
+
console.log(JSON.stringify(results, null, 2));
|
|
4561
|
+
}
|
|
4562
|
+
if (import.meta.main)
|
|
4563
|
+
await main().catch((error) => {
|
|
4564
|
+
if (error instanceof Error && error.name === "ExitPromptError") {
|
|
4565
|
+
console.error("\u5DF2\u53D6\u6D88\u3002");
|
|
4566
|
+
process.exitCode = 130;
|
|
4567
|
+
return;
|
|
4568
|
+
}
|
|
4569
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
4570
|
+
process.exitCode = 1;
|
|
4571
|
+
});
|
|
4572
|
+
export {
|
|
4573
|
+
moduleChoices,
|
|
4574
|
+
main,
|
|
4575
|
+
hostChoices
|
|
4576
|
+
};
|