@duyquangnvx/create-agent-cli 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -0
- package/README.md +2 -2
- package/dist/bin.js +1963 -1557
- package/package.json +2 -2
- package/template/AGENTS.md +2 -2
- package/template/README.md +8 -0
- package/template/skills/{{binName}}/SKILL.md +1 -1
- package/template/skills/{{binName}}/references/setup.md +47 -0
- package/template/src/cli.ts +1 -0
- package/template/test/cli.test.ts +50 -1
package/dist/bin.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { parseArgs, parseEnv } from "node:util";
|
|
3
3
|
import { basename, delimiter, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
4
|
-
import { access, chmod, link, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
5
4
|
import { constants, existsSync, readFileSync, realpathSync } from "node:fs";
|
|
5
|
+
import { access, chmod, link, lstat, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
|
|
6
6
|
import { constants as constants$1, homedir, tmpdir } from "node:os";
|
|
7
7
|
import { spawn } from "node:child_process";
|
|
8
8
|
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
@@ -2425,6 +2425,138 @@ function handleIntersectionResults(result, left, right) {
|
|
|
2425
2425
|
result.value = merged.data;
|
|
2426
2426
|
return result;
|
|
2427
2427
|
}
|
|
2428
|
+
const $ZodRecord = /*@__PURE__*/ $constructor("$ZodRecord", (inst, def) => {
|
|
2429
|
+
$ZodType.init(inst, def);
|
|
2430
|
+
const memo = globalConfig.memoizer;
|
|
2431
|
+
memo?.attach(inst);
|
|
2432
|
+
inst._zod.parse = (payload, ctx) => {
|
|
2433
|
+
const input = payload.value;
|
|
2434
|
+
if (!isPlainObject(input)) {
|
|
2435
|
+
payload.issues.push({
|
|
2436
|
+
expected: "record",
|
|
2437
|
+
code: "invalid_type",
|
|
2438
|
+
input,
|
|
2439
|
+
inst
|
|
2440
|
+
});
|
|
2441
|
+
return payload;
|
|
2442
|
+
}
|
|
2443
|
+
const proms = [];
|
|
2444
|
+
const values = def.keyType._zod.values;
|
|
2445
|
+
if (values && !def.partial) {
|
|
2446
|
+
payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};
|
|
2447
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
2448
|
+
for (const key of values) if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
2449
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
2450
|
+
if (key === "__proto__") continue;
|
|
2451
|
+
const keyResult = def.keyType._zod.run({
|
|
2452
|
+
value: key,
|
|
2453
|
+
issues: []
|
|
2454
|
+
}, ctx);
|
|
2455
|
+
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2456
|
+
if (keyResult.issues.length) {
|
|
2457
|
+
payload.issues.push({
|
|
2458
|
+
code: "invalid_key",
|
|
2459
|
+
origin: "record",
|
|
2460
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
2461
|
+
input: key,
|
|
2462
|
+
path: [key],
|
|
2463
|
+
inst
|
|
2464
|
+
});
|
|
2465
|
+
continue;
|
|
2466
|
+
}
|
|
2467
|
+
const outKey = keyResult.value;
|
|
2468
|
+
if (outKey === "__proto__") continue;
|
|
2469
|
+
const result = def.valueType._zod.run({
|
|
2470
|
+
value: input[key],
|
|
2471
|
+
issues: []
|
|
2472
|
+
}, ctx);
|
|
2473
|
+
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
2474
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2475
|
+
payload.value[outKey] = result.value;
|
|
2476
|
+
}));
|
|
2477
|
+
else {
|
|
2478
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2479
|
+
payload.value[outKey] = result.value;
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
let unrecognized;
|
|
2483
|
+
for (const key in input) if (!recordKeys.has(key)) {
|
|
2484
|
+
if (def.mode === "loose") {
|
|
2485
|
+
if (key === "__proto__") continue;
|
|
2486
|
+
payload.value[key] = input[key];
|
|
2487
|
+
} else {
|
|
2488
|
+
unrecognized = unrecognized ?? [];
|
|
2489
|
+
unrecognized.push(key);
|
|
2490
|
+
}
|
|
2491
|
+
}
|
|
2492
|
+
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
2493
|
+
code: "unrecognized_keys",
|
|
2494
|
+
input,
|
|
2495
|
+
inst,
|
|
2496
|
+
keys: unrecognized,
|
|
2497
|
+
continue: true
|
|
2498
|
+
});
|
|
2499
|
+
} else {
|
|
2500
|
+
payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};
|
|
2501
|
+
let unrecognized;
|
|
2502
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
2503
|
+
if (key === "__proto__") continue;
|
|
2504
|
+
if (!Object.prototype.propertyIsEnumerable.call(input, key)) continue;
|
|
2505
|
+
let keyResult = def.keyType._zod.run({
|
|
2506
|
+
value: key,
|
|
2507
|
+
issues: []
|
|
2508
|
+
}, ctx);
|
|
2509
|
+
if (keyResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2510
|
+
if (typeof key === "string" && number$1.test(key) && keyResult.issues.length) {
|
|
2511
|
+
const retryResult = def.keyType._zod.run({
|
|
2512
|
+
value: Number(key),
|
|
2513
|
+
issues: []
|
|
2514
|
+
}, ctx);
|
|
2515
|
+
if (retryResult instanceof Promise) throw new Error("Async schemas not supported in object keys currently");
|
|
2516
|
+
if (retryResult.issues.length === 0) keyResult = retryResult;
|
|
2517
|
+
}
|
|
2518
|
+
if (keyResult.issues.length) {
|
|
2519
|
+
if (def.mode === "loose") payload.value[key] = input[key];
|
|
2520
|
+
else if (values) {
|
|
2521
|
+
unrecognized = unrecognized ?? [];
|
|
2522
|
+
unrecognized.push(key);
|
|
2523
|
+
} else payload.issues.push({
|
|
2524
|
+
code: "invalid_key",
|
|
2525
|
+
origin: "record",
|
|
2526
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
2527
|
+
input: key,
|
|
2528
|
+
path: [key],
|
|
2529
|
+
inst
|
|
2530
|
+
});
|
|
2531
|
+
continue;
|
|
2532
|
+
}
|
|
2533
|
+
const outKey = keyResult.value;
|
|
2534
|
+
if (outKey === "__proto__") continue;
|
|
2535
|
+
const result = def.valueType._zod.run({
|
|
2536
|
+
value: input[key],
|
|
2537
|
+
issues: []
|
|
2538
|
+
}, ctx);
|
|
2539
|
+
if (result instanceof Promise) proms.push(result.then((result) => {
|
|
2540
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2541
|
+
payload.value[outKey] = result.value;
|
|
2542
|
+
}));
|
|
2543
|
+
else {
|
|
2544
|
+
if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));
|
|
2545
|
+
payload.value[outKey] = result.value;
|
|
2546
|
+
}
|
|
2547
|
+
}
|
|
2548
|
+
if (unrecognized && unrecognized.length > 0) payload.issues.push({
|
|
2549
|
+
code: "unrecognized_keys",
|
|
2550
|
+
input,
|
|
2551
|
+
inst,
|
|
2552
|
+
keys: unrecognized,
|
|
2553
|
+
continue: true
|
|
2554
|
+
});
|
|
2555
|
+
}
|
|
2556
|
+
if (proms.length) return Promise.all(proms).then(() => payload);
|
|
2557
|
+
return payload;
|
|
2558
|
+
};
|
|
2559
|
+
});
|
|
2428
2560
|
const $ZodEnum = /*@__PURE__*/ $constructor("$ZodEnum", (inst, def) => {
|
|
2429
2561
|
$ZodType.init(inst, def);
|
|
2430
2562
|
const values = getEnumValues(def.entries);
|
|
@@ -5093,6 +5225,9 @@ const ZodURL = /*@__PURE__*/ $constructor("ZodURL", (inst, def) => {
|
|
|
5093
5225
|
$ZodURL.init(inst, def);
|
|
5094
5226
|
ZodStringFormat.init(inst, def);
|
|
5095
5227
|
});
|
|
5228
|
+
function url(params) {
|
|
5229
|
+
return /* @__PURE__ */ _url(ZodURL, params);
|
|
5230
|
+
}
|
|
5096
5231
|
const ZodEmoji = /*@__PURE__*/ $constructor("ZodEmoji", (inst, def) => {
|
|
5097
5232
|
$ZodEmoji.init(inst, def);
|
|
5098
5233
|
ZodStringFormat.init(inst, def);
|
|
@@ -5367,6 +5502,28 @@ function intersection(left, right) {
|
|
|
5367
5502
|
right
|
|
5368
5503
|
});
|
|
5369
5504
|
}
|
|
5505
|
+
const ZodRecord = /*@__PURE__*/ $constructor("ZodRecord", (inst, def) => {
|
|
5506
|
+
_ensureDefaultMemoizer();
|
|
5507
|
+
$ZodRecord.init(inst, def);
|
|
5508
|
+
ZodType.init(inst, def);
|
|
5509
|
+
inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);
|
|
5510
|
+
inst.keyType = def.keyType;
|
|
5511
|
+
inst.valueType = def.valueType;
|
|
5512
|
+
});
|
|
5513
|
+
function record(keyType, valueType, params) {
|
|
5514
|
+
if (!valueType || !valueType._zod) return new ZodRecord({
|
|
5515
|
+
type: "record",
|
|
5516
|
+
keyType: string(),
|
|
5517
|
+
valueType: keyType,
|
|
5518
|
+
...normalizeParams(valueType)
|
|
5519
|
+
});
|
|
5520
|
+
return new ZodRecord({
|
|
5521
|
+
type: "record",
|
|
5522
|
+
keyType,
|
|
5523
|
+
valueType,
|
|
5524
|
+
...normalizeParams(params)
|
|
5525
|
+
});
|
|
5526
|
+
}
|
|
5370
5527
|
const ZodEnum = /*@__PURE__*/ $constructor("ZodEnum", (inst, def) => {
|
|
5371
5528
|
$ZodEnum.init(inst, def);
|
|
5372
5529
|
ZodType.init(inst, def);
|
|
@@ -5582,6 +5739,146 @@ function untilAborted(signal) {
|
|
|
5582
5739
|
});
|
|
5583
5740
|
}
|
|
5584
5741
|
//#endregion
|
|
5742
|
+
//#region ../agent-cli/dist/clock.js
|
|
5743
|
+
const realClock = {
|
|
5744
|
+
now: () => Date.now(),
|
|
5745
|
+
sleep: (ms, signal) => new Promise((resolve, reject) => {
|
|
5746
|
+
if (signal?.aborted === true) {
|
|
5747
|
+
reject(signal.reason);
|
|
5748
|
+
return;
|
|
5749
|
+
}
|
|
5750
|
+
const onAbort = () => {
|
|
5751
|
+
clearTimeout(timer);
|
|
5752
|
+
reject(signal?.reason);
|
|
5753
|
+
};
|
|
5754
|
+
const timer = setTimeout(() => {
|
|
5755
|
+
signal?.removeEventListener("abort", onAbort);
|
|
5756
|
+
resolve();
|
|
5757
|
+
}, ms);
|
|
5758
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
5759
|
+
})
|
|
5760
|
+
};
|
|
5761
|
+
/** Runs `then` once `ms` have passed on `clock`; aborting `cancel` drops it. */
|
|
5762
|
+
function after(clock, ms, cancel, then) {
|
|
5763
|
+
clock.sleep(ms, cancel).then(then, (error) => {
|
|
5764
|
+
if (!cancel.aborted) throw error;
|
|
5765
|
+
});
|
|
5766
|
+
}
|
|
5767
|
+
async function poll(clock, check, intervalMs, signal) {
|
|
5768
|
+
for (;;) {
|
|
5769
|
+
signal.throwIfAborted();
|
|
5770
|
+
const value = await check();
|
|
5771
|
+
if (value !== void 0) return value;
|
|
5772
|
+
await clock.sleep(intervalMs, signal);
|
|
5773
|
+
}
|
|
5774
|
+
}
|
|
5775
|
+
//#endregion
|
|
5776
|
+
//#region ../agent-cli/dist/errors.js
|
|
5777
|
+
var CliError = class extends Error {
|
|
5778
|
+
code;
|
|
5779
|
+
hint;
|
|
5780
|
+
details;
|
|
5781
|
+
retryAt;
|
|
5782
|
+
constructor({ code, message, hint, details, retryAt }, options) {
|
|
5783
|
+
super(message, options);
|
|
5784
|
+
this.name = "CliError";
|
|
5785
|
+
this.code = code;
|
|
5786
|
+
this.hint = hint;
|
|
5787
|
+
this.details = details;
|
|
5788
|
+
this.retryAt = retryAt;
|
|
5789
|
+
}
|
|
5790
|
+
};
|
|
5791
|
+
/** The caller called the Agent CLI wrong; the same call can't succeed. */
|
|
5792
|
+
var UsageError = class extends CliError {
|
|
5793
|
+
constructor(fields) {
|
|
5794
|
+
super(fields);
|
|
5795
|
+
this.name = "UsageError";
|
|
5796
|
+
}
|
|
5797
|
+
};
|
|
5798
|
+
const INTERNAL = "INTERNAL";
|
|
5799
|
+
function errnoOf(error) {
|
|
5800
|
+
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
5801
|
+
}
|
|
5802
|
+
function isMissingFile(error) {
|
|
5803
|
+
return errnoOf(error) === "ENOENT";
|
|
5804
|
+
}
|
|
5805
|
+
function isNothingThere(error) {
|
|
5806
|
+
return isMissingFile(error) || errnoOf(error) === "ENOTDIR";
|
|
5807
|
+
}
|
|
5808
|
+
function debugVariable(cliName) {
|
|
5809
|
+
return `${cliName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_DEBUG`;
|
|
5810
|
+
}
|
|
5811
|
+
function messageOf(error) {
|
|
5812
|
+
return error instanceof Error ? error.message : String(error);
|
|
5813
|
+
}
|
|
5814
|
+
function isDebug({ env, cliName }) {
|
|
5815
|
+
return Boolean(env[debugVariable(cliName)]);
|
|
5816
|
+
}
|
|
5817
|
+
function bugHint(format) {
|
|
5818
|
+
const bugs = format.bugs?.();
|
|
5819
|
+
if (isDebug(format)) {
|
|
5820
|
+
const where = "the stack trace shows where it failed";
|
|
5821
|
+
return bugs === void 0 ? where : `${where}; report it at ${bugs}`;
|
|
5822
|
+
}
|
|
5823
|
+
const rerun = `rerun with ${debugVariable(format.cliName)}=1 to see the stack trace`;
|
|
5824
|
+
return bugs === void 0 ? rerun : `${rerun}, then report it at ${bugs}`;
|
|
5825
|
+
}
|
|
5826
|
+
function fieldsOf$1(error, format) {
|
|
5827
|
+
if (error instanceof CliError) {
|
|
5828
|
+
const { code, message, hint, details, retryAt } = error;
|
|
5829
|
+
return {
|
|
5830
|
+
code,
|
|
5831
|
+
message,
|
|
5832
|
+
hint: format.isBug(error) ? bugHint(format) : hint,
|
|
5833
|
+
details,
|
|
5834
|
+
retryAt
|
|
5835
|
+
};
|
|
5836
|
+
}
|
|
5837
|
+
return {
|
|
5838
|
+
code: INTERNAL,
|
|
5839
|
+
message: messageOf(error),
|
|
5840
|
+
hint: bugHint(format)
|
|
5841
|
+
};
|
|
5842
|
+
}
|
|
5843
|
+
function causesOf(error) {
|
|
5844
|
+
return error instanceof Error && error.cause !== void 0 ? [error.cause, ...causesOf(error.cause)] : [];
|
|
5845
|
+
}
|
|
5846
|
+
function traceOf(error) {
|
|
5847
|
+
return error instanceof Error ? error.stack ?? error.message : String(error);
|
|
5848
|
+
}
|
|
5849
|
+
/** Under debug: a bug's stack trace, then every error's cause chain. */
|
|
5850
|
+
function debugTrace(error, format) {
|
|
5851
|
+
if (!isDebug(format)) return void 0;
|
|
5852
|
+
const lines = [...format.isBug(error) ? [traceOf(error)] : [], ...causesOf(error).map((cause) => `caused by: ${traceOf(cause)}`)];
|
|
5853
|
+
return lines.length === 0 ? void 0 : lines.join("\n");
|
|
5854
|
+
}
|
|
5855
|
+
/**
|
|
5856
|
+
* The errors a run failed with: the leaves of nested `AggregateError`s, or the one it threw. An
|
|
5857
|
+
* empty `AggregateError` is a leaf.
|
|
5858
|
+
*/
|
|
5859
|
+
function errorsOf(error) {
|
|
5860
|
+
return error instanceof AggregateError && error.errors.length > 0 ? error.errors.flatMap(errorsOf) : [error];
|
|
5861
|
+
}
|
|
5862
|
+
function errorLines(error, format) {
|
|
5863
|
+
const fields = fieldsOf$1(error, format);
|
|
5864
|
+
const stack = debugTrace(error, format);
|
|
5865
|
+
const { style } = format;
|
|
5866
|
+
const label = style.red(format.isBug(error) ? "internal error:" : "error:");
|
|
5867
|
+
const trace = stack === void 0 ? "" : `${stack}\n`;
|
|
5868
|
+
return `${label} ${fields.message}\n${trace}${style.cyan("hint:")} ${fields.hint}\n`;
|
|
5869
|
+
}
|
|
5870
|
+
function formatRuntimeError(error, format) {
|
|
5871
|
+
const errors = errorsOf(error);
|
|
5872
|
+
if (format.json) {
|
|
5873
|
+
const printed = errors.map((each) => ({
|
|
5874
|
+
...fieldsOf$1(each, format),
|
|
5875
|
+
stack: debugTrace(each, format)
|
|
5876
|
+
}));
|
|
5877
|
+
return `${JSON.stringify({ errors: printed })}\n`;
|
|
5878
|
+
}
|
|
5879
|
+
return errors.map((each) => errorLines(each, format)).join("");
|
|
5880
|
+
}
|
|
5881
|
+
//#endregion
|
|
5585
5882
|
//#region ../agent-cli/dist/stdin.js
|
|
5586
5883
|
const STDIN_META = "stdin";
|
|
5587
5884
|
function isStdinSchema(schema) {
|
|
@@ -5597,13 +5894,37 @@ function readingLine(name, platform) {
|
|
|
5597
5894
|
function isTerminal(source) {
|
|
5598
5895
|
return typeof source !== "string" && "isTTY" in source && source.isTTY === true;
|
|
5599
5896
|
}
|
|
5600
|
-
|
|
5601
|
-
|
|
5897
|
+
const STDIN_STALLED = "STDIN_STALLED";
|
|
5898
|
+
/** How long a stdin that is not a terminal may send nothing, from the start of the read and from each chunk. */
|
|
5899
|
+
const STDIN_IDLE_MS = 3e4;
|
|
5900
|
+
function stdinStalled(callerLine) {
|
|
5901
|
+
return new CliError({
|
|
5902
|
+
code: STDIN_STALLED,
|
|
5903
|
+
message: `stdin sent nothing for ${STDIN_IDLE_MS} ms`,
|
|
5904
|
+
hint: `stdin never ended: close the pipe or heredoc that feeds \`${callerLine}\`, pass the text as an argument instead, or write a slow producer's output to a file and redirect it in`
|
|
5905
|
+
});
|
|
5906
|
+
}
|
|
5907
|
+
/**
|
|
5908
|
+
* The whole of `source` as UTF-8; rejects with the signal's reason once it aborts, and with
|
|
5909
|
+
* `idle.stalled()` once a stream that is not a terminal sends nothing for `STDIN_IDLE_MS`.
|
|
5910
|
+
*/
|
|
5911
|
+
function readStdin(source, signal, idle) {
|
|
5602
5912
|
if (typeof source === "string") return signal.aborted ? Promise.reject(signal.reason) : Promise.resolve(source);
|
|
5603
5913
|
return new Promise((resolve, reject) => {
|
|
5604
5914
|
const chunks = [];
|
|
5915
|
+
let idleWindow = new AbortController();
|
|
5916
|
+
const watchIdle = () => {
|
|
5917
|
+
idleWindow.abort();
|
|
5918
|
+
idleWindow = new AbortController();
|
|
5919
|
+
if (isTerminal(source)) return;
|
|
5920
|
+
after(idle.clock, STDIN_IDLE_MS, idleWindow.signal, () => {
|
|
5921
|
+
stop();
|
|
5922
|
+
reject(idle.stalled());
|
|
5923
|
+
});
|
|
5924
|
+
};
|
|
5605
5925
|
const onData = (chunk) => {
|
|
5606
5926
|
chunks.push(chunk instanceof Uint8Array ? chunk : Buffer.from(String(chunk)));
|
|
5927
|
+
watchIdle();
|
|
5607
5928
|
};
|
|
5608
5929
|
const onEnd = () => {
|
|
5609
5930
|
stop();
|
|
@@ -5620,12 +5941,14 @@ function readStdin(source, signal) {
|
|
|
5620
5941
|
const stop = () => {
|
|
5621
5942
|
source.off("data", onData).off("end", onEnd).off("error", onError).pause();
|
|
5622
5943
|
signal.removeEventListener("abort", onAbort);
|
|
5944
|
+
idleWindow.abort();
|
|
5623
5945
|
};
|
|
5624
5946
|
if (signal.aborted) {
|
|
5625
5947
|
reject(signal.reason);
|
|
5626
5948
|
return;
|
|
5627
5949
|
}
|
|
5628
5950
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
5951
|
+
watchIdle();
|
|
5629
5952
|
source.on("data", onData).once("end", onEnd).once("error", onError);
|
|
5630
5953
|
});
|
|
5631
5954
|
}
|
|
@@ -5699,11 +6022,11 @@ function optionField(key, schema) {
|
|
|
5699
6022
|
usage
|
|
5700
6023
|
};
|
|
5701
6024
|
}
|
|
5702
|
-
function fieldsOf
|
|
6025
|
+
function fieldsOf(schema, toField) {
|
|
5703
6026
|
return schema === void 0 ? [] : Object.entries(schema.shape).map(([key, value]) => toField(key, value));
|
|
5704
6027
|
}
|
|
5705
6028
|
function argFields(schema) {
|
|
5706
|
-
return fieldsOf
|
|
6029
|
+
return fieldsOf(schema, argField);
|
|
5707
6030
|
}
|
|
5708
6031
|
function keysOf(fields) {
|
|
5709
6032
|
return fields.map(({ key }) => `'${key}'`).join(", ");
|
|
@@ -5724,7 +6047,7 @@ function checkStdinFields(name, args, options) {
|
|
|
5724
6047
|
}
|
|
5725
6048
|
}
|
|
5726
6049
|
function optionFields(schema) {
|
|
5727
|
-
return fieldsOf
|
|
6050
|
+
return fieldsOf(schema, optionField);
|
|
5728
6051
|
}
|
|
5729
6052
|
/** Throws when an option is an array of booleans, which a switch cannot express. */
|
|
5730
6053
|
function checkNoBooleanArrayOption(name, options) {
|
|
@@ -5732,142 +6055,45 @@ function checkNoBooleanArrayOption(name, options) {
|
|
|
5732
6055
|
if (booleans.length > 0) throw new Error(`Command '${name}' declares boolean array option ${keysOf(booleans)}; a switch cannot repeat, use a boolean`);
|
|
5733
6056
|
}
|
|
5734
6057
|
//#endregion
|
|
5735
|
-
//#region ../agent-cli/dist/
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
details;
|
|
5740
|
-
retryAt;
|
|
5741
|
-
constructor({ code, message, hint, details, retryAt }, options) {
|
|
5742
|
-
super(message, options);
|
|
5743
|
-
this.name = "CliError";
|
|
5744
|
-
this.code = code;
|
|
5745
|
-
this.hint = hint;
|
|
5746
|
-
this.details = details;
|
|
5747
|
-
this.retryAt = retryAt;
|
|
5748
|
-
}
|
|
5749
|
-
};
|
|
5750
|
-
/** The caller called the Agent CLI wrong; the same call can't succeed. */
|
|
5751
|
-
var UsageError = class extends CliError {
|
|
5752
|
-
constructor(fields) {
|
|
5753
|
-
super(fields);
|
|
5754
|
-
this.name = "UsageError";
|
|
5755
|
-
}
|
|
5756
|
-
};
|
|
5757
|
-
const INTERNAL_CODE = "INTERNAL";
|
|
5758
|
-
function errnoOf(error) {
|
|
5759
|
-
return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
6058
|
+
//#region ../agent-cli/dist/tokenize.js
|
|
6059
|
+
const NEGATIVE_NUMBER = /^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/;
|
|
6060
|
+
function isOptionLike(word) {
|
|
6061
|
+
return word !== void 0 && word.length > 1 && word[0] === "-" && !NEGATIVE_NUMBER.test(word);
|
|
5760
6062
|
}
|
|
5761
|
-
function
|
|
5762
|
-
return
|
|
6063
|
+
function parseArgsOptions(known) {
|
|
6064
|
+
return Object.fromEntries(known.map(({ flag, takes }) => [flag.slice(2), { type: takes === "value" ? "string" : "boolean" }]));
|
|
5763
6065
|
}
|
|
5764
|
-
function
|
|
5765
|
-
|
|
6066
|
+
function flagItem(token, { flag, takes }, words) {
|
|
6067
|
+
if (takes !== "optional value" || token.inlineValue === true) return {
|
|
6068
|
+
kind: "flag",
|
|
6069
|
+
flag,
|
|
6070
|
+
value: token.value ?? true
|
|
6071
|
+
};
|
|
6072
|
+
const took = token.index + 1;
|
|
6073
|
+
const next = words[took];
|
|
6074
|
+
return next === void 0 || isOptionLike(next) ? {
|
|
6075
|
+
kind: "flag",
|
|
6076
|
+
flag,
|
|
6077
|
+
value: true
|
|
6078
|
+
} : {
|
|
6079
|
+
kind: "flag",
|
|
6080
|
+
flag,
|
|
6081
|
+
value: next,
|
|
6082
|
+
took
|
|
6083
|
+
};
|
|
5766
6084
|
}
|
|
5767
|
-
function
|
|
5768
|
-
|
|
5769
|
-
}
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5776
|
-
|
|
5777
|
-
|
|
5778
|
-
}
|
|
5779
|
-
function fieldsOf(error, format) {
|
|
5780
|
-
if (error instanceof CliError) {
|
|
5781
|
-
const { code, message, hint, details, retryAt } = error;
|
|
5782
|
-
return {
|
|
5783
|
-
code,
|
|
5784
|
-
message,
|
|
5785
|
-
hint: format.isBug(error) ? bugHint(format) : hint,
|
|
5786
|
-
details,
|
|
5787
|
-
retryAt
|
|
5788
|
-
};
|
|
5789
|
-
}
|
|
5790
|
-
return {
|
|
5791
|
-
code: INTERNAL_CODE,
|
|
5792
|
-
message: messageOf(error),
|
|
5793
|
-
hint: bugHint(format)
|
|
5794
|
-
};
|
|
5795
|
-
}
|
|
5796
|
-
function causesOf(error) {
|
|
5797
|
-
return error instanceof Error && error.cause !== void 0 ? [error.cause, ...causesOf(error.cause)] : [];
|
|
5798
|
-
}
|
|
5799
|
-
function traceOf(error) {
|
|
5800
|
-
return error instanceof Error ? error.stack ?? error.message : String(error);
|
|
5801
|
-
}
|
|
5802
|
-
/** Under debug: a bug's stack trace, then every error's cause chain. */
|
|
5803
|
-
function debugTrace(error, format) {
|
|
5804
|
-
if (!isDebug(format)) return void 0;
|
|
5805
|
-
const lines = [...format.isBug(error) ? [traceOf(error)] : [], ...causesOf(error).map((cause) => `caused by: ${traceOf(cause)}`)];
|
|
5806
|
-
return lines.length === 0 ? void 0 : lines.join("\n");
|
|
5807
|
-
}
|
|
5808
|
-
/** The errors a run failed with: each one an `AggregateError` holds, or the one it threw. */
|
|
5809
|
-
function errorsOf(error) {
|
|
5810
|
-
return error instanceof AggregateError && error.errors.length > 0 ? error.errors : [error];
|
|
5811
|
-
}
|
|
5812
|
-
function errorLines(error, format) {
|
|
5813
|
-
const fields = fieldsOf(error, format);
|
|
5814
|
-
const stack = debugTrace(error, format);
|
|
5815
|
-
const { style } = format;
|
|
5816
|
-
const label = style.red(format.isBug(error) ? "internal error:" : "error:");
|
|
5817
|
-
const trace = stack === void 0 ? "" : `${stack}\n`;
|
|
5818
|
-
return `${label} ${fields.message}\n${trace}${style.cyan("hint:")} ${fields.hint}\n`;
|
|
5819
|
-
}
|
|
5820
|
-
function formatRuntimeError(error, format) {
|
|
5821
|
-
const errors = errorsOf(error);
|
|
5822
|
-
if (format.json) {
|
|
5823
|
-
const printed = errors.map((each) => ({
|
|
5824
|
-
...fieldsOf(each, format),
|
|
5825
|
-
stack: debugTrace(each, format)
|
|
5826
|
-
}));
|
|
5827
|
-
return `${JSON.stringify({ errors: printed })}\n`;
|
|
5828
|
-
}
|
|
5829
|
-
return errors.map((each) => errorLines(each, format)).join("");
|
|
5830
|
-
}
|
|
5831
|
-
//#endregion
|
|
5832
|
-
//#region ../agent-cli/dist/tokenize.js
|
|
5833
|
-
const NEGATIVE_NUMBER = /^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/;
|
|
5834
|
-
function isOptionLike(word) {
|
|
5835
|
-
return word !== void 0 && word.length > 1 && word[0] === "-" && !NEGATIVE_NUMBER.test(word);
|
|
5836
|
-
}
|
|
5837
|
-
function parseArgsOptions(known) {
|
|
5838
|
-
return Object.fromEntries(known.map(({ flag, takes }) => [flag.slice(2), { type: takes === "value" ? "string" : "boolean" }]));
|
|
5839
|
-
}
|
|
5840
|
-
function flagItem(token, { flag, takes }, words) {
|
|
5841
|
-
if (takes !== "optional value" || token.inlineValue === true) return {
|
|
5842
|
-
kind: "flag",
|
|
5843
|
-
flag,
|
|
5844
|
-
value: token.value ?? true
|
|
5845
|
-
};
|
|
5846
|
-
const took = token.index + 1;
|
|
5847
|
-
const next = words[took];
|
|
5848
|
-
return next === void 0 || isOptionLike(next) ? {
|
|
5849
|
-
kind: "flag",
|
|
5850
|
-
flag,
|
|
5851
|
-
value: true
|
|
5852
|
-
} : {
|
|
5853
|
-
kind: "flag",
|
|
5854
|
-
flag,
|
|
5855
|
-
value: next,
|
|
5856
|
-
took
|
|
5857
|
-
};
|
|
5858
|
-
}
|
|
5859
|
-
function itemOf(token, words, byFlag) {
|
|
5860
|
-
const word = words[token.index] ?? "";
|
|
5861
|
-
if (token.kind === "option-terminator") return { kind: "end" };
|
|
5862
|
-
if (token.kind === "positional" || NEGATIVE_NUMBER.test(word)) return {
|
|
5863
|
-
kind: "operand",
|
|
5864
|
-
value: word
|
|
5865
|
-
};
|
|
5866
|
-
const flag = byFlag.get(token.rawName);
|
|
5867
|
-
return flag === void 0 || flag.takes === "nothing" && token.inlineValue === true ? {
|
|
5868
|
-
kind: "unknown option",
|
|
5869
|
-
word
|
|
5870
|
-
} : flagItem(token, flag, words);
|
|
6085
|
+
function itemOf(token, words, byFlag) {
|
|
6086
|
+
const word = words[token.index] ?? "";
|
|
6087
|
+
if (token.kind === "option-terminator") return { kind: "end" };
|
|
6088
|
+
if (token.kind === "positional" || NEGATIVE_NUMBER.test(word)) return {
|
|
6089
|
+
kind: "operand",
|
|
6090
|
+
value: word
|
|
6091
|
+
};
|
|
6092
|
+
const flag = byFlag.get(token.rawName);
|
|
6093
|
+
return flag === void 0 || flag.takes === "nothing" && token.inlineValue === true ? {
|
|
6094
|
+
kind: "unknown option",
|
|
6095
|
+
word
|
|
6096
|
+
} : flagItem(token, flag, words);
|
|
5871
6097
|
}
|
|
5872
6098
|
/** Splits a Command's words into operands, unknown options and the values of known flags. */
|
|
5873
6099
|
function tokenize(words, known) {
|
|
@@ -5986,6 +6212,18 @@ function unknownOptionError(commandLine, invocation, flag, suggestions) {
|
|
|
5986
6212
|
listed: "options"
|
|
5987
6213
|
});
|
|
5988
6214
|
}
|
|
6215
|
+
/** Text opening with `-` was read as an option, where the Command could have read it from stdin. */
|
|
6216
|
+
function stdinTextError(commandLine, invocation, word) {
|
|
6217
|
+
const withStdin = commandLineOf(invocation, {
|
|
6218
|
+
remove: [word],
|
|
6219
|
+
add: ["-"]
|
|
6220
|
+
});
|
|
6221
|
+
return new UsageError({
|
|
6222
|
+
code: UNKNOWN_OPTION,
|
|
6223
|
+
message: `unknown option '${word}' for \`${commandLine}\``,
|
|
6224
|
+
hint: `to pass text opening with \`-\`, pass \`-\` and send the text on stdin through a heredoc: \`${withStdin} <<'EOF'\`, then the text, then \`EOF\``
|
|
6225
|
+
});
|
|
6226
|
+
}
|
|
5989
6227
|
function unknownCommandError(commandLine, name, suggestions) {
|
|
5990
6228
|
return unknownError({
|
|
5991
6229
|
code: UNKNOWN_COMMAND,
|
|
@@ -6012,7 +6250,7 @@ const COLUMN_SEPARATOR = " ";
|
|
|
6012
6250
|
const UNSAFE_IN_COLUMN = /[\t\n\r]/;
|
|
6013
6251
|
const PAGE_INPUT = object({
|
|
6014
6252
|
limit: number().int().positive().default(DEFAULT_PAGE_LIMIT),
|
|
6015
|
-
cursor:
|
|
6253
|
+
cursor: string().min(1).optional()
|
|
6016
6254
|
});
|
|
6017
6255
|
var Page = class {
|
|
6018
6256
|
items;
|
|
@@ -6100,12 +6338,16 @@ function cell(value) {
|
|
|
6100
6338
|
function renderRows(rows, fields) {
|
|
6101
6339
|
return `${[fields, ...rows.map((row) => fields.map((field) => cell(row[field])))].map((line) => line.join(COLUMN_SEPARATOR)).join("\n")}\n`;
|
|
6102
6340
|
}
|
|
6341
|
+
function cursorWords(cursor) {
|
|
6342
|
+
const { flag } = PAGE_FLAGS.cursor;
|
|
6343
|
+
return cursor.startsWith("-") ? [`${flag}=${cursor}`] : [flag, cursor];
|
|
6344
|
+
}
|
|
6103
6345
|
function printedPage(page, invocation) {
|
|
6104
6346
|
return page.nextCursor === void 0 ? { items: page.items } : {
|
|
6105
6347
|
items: page.items,
|
|
6106
6348
|
next: commandLineOf(invocation, {
|
|
6107
6349
|
remove: [PAGE_FLAGS.cursor.flag],
|
|
6108
|
-
add:
|
|
6350
|
+
add: cursorWords(page.nextCursor)
|
|
6109
6351
|
})
|
|
6110
6352
|
};
|
|
6111
6353
|
}
|
|
@@ -6234,71 +6476,50 @@ function isCommand(node) {
|
|
|
6234
6476
|
return typeof node.effect === "string";
|
|
6235
6477
|
}
|
|
6236
6478
|
//#endregion
|
|
6237
|
-
//#region ../agent-cli/dist/
|
|
6238
|
-
const
|
|
6239
|
-
|
|
6240
|
-
|
|
6241
|
-
|
|
6242
|
-
}
|
|
6243
|
-
|
|
6244
|
-
|
|
6245
|
-
const yNumeric = /^\d+$/.test(y);
|
|
6246
|
-
if (xNumeric && yNumeric) return Number(x) - Number(y);
|
|
6247
|
-
if (xNumeric !== yNumeric) return xNumeric ? -1 : 1;
|
|
6248
|
-
if (x === y) return 0;
|
|
6249
|
-
return x < y ? -1 : 1;
|
|
6479
|
+
//#region ../agent-cli/dist/project.js
|
|
6480
|
+
const PROJECT_INVALID = "PROJECT_INVALID";
|
|
6481
|
+
function invalid(path, problem, options) {
|
|
6482
|
+
return new CliError({
|
|
6483
|
+
code: PROJECT_INVALID,
|
|
6484
|
+
message: `the Project file ${path} is invalid: ${problem}`,
|
|
6485
|
+
hint: `fix ${path}, then run the command again`
|
|
6486
|
+
}, options);
|
|
6250
6487
|
}
|
|
6251
|
-
function
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6255
|
-
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6488
|
+
function readText(path, fileError) {
|
|
6489
|
+
try {
|
|
6490
|
+
return readFileSync(path, "utf8");
|
|
6491
|
+
} catch (error) {
|
|
6492
|
+
if (isMissingFile(error)) return void 0;
|
|
6493
|
+
throw fileError(error, {
|
|
6494
|
+
path,
|
|
6495
|
+
access: "read"
|
|
6496
|
+
});
|
|
6260
6497
|
}
|
|
6261
|
-
return left.length - right.length;
|
|
6262
6498
|
}
|
|
6263
|
-
|
|
6264
|
-
|
|
6265
|
-
|
|
6266
|
-
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
1,
|
|
6270
|
-
2,
|
|
6271
|
-
3
|
|
6272
|
-
]) {
|
|
6273
|
-
const difference = Number(left[part]) - Number(right[part]);
|
|
6274
|
-
if (difference !== 0) return difference;
|
|
6499
|
+
function parsed(path, text, schema) {
|
|
6500
|
+
let json;
|
|
6501
|
+
try {
|
|
6502
|
+
json = JSON.parse(text);
|
|
6503
|
+
} catch (error) {
|
|
6504
|
+
throw invalid(path, messageOf(error), { cause: error });
|
|
6275
6505
|
}
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
function standingOf(version, latest) {
|
|
6280
|
-
const difference = compareVersions(version, latest);
|
|
6281
|
-
if (difference < 0) return "behind";
|
|
6282
|
-
return difference > 0 ? "ahead" : "current";
|
|
6283
|
-
}
|
|
6284
|
-
/** The minimum an `engines.node` range asks for, or undefined when it is not `>=X[.Y[.Z]]`. */
|
|
6285
|
-
function engineMinimum(range) {
|
|
6286
|
-
const match = ENGINE.exec(range.trim());
|
|
6287
|
-
return match === null ? void 0 : match.slice(1).map((part) => Number(part ?? 0));
|
|
6506
|
+
const result = schema.safeParse(json);
|
|
6507
|
+
if (!result.success) throw invalid(path, prettifyError(result.error));
|
|
6508
|
+
return result.data;
|
|
6288
6509
|
}
|
|
6289
|
-
function
|
|
6290
|
-
const
|
|
6291
|
-
|
|
6292
|
-
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
|
|
6510
|
+
function projectFrom(projectFile, folder, fileError) {
|
|
6511
|
+
const path = join(folder, projectFile.file);
|
|
6512
|
+
const text = readText(path, fileError);
|
|
6513
|
+
if (text !== void 0) return {
|
|
6514
|
+
root: folder,
|
|
6515
|
+
settings: parsed(path, text, projectFile.schema)
|
|
6516
|
+
};
|
|
6517
|
+
const parent = dirname(folder);
|
|
6518
|
+
return parent === folder ? void 0 : projectFrom(projectFile, parent, fileError);
|
|
6296
6519
|
}
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
function lastLines(output, count) {
|
|
6301
|
-
return output.trim().split("\n").slice(-count).join("\n");
|
|
6520
|
+
/** The nearest Project file at or above `cwd`, parsed by its schema; undefined when there is none. */
|
|
6521
|
+
function projectOf(projectFile, cwd, fileError) {
|
|
6522
|
+
return projectFrom(projectFile, resolve(cwd), fileError);
|
|
6302
6523
|
}
|
|
6303
6524
|
//#endregion
|
|
6304
6525
|
//#region ../agent-cli/dist/tools.js
|
|
@@ -6363,6 +6584,18 @@ function toolRows(tools, commands) {
|
|
|
6363
6584
|
}));
|
|
6364
6585
|
}
|
|
6365
6586
|
//#endregion
|
|
6587
|
+
//#region ../agent-cli/dist/version.js
|
|
6588
|
+
/** The first line of `--version`: the version, and the commit and time of a stamped build. */
|
|
6589
|
+
function versionLine({ version, build }) {
|
|
6590
|
+
return build === void 0 ? version : `${version} (${build.sha}${build.dirty ? "+dirty" : ""}) built ${build.builtAt}`;
|
|
6591
|
+
}
|
|
6592
|
+
//#endregion
|
|
6593
|
+
//#region ../agent-cli/dist/tail.js
|
|
6594
|
+
/** The last `count` lines of a child's output, trimmed; empty when it wrote nothing. */
|
|
6595
|
+
function lastLines(output, count) {
|
|
6596
|
+
return output.trim().split("\n").slice(-count).join("\n");
|
|
6597
|
+
}
|
|
6598
|
+
//#endregion
|
|
6366
6599
|
//#region ../agent-cli/dist/spawn.js
|
|
6367
6600
|
const TOOL_FAILED = "TOOL_FAILED";
|
|
6368
6601
|
const STDERR_TAIL_LINES$1 = 20;
|
|
@@ -6537,56 +6770,117 @@ function contextSpawn(run, defaults, fileError) {
|
|
|
6537
6770
|
};
|
|
6538
6771
|
}
|
|
6539
6772
|
//#endregion
|
|
6540
|
-
//#region ../agent-cli/dist/
|
|
6541
|
-
const
|
|
6542
|
-
const
|
|
6543
|
-
|
|
6544
|
-
|
|
6545
|
-
const NO_LATEST = "NO_LATEST";
|
|
6546
|
-
function npmContext(cli, install, ctx, node) {
|
|
6547
|
-
return {
|
|
6548
|
-
cliName: cli.name,
|
|
6549
|
-
install,
|
|
6550
|
-
env: ctx.env,
|
|
6551
|
-
signal: ctx.signal,
|
|
6552
|
-
node
|
|
6553
|
-
};
|
|
6554
|
-
}
|
|
6555
|
-
const NPMJS = "https://registry.npmjs.org/";
|
|
6556
|
-
const STDERR_TAIL_LINES = 10;
|
|
6557
|
-
const RM_RETRIES = 3;
|
|
6558
|
-
const NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
6559
|
-
"ENOTFOUND",
|
|
6560
|
-
"EAI_AGAIN",
|
|
6561
|
-
"ECONNREFUSED",
|
|
6562
|
-
"ECONNRESET",
|
|
6563
|
-
"ETIMEDOUT",
|
|
6564
|
-
"ENETUNREACH",
|
|
6565
|
-
"EHOSTUNREACH",
|
|
6566
|
-
"ERR_SOCKET_TIMEOUT"
|
|
6567
|
-
]);
|
|
6568
|
-
const AUTH_CODES = /* @__PURE__ */ new Set(["E401", "E403"]);
|
|
6569
|
-
const NPM_CODE = /^npm (?:error|ERR!) code (\S+)$/m;
|
|
6570
|
-
/** The flag that points npm at the CLI's registry; none for npmjs, npm's default. */
|
|
6571
|
-
function registryFlags({ package: name, registry }) {
|
|
6572
|
-
if (registry === NPMJS) return [];
|
|
6573
|
-
const scope = /^(@[^/]+)\//.exec(name)?.[1];
|
|
6574
|
-
return [scope === void 0 ? `--registry=${registry}` : `--${scope}:registry=${registry}`];
|
|
6773
|
+
//#region ../agent-cli/dist/built-ins/semver.js
|
|
6774
|
+
const VERSION = /^(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;
|
|
6775
|
+
const ENGINE = /^>=\s*(\d+)(?:\.(\d+))?(?:\.(\d+))?$/;
|
|
6776
|
+
function isVersion(text) {
|
|
6777
|
+
return VERSION.test(text);
|
|
6575
6778
|
}
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6580
|
-
|
|
6581
|
-
|
|
6582
|
-
|
|
6583
|
-
...registryFlags(install)
|
|
6584
|
-
].join(" ");
|
|
6779
|
+
function compareIdentifiers(x, y) {
|
|
6780
|
+
const xNumeric = /^\d+$/.test(x);
|
|
6781
|
+
const yNumeric = /^\d+$/.test(y);
|
|
6782
|
+
if (xNumeric && yNumeric) return Number(x) - Number(y);
|
|
6783
|
+
if (xNumeric !== yNumeric) return xNumeric ? -1 : 1;
|
|
6784
|
+
if (x === y) return 0;
|
|
6785
|
+
return x < y ? -1 : 1;
|
|
6585
6786
|
}
|
|
6586
|
-
function
|
|
6587
|
-
|
|
6588
|
-
if (
|
|
6589
|
-
|
|
6787
|
+
function comparePrerelease(a, b) {
|
|
6788
|
+
if (a === b) return 0;
|
|
6789
|
+
if (a === void 0) return 1;
|
|
6790
|
+
if (b === void 0) return -1;
|
|
6791
|
+
const left = a.split(".");
|
|
6792
|
+
const right = b.split(".");
|
|
6793
|
+
for (let i = 0; i < Math.min(left.length, right.length); i += 1) {
|
|
6794
|
+
const difference = compareIdentifiers(left[i] ?? "", right[i] ?? "");
|
|
6795
|
+
if (difference !== 0) return difference;
|
|
6796
|
+
}
|
|
6797
|
+
return left.length - right.length;
|
|
6798
|
+
}
|
|
6799
|
+
/** Negative when `a` is older than `b`, positive when newer, 0 when the same release. */
|
|
6800
|
+
function compareVersions(a, b) {
|
|
6801
|
+
const left = VERSION.exec(a);
|
|
6802
|
+
const right = VERSION.exec(b);
|
|
6803
|
+
if (left === null || right === null) throw new Error(`cannot compare ${a} with ${b}: both must be X.Y.Z versions`);
|
|
6804
|
+
for (const part of [
|
|
6805
|
+
1,
|
|
6806
|
+
2,
|
|
6807
|
+
3
|
|
6808
|
+
]) {
|
|
6809
|
+
const difference = Number(left[part]) - Number(right[part]);
|
|
6810
|
+
if (difference !== 0) return difference;
|
|
6811
|
+
}
|
|
6812
|
+
return comparePrerelease(left[4], right[4]);
|
|
6813
|
+
}
|
|
6814
|
+
/** Where `version` stands against `latest`. */
|
|
6815
|
+
function standingOf(version, latest) {
|
|
6816
|
+
const difference = compareVersions(version, latest);
|
|
6817
|
+
if (difference < 0) return "behind";
|
|
6818
|
+
return difference > 0 ? "ahead" : "current";
|
|
6819
|
+
}
|
|
6820
|
+
/** The minimum an `engines.node` range asks for, or undefined when it is not `>=X[.Y[.Z]]`. */
|
|
6821
|
+
function engineMinimum(range) {
|
|
6822
|
+
const match = ENGINE.exec(range.trim());
|
|
6823
|
+
return match === null ? void 0 : match.slice(1).map((part) => Number(part ?? 0));
|
|
6824
|
+
}
|
|
6825
|
+
function meetsMinimum(version, minimum) {
|
|
6826
|
+
const parts = version.split(".").map(Number);
|
|
6827
|
+
for (const [i, wanted] of minimum.entries()) {
|
|
6828
|
+
const found = parts[i] ?? 0;
|
|
6829
|
+
if (found !== wanted) return found > wanted;
|
|
6830
|
+
}
|
|
6831
|
+
return true;
|
|
6832
|
+
}
|
|
6833
|
+
//#endregion
|
|
6834
|
+
//#region ../agent-cli/dist/built-ins/npm.js
|
|
6835
|
+
const REGISTRY_UNREACHABLE = "REGISTRY_UNREACHABLE";
|
|
6836
|
+
const REGISTRY_AUTH = "REGISTRY_AUTH";
|
|
6837
|
+
const INSTALL_FAILED = "INSTALL_FAILED";
|
|
6838
|
+
const NPM_FAILED = "NPM_FAILED";
|
|
6839
|
+
const NO_LATEST = "NO_LATEST";
|
|
6840
|
+
function npmContext(cli, install, ctx, node) {
|
|
6841
|
+
return {
|
|
6842
|
+
cliName: cli.name,
|
|
6843
|
+
install,
|
|
6844
|
+
env: ctx.env,
|
|
6845
|
+
signal: ctx.signal,
|
|
6846
|
+
node
|
|
6847
|
+
};
|
|
6848
|
+
}
|
|
6849
|
+
const NPMJS = "https://registry.npmjs.org/";
|
|
6850
|
+
const STDERR_TAIL_LINES = 10;
|
|
6851
|
+
const RM_RETRIES = 3;
|
|
6852
|
+
const NETWORK_CODES = /* @__PURE__ */ new Set([
|
|
6853
|
+
"ENOTFOUND",
|
|
6854
|
+
"EAI_AGAIN",
|
|
6855
|
+
"ECONNREFUSED",
|
|
6856
|
+
"ECONNRESET",
|
|
6857
|
+
"ETIMEDOUT",
|
|
6858
|
+
"ENETUNREACH",
|
|
6859
|
+
"EHOSTUNREACH",
|
|
6860
|
+
"ERR_SOCKET_TIMEOUT"
|
|
6861
|
+
]);
|
|
6862
|
+
const AUTH_CODES = /* @__PURE__ */ new Set(["E401", "E403"]);
|
|
6863
|
+
const NPM_CODE = /^npm (?:error|ERR!) code (\S+)$/m;
|
|
6864
|
+
/** The flag that points npm at the CLI's registry; none for npmjs, npm's default. */
|
|
6865
|
+
function registryFlags({ package: name, registry }) {
|
|
6866
|
+
if (registry === NPMJS) return [];
|
|
6867
|
+
const scope = /^(@[^/]+)\//.exec(name)?.[1];
|
|
6868
|
+
return [scope === void 0 ? `--registry=${registry}` : `--${scope}:registry=${registry}`];
|
|
6869
|
+
}
|
|
6870
|
+
/** The command a person runs to install the CLI globally from its registry. */
|
|
6871
|
+
function installCommandLine(install, version = "latest") {
|
|
6872
|
+
return [
|
|
6873
|
+
"npm",
|
|
6874
|
+
"install",
|
|
6875
|
+
"--global",
|
|
6876
|
+
`${install.package}@${version}`,
|
|
6877
|
+
...registryFlags(install)
|
|
6878
|
+
].join(" ");
|
|
6879
|
+
}
|
|
6880
|
+
function npmOf(ctx, windows) {
|
|
6881
|
+
const beside = ctx.node === void 0 ? void 0 : join(dirname(ctx.node), windows ? "npm.cmd" : "npm");
|
|
6882
|
+
if (beside === void 0 || !existsSync(beside)) return {
|
|
6883
|
+
path: "npm",
|
|
6590
6884
|
env: ctx.env
|
|
6591
6885
|
};
|
|
6592
6886
|
if (windows) return {
|
|
@@ -6714,7 +7008,7 @@ async function latestVersion(ctx) {
|
|
|
6714
7008
|
return version;
|
|
6715
7009
|
}
|
|
6716
7010
|
//#endregion
|
|
6717
|
-
//#region ../agent-cli/dist/global-install.js
|
|
7011
|
+
//#region ../agent-cli/dist/built-ins/global-install.js
|
|
6718
7012
|
const NOT_GLOBAL_INSTALL = "NOT_GLOBAL_INSTALL";
|
|
6719
7013
|
/** Where npm puts global packages under its global prefix. */
|
|
6720
7014
|
function globalModulesDir(prefix) {
|
|
@@ -6755,101 +7049,747 @@ async function globalInstallOf(bin, ctx) {
|
|
|
6755
7049
|
};
|
|
6756
7050
|
}
|
|
6757
7051
|
//#endregion
|
|
6758
|
-
//#region ../agent-cli/dist/
|
|
6759
|
-
const
|
|
6760
|
-
const
|
|
6761
|
-
|
|
6762
|
-
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
}
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
message: `${CONFIRM_FLAG.flag} ${JSON.stringify(given)} does not match the target of \`${commandLine}\``,
|
|
6775
|
-
hint
|
|
6776
|
-
});
|
|
7052
|
+
//#region ../agent-cli/dist/manifest.js
|
|
7053
|
+
const link$1 = union([string(), object({ url: string() })]).transform((value) => typeof value === "string" ? value : value.url).optional().catch(void 0);
|
|
7054
|
+
const manifestSchema = object({
|
|
7055
|
+
repository: link$1,
|
|
7056
|
+
bugs: link$1
|
|
7057
|
+
});
|
|
7058
|
+
const NO_MANIFEST = {};
|
|
7059
|
+
function manifestAt(packageRoot) {
|
|
7060
|
+
let manifest;
|
|
7061
|
+
try {
|
|
7062
|
+
manifest = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8"));
|
|
7063
|
+
} catch {
|
|
7064
|
+
return NO_MANIFEST;
|
|
7065
|
+
}
|
|
7066
|
+
const parsed = manifestSchema.safeParse(manifest);
|
|
7067
|
+
return parsed.success ? parsed.data : NO_MANIFEST;
|
|
6777
7068
|
}
|
|
6778
7069
|
//#endregion
|
|
6779
|
-
//#region ../agent-cli/dist/
|
|
6780
|
-
const
|
|
6781
|
-
/**
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
6787
|
-
|
|
6788
|
-
|
|
7070
|
+
//#region ../agent-cli/dist/built-ins/skills.js
|
|
7071
|
+
const SKILL_DIRS = [[".claude", "skills"], [".agents", "skills"]];
|
|
7072
|
+
/** The branch a release moves to the released commit, which holds the skill of that version. */
|
|
7073
|
+
const RELEASE_BRANCH$1 = "release";
|
|
7074
|
+
const SHORTHAND = /^(?:(?:github:)?[\w.-]+\/[\w.-]+|gitlab:[\w.-]+(?:\/[\w.-]+)+)$/;
|
|
7075
|
+
const GIT_URL_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
7076
|
+
"https:",
|
|
7077
|
+
"http:",
|
|
7078
|
+
"ssh:",
|
|
7079
|
+
"git:"
|
|
7080
|
+
]);
|
|
7081
|
+
const SCP_STYLE = /^[\w.-]+@[\w.-]+:[\w./-]+$/;
|
|
7082
|
+
const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
7083
|
+
const METADATA_VERSION = /^metadata:[ \t]*\r?\n(?:[ \t]+.*\r?\n)*?[ \t]+version:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/m;
|
|
7084
|
+
/** The version a SKILL.md's frontmatter `metadata.version` states. */
|
|
7085
|
+
function skillVersionIn(skill) {
|
|
7086
|
+
const frontmatter = FRONTMATTER.exec(skill)?.[1];
|
|
7087
|
+
return frontmatter === void 0 ? void 0 : METADATA_VERSION.exec(`${frontmatter}\n`)?.[1];
|
|
6789
7088
|
}
|
|
6790
|
-
|
|
6791
|
-
|
|
6792
|
-
|
|
6793
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
6797
|
-
|
|
6798
|
-
|
|
6799
|
-
|
|
6800
|
-
|
|
6801
|
-
|
|
6802
|
-
|
|
6803
|
-
|
|
6804
|
-
|
|
6805
|
-
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6814
|
-
|
|
6815
|
-
|
|
6816
|
-
|
|
6817
|
-
|
|
6818
|
-
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
7089
|
+
function homeOf(env) {
|
|
7090
|
+
return env.HOME ?? env.USERPROFILE ?? homedir();
|
|
7091
|
+
}
|
|
7092
|
+
async function copyAt(path, version) {
|
|
7093
|
+
let skill;
|
|
7094
|
+
try {
|
|
7095
|
+
skill = await readFile(join(path, "SKILL.md"), "utf8");
|
|
7096
|
+
} catch (error) {
|
|
7097
|
+
if (isMissingFile(error)) return;
|
|
7098
|
+
return {
|
|
7099
|
+
path,
|
|
7100
|
+
version: void 0,
|
|
7101
|
+
state: "unreadable"
|
|
7102
|
+
};
|
|
7103
|
+
}
|
|
7104
|
+
const stated = skillVersionIn(skill);
|
|
7105
|
+
if (stated === void 0 || !isVersion(stated) || !isVersion(version)) return {
|
|
7106
|
+
path,
|
|
7107
|
+
version: stated,
|
|
7108
|
+
state: "unversioned"
|
|
7109
|
+
};
|
|
7110
|
+
return {
|
|
7111
|
+
path,
|
|
7112
|
+
version: stated,
|
|
7113
|
+
state: standingOf(stated, version)
|
|
7114
|
+
};
|
|
7115
|
+
}
|
|
7116
|
+
async function skillCopies(cliName, version, { cwd, env }) {
|
|
7117
|
+
const paths = [cwd, homeOf(env)].flatMap((root) => SKILL_DIRS.map((dir) => join(root, ...dir, cliName)));
|
|
7118
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7119
|
+
const copies = [];
|
|
7120
|
+
for (const path of paths) {
|
|
7121
|
+
const copy = await copyAt(path, version);
|
|
7122
|
+
const real = copy === void 0 ? void 0 : await realpath(path);
|
|
7123
|
+
if (copy !== void 0 && real !== void 0 && !seen.has(real)) {
|
|
7124
|
+
seen.add(real);
|
|
7125
|
+
copies.push(copy);
|
|
7126
|
+
}
|
|
7127
|
+
}
|
|
7128
|
+
return copies;
|
|
7129
|
+
}
|
|
7130
|
+
function sourceFromRepository(repository) {
|
|
7131
|
+
if (SHORTHAND.test(repository)) return `${repository}#${RELEASE_BRANCH$1}`;
|
|
7132
|
+
const url = repository.replace(/^git\+/, "");
|
|
7133
|
+
if (!(URL.canParse(url) && GIT_URL_PROTOCOLS.has(new URL(url).protocol)) && !SCP_STYLE.test(url)) return void 0;
|
|
7134
|
+
return `${url.endsWith(".git") ? url : `${url}.git`}#${RELEASE_BRANCH$1}`;
|
|
7135
|
+
}
|
|
7136
|
+
/** What the installer installs the CLI's skill from: the declared source, else the package's repository. */
|
|
7137
|
+
function skillSource({ skill }, packageRoot) {
|
|
7138
|
+
if (skill !== void 0) return skill.source;
|
|
7139
|
+
const { repository } = manifestAt(packageRoot);
|
|
7140
|
+
return repository === void 0 ? void 0 : sourceFromRepository(repository);
|
|
7141
|
+
}
|
|
7142
|
+
function fixFor(cliName, copies, source) {
|
|
7143
|
+
const has = (wanted) => copies.some(({ state }) => state === wanted);
|
|
7144
|
+
const update = `npx -y skills update ${cliName}`;
|
|
7145
|
+
const add = source === void 0 ? void 0 : `npx -y skills add ${source} --skill ${cliName} -g`;
|
|
7146
|
+
if (copies.length === 0) return add;
|
|
7147
|
+
if (has("unversioned") && add !== void 0) return has("behind") ? `${update} && ${add}` : add;
|
|
7148
|
+
return has("behind") || has("unversioned") ? update : void 0;
|
|
7149
|
+
}
|
|
7150
|
+
async function skillReport(cli, version, ctx) {
|
|
7151
|
+
const copies = await skillCopies(cli.name, version, ctx);
|
|
7152
|
+
return {
|
|
7153
|
+
copies,
|
|
7154
|
+
fix: fixFor(cli.name, copies, skillSource(cli, ctx.packageRoot))
|
|
7155
|
+
};
|
|
6823
7156
|
}
|
|
6824
7157
|
//#endregion
|
|
6825
|
-
//#region ../agent-cli/dist/
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
function permissionHint({ path, access, callerLine, env, platform }) {
|
|
6832
|
-
if (platform === "win32") return `a program may hold ${path} open: close it, then run the same command again`;
|
|
6833
|
-
if (!isAgent(env)) return `check the permissions of ${path} and its folder`;
|
|
6834
|
-
return `your sandbox may block it: ask your user to run \`! ${callerLine}\`, or ${access === "read" ? `to allow reading ${path} in the sandbox` : `to allow ${path} in the sandbox's write list`}`;
|
|
7158
|
+
//#region ../agent-cli/dist/built-ins/doctor-rows.js
|
|
7159
|
+
function ok(message) {
|
|
7160
|
+
return {
|
|
7161
|
+
state: "ok",
|
|
7162
|
+
message
|
|
7163
|
+
};
|
|
6835
7164
|
}
|
|
6836
|
-
function
|
|
6837
|
-
return
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
}
|
|
7165
|
+
function buildRow(cli) {
|
|
7166
|
+
return {
|
|
7167
|
+
name: "build",
|
|
7168
|
+
run: () => ok(versionLine(cli))
|
|
7169
|
+
};
|
|
6841
7170
|
}
|
|
6842
|
-
function
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
|
|
6846
|
-
|
|
6847
|
-
|
|
6848
|
-
|
|
6849
|
-
|
|
6850
|
-
|
|
6851
|
-
|
|
6852
|
-
|
|
7171
|
+
function nodeRow(cli) {
|
|
7172
|
+
return {
|
|
7173
|
+
name: "node",
|
|
7174
|
+
run: () => {
|
|
7175
|
+
const found = process.versions.node;
|
|
7176
|
+
const range = cli.engines?.node;
|
|
7177
|
+
if (range === void 0) return ok(`Node ${found}; ${cli.name} declares no engines.node to check it against`);
|
|
7178
|
+
const minimum = engineMinimum(range);
|
|
7179
|
+
if (minimum === void 0) return {
|
|
7180
|
+
state: "problem",
|
|
7181
|
+
message: `${cli.name} declares engines.node "${range}", which doctor cannot read: only >=X.Y.Z is supported`
|
|
7182
|
+
};
|
|
7183
|
+
if (meetsMinimum(found, minimum)) return ok(`Node ${found} meets ${range}`);
|
|
7184
|
+
const major = minimum[0];
|
|
7185
|
+
return {
|
|
7186
|
+
state: "problem",
|
|
7187
|
+
message: `${cli.name} runs on Node ${found}, older than the ${range} it needs; install Node ${minimum.join(".")} or newer and make it the default`,
|
|
7188
|
+
fix: `nvm install ${major} && nvm alias default ${major}`
|
|
7189
|
+
};
|
|
7190
|
+
}
|
|
7191
|
+
};
|
|
7192
|
+
}
|
|
7193
|
+
/** A row's thrown error as its problem: a `CliError` with its hint and code, anything else a bug. */
|
|
7194
|
+
function problemOfError(name, error) {
|
|
7195
|
+
if (error instanceof CliError) return {
|
|
7196
|
+
state: "problem",
|
|
7197
|
+
message: `${error.message}; ${error.hint}`,
|
|
7198
|
+
code: error.code
|
|
7199
|
+
};
|
|
7200
|
+
return {
|
|
7201
|
+
state: "problem",
|
|
7202
|
+
message: `the ${name} row hit a bug: ${messageOf(error)}`
|
|
7203
|
+
};
|
|
7204
|
+
}
|
|
7205
|
+
function readProject(projectFile, ctx) {
|
|
7206
|
+
if (projectFile === void 0) return {
|
|
7207
|
+
ok: true,
|
|
7208
|
+
project: void 0
|
|
7209
|
+
};
|
|
7210
|
+
try {
|
|
7211
|
+
return {
|
|
7212
|
+
ok: true,
|
|
7213
|
+
project: projectOf(projectFile, ctx.cwd, ctx.fileError)
|
|
7214
|
+
};
|
|
7215
|
+
} catch (error) {
|
|
7216
|
+
return {
|
|
7217
|
+
ok: false,
|
|
7218
|
+
error
|
|
7219
|
+
};
|
|
7220
|
+
}
|
|
7221
|
+
}
|
|
7222
|
+
function projectRow({ file }, read) {
|
|
7223
|
+
return {
|
|
7224
|
+
name: "project",
|
|
7225
|
+
run: (ctx) => {
|
|
7226
|
+
if (!read.ok) return problemOfError("project", read.error);
|
|
7227
|
+
return ok(read.project === void 0 ? `none found: no ${file} at or above ${ctx.cwd}` : join(read.project.root, file));
|
|
7228
|
+
}
|
|
7229
|
+
};
|
|
7230
|
+
}
|
|
7231
|
+
function installRow(cli, { bin, node }) {
|
|
7232
|
+
return {
|
|
7233
|
+
name: "install",
|
|
7234
|
+
advisory: true,
|
|
7235
|
+
run: async (ctx) => {
|
|
7236
|
+
const { install } = cli;
|
|
7237
|
+
if (install === void 0) return ok(`${cli.name} declares no install, so it has no \`update\``);
|
|
7238
|
+
try {
|
|
7239
|
+
return ok(`a global npm install under ${(await globalInstallOf(bin, npmContext(cli, install, ctx, node))).prefix}`);
|
|
7240
|
+
} catch (error) {
|
|
7241
|
+
if (error instanceof CliError && error.code === "NOT_GLOBAL_INSTALL") return {
|
|
7242
|
+
state: "problem",
|
|
7243
|
+
message: error.message,
|
|
7244
|
+
fix: installCommandLine(install)
|
|
7245
|
+
};
|
|
7246
|
+
throw error;
|
|
7247
|
+
}
|
|
7248
|
+
}
|
|
7249
|
+
};
|
|
7250
|
+
}
|
|
7251
|
+
function registryRow(cli, node) {
|
|
7252
|
+
return {
|
|
7253
|
+
name: "registry",
|
|
7254
|
+
advisory: true,
|
|
7255
|
+
run: async (ctx) => {
|
|
7256
|
+
const { install } = cli;
|
|
7257
|
+
if (install === void 0) return ok(`${cli.name} declares no registry to compare this build with`);
|
|
7258
|
+
const latest = await latestVersion(npmContext(cli, install, ctx, node));
|
|
7259
|
+
const standing = standingOf(cli.version, latest);
|
|
7260
|
+
const head = `${install.registry} has ${latest} as latest: this build`;
|
|
7261
|
+
if (standing === "behind") return {
|
|
7262
|
+
state: "problem",
|
|
7263
|
+
message: `${head} (${cli.version}) is older`,
|
|
7264
|
+
fix: `${cli.name} update`
|
|
7265
|
+
};
|
|
7266
|
+
return ok(`${head} is ${standing === "current" ? "current" : `newer (${cli.version})`}`);
|
|
7267
|
+
}
|
|
7268
|
+
};
|
|
7269
|
+
}
|
|
7270
|
+
const SKILL_STATE_NOTES = {
|
|
7271
|
+
current: "the same as this build",
|
|
7272
|
+
behind: "older than this build",
|
|
7273
|
+
ahead: "newer than this build",
|
|
7274
|
+
unversioned: "states no metadata.version",
|
|
7275
|
+
unreadable: "could not be read"
|
|
7276
|
+
};
|
|
7277
|
+
function describeCopy({ path, version, state }) {
|
|
7278
|
+
return `${path}${version === void 0 ? "" : ` ${version}`} (${SKILL_STATE_NOTES[state]})`;
|
|
7279
|
+
}
|
|
7280
|
+
function skillRow(cli) {
|
|
7281
|
+
return {
|
|
7282
|
+
name: "skill",
|
|
7283
|
+
run: async (ctx) => {
|
|
7284
|
+
const { copies, fix } = await skillReport(cli, cli.version, ctx);
|
|
7285
|
+
const message = copies.length === 0 ? `no copy of the ${cli.name} skill is installed` : copies.map(describeCopy).join("; ");
|
|
7286
|
+
return fix === void 0 ? ok(message) : {
|
|
7287
|
+
state: "ok",
|
|
7288
|
+
message,
|
|
7289
|
+
fix
|
|
7290
|
+
};
|
|
7291
|
+
}
|
|
7292
|
+
};
|
|
7293
|
+
}
|
|
7294
|
+
/** Every row `doctor` reports, in order: the fixed rows around the CLI's own and its tools'. */
|
|
7295
|
+
function doctorChecks(cli, launch, read) {
|
|
7296
|
+
return [
|
|
7297
|
+
buildRow(cli),
|
|
7298
|
+
nodeRow(cli),
|
|
7299
|
+
...cli.project === void 0 ? [] : [projectRow(cli.project, read)],
|
|
7300
|
+
...cli.doctor ?? [],
|
|
7301
|
+
...toolRows(cli.tools ?? [], cli.commands),
|
|
7302
|
+
installRow(cli, launch),
|
|
7303
|
+
registryRow(cli, launch.node),
|
|
7304
|
+
skillRow(cli)
|
|
7305
|
+
];
|
|
7306
|
+
}
|
|
7307
|
+
//#endregion
|
|
7308
|
+
//#region ../agent-cli/dist/built-ins/doctor.js
|
|
7309
|
+
const DOCTOR_PROBLEMS = "DOCTOR_PROBLEMS";
|
|
7310
|
+
const DEFAULT_DEADLINE_MS = 1e4;
|
|
7311
|
+
const MS_PER_SECOND = 1e3;
|
|
7312
|
+
const MIN_LABEL_WIDTH = 8;
|
|
7313
|
+
const reportSchema = object({
|
|
7314
|
+
rows: array(object({
|
|
7315
|
+
check: string(),
|
|
7316
|
+
state: _enum([
|
|
7317
|
+
"ok",
|
|
7318
|
+
"problem",
|
|
7319
|
+
"skipped"
|
|
7320
|
+
]),
|
|
7321
|
+
message: string(),
|
|
7322
|
+
fix: string().optional(),
|
|
7323
|
+
code: string().optional()
|
|
7324
|
+
})),
|
|
7325
|
+
next: array(string())
|
|
7326
|
+
});
|
|
7327
|
+
function problemOf(check, error, { signal, deadline, ms }) {
|
|
7328
|
+
if (!signal.aborted && deadline.aborted && error === deadline.reason) return {
|
|
7329
|
+
state: "problem",
|
|
7330
|
+
message: `${check.name} did not answer within ${ms / MS_PER_SECOND} s`
|
|
7331
|
+
};
|
|
7332
|
+
return problemOfError(check.name, error);
|
|
7333
|
+
}
|
|
7334
|
+
function rowContext(ctx, signal, read) {
|
|
7335
|
+
return Object.create(ctx, {
|
|
7336
|
+
signal: { value: signal },
|
|
7337
|
+
project: { get: () => {
|
|
7338
|
+
if (!read.ok) throw read.error;
|
|
7339
|
+
return read.project;
|
|
7340
|
+
} }
|
|
7341
|
+
});
|
|
7342
|
+
}
|
|
7343
|
+
async function rowOf(check, ctx, read) {
|
|
7344
|
+
const ms = check.deadlineMs ?? DEFAULT_DEADLINE_MS;
|
|
7345
|
+
const signal = ctx.deadline(ms);
|
|
7346
|
+
let finding;
|
|
7347
|
+
try {
|
|
7348
|
+
finding = await Promise.race([Promise.resolve().then(() => check.run(rowContext(ctx, signal, read))), untilAborted(signal)]);
|
|
7349
|
+
} catch (error) {
|
|
7350
|
+
if (ctx.signal.aborted) return void 0;
|
|
7351
|
+
finding = !read.ok && error === read.error ? {
|
|
7352
|
+
state: "skipped",
|
|
7353
|
+
message: "the Project file is unusable; the project row says why"
|
|
7354
|
+
} : problemOf(check, error, {
|
|
7355
|
+
signal: ctx.signal,
|
|
7356
|
+
deadline: signal,
|
|
7357
|
+
ms
|
|
7358
|
+
});
|
|
7359
|
+
}
|
|
7360
|
+
return {
|
|
7361
|
+
row: {
|
|
7362
|
+
check: check.name,
|
|
7363
|
+
...finding
|
|
7364
|
+
},
|
|
7365
|
+
advisory: check.advisory === true
|
|
7366
|
+
};
|
|
7367
|
+
}
|
|
7368
|
+
function nextOf(rows) {
|
|
7369
|
+
return [...new Set(rows.flatMap(({ fix }) => fix === void 0 ? [] : [fix]))];
|
|
7370
|
+
}
|
|
7371
|
+
function render({ rows, next }, style) {
|
|
7372
|
+
const width = Math.max(MIN_LABEL_WIDTH, ...rows.map(({ check }) => check.length)) + 2;
|
|
7373
|
+
const stateWidth = Math.max(...rows.map(({ state }) => state.length)) + 2;
|
|
7374
|
+
return [...rows.map(({ check, state, message }) => {
|
|
7375
|
+
const label = state === "problem" ? style.red(state) : state;
|
|
7376
|
+
return `${check.padEnd(width)}${label}${" ".repeat(stateWidth - state.length)}${message}`;
|
|
7377
|
+
}), ...next.map((fix) => `${"next".padEnd(width)}${fix}`)].join("\n");
|
|
7378
|
+
}
|
|
7379
|
+
function failure(cliName, problems) {
|
|
7380
|
+
const errors = problems.map(({ check, message, fix, code }) => new CliError({
|
|
7381
|
+
code: code ?? "DOCTOR_PROBLEMS",
|
|
7382
|
+
message: `${cliName} doctor found a problem in ${check}: ${message}`,
|
|
7383
|
+
hint: fix === void 0 ? "the row says what is wrong" : `run ${fix}, then run doctor again`
|
|
7384
|
+
}));
|
|
7385
|
+
return new AggregateError(errors);
|
|
7386
|
+
}
|
|
7387
|
+
/** The built-in `doctor`: the fixed rows around the CLI's own, each under its own deadline. */
|
|
7388
|
+
function doctorCommand(cli, launch) {
|
|
7389
|
+
return defineCommand$1({
|
|
7390
|
+
name: "doctor",
|
|
7391
|
+
description: "check the setup and say what fixes each problem",
|
|
7392
|
+
examples: [{
|
|
7393
|
+
command: `${cli.name} doctor`,
|
|
7394
|
+
note: "check the setup and list the commands that fix it"
|
|
7395
|
+
}, {
|
|
7396
|
+
command: `${cli.name} doctor --json`,
|
|
7397
|
+
note: "get the rows and fixes as data"
|
|
7398
|
+
}],
|
|
7399
|
+
effect: "read",
|
|
7400
|
+
output: reportSchema,
|
|
7401
|
+
run: async (_input, ctx) => {
|
|
7402
|
+
const read = readProject(cli.project, ctx);
|
|
7403
|
+
const checked = (await Promise.all(doctorChecks(cli, launch, read).map((check) => rowOf(check, ctx, read)))).filter((row) => row !== void 0);
|
|
7404
|
+
const rows = checked.map(({ row }) => row);
|
|
7405
|
+
const report = {
|
|
7406
|
+
rows,
|
|
7407
|
+
next: nextOf(rows)
|
|
7408
|
+
};
|
|
7409
|
+
if (ctx.signal.aborted) {
|
|
7410
|
+
ctx.deliver(report);
|
|
7411
|
+
ctx.signal.throwIfAborted();
|
|
7412
|
+
}
|
|
7413
|
+
const problems = checked.filter(({ row, advisory }) => row.state === "problem" && !advisory).map(({ row }) => row);
|
|
7414
|
+
if (problems.length > 0) {
|
|
7415
|
+
ctx.deliver(report);
|
|
7416
|
+
throw failure(cli.name, problems);
|
|
7417
|
+
}
|
|
7418
|
+
return report;
|
|
7419
|
+
},
|
|
7420
|
+
render
|
|
7421
|
+
});
|
|
7422
|
+
}
|
|
7423
|
+
//#endregion
|
|
7424
|
+
//#region ../agent-cli/dist/interrupts.js
|
|
7425
|
+
const INTERRUPTED = "INTERRUPTED";
|
|
7426
|
+
const DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED";
|
|
7427
|
+
/** How long an interrupted Command may take to settle before the run ends without it. */
|
|
7428
|
+
const GRACE_MS = 3e3;
|
|
7429
|
+
const GRACE_OVER = Symbol("grace over");
|
|
7430
|
+
function interruptedError() {
|
|
7431
|
+
return new CliError({
|
|
7432
|
+
code: INTERRUPTED,
|
|
7433
|
+
message: "interrupted before it finished",
|
|
7434
|
+
hint: "run the command again"
|
|
7435
|
+
});
|
|
7436
|
+
}
|
|
7437
|
+
const WAIT_HINT = "run it again later, when the service it waits on may answer faster";
|
|
7438
|
+
function deadlineError(commandLine, ms, hint, bound = "deadline") {
|
|
7439
|
+
return new CliError({
|
|
7440
|
+
code: DEADLINE_EXCEEDED,
|
|
7441
|
+
message: `${commandLine} ran past its ${ms} ms ${bound}`,
|
|
7442
|
+
hint
|
|
7443
|
+
});
|
|
7444
|
+
}
|
|
7445
|
+
/** One Command run's cancellation: its signal, its deadlines and the steps it must finish. */
|
|
7446
|
+
var RunControl = class {
|
|
7447
|
+
signal;
|
|
7448
|
+
#controller = new AbortController();
|
|
7449
|
+
#commandLine;
|
|
7450
|
+
#outer;
|
|
7451
|
+
#onOuterAbort = () => this.#controller.abort(interruptedError());
|
|
7452
|
+
/** Each running must-finish step, tracked until it settles, with its name. */
|
|
7453
|
+
#steps = /* @__PURE__ */ new Map();
|
|
7454
|
+
#progress;
|
|
7455
|
+
#clock;
|
|
7456
|
+
#disposed = new AbortController();
|
|
7457
|
+
/** The reasons this run's deadlines and timeouts aborted with, to tell them in a Command's error. */
|
|
7458
|
+
#abortReasons = /* @__PURE__ */ new WeakSet();
|
|
7459
|
+
#graceCancel = new AbortController();
|
|
7460
|
+
#endGrace = () => {};
|
|
7461
|
+
#graceOver = new Promise((resolve) => {
|
|
7462
|
+
this.#endGrace = resolve;
|
|
7463
|
+
});
|
|
7464
|
+
constructor({ commandLine, outer, clock, progress, runDeadline }) {
|
|
7465
|
+
this.#commandLine = commandLine;
|
|
7466
|
+
this.#outer = outer;
|
|
7467
|
+
this.#clock = clock;
|
|
7468
|
+
this.#progress = progress;
|
|
7469
|
+
this.signal = this.#controller.signal;
|
|
7470
|
+
this.signal.addEventListener("abort", () => this.#onStop(), { once: true });
|
|
7471
|
+
if (outer?.aborted === true) this.#onOuterAbort();
|
|
7472
|
+
else outer?.addEventListener("abort", this.#onOuterAbort, { once: true });
|
|
7473
|
+
if (runDeadline !== void 0) {
|
|
7474
|
+
const { ms, hint } = runDeadline;
|
|
7475
|
+
after(clock, ms, this.#disposed.signal, () => this.#controller.abort(deadlineError(commandLine, ms, hint())));
|
|
7476
|
+
}
|
|
7477
|
+
}
|
|
7478
|
+
deadline(ms) {
|
|
7479
|
+
return AbortSignal.any([this.signal, this.#abortsAfter(ms, "deadline")]);
|
|
7480
|
+
}
|
|
7481
|
+
timeout(ms) {
|
|
7482
|
+
return this.#abortsAfter(ms, "timeout");
|
|
7483
|
+
}
|
|
7484
|
+
#abortsAfter(ms, bound) {
|
|
7485
|
+
const controller = new AbortController();
|
|
7486
|
+
after(this.#clock, ms, this.#disposed.signal, () => {
|
|
7487
|
+
const reason = deadlineError(this.#commandLine, ms, WAIT_HINT, bound);
|
|
7488
|
+
this.#abortReasons.add(reason);
|
|
7489
|
+
controller.abort(reason);
|
|
7490
|
+
});
|
|
7491
|
+
return controller.signal;
|
|
7492
|
+
}
|
|
7493
|
+
async runToEnd(name, work) {
|
|
7494
|
+
this.#graceCancel.abort();
|
|
7495
|
+
if (this.signal.aborted) this.#finishing(name);
|
|
7496
|
+
const step = work();
|
|
7497
|
+
const settled = step.then(() => {}, () => {});
|
|
7498
|
+
this.#steps.set(settled, name);
|
|
7499
|
+
try {
|
|
7500
|
+
return await step;
|
|
7501
|
+
} finally {
|
|
7502
|
+
this.#steps.delete(settled);
|
|
7503
|
+
this.#startGrace();
|
|
7504
|
+
}
|
|
7505
|
+
}
|
|
7506
|
+
/** Waits for the Command, its must-finish steps, and no longer than the grace once interrupted. */
|
|
7507
|
+
async settle(work) {
|
|
7508
|
+
try {
|
|
7509
|
+
const value = await Promise.race([work, this.#graceOver]);
|
|
7510
|
+
if (this.signal.aborted || value === GRACE_OVER) throw this.signal.reason;
|
|
7511
|
+
return value;
|
|
7512
|
+
} finally {
|
|
7513
|
+
await this.#stepsDone();
|
|
7514
|
+
this.close();
|
|
7515
|
+
}
|
|
7516
|
+
}
|
|
7517
|
+
/**
|
|
7518
|
+
* The error a run ends with: an interrupt or the run deadline outranks what the Command threw,
|
|
7519
|
+
* unless the Command threw its own `INTERRUPTED`, saying what it finished before it stopped.
|
|
7520
|
+
* Otherwise each leaf that is not a `CliError` and whose cause chain holds a deadline's or timeout's
|
|
7521
|
+
* abort is reported as that abort, so a declared error keeps its own code.
|
|
7522
|
+
*/
|
|
7523
|
+
errorAfter(error) {
|
|
7524
|
+
if (this.signal.aborted) return error instanceof CliError && error.code === "INTERRUPTED" ? error : this.signal.reason;
|
|
7525
|
+
const leaves = errorsOf(error).map((leaf) => this.#abortIn(leaf) ?? leaf);
|
|
7526
|
+
return leaves.length === 1 ? leaves[0] : new AggregateError(leaves);
|
|
7527
|
+
}
|
|
7528
|
+
#abortIn(error) {
|
|
7529
|
+
if (error instanceof CliError) return void 0;
|
|
7530
|
+
return causesOf(error).find((each) => each instanceof CliError && this.#abortReasons.has(each));
|
|
7531
|
+
}
|
|
7532
|
+
#onStop() {
|
|
7533
|
+
for (const name of this.#steps.values()) this.#finishing(name);
|
|
7534
|
+
this.#startGrace();
|
|
7535
|
+
}
|
|
7536
|
+
#finishing(name) {
|
|
7537
|
+
this.#progress(`finishing ${name}`);
|
|
7538
|
+
}
|
|
7539
|
+
#startGrace() {
|
|
7540
|
+
if (this.signal.aborted && this.#steps.size === 0) {
|
|
7541
|
+
this.#graceCancel.abort();
|
|
7542
|
+
this.#graceCancel = new AbortController();
|
|
7543
|
+
after(this.#clock, GRACE_MS, this.#graceCancel.signal, () => this.#endGrace(GRACE_OVER));
|
|
7544
|
+
}
|
|
7545
|
+
}
|
|
7546
|
+
async #stepsDone() {
|
|
7547
|
+
while (this.#steps.size > 0) await Promise.all(this.#steps.keys());
|
|
7548
|
+
}
|
|
7549
|
+
/** Stops the run's timers and its hold on the caller's signal, for a run that never settles. */
|
|
7550
|
+
close() {
|
|
7551
|
+
this.#graceCancel.abort();
|
|
7552
|
+
this.#disposed.abort();
|
|
7553
|
+
this.#outer?.removeEventListener("abort", this.#onOuterAbort);
|
|
7554
|
+
}
|
|
7555
|
+
};
|
|
7556
|
+
//#endregion
|
|
7557
|
+
//#region ../agent-cli/dist/built-ins/upgrade-notes.js
|
|
7558
|
+
const RELEASE_HEADING = /^## v?(\S+)/;
|
|
7559
|
+
function releasesIn(changelog) {
|
|
7560
|
+
const releases = [];
|
|
7561
|
+
let current;
|
|
7562
|
+
for (const line of changelog.split(/\r?\n/)) {
|
|
7563
|
+
const heading = RELEASE_HEADING.exec(line);
|
|
7564
|
+
if (heading !== null) {
|
|
7565
|
+
const version = heading[1] ?? "";
|
|
7566
|
+
current = isVersion(version) ? {
|
|
7567
|
+
version,
|
|
7568
|
+
lines: []
|
|
7569
|
+
} : void 0;
|
|
7570
|
+
if (current !== void 0) releases.push(current);
|
|
7571
|
+
} else current?.lines.push(line);
|
|
7572
|
+
}
|
|
7573
|
+
return releases.map(({ version, lines }) => ({
|
|
7574
|
+
version,
|
|
7575
|
+
notes: lines.join("\n").trim()
|
|
7576
|
+
}));
|
|
7577
|
+
}
|
|
7578
|
+
/**
|
|
7579
|
+
* What changed in each release after `from` up to `to`, oldest first, from the CHANGELOG.md in
|
|
7580
|
+
* `packageDir`; none when the package ships no CHANGELOG.
|
|
7581
|
+
*/
|
|
7582
|
+
async function upgradeNotes(packageDir, from, to) {
|
|
7583
|
+
let changelog;
|
|
7584
|
+
try {
|
|
7585
|
+
changelog = await readFile(join(packageDir, "CHANGELOG.md"), "utf8");
|
|
7586
|
+
} catch (error) {
|
|
7587
|
+
if (isMissingFile(error)) return [];
|
|
7588
|
+
throw error;
|
|
7589
|
+
}
|
|
7590
|
+
return releasesIn(changelog).filter(({ version }) => compareVersions(version, from) > 0 && compareVersions(version, to) <= 0).sort((a, b) => compareVersions(a.version, b.version));
|
|
7591
|
+
}
|
|
7592
|
+
//#endregion
|
|
7593
|
+
//#region ../agent-cli/dist/built-ins/update.js
|
|
7594
|
+
const updateSchema = object({
|
|
7595
|
+
from: string(),
|
|
7596
|
+
latest: string(),
|
|
7597
|
+
installed: object({
|
|
7598
|
+
version: string(),
|
|
7599
|
+
prefix: string()
|
|
7600
|
+
}).nullable(),
|
|
7601
|
+
upgrades: array(object({
|
|
7602
|
+
version: string(),
|
|
7603
|
+
notes: string()
|
|
7604
|
+
})),
|
|
7605
|
+
next: array(string())
|
|
7606
|
+
});
|
|
7607
|
+
function nothingToInstall({ from, latest }) {
|
|
7608
|
+
return standingOf(from, latest) === "current" ? `already on ${from}, the latest release: nothing to install` : `${from} is newer than the latest release ${latest}: nothing to install`;
|
|
7609
|
+
}
|
|
7610
|
+
function renderUpdate(cli, install, update) {
|
|
7611
|
+
const { installed } = update;
|
|
7612
|
+
const head = installed === null ? [nothingToInstall(update)] : [`installed ${install.package}@${installed.version} with the npm under ${installed.prefix}, replacing ${update.from}`, ...update.upgrades.map(({ version, notes }) => `\nchanges in ${version}:\n${notes}`)];
|
|
7613
|
+
const next = update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${update.latest}`);
|
|
7614
|
+
return (next.length === 0 ? head : [
|
|
7615
|
+
...head,
|
|
7616
|
+
"",
|
|
7617
|
+
...next
|
|
7618
|
+
]).join("\n");
|
|
7619
|
+
}
|
|
7620
|
+
async function skillNext(cli, latest, ctx) {
|
|
7621
|
+
const { fix } = await skillReport(cli, latest, ctx);
|
|
7622
|
+
return fix === void 0 ? [] : [fix];
|
|
7623
|
+
}
|
|
7624
|
+
function interruptedAfterInstall(plan) {
|
|
7625
|
+
return new CliError({
|
|
7626
|
+
code: INTERRUPTED,
|
|
7627
|
+
message: `interrupted, but ${plan.package}@${plan.latest} had already been installed with the npm under ${plan.prefix}, replacing ${plan.from}`,
|
|
7628
|
+
hint: "nothing to run again: run the commands under next"
|
|
7629
|
+
});
|
|
7630
|
+
}
|
|
7631
|
+
/** The built-in `update`, for a CLI installed globally with npm. */
|
|
7632
|
+
function updateCommand(cli, install, { bin, node }) {
|
|
7633
|
+
return defineCommand$1({
|
|
7634
|
+
name: "update",
|
|
7635
|
+
description: "install the latest version of this CLI from its registry",
|
|
7636
|
+
examples: [{
|
|
7637
|
+
command: `${cli.name} update`,
|
|
7638
|
+
note: "install the latest version and show what changed"
|
|
7639
|
+
}, {
|
|
7640
|
+
command: `${cli.name} update --dry-run`,
|
|
7641
|
+
note: "show the version it would install"
|
|
7642
|
+
}],
|
|
7643
|
+
effect: "write",
|
|
7644
|
+
output: updateSchema,
|
|
7645
|
+
plan: async (_input, ctx) => {
|
|
7646
|
+
const npm = npmContext(cli, install, ctx, node);
|
|
7647
|
+
const copy = await globalInstallOf(bin, npm);
|
|
7648
|
+
return {
|
|
7649
|
+
package: install.package,
|
|
7650
|
+
from: cli.version,
|
|
7651
|
+
latest: await latestVersion(npm),
|
|
7652
|
+
prefix: copy.prefix,
|
|
7653
|
+
packageDir: copy.packageDir
|
|
7654
|
+
};
|
|
7655
|
+
},
|
|
7656
|
+
apply: async (plan, ctx) => {
|
|
7657
|
+
const { from, latest, prefix } = plan;
|
|
7658
|
+
if (standingOf(from, latest) !== "behind") return {
|
|
7659
|
+
from,
|
|
7660
|
+
latest,
|
|
7661
|
+
installed: null,
|
|
7662
|
+
upgrades: [],
|
|
7663
|
+
next: await skillNext(cli, latest, ctx)
|
|
7664
|
+
};
|
|
7665
|
+
ctx.signal.throwIfAborted();
|
|
7666
|
+
ctx.progress(`installing ${plan.package}@${latest} with the npm under ${prefix}…`);
|
|
7667
|
+
await ctx.runToEnd(`installing ${plan.package}@${latest}`, () => installGlobally(latest, npmContext(cli, install, ctx, node)));
|
|
7668
|
+
const update = {
|
|
7669
|
+
from,
|
|
7670
|
+
latest,
|
|
7671
|
+
installed: {
|
|
7672
|
+
version: latest,
|
|
7673
|
+
prefix
|
|
7674
|
+
},
|
|
7675
|
+
upgrades: await upgradeNotes(plan.packageDir, from, latest),
|
|
7676
|
+
next: await skillNext(cli, latest, ctx)
|
|
7677
|
+
};
|
|
7678
|
+
if (ctx.signal.aborted) {
|
|
7679
|
+
ctx.deliver(update);
|
|
7680
|
+
throw interruptedAfterInstall(plan);
|
|
7681
|
+
}
|
|
7682
|
+
return update;
|
|
7683
|
+
},
|
|
7684
|
+
render: (update) => renderUpdate(cli, install, update),
|
|
7685
|
+
renderPlan: (plan) => standingOf(plan.from, plan.latest) === "behind" ? `would install ${plan.package}@${plan.latest} with the npm under ${plan.prefix}, replacing ${plan.from}` : nothingToInstall(plan)
|
|
7686
|
+
});
|
|
7687
|
+
}
|
|
7688
|
+
//#endregion
|
|
7689
|
+
//#region ../agent-cli/dist/built-ins/commands.js
|
|
7690
|
+
/** The Commands the Runtime adds to a multi-Command CLI: `update` only when it declares an install. */
|
|
7691
|
+
function builtInCommands(cli, launch) {
|
|
7692
|
+
return {
|
|
7693
|
+
doctor: doctorCommand(cli, launch),
|
|
7694
|
+
...cli.install === void 0 ? {} : { update: updateCommand(cli, cli.install, launch) }
|
|
7695
|
+
};
|
|
7696
|
+
}
|
|
7697
|
+
//#endregion
|
|
7698
|
+
//#region ../agent-cli/dist/confirm.js
|
|
7699
|
+
const CONFIRMATION_REQUIRED = "CONFIRMATION_REQUIRED";
|
|
7700
|
+
const CONFIRMATION_MISMATCH = "CONFIRMATION_MISMATCH";
|
|
7701
|
+
function checkConfirmation({ invocation, commandLine, given }, expected) {
|
|
7702
|
+
if (given === expected) return;
|
|
7703
|
+
const hint = `to confirm, run \`${commandLineOf(invocation, {
|
|
7704
|
+
remove: [CONFIRM_FLAG.flag],
|
|
7705
|
+
add: [CONFIRM_FLAG.flag, expected]
|
|
7706
|
+
})}\``;
|
|
7707
|
+
if (given === void 0) throw new UsageError({
|
|
7708
|
+
code: CONFIRMATION_REQUIRED,
|
|
7709
|
+
message: `\`${commandLine}\` is destructive and needs ${CONFIRM_FLAG.flag}`,
|
|
7710
|
+
hint
|
|
7711
|
+
});
|
|
7712
|
+
throw new UsageError({
|
|
7713
|
+
code: CONFIRMATION_MISMATCH,
|
|
7714
|
+
message: `${CONFIRM_FLAG.flag} ${JSON.stringify(given)} does not match the target of \`${commandLine}\``,
|
|
7715
|
+
hint
|
|
7716
|
+
});
|
|
7717
|
+
}
|
|
7718
|
+
//#endregion
|
|
7719
|
+
//#region ../agent-cli/dist/cost.js
|
|
7720
|
+
const NOT_CONFIRMED = "NOT_CONFIRMED";
|
|
7721
|
+
/** Refuses a run whose Plan states a cost the caller has not approved with `--yes`. */
|
|
7722
|
+
function checkCost({ invocation, commandLine, yes }, cost) {
|
|
7723
|
+
if (cost === void 0 || yes) return;
|
|
7724
|
+
throw new CliError({
|
|
7725
|
+
code: NOT_CONFIRMED,
|
|
7726
|
+
message: `\`${commandLine}\` needs ${YES_FLAG.flag}: ${cost}`,
|
|
7727
|
+
hint: `to approve the cost, run \`${commandLineOf(invocation, { add: [YES_FLAG.flag] })}\``
|
|
7728
|
+
});
|
|
7729
|
+
}
|
|
7730
|
+
//#endregion
|
|
7731
|
+
//#region ../agent-cli/dist/agent.js
|
|
7732
|
+
const AGENT_NAME = /^[a-zA-Z0-9_-]+$/u;
|
|
7733
|
+
const isSet = (name) => (env) => (env[name] ?? "") !== "";
|
|
7734
|
+
const equals = (name, value) => (env) => env[name] === value;
|
|
7735
|
+
const MARKERS = [
|
|
7736
|
+
(env) => AGENT_NAME.test(env.AI_AGENT ?? ""),
|
|
7737
|
+
equals("AGENT", "amp"),
|
|
7738
|
+
isSet("CODEX_SANDBOX"),
|
|
7739
|
+
isSet("CODEX_CI"),
|
|
7740
|
+
isSet("CODEX_THREAD_ID"),
|
|
7741
|
+
isSet("GEMINI_CLI"),
|
|
7742
|
+
isSet("COPILOT_CLI"),
|
|
7743
|
+
isSet("OPENCODE"),
|
|
7744
|
+
isSet("ANTIGRAVITY_AGENT"),
|
|
7745
|
+
isSet("AUGMENT_AGENT"),
|
|
7746
|
+
isSet("REPL_ID"),
|
|
7747
|
+
isSet("CLAUDE_CODE_IS_COWORK"),
|
|
7748
|
+
isSet("CLAUDECODE"),
|
|
7749
|
+
isSet("CLAUDE_CODE"),
|
|
7750
|
+
isSet("CURSOR_TRACE_ID"),
|
|
7751
|
+
isSet("CURSOR_AGENT"),
|
|
7752
|
+
equals("CURSOR_EXTENSION_HOST_ROLE", "agent-exec"),
|
|
7753
|
+
equals("TERM_PROGRAM", "kiro"),
|
|
7754
|
+
(env) => ["/.pi/agent", "\\.pi\\agent"].some((dir) => (env.PATH ?? "").includes(dir)),
|
|
7755
|
+
isSet("GOOSE_PROVIDER")
|
|
7756
|
+
];
|
|
7757
|
+
/**
|
|
7758
|
+
* Whether a Coding agent, not a person, is running the Agent CLI. Some Coding agents run commands
|
|
7759
|
+
* in a PTY, so a TTY alone doesn't mean a person is watching.
|
|
7760
|
+
*/
|
|
7761
|
+
function isAgent(env) {
|
|
7762
|
+
return MARKERS.some((marker) => marker(env));
|
|
7763
|
+
}
|
|
7764
|
+
//#endregion
|
|
7765
|
+
//#region ../agent-cli/dist/errno.js
|
|
7766
|
+
const PERMISSION_DENIED = "PERMISSION_DENIED";
|
|
7767
|
+
const DISK_FULL = "DISK_FULL";
|
|
7768
|
+
const NOT_FOUND = "NOT_FOUND";
|
|
7769
|
+
const ALREADY_EXISTS = "ALREADY_EXISTS";
|
|
7770
|
+
const NOT_A_FILE = "NOT_A_FILE";
|
|
7771
|
+
function permissionHint({ path, access, callerLine, env, platform }) {
|
|
7772
|
+
if (platform === "win32") return `a program may hold ${path} open: close it, then run the same command again`;
|
|
7773
|
+
if (!isAgent(env)) return `check the permissions of ${path} and its folder`;
|
|
7774
|
+
return `your sandbox may block it: ask your user to run \`! ${callerLine}\`, or ${access === "read" ? `to allow reading ${path} in the sandbox` : `to allow ${path} in the sandbox's write list`}`;
|
|
7775
|
+
}
|
|
7776
|
+
function fileErrorOf(scope) {
|
|
7777
|
+
return (error, at) => classifyErrno(error, {
|
|
7778
|
+
...at,
|
|
7779
|
+
...scope
|
|
7780
|
+
});
|
|
7781
|
+
}
|
|
7782
|
+
function classifyErrno(error, context) {
|
|
7783
|
+
const { path } = context;
|
|
7784
|
+
switch (errnoOf(error)) {
|
|
7785
|
+
case "EACCES":
|
|
7786
|
+
case "EPERM":
|
|
7787
|
+
case "EROFS":
|
|
7788
|
+
case "EBUSY": return new CliError({
|
|
7789
|
+
code: PERMISSION_DENIED,
|
|
7790
|
+
message: `permission denied: ${path}`,
|
|
7791
|
+
hint: permissionHint(context)
|
|
7792
|
+
}, { cause: error });
|
|
6853
7793
|
case "ENOSPC":
|
|
6854
7794
|
case "EDQUOT": return new CliError({
|
|
6855
7795
|
code: DISK_FULL,
|
|
@@ -6877,159 +7817,6 @@ function classifyErrno(error, context) {
|
|
|
6877
7817
|
}
|
|
6878
7818
|
}
|
|
6879
7819
|
//#endregion
|
|
6880
|
-
//#region ../agent-cli/dist/clock.js
|
|
6881
|
-
const realClock = {
|
|
6882
|
-
now: () => Date.now(),
|
|
6883
|
-
sleep: (ms, signal) => new Promise((resolve, reject) => {
|
|
6884
|
-
if (signal?.aborted === true) {
|
|
6885
|
-
reject(signal.reason);
|
|
6886
|
-
return;
|
|
6887
|
-
}
|
|
6888
|
-
const onAbort = () => {
|
|
6889
|
-
clearTimeout(timer);
|
|
6890
|
-
reject(signal?.reason);
|
|
6891
|
-
};
|
|
6892
|
-
const timer = setTimeout(() => {
|
|
6893
|
-
signal?.removeEventListener("abort", onAbort);
|
|
6894
|
-
resolve();
|
|
6895
|
-
}, ms);
|
|
6896
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
6897
|
-
})
|
|
6898
|
-
};
|
|
6899
|
-
/** Runs `then` once `ms` have passed on `clock`; aborting `cancel` drops it. */
|
|
6900
|
-
function after(clock, ms, cancel, then) {
|
|
6901
|
-
clock.sleep(ms, cancel).then(then, (error) => {
|
|
6902
|
-
if (!cancel.aborted) throw error;
|
|
6903
|
-
});
|
|
6904
|
-
}
|
|
6905
|
-
async function poll(clock, check, intervalMs, signal) {
|
|
6906
|
-
for (;;) {
|
|
6907
|
-
signal.throwIfAborted();
|
|
6908
|
-
const value = await check();
|
|
6909
|
-
if (value !== void 0) return value;
|
|
6910
|
-
await clock.sleep(intervalMs, signal);
|
|
6911
|
-
}
|
|
6912
|
-
}
|
|
6913
|
-
//#endregion
|
|
6914
|
-
//#region ../agent-cli/dist/interrupts.js
|
|
6915
|
-
const INTERRUPTED = "INTERRUPTED";
|
|
6916
|
-
const DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED";
|
|
6917
|
-
/** How long an interrupted Command may take to settle before the run ends without it. */
|
|
6918
|
-
const GRACE_MS = 3e3;
|
|
6919
|
-
const GRACE_OVER = Symbol("grace over");
|
|
6920
|
-
function interruptedError() {
|
|
6921
|
-
return new CliError({
|
|
6922
|
-
code: INTERRUPTED,
|
|
6923
|
-
message: "interrupted before it finished",
|
|
6924
|
-
hint: "run the command again"
|
|
6925
|
-
});
|
|
6926
|
-
}
|
|
6927
|
-
const WAIT_HINT = "run it again later, when the service it waits on may answer faster";
|
|
6928
|
-
function deadlineError(commandLine, ms, hint) {
|
|
6929
|
-
return new CliError({
|
|
6930
|
-
code: DEADLINE_EXCEEDED,
|
|
6931
|
-
message: `${commandLine} ran past its ${ms} ms deadline`,
|
|
6932
|
-
hint
|
|
6933
|
-
});
|
|
6934
|
-
}
|
|
6935
|
-
/** One Command run's cancellation: its signal, its deadlines and the steps it must finish. */
|
|
6936
|
-
var RunControl = class {
|
|
6937
|
-
signal;
|
|
6938
|
-
#controller = new AbortController();
|
|
6939
|
-
#commandLine;
|
|
6940
|
-
#outer;
|
|
6941
|
-
#onOuterAbort = () => this.#controller.abort(interruptedError());
|
|
6942
|
-
/** Each running must-finish step, tracked until it settles, with its name. */
|
|
6943
|
-
#steps = /* @__PURE__ */ new Map();
|
|
6944
|
-
#progress;
|
|
6945
|
-
#clock;
|
|
6946
|
-
#disposed = new AbortController();
|
|
6947
|
-
#deadlineHit;
|
|
6948
|
-
#graceCancel = new AbortController();
|
|
6949
|
-
#endGrace = () => {};
|
|
6950
|
-
#graceOver = new Promise((resolve) => {
|
|
6951
|
-
this.#endGrace = resolve;
|
|
6952
|
-
});
|
|
6953
|
-
constructor({ commandLine, outer, clock, progress, runDeadline }) {
|
|
6954
|
-
this.#commandLine = commandLine;
|
|
6955
|
-
this.#outer = outer;
|
|
6956
|
-
this.#clock = clock;
|
|
6957
|
-
this.#progress = progress;
|
|
6958
|
-
this.signal = this.#controller.signal;
|
|
6959
|
-
this.signal.addEventListener("abort", () => this.#onStop(), { once: true });
|
|
6960
|
-
if (outer?.aborted === true) this.#onOuterAbort();
|
|
6961
|
-
else outer?.addEventListener("abort", this.#onOuterAbort, { once: true });
|
|
6962
|
-
if (runDeadline !== void 0) {
|
|
6963
|
-
const { ms, hint } = runDeadline;
|
|
6964
|
-
after(clock, ms, this.#disposed.signal, () => this.#controller.abort(deadlineError(commandLine, ms, hint())));
|
|
6965
|
-
}
|
|
6966
|
-
}
|
|
6967
|
-
deadline(ms) {
|
|
6968
|
-
const controller = new AbortController();
|
|
6969
|
-
after(this.#clock, ms, this.#disposed.signal, () => {
|
|
6970
|
-
this.#deadlineHit ??= deadlineError(this.#commandLine, ms, WAIT_HINT);
|
|
6971
|
-
controller.abort(this.#deadlineHit);
|
|
6972
|
-
});
|
|
6973
|
-
return AbortSignal.any([this.signal, controller.signal]);
|
|
6974
|
-
}
|
|
6975
|
-
async runToEnd(name, work) {
|
|
6976
|
-
this.#graceCancel.abort();
|
|
6977
|
-
if (this.signal.aborted) this.#finishing(name);
|
|
6978
|
-
const step = work();
|
|
6979
|
-
const settled = step.then(() => {}, () => {});
|
|
6980
|
-
this.#steps.set(settled, name);
|
|
6981
|
-
try {
|
|
6982
|
-
return await step;
|
|
6983
|
-
} finally {
|
|
6984
|
-
this.#steps.delete(settled);
|
|
6985
|
-
this.#startGrace();
|
|
6986
|
-
}
|
|
6987
|
-
}
|
|
6988
|
-
/** Waits for the Command, its must-finish steps, and no longer than the grace once interrupted. */
|
|
6989
|
-
async settle(work) {
|
|
6990
|
-
try {
|
|
6991
|
-
const value = await Promise.race([work, this.#graceOver]);
|
|
6992
|
-
if (this.signal.aborted || value === GRACE_OVER) throw this.signal.reason;
|
|
6993
|
-
return value;
|
|
6994
|
-
} finally {
|
|
6995
|
-
await this.#stepsDone();
|
|
6996
|
-
this.close();
|
|
6997
|
-
}
|
|
6998
|
-
}
|
|
6999
|
-
/**
|
|
7000
|
-
* The error a run ends with: an interrupt or a missed deadline outranks what the Command threw,
|
|
7001
|
-
* unless the Command threw its own `INTERRUPTED`, saying what it finished before it stopped.
|
|
7002
|
-
*/
|
|
7003
|
-
errorAfter(error) {
|
|
7004
|
-
if (this.signal.aborted) return error instanceof CliError && error.code === "INTERRUPTED" ? error : this.signal.reason;
|
|
7005
|
-
if (this.#deadlineHit !== void 0 && !(error instanceof CliError)) return this.#deadlineHit;
|
|
7006
|
-
return error;
|
|
7007
|
-
}
|
|
7008
|
-
#onStop() {
|
|
7009
|
-
for (const name of this.#steps.values()) this.#finishing(name);
|
|
7010
|
-
this.#startGrace();
|
|
7011
|
-
}
|
|
7012
|
-
#finishing(name) {
|
|
7013
|
-
this.#progress(`finishing ${name}`);
|
|
7014
|
-
}
|
|
7015
|
-
#startGrace() {
|
|
7016
|
-
if (this.signal.aborted && this.#steps.size === 0) {
|
|
7017
|
-
this.#graceCancel.abort();
|
|
7018
|
-
this.#graceCancel = new AbortController();
|
|
7019
|
-
after(this.#clock, GRACE_MS, this.#graceCancel.signal, () => this.#endGrace(GRACE_OVER));
|
|
7020
|
-
}
|
|
7021
|
-
}
|
|
7022
|
-
async #stepsDone() {
|
|
7023
|
-
while (this.#steps.size > 0) await Promise.all(this.#steps.keys());
|
|
7024
|
-
}
|
|
7025
|
-
/** Stops the run's timers and its hold on the caller's signal, for a run that never settles. */
|
|
7026
|
-
close() {
|
|
7027
|
-
this.#graceCancel.abort();
|
|
7028
|
-
this.#disposed.abort();
|
|
7029
|
-
this.#outer?.removeEventListener("abort", this.#onOuterAbort);
|
|
7030
|
-
}
|
|
7031
|
-
};
|
|
7032
|
-
//#endregion
|
|
7033
7820
|
//#region ../agent-cli/dist/operator.js
|
|
7034
7821
|
const NEEDS_OPERATOR = "NEEDS_OPERATOR";
|
|
7035
7822
|
/** Fails with `NEEDS_OPERATOR` when a Coding agent runs an Operator Command. */
|
|
@@ -7160,12 +7947,19 @@ function realFiles() {
|
|
|
7160
7947
|
force: true
|
|
7161
7948
|
}),
|
|
7162
7949
|
mkdir: async (path, options) => {
|
|
7950
|
+
const mode = options?.mode;
|
|
7163
7951
|
if (options?.exclusive !== true) {
|
|
7164
|
-
await mkdir(path, {
|
|
7952
|
+
await mkdir(path, {
|
|
7953
|
+
recursive: true,
|
|
7954
|
+
mode
|
|
7955
|
+
});
|
|
7165
7956
|
return;
|
|
7166
7957
|
}
|
|
7167
|
-
await mkdir(dirname(path), {
|
|
7168
|
-
|
|
7958
|
+
await mkdir(dirname(path), {
|
|
7959
|
+
recursive: true,
|
|
7960
|
+
mode
|
|
7961
|
+
});
|
|
7962
|
+
await mkdir(path, { mode });
|
|
7169
7963
|
},
|
|
7170
7964
|
stat: async (path) => {
|
|
7171
7965
|
try {
|
|
@@ -7265,62 +8059,16 @@ async function probeOutputs({ files, cwd, fileError }, outputs) {
|
|
|
7265
8059
|
await Promise.all([...folders].map(async (folder) => {
|
|
7266
8060
|
const probe = tempPathOf(join(folder, "outputs-probe"));
|
|
7267
8061
|
try {
|
|
7268
|
-
await files.mkdir(folder);
|
|
7269
|
-
await files.write(probe, "");
|
|
7270
|
-
await files.remove(probe);
|
|
7271
|
-
} catch (error) {
|
|
7272
|
-
throw fileError(error, {
|
|
7273
|
-
path: folder,
|
|
7274
|
-
access: "write"
|
|
7275
|
-
});
|
|
7276
|
-
}
|
|
7277
|
-
}));
|
|
7278
|
-
}
|
|
7279
|
-
//#endregion
|
|
7280
|
-
//#region ../agent-cli/dist/project.js
|
|
7281
|
-
const PROJECT_INVALID = "PROJECT_INVALID";
|
|
7282
|
-
function invalid(path, problem, options) {
|
|
7283
|
-
return new CliError({
|
|
7284
|
-
code: PROJECT_INVALID,
|
|
7285
|
-
message: `the Project file ${path} is invalid: ${problem}`,
|
|
7286
|
-
hint: `fix ${path}, then run the command again`
|
|
7287
|
-
}, options);
|
|
7288
|
-
}
|
|
7289
|
-
function readText(path) {
|
|
7290
|
-
try {
|
|
7291
|
-
return readFileSync(path, "utf8");
|
|
7292
|
-
} catch (error) {
|
|
7293
|
-
if (isMissingFile(error)) return void 0;
|
|
7294
|
-
throw error;
|
|
7295
|
-
}
|
|
7296
|
-
}
|
|
7297
|
-
function parsed(path, text, schema) {
|
|
7298
|
-
let json;
|
|
7299
|
-
try {
|
|
7300
|
-
json = JSON.parse(text);
|
|
7301
|
-
} catch (error) {
|
|
7302
|
-
throw invalid(path, messageOf(error), { cause: error });
|
|
7303
|
-
}
|
|
7304
|
-
const result = schema.safeParse(json);
|
|
7305
|
-
if (!result.success) throw invalid(path, prettifyError(result.error));
|
|
7306
|
-
return result.data;
|
|
7307
|
-
}
|
|
7308
|
-
function projectFrom({ file, schema }, folder) {
|
|
7309
|
-
const path = join(folder, file);
|
|
7310
|
-
const text = readText(path);
|
|
7311
|
-
if (text !== void 0) return {
|
|
7312
|
-
root: folder,
|
|
7313
|
-
settings: parsed(path, text, schema)
|
|
7314
|
-
};
|
|
7315
|
-
const parent = dirname(folder);
|
|
7316
|
-
return parent === folder ? void 0 : projectFrom({
|
|
7317
|
-
file,
|
|
7318
|
-
schema
|
|
7319
|
-
}, parent);
|
|
7320
|
-
}
|
|
7321
|
-
/** The nearest Project file at or above `cwd`, parsed by its schema; undefined when there is none. */
|
|
7322
|
-
function projectOf(projectFile, cwd) {
|
|
7323
|
-
return projectFrom(projectFile, resolve(cwd));
|
|
8062
|
+
await files.mkdir(folder);
|
|
8063
|
+
await files.write(probe, "");
|
|
8064
|
+
await files.remove(probe);
|
|
8065
|
+
} catch (error) {
|
|
8066
|
+
throw fileError(error, {
|
|
8067
|
+
path: folder,
|
|
8068
|
+
access: "write"
|
|
8069
|
+
});
|
|
8070
|
+
}
|
|
8071
|
+
}));
|
|
7324
8072
|
}
|
|
7325
8073
|
//#endregion
|
|
7326
8074
|
//#region ../agent-cli/dist/exit-classes.js
|
|
@@ -7335,46 +8083,44 @@ const EXIT_CODES = {
|
|
|
7335
8083
|
wait: 75,
|
|
7336
8084
|
bug: 70
|
|
7337
8085
|
};
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
|
|
7341
|
-
|
|
7342
|
-
|
|
7343
|
-
|
|
7344
|
-
|
|
7345
|
-
|
|
7346
|
-
|
|
7347
|
-
|
|
7348
|
-
|
|
7349
|
-
|
|
7350
|
-
|
|
7351
|
-
|
|
7352
|
-
|
|
7353
|
-
|
|
7354
|
-
|
|
7355
|
-
|
|
7356
|
-
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
7361
|
-
|
|
7362
|
-
|
|
7363
|
-
|
|
7364
|
-
|
|
7365
|
-
|
|
7366
|
-
|
|
7367
|
-
|
|
7368
|
-
};
|
|
7369
|
-
}
|
|
8086
|
+
const RUNTIME_EXIT_CLASSES = {
|
|
8087
|
+
[INVALID_INPUT]: "caller",
|
|
8088
|
+
[UNKNOWN_OPTION]: "caller",
|
|
8089
|
+
[UNKNOWN_COMMAND]: "caller",
|
|
8090
|
+
[UNKNOWN_FIELD]: "caller",
|
|
8091
|
+
[CONFIRMATION_REQUIRED]: "caller",
|
|
8092
|
+
[CONFIRMATION_MISMATCH]: "caller",
|
|
8093
|
+
[NOT_CONFIRMED]: "operator",
|
|
8094
|
+
[NEEDS_OPERATOR]: "operator",
|
|
8095
|
+
[OUTPUT_EXISTS]: "caller",
|
|
8096
|
+
[STDIN_STALLED]: "caller",
|
|
8097
|
+
[INTERRUPTED]: "interrupted",
|
|
8098
|
+
[DEADLINE_EXCEEDED]: "wait",
|
|
8099
|
+
[INTERNAL]: "bug",
|
|
8100
|
+
[PERMISSION_DENIED]: "operator",
|
|
8101
|
+
[DISK_FULL]: "operator",
|
|
8102
|
+
[NOT_FOUND]: "caller",
|
|
8103
|
+
[ALREADY_EXISTS]: "caller",
|
|
8104
|
+
[NOT_A_FILE]: "caller",
|
|
8105
|
+
[TOOL_FAILED]: "operator",
|
|
8106
|
+
[TOOL_MISSING]: "operator",
|
|
8107
|
+
[PROJECT_INVALID]: "operator",
|
|
8108
|
+
[DOCTOR_PROBLEMS]: "operator",
|
|
8109
|
+
[NOT_GLOBAL_INSTALL]: "operator",
|
|
8110
|
+
[REGISTRY_UNREACHABLE]: "operator",
|
|
8111
|
+
[REGISTRY_AUTH]: "operator",
|
|
8112
|
+
[INSTALL_FAILED]: "operator",
|
|
8113
|
+
[NPM_FAILED]: "operator",
|
|
8114
|
+
[NO_LATEST]: "source"
|
|
8115
|
+
};
|
|
7370
8116
|
/** The codes of `errors` that the Runtime already declares, which a CLI cannot redeclare. */
|
|
7371
8117
|
function runtimeCodesIn(errors) {
|
|
7372
|
-
return Object.keys(errors).filter((code) => Object.hasOwn(
|
|
8118
|
+
return Object.keys(errors).filter((code) => Object.hasOwn(RUNTIME_EXIT_CLASSES, code));
|
|
7373
8119
|
}
|
|
7374
8120
|
function exitClassOfOne(error, errors) {
|
|
7375
8121
|
if (!(error instanceof CliError)) return "bug";
|
|
7376
8122
|
if (error instanceof UsageError) return "caller";
|
|
7377
|
-
return
|
|
8123
|
+
return RUNTIME_EXIT_CLASSES[error.code] ?? errors[error.code]?.class ?? "bug";
|
|
7378
8124
|
}
|
|
7379
8125
|
function isBug(error, errors) {
|
|
7380
8126
|
return exitClassOfOne(error, errors) === "bug";
|
|
@@ -7418,6 +8164,50 @@ function exitCodeOf(error, errors, stop) {
|
|
|
7418
8164
|
return exitClass === "interrupted" ? SIGNAL_EXIT_CODES[stopSignalOf(stop?.reason)] : EXIT_CODES[exitClass];
|
|
7419
8165
|
}
|
|
7420
8166
|
//#endregion
|
|
8167
|
+
//#region ../agent-cli/dist/agent-cli.js
|
|
8168
|
+
function checkOwnCodes(cli) {
|
|
8169
|
+
const redeclared = runtimeCodesIn(cli.errors ?? {});
|
|
8170
|
+
if (redeclared.length > 0) throw new Error(`${cli.name} declares ${redeclared.join(", ")}, an error code the Runtime already declares`);
|
|
8171
|
+
}
|
|
8172
|
+
function defineCli$1(cli) {
|
|
8173
|
+
checkOwnCodes(cli);
|
|
8174
|
+
if (cli.commands === void 0) return cli;
|
|
8175
|
+
const { commands } = cli;
|
|
8176
|
+
const taken = Object.keys(builtInCommands(cli, {
|
|
8177
|
+
bin: void 0,
|
|
8178
|
+
node: void 0
|
|
8179
|
+
})).filter((name) => commands[name] !== void 0);
|
|
8180
|
+
if (taken.length > 0) throw new Error(`${cli.name} defines ${taken.join(", ")}, a built-in Command it cannot replace`);
|
|
8181
|
+
return cli;
|
|
8182
|
+
}
|
|
8183
|
+
/**
|
|
8184
|
+
* Declares the CLI's ports and its Project file's settings once; the `defineCommand` and
|
|
8185
|
+
* `defineCli` it returns type `ctx.ports` and `ctx.project`.
|
|
8186
|
+
*/
|
|
8187
|
+
function agentCli() {
|
|
8188
|
+
return {
|
|
8189
|
+
defineCommand: defineCommandFor(),
|
|
8190
|
+
defineCli: defineCli$1
|
|
8191
|
+
};
|
|
8192
|
+
}
|
|
8193
|
+
//#endregion
|
|
8194
|
+
//#region ../agent-cli/dist/error-table.js
|
|
8195
|
+
/** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
|
|
8196
|
+
function defineErrors(table) {
|
|
8197
|
+
return table;
|
|
8198
|
+
}
|
|
8199
|
+
/**
|
|
8200
|
+
* A `CliError` for a code of `table`, whose `details` must match the code's schema. The `hint`
|
|
8201
|
+
* names the next command to run and says whether running it again can help; `retryAt` (ISO 8601)
|
|
8202
|
+
* is allowed only on a wait-class code.
|
|
8203
|
+
*/
|
|
8204
|
+
function cliError(_table, code, init, options) {
|
|
8205
|
+
return new CliError({
|
|
8206
|
+
...init,
|
|
8207
|
+
code
|
|
8208
|
+
}, options);
|
|
8209
|
+
}
|
|
8210
|
+
//#endregion
|
|
7421
8211
|
//#region ../agent-cli/dist/command-spec.js
|
|
7422
8212
|
/** The group's Commands and groups that help and suggestions may name: hidden Commands left out. */
|
|
7423
8213
|
function visibleCommands({ commands }) {
|
|
@@ -7435,12 +8225,18 @@ function declaredOf(command) {
|
|
|
7435
8225
|
cost: command.cost !== void 0
|
|
7436
8226
|
};
|
|
7437
8227
|
}
|
|
7438
|
-
|
|
8228
|
+
const SINGLE_COMMAND = {
|
|
8229
|
+
path: [],
|
|
8230
|
+
builtIn: false
|
|
8231
|
+
};
|
|
8232
|
+
function commandSpec(commandLine, command, { path, builtIn } = SINGLE_COMMAND) {
|
|
7439
8233
|
const list = command.rows === void 0 ? void 0 : listSpec(command.rows);
|
|
7440
8234
|
return {
|
|
7441
8235
|
kind: "command",
|
|
7442
8236
|
commandLine,
|
|
8237
|
+
path,
|
|
7443
8238
|
command,
|
|
8239
|
+
builtIn,
|
|
7444
8240
|
description: command.description,
|
|
7445
8241
|
help: command.help,
|
|
7446
8242
|
hidden: command.hidden === true,
|
|
@@ -7454,15 +8250,34 @@ function commandSpec(commandLine, command) {
|
|
|
7454
8250
|
output: list?.output ?? command.output
|
|
7455
8251
|
};
|
|
7456
8252
|
}
|
|
7457
|
-
function
|
|
8253
|
+
function group(commandLine, commands) {
|
|
7458
8254
|
return {
|
|
7459
8255
|
kind: "group",
|
|
7460
8256
|
commandLine,
|
|
7461
|
-
commands
|
|
8257
|
+
commands
|
|
7462
8258
|
};
|
|
7463
8259
|
}
|
|
7464
|
-
|
|
7465
|
-
|
|
8260
|
+
/** The root group of a multi-Command CLI: the author's Commands, then the Built-in Commands. */
|
|
8261
|
+
function groupSpec(commandLine, commands, builtIns) {
|
|
8262
|
+
return group(commandLine, {
|
|
8263
|
+
...specsOf(commandLine, commands, {
|
|
8264
|
+
path: [],
|
|
8265
|
+
builtIn: false
|
|
8266
|
+
}),
|
|
8267
|
+
...specsOf(commandLine, builtIns, {
|
|
8268
|
+
path: [],
|
|
8269
|
+
builtIn: true
|
|
8270
|
+
})
|
|
8271
|
+
});
|
|
8272
|
+
}
|
|
8273
|
+
function specsOf(commandLine, commands, { path, builtIn }) {
|
|
8274
|
+
return Object.fromEntries(Object.entries(commands).map(([key, node]) => [key, specOf(`${commandLine} ${key}`, node, {
|
|
8275
|
+
path: [...path, key],
|
|
8276
|
+
builtIn
|
|
8277
|
+
})]));
|
|
8278
|
+
}
|
|
8279
|
+
function specOf(commandLine, node, place) {
|
|
8280
|
+
return isCommand(node) ? commandSpec(commandLine, node, place) : group(commandLine, specsOf(commandLine, node, place));
|
|
7466
8281
|
}
|
|
7467
8282
|
//#endregion
|
|
7468
8283
|
//#region ../agent-cli/dist/help.js
|
|
@@ -7487,9 +8302,10 @@ function commandRows(group) {
|
|
|
7487
8302
|
function lines(...parts) {
|
|
7488
8303
|
return `${parts.join("\n")}\n`;
|
|
7489
8304
|
}
|
|
7490
|
-
function listingLines(heading, group, style) {
|
|
8305
|
+
function listingLines(heading, group, style, description) {
|
|
7491
8306
|
return [
|
|
7492
8307
|
style.bold(heading),
|
|
8308
|
+
...description === void 0 ? [] : [description],
|
|
7493
8309
|
...section("Commands", commandRows(group), style),
|
|
7494
8310
|
"",
|
|
7495
8311
|
`Run \`${group.commandLine} <command> --help\` for its examples and input.`
|
|
@@ -7522,753 +8338,350 @@ function examplesSection(examples, style) {
|
|
|
7522
8338
|
}
|
|
7523
8339
|
/** The CLI's own help: a listing or its single Command's help, ending with exit codes and examples. */
|
|
7524
8340
|
function cliHelp(cli, root, style) {
|
|
7525
|
-
return lines(...root.kind === "command" ? commandLines(root, style, { examples: false }) : listingLines(`${root.commandLine} ${cli.version}`, root, style), ...section("Exit codes", exitCodeRows(cli), style), ...examplesSection(rootExamples(root), style));
|
|
8341
|
+
return lines(...root.kind === "command" ? commandLines(root, style, { examples: false }) : listingLines(`${root.commandLine} ${cli.version}`, root, style, cli.description), ...section("Exit codes", exitCodeRows(cli), style), ...examplesSection(rootExamples(root), style));
|
|
7526
8342
|
}
|
|
7527
8343
|
function groupHelp(group, style) {
|
|
7528
8344
|
return lines(...listingLines(group.commandLine, group, style));
|
|
7529
8345
|
}
|
|
7530
|
-
const EFFECT_NOTES = {
|
|
7531
|
-
read: "changes nothing",
|
|
7532
|
-
write: "changes something; show the Plan with --dry-run",
|
|
7533
|
-
destructive: "changes something hard to undo; show the Plan with --dry-run, run with --confirm",
|
|
7534
|
-
serve: "changes nothing; prints its data at once, then runs until Ctrl-C, which exits 0"
|
|
7535
|
-
};
|
|
7536
|
-
const OPERATOR_NOTE = "only a person at a terminal runs it; a Coding agent asks the operator to type it after `!`";
|
|
7537
|
-
function choicesOf(field) {
|
|
7538
|
-
return field.choices === void 0 ? [] : [`one of: ${field.choices.join(", ")}`];
|
|
7539
|
-
}
|
|
7540
|
-
function defaultsOf(field) {
|
|
7541
|
-
if (field.defaultValue === void 0) return [];
|
|
7542
|
-
if (field.type !== "boolean") return [`default: ${JSON.stringify(field.defaultValue)}`];
|
|
7543
|
-
return field.defaultValue === true ? ["on by default; this flag turns it off"] : [];
|
|
7544
|
-
}
|
|
7545
|
-
function fieldRow(field, notes) {
|
|
7546
|
-
const all = [...field.required ? ["required"] : [], ...notes];
|
|
7547
|
-
const suffix = all.length === 0 ? "" : `(${all.join("; ")})`;
|
|
7548
|
-
return [field.usage, [field.description ?? "", suffix].filter((part) => part !== "").join(" ")];
|
|
7549
|
-
}
|
|
7550
|
-
function argRow(field) {
|
|
7551
|
-
return fieldRow(field, [...choicesOf(field), ...defaultsOf(field)]);
|
|
7552
|
-
}
|
|
7553
|
-
function optionRow(field) {
|
|
7554
|
-
return fieldRow(field, defaultsOf(field));
|
|
7555
|
-
}
|
|
7556
|
-
function flagRow({ usage, description }) {
|
|
7557
|
-
return [usage, description];
|
|
7558
|
-
}
|
|
7559
|
-
function commandLines(spec, style, { examples }) {
|
|
7560
|
-
return [
|
|
7561
|
-
style.bold(spec.commandLine),
|
|
7562
|
-
spec.description,
|
|
7563
|
-
...examples ? examplesSection(spec.examples, style) : [],
|
|
7564
|
-
...section("Arguments", spec.args.map(argRow), style),
|
|
7565
|
-
...section("Options", spec.options.map(optionRow), style),
|
|
7566
|
-
...spec.help === void 0 ? [] : ["", spec.help],
|
|
7567
|
-
"",
|
|
7568
|
-
`${style.bold("Effect:")} ${spec.effect} (${EFFECT_NOTES[spec.effect]})`,
|
|
7569
|
-
...spec.operator ? [`${style.bold("Operator Command:")} ${OPERATOR_NOTE}`] : [],
|
|
7570
|
-
...section("Standard flags", spec.standardFlags.map(flagRow), style)
|
|
7571
|
-
];
|
|
7572
|
-
}
|
|
7573
|
-
function commandHelp(spec, style) {
|
|
7574
|
-
return lines(...commandLines(spec, style, { examples: true }));
|
|
7575
|
-
}
|
|
7576
|
-
//#endregion
|
|
7577
|
-
//#region ../agent-cli/dist/help-json.js
|
|
7578
|
-
function inputSchema(schema) {
|
|
7579
|
-
return toJSONSchema(schema, {
|
|
7580
|
-
io: "input",
|
|
7581
|
-
unrepresentable: "any"
|
|
7582
|
-
});
|
|
7583
|
-
}
|
|
7584
|
-
function optionsSchema(options) {
|
|
7585
|
-
return inputSchema(object(Object.fromEntries(options.map(({ name, schema }) => [name, schema]))));
|
|
7586
|
-
}
|
|
7587
|
-
function commandData(spec) {
|
|
7588
|
-
return {
|
|
7589
|
-
name: spec.commandLine,
|
|
7590
|
-
description: spec.description,
|
|
7591
|
-
help: spec.help ?? null,
|
|
7592
|
-
effect: spec.effect,
|
|
7593
|
-
operator: spec.operator,
|
|
7594
|
-
examples: spec.examples,
|
|
7595
|
-
args: inputSchema(spec.command.args ?? object({})),
|
|
7596
|
-
options: optionsSchema(spec.options),
|
|
7597
|
-
standardFlags: spec.standardFlags.map(({ usage, description, schema }) => ({
|
|
7598
|
-
usage,
|
|
7599
|
-
description,
|
|
7600
|
-
schema: inputSchema(schema)
|
|
7601
|
-
})),
|
|
7602
|
-
output: spec.output === void 0 ? null : toJSONSchema(spec.output, { unrepresentable: "any" })
|
|
7603
|
-
};
|
|
7604
|
-
}
|
|
7605
|
-
function nodeData(node) {
|
|
7606
|
-
return node.kind === "command" ? commandData(node) : groupData(node);
|
|
7607
|
-
}
|
|
7608
|
-
function groupData(group) {
|
|
7609
|
-
return {
|
|
7610
|
-
name: group.commandLine,
|
|
7611
|
-
commands: Object.values(visibleCommands(group)).map(nodeData)
|
|
7612
|
-
};
|
|
7613
|
-
}
|
|
7614
|
-
function printed$1(data) {
|
|
7615
|
-
return `${JSON.stringify(data)}\n`;
|
|
7616
|
-
}
|
|
7617
|
-
function errorsData(errors) {
|
|
7618
|
-
return Object.fromEntries(Object.entries(errors).map(([code, declaration]) => [code, {
|
|
7619
|
-
class: declaration.class,
|
|
7620
|
-
details: declaration.details === void 0 ? null : toJSONSchema(declaration.details, { unrepresentable: "any" })
|
|
7621
|
-
}]));
|
|
7622
|
-
}
|
|
7623
|
-
function cliHelpJson({ version, errors }, root) {
|
|
7624
|
-
return printed$1({
|
|
7625
|
-
name: root.commandLine,
|
|
7626
|
-
version,
|
|
7627
|
-
...nodeData(root),
|
|
7628
|
-
errors: errorsData(errors ?? {})
|
|
7629
|
-
});
|
|
7630
|
-
}
|
|
7631
|
-
function groupHelpJson(group) {
|
|
7632
|
-
return printed$1(groupData(group));
|
|
7633
|
-
}
|
|
7634
|
-
function commandHelpJson(spec) {
|
|
7635
|
-
return printed$1(commandData(spec));
|
|
7636
|
-
}
|
|
7637
|
-
//#endregion
|
|
7638
|
-
//#region ../agent-cli/dist/output.js
|
|
7639
|
-
const SUCCESS_EXIT_CODE = 0;
|
|
7640
|
-
function withTrailingNewline(text) {
|
|
7641
|
-
return text === "" || text.endsWith("\n") ? text : `${text}\n`;
|
|
7642
|
-
}
|
|
7643
|
-
function printed(value, render, { json, invocation, style, fields }) {
|
|
7644
|
-
if (!(value instanceof Page)) return json ? `${JSON.stringify(value)}\n` : withTrailingNewline(render(style));
|
|
7645
|
-
const page = printedPage(value, invocation);
|
|
7646
|
-
if (fields === void 0) return json ? `${JSON.stringify(page)}\n` : `${withTrailingNewline(render(style))}${pageFooter(page)}`;
|
|
7647
|
-
const rows = projected(page.items, fields);
|
|
7648
|
-
return json ? `${JSON.stringify({
|
|
7649
|
-
...page,
|
|
7650
|
-
items: rows
|
|
7651
|
-
})}\n` : `${renderRows(rows, fields)}${pageFooter(page)}`;
|
|
7652
|
-
}
|
|
7653
|
-
/** A progress message as stderr carries it: one JSON object per line under `--json` (ADR 0006). */
|
|
7654
|
-
function progressLine(message, json) {
|
|
7655
|
-
return json ? `${JSON.stringify({ progress: message })}\n` : `${message}\n`;
|
|
7656
|
-
}
|
|
7657
|
-
function errorText(error, format) {
|
|
7658
|
-
const text = formatRuntimeError(error, {
|
|
7659
|
-
...format,
|
|
7660
|
-
isBug: (each) => isBug(each, format.errors)
|
|
7661
|
-
});
|
|
7662
|
-
const { usageHelp, json } = format;
|
|
7663
|
-
return usageHelp !== void 0 && !json && error instanceof UsageError ? `${text}\n${usageHelp}` : text;
|
|
7664
|
-
}
|
|
7665
|
-
function stdoutOf({ value, render }, format, spill) {
|
|
7666
|
-
const text = printed(value, render, format);
|
|
7667
|
-
return value instanceof Page ? text : spill(text, format.json);
|
|
7668
|
-
}
|
|
7669
|
-
/** What a serve Command prints the moment it starts. */
|
|
7670
|
-
function startedOutput(outcome, format, spill) {
|
|
7671
|
-
return stdoutOf(outcome, {
|
|
7672
|
-
...format,
|
|
7673
|
-
fields: void 0
|
|
7674
|
-
}, spill);
|
|
7675
|
-
}
|
|
7676
|
-
/** A serve Command stopped after it started: stopping it is how it is meant to end. */
|
|
7677
|
-
const STOPPED_RESULT = {
|
|
7678
|
-
stdout: "",
|
|
7679
|
-
stderr: "",
|
|
7680
|
-
exitCode: SUCCESS_EXIT_CODE
|
|
7681
|
-
};
|
|
7682
|
-
function errorResult(error, format) {
|
|
7683
|
-
return {
|
|
7684
|
-
stdout: "",
|
|
7685
|
-
stderr: errorText(error, format),
|
|
7686
|
-
exitCode: exitCodeOf(error, format.errors, format.stop)
|
|
7687
|
-
};
|
|
7688
|
-
}
|
|
7689
|
-
async function commandResult(settled, format, spill) {
|
|
7690
|
-
if (settled.ok) try {
|
|
7691
|
-
return {
|
|
7692
|
-
stdout: await stdoutOf(settled.outcome, format, spill),
|
|
7693
|
-
stderr: "",
|
|
7694
|
-
exitCode: SUCCESS_EXIT_CODE
|
|
7695
|
-
};
|
|
7696
|
-
} catch (spillError) {
|
|
7697
|
-
return errorResult(spillError, format);
|
|
7698
|
-
}
|
|
7699
|
-
const { error, delivered } = settled;
|
|
7700
|
-
const result = errorResult(error, format);
|
|
7701
|
-
if (delivered === void 0) return result;
|
|
7702
|
-
try {
|
|
7703
|
-
return {
|
|
7704
|
-
...result,
|
|
7705
|
-
stdout: await stdoutOf(delivered, format, spill)
|
|
7706
|
-
};
|
|
7707
|
-
} catch (spillError) {
|
|
7708
|
-
const both = new AggregateError([...errorsOf(error), spillError]);
|
|
7709
|
-
return {
|
|
7710
|
-
...result,
|
|
7711
|
-
stderr: errorText(both, format)
|
|
7712
|
-
};
|
|
7713
|
-
}
|
|
7714
|
-
}
|
|
7715
|
-
function textHelp(node, root, cli, style) {
|
|
7716
|
-
if (node === root) return cliHelp(cli, node, style);
|
|
7717
|
-
return node.kind === "command" ? commandHelp(node, style) : groupHelp(node, style);
|
|
7718
|
-
}
|
|
7719
|
-
function helpOf(node, root, cli, style, json) {
|
|
7720
|
-
if (!json) return textHelp(node, root, cli, style);
|
|
7721
|
-
if (node === root) return cliHelpJson(cli, node);
|
|
7722
|
-
return node.kind === "command" ? commandHelpJson(node) : groupHelpJson(node);
|
|
7723
|
-
}
|
|
7724
|
-
function helpResult(node, root, cli, { style, json }) {
|
|
7725
|
-
return {
|
|
7726
|
-
stdout: helpOf(node, root, cli, style, json),
|
|
7727
|
-
stderr: "",
|
|
7728
|
-
exitCode: SUCCESS_EXIT_CODE
|
|
7729
|
-
};
|
|
8346
|
+
const EFFECT_NOTES = {
|
|
8347
|
+
read: "changes nothing",
|
|
8348
|
+
write: "changes something; show the Plan with --dry-run",
|
|
8349
|
+
destructive: "changes something hard to undo; show the Plan with --dry-run, run with --confirm",
|
|
8350
|
+
serve: "changes nothing; prints its data at once, then runs until Ctrl-C, which exits 0"
|
|
8351
|
+
};
|
|
8352
|
+
const OPERATOR_NOTE = "only a person at a terminal runs it; a Coding agent asks the operator to type it after `!`";
|
|
8353
|
+
function choicesOf(field) {
|
|
8354
|
+
return field.choices === void 0 ? [] : [`one of: ${field.choices.join(", ")}`];
|
|
7730
8355
|
}
|
|
7731
|
-
|
|
7732
|
-
|
|
7733
|
-
|
|
8356
|
+
function defaultsOf(field) {
|
|
8357
|
+
if (field.defaultValue === void 0) return [];
|
|
8358
|
+
if (field.type !== "boolean") return [`default: ${JSON.stringify(field.defaultValue)}`];
|
|
8359
|
+
return field.defaultValue === true ? ["on by default; this flag turns it off"] : [];
|
|
7734
8360
|
}
|
|
7735
|
-
function
|
|
7736
|
-
|
|
7737
|
-
|
|
7738
|
-
|
|
7739
|
-
exitCode: SUCCESS_EXIT_CODE
|
|
7740
|
-
};
|
|
8361
|
+
function fieldRow(field, notes) {
|
|
8362
|
+
const all = [...field.required ? ["required"] : [], ...notes];
|
|
8363
|
+
const suffix = all.length === 0 ? "" : `(${all.join("; ")})`;
|
|
8364
|
+
return [field.usage, [field.description ?? "", suffix].filter((part) => part !== "").join(" ")];
|
|
7741
8365
|
}
|
|
7742
|
-
|
|
7743
|
-
|
|
7744
|
-
/** The branch a release moves to the released commit, which holds the skill of that version. */
|
|
7745
|
-
const RELEASE_BRANCH = "release";
|
|
7746
|
-
const GITHUB_SHORTHAND = /^[\w.-]+\/[\w.-]+$/;
|
|
7747
|
-
const GIT_URL_PROTOCOLS = /* @__PURE__ */ new Set([
|
|
7748
|
-
"https:",
|
|
7749
|
-
"http:",
|
|
7750
|
-
"ssh:",
|
|
7751
|
-
"git:"
|
|
7752
|
-
]);
|
|
7753
|
-
const SCP_STYLE = /^[\w.-]+@[\w.-]+:[\w./-]+$/;
|
|
7754
|
-
const manifestSchema = object({ repository: union([string(), object({ url: string() })]).optional() });
|
|
7755
|
-
function sourceFromRepository(repository) {
|
|
7756
|
-
if (GITHUB_SHORTHAND.test(repository)) return repository;
|
|
7757
|
-
const url = repository.replace(/^git\+/, "");
|
|
7758
|
-
if (!(URL.canParse(url) && GIT_URL_PROTOCOLS.has(new URL(url).protocol)) && !SCP_STYLE.test(url)) return void 0;
|
|
7759
|
-
return `${url.endsWith(".git") ? url : `${url}.git`}#${RELEASE_BRANCH}`;
|
|
8366
|
+
function argRow(field) {
|
|
8367
|
+
return fieldRow(field, [...choicesOf(field), ...defaultsOf(field)]);
|
|
7760
8368
|
}
|
|
7761
|
-
|
|
7762
|
-
|
|
7763
|
-
try {
|
|
7764
|
-
manifest = JSON.parse(await readFile(join(packageRoot, "package.json"), "utf8"));
|
|
7765
|
-
} catch {
|
|
7766
|
-
return;
|
|
7767
|
-
}
|
|
7768
|
-
const parsed = manifestSchema.safeParse(manifest);
|
|
7769
|
-
const repository = parsed.success ? parsed.data.repository : void 0;
|
|
7770
|
-
return typeof repository === "object" ? repository.url : repository;
|
|
8369
|
+
function optionRow(field) {
|
|
8370
|
+
return fieldRow(field, defaultsOf(field));
|
|
7771
8371
|
}
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
if (declared !== void 0) return declared.source;
|
|
7775
|
-
const repository = await repositoryAt(packageRoot);
|
|
7776
|
-
return repository === void 0 ? void 0 : sourceFromRepository(repository);
|
|
8372
|
+
function flagRow({ usage, description }) {
|
|
8373
|
+
return [usage, description];
|
|
7777
8374
|
}
|
|
7778
|
-
|
|
7779
|
-
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
7783
|
-
|
|
8375
|
+
function commandLines(spec, style, { examples }) {
|
|
8376
|
+
return [
|
|
8377
|
+
style.bold(spec.commandLine),
|
|
8378
|
+
spec.description,
|
|
8379
|
+
...examples ? examplesSection(spec.examples, style) : [],
|
|
8380
|
+
...section("Arguments", spec.args.map(argRow), style),
|
|
8381
|
+
...section("Options", spec.options.map(optionRow), style),
|
|
8382
|
+
...spec.help === void 0 ? [] : ["", spec.help],
|
|
8383
|
+
"",
|
|
8384
|
+
`${style.bold("Effect:")} ${spec.effect} (${EFFECT_NOTES[spec.effect]})`,
|
|
8385
|
+
...spec.operator ? [`${style.bold("Operator Command:")} ${OPERATOR_NOTE}`] : [],
|
|
8386
|
+
...section("Standard flags", spec.standardFlags.map(flagRow), style)
|
|
8387
|
+
];
|
|
7784
8388
|
}
|
|
7785
|
-
function
|
|
7786
|
-
return
|
|
8389
|
+
function commandHelp(spec, style) {
|
|
8390
|
+
return lines(...commandLines(spec, style, { examples: true }));
|
|
7787
8391
|
}
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
|
|
8392
|
+
//#endregion
|
|
8393
|
+
//#region ../agent-cli/dist/help-json.js
|
|
8394
|
+
function inputSchema(schema) {
|
|
8395
|
+
return toJSONSchema(schema, {
|
|
8396
|
+
io: "input",
|
|
8397
|
+
unrepresentable: "any"
|
|
8398
|
+
});
|
|
7794
8399
|
}
|
|
7795
|
-
function
|
|
7796
|
-
return
|
|
8400
|
+
function optionsSchema(options) {
|
|
8401
|
+
return inputSchema(object(Object.fromEntries(options.map(({ name, schema }) => [name, schema]))));
|
|
7797
8402
|
}
|
|
7798
|
-
|
|
7799
|
-
let skill;
|
|
7800
|
-
try {
|
|
7801
|
-
skill = await readFile(join(path, "SKILL.md"), "utf8");
|
|
7802
|
-
} catch (error) {
|
|
7803
|
-
if (isMissingFile(error)) return;
|
|
7804
|
-
return {
|
|
7805
|
-
path,
|
|
7806
|
-
version: void 0,
|
|
7807
|
-
state: "unreadable"
|
|
7808
|
-
};
|
|
7809
|
-
}
|
|
7810
|
-
const version = skillVersionIn(skill);
|
|
7811
|
-
if (version === void 0 || !isVersion(version) || !isVersion(cliVersion)) return {
|
|
7812
|
-
path,
|
|
7813
|
-
version,
|
|
7814
|
-
state: "unversioned"
|
|
7815
|
-
};
|
|
8403
|
+
function commandData(spec) {
|
|
7816
8404
|
return {
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
8405
|
+
name: spec.commandLine,
|
|
8406
|
+
description: spec.description,
|
|
8407
|
+
help: spec.help ?? null,
|
|
8408
|
+
effect: spec.effect,
|
|
8409
|
+
operator: spec.operator,
|
|
8410
|
+
examples: spec.examples,
|
|
8411
|
+
args: inputSchema(spec.command.args ?? object({})),
|
|
8412
|
+
options: optionsSchema(spec.options),
|
|
8413
|
+
standardFlags: spec.standardFlags.map(({ usage, description, schema }) => ({
|
|
8414
|
+
usage,
|
|
8415
|
+
description,
|
|
8416
|
+
schema: inputSchema(schema)
|
|
8417
|
+
})),
|
|
8418
|
+
output: spec.output === void 0 ? null : toJSONSchema(spec.output, { unrepresentable: "any" })
|
|
7820
8419
|
};
|
|
7821
8420
|
}
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
const paths = [cwd, homeOf(env)].flatMap((root) => SKILL_DIRS.map((dir) => join(root, ...dir, skillName)));
|
|
7825
|
-
const seen = /* @__PURE__ */ new Set();
|
|
7826
|
-
const copies = [];
|
|
7827
|
-
for (const path of paths) {
|
|
7828
|
-
const copy = await copyAt(path, cliVersion);
|
|
7829
|
-
const real = copy === void 0 ? void 0 : await realpath(path);
|
|
7830
|
-
if (copy !== void 0 && real !== void 0 && !seen.has(real)) {
|
|
7831
|
-
seen.add(real);
|
|
7832
|
-
copies.push(copy);
|
|
7833
|
-
}
|
|
7834
|
-
}
|
|
7835
|
-
return copies;
|
|
8421
|
+
function nodeData(node) {
|
|
8422
|
+
return node.kind === "command" ? commandData(node) : groupData(node);
|
|
7836
8423
|
}
|
|
7837
|
-
|
|
7838
|
-
//#region ../agent-cli/dist/doctor-rows.js
|
|
7839
|
-
function ok(message) {
|
|
8424
|
+
function groupData(group) {
|
|
7840
8425
|
return {
|
|
7841
|
-
|
|
7842
|
-
|
|
8426
|
+
name: group.commandLine,
|
|
8427
|
+
commands: Object.values(visibleCommands(group)).map(nodeData)
|
|
7843
8428
|
};
|
|
7844
8429
|
}
|
|
7845
|
-
function
|
|
7846
|
-
return {
|
|
7847
|
-
name: "build",
|
|
7848
|
-
run: () => ok(versionLine(cli))
|
|
7849
|
-
};
|
|
8430
|
+
function printed$1(data) {
|
|
8431
|
+
return `${JSON.stringify(data)}\n`;
|
|
7850
8432
|
}
|
|
7851
|
-
function
|
|
7852
|
-
return {
|
|
7853
|
-
|
|
7854
|
-
|
|
7855
|
-
|
|
7856
|
-
const range = cli.engines?.node;
|
|
7857
|
-
if (range === void 0) return ok(`Node ${found}; ${cli.name} declares no engines.node to check it against`);
|
|
7858
|
-
const minimum = engineMinimum(range);
|
|
7859
|
-
if (minimum === void 0) return {
|
|
7860
|
-
state: "problem",
|
|
7861
|
-
message: `${cli.name} declares engines.node "${range}", which doctor cannot read: only >=X.Y.Z is supported`
|
|
7862
|
-
};
|
|
7863
|
-
if (meetsMinimum(found, minimum)) return ok(`Node ${found} meets ${range}`);
|
|
7864
|
-
const major = minimum[0];
|
|
7865
|
-
return {
|
|
7866
|
-
state: "problem",
|
|
7867
|
-
message: `${cli.name} runs on Node ${found}, older than the ${range} it needs; install Node ${minimum.join(".")} or newer and make it the default`,
|
|
7868
|
-
fix: `nvm install ${major} && nvm alias default ${major}`
|
|
7869
|
-
};
|
|
7870
|
-
}
|
|
7871
|
-
};
|
|
8433
|
+
function errorsData(errors) {
|
|
8434
|
+
return Object.fromEntries(Object.entries(errors).map(([code, declaration]) => [code, {
|
|
8435
|
+
class: declaration.class,
|
|
8436
|
+
details: declaration.details === void 0 ? null : toJSONSchema(declaration.details, { unrepresentable: "any" })
|
|
8437
|
+
}]));
|
|
7872
8438
|
}
|
|
7873
|
-
function
|
|
7874
|
-
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
} catch (error) {
|
|
7882
|
-
if (error instanceof CliError && error.code === "PROJECT_INVALID") return {
|
|
7883
|
-
state: "problem",
|
|
7884
|
-
message: error.message
|
|
7885
|
-
};
|
|
7886
|
-
throw error;
|
|
7887
|
-
}
|
|
7888
|
-
return ok(project === void 0 ? `none found: no ${file} at or above ${ctx.cwd}` : join(project.root, file));
|
|
7889
|
-
}
|
|
7890
|
-
};
|
|
8439
|
+
function cliHelpJson({ version, description, errors }, root) {
|
|
8440
|
+
return printed$1({
|
|
8441
|
+
name: root.commandLine,
|
|
8442
|
+
version,
|
|
8443
|
+
description,
|
|
8444
|
+
...nodeData(root),
|
|
8445
|
+
errors: errorsData(errors ?? {})
|
|
8446
|
+
});
|
|
7891
8447
|
}
|
|
7892
|
-
function
|
|
7893
|
-
return
|
|
7894
|
-
name: "install",
|
|
7895
|
-
advisory: true,
|
|
7896
|
-
run: async (ctx) => {
|
|
7897
|
-
const { install } = cli;
|
|
7898
|
-
if (install === void 0) return ok(`${cli.name} declares no install, so it has no \`update\``);
|
|
7899
|
-
try {
|
|
7900
|
-
return ok(`a global npm install under ${(await globalInstallOf(bin, npmContext(cli, install, ctx, node))).prefix}`);
|
|
7901
|
-
} catch (error) {
|
|
7902
|
-
if (error instanceof CliError && error.code === "NOT_GLOBAL_INSTALL") return {
|
|
7903
|
-
state: "problem",
|
|
7904
|
-
message: error.message,
|
|
7905
|
-
fix: installCommandLine(install)
|
|
7906
|
-
};
|
|
7907
|
-
throw error;
|
|
7908
|
-
}
|
|
7909
|
-
}
|
|
7910
|
-
};
|
|
8448
|
+
function groupHelpJson(group) {
|
|
8449
|
+
return printed$1(groupData(group));
|
|
7911
8450
|
}
|
|
7912
|
-
function
|
|
7913
|
-
return
|
|
7914
|
-
name: "registry",
|
|
7915
|
-
advisory: true,
|
|
7916
|
-
run: async (ctx) => {
|
|
7917
|
-
const { install } = cli;
|
|
7918
|
-
if (install === void 0) return ok(`${cli.name} declares no registry to compare this build with`);
|
|
7919
|
-
const latest = await latestVersion(npmContext(cli, install, ctx, node));
|
|
7920
|
-
const standing = standingOf(cli.version, latest);
|
|
7921
|
-
const head = `${install.registry} has ${latest} as latest: this build`;
|
|
7922
|
-
if (standing === "behind") return {
|
|
7923
|
-
state: "problem",
|
|
7924
|
-
message: `${head} (${cli.version}) is older`,
|
|
7925
|
-
fix: `${cli.name} update`
|
|
7926
|
-
};
|
|
7927
|
-
return ok(`${head} is ${standing === "current" ? "current" : `newer (${cli.version})`}`);
|
|
7928
|
-
}
|
|
7929
|
-
};
|
|
8451
|
+
function commandHelpJson(spec) {
|
|
8452
|
+
return printed$1(commandData(spec));
|
|
7930
8453
|
}
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
7936
|
-
|
|
7937
|
-
}
|
|
7938
|
-
|
|
7939
|
-
|
|
8454
|
+
//#endregion
|
|
8455
|
+
//#region ../agent-cli/dist/output.js
|
|
8456
|
+
const SUCCESS_EXIT_CODE = 0;
|
|
8457
|
+
function withTrailingNewline(text) {
|
|
8458
|
+
return text === "" || text.endsWith("\n") ? text : `${text}\n`;
|
|
8459
|
+
}
|
|
8460
|
+
function printed(value, render, { json, invocation, style, fields }) {
|
|
8461
|
+
if (!(value instanceof Page)) return json ? `${JSON.stringify(value)}\n` : withTrailingNewline(render(style));
|
|
8462
|
+
const page = printedPage(value, invocation);
|
|
8463
|
+
if (fields === void 0) return json ? `${JSON.stringify(page)}\n` : `${withTrailingNewline(render(style))}${pageFooter(page)}`;
|
|
8464
|
+
const rows = projected(page.items, fields);
|
|
8465
|
+
return json ? `${JSON.stringify({
|
|
8466
|
+
...page,
|
|
8467
|
+
items: rows
|
|
8468
|
+
})}\n` : `${renderRows(rows, fields)}${pageFooter(page)}`;
|
|
7940
8469
|
}
|
|
7941
|
-
|
|
7942
|
-
|
|
7943
|
-
return
|
|
8470
|
+
/** A progress message as stderr carries it: one JSON object per line under `--json` (ADR 0006). */
|
|
8471
|
+
function progressLine(message, json) {
|
|
8472
|
+
return json ? `${JSON.stringify({ progress: message })}\n` : `${message}\n`;
|
|
7944
8473
|
}
|
|
7945
|
-
function
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
|
|
7952
|
-
const source = await skillSource(cli.skill, ctx.packageRoot);
|
|
7953
|
-
return source === void 0 ? ok(message) : {
|
|
7954
|
-
state: "ok",
|
|
7955
|
-
message,
|
|
7956
|
-
fix: skillAddCommand(source, cli.name)
|
|
7957
|
-
};
|
|
7958
|
-
}
|
|
7959
|
-
const fix = skillFix(cli, copies);
|
|
7960
|
-
const message = copies.map(describeCopy).join("; ");
|
|
7961
|
-
return fix === void 0 ? ok(message) : {
|
|
7962
|
-
state: "ok",
|
|
7963
|
-
message,
|
|
7964
|
-
fix
|
|
7965
|
-
};
|
|
7966
|
-
}
|
|
7967
|
-
};
|
|
8474
|
+
function errorText(error, format) {
|
|
8475
|
+
const text = formatRuntimeError(error, {
|
|
8476
|
+
...format,
|
|
8477
|
+
isBug: (each) => isBug(each, format.errors)
|
|
8478
|
+
});
|
|
8479
|
+
const { usageHelp, json } = format;
|
|
8480
|
+
return usageHelp !== void 0 && !json && error instanceof UsageError ? `${text}\n${usageHelp}` : text;
|
|
7968
8481
|
}
|
|
7969
|
-
|
|
7970
|
-
|
|
7971
|
-
return
|
|
7972
|
-
buildRow(cli),
|
|
7973
|
-
nodeRow(cli),
|
|
7974
|
-
...cli.project === void 0 ? [] : [projectRow(cli.project)],
|
|
7975
|
-
...cli.doctor ?? [],
|
|
7976
|
-
...toolRows(cli.tools ?? [], cli.commands),
|
|
7977
|
-
installRow(cli, launch),
|
|
7978
|
-
registryRow(cli, launch.node),
|
|
7979
|
-
skillRow(cli)
|
|
7980
|
-
];
|
|
8482
|
+
function stdoutOf({ value, render }, format, spill) {
|
|
8483
|
+
const text = printed(value, render, format);
|
|
8484
|
+
return value instanceof Page ? text : spill(text, format.json);
|
|
7981
8485
|
}
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
|
|
7990
|
-
|
|
7991
|
-
|
|
7992
|
-
|
|
7993
|
-
|
|
7994
|
-
|
|
7995
|
-
|
|
7996
|
-
message: string(),
|
|
7997
|
-
fix: string().optional(),
|
|
7998
|
-
code: string().optional()
|
|
7999
|
-
})),
|
|
8000
|
-
next: array(string())
|
|
8001
|
-
});
|
|
8002
|
-
function problemOf(check, error, { signal, deadline, ms }) {
|
|
8003
|
-
if (!signal.aborted && deadline.aborted && error === deadline.reason) return {
|
|
8004
|
-
state: "problem",
|
|
8005
|
-
message: `${check.name} did not answer within ${ms / MS_PER_SECOND} s`
|
|
8006
|
-
};
|
|
8007
|
-
if (error instanceof CliError) return {
|
|
8008
|
-
state: "problem",
|
|
8009
|
-
message: `${error.message}; ${error.hint}`,
|
|
8010
|
-
code: error.code
|
|
8011
|
-
};
|
|
8486
|
+
/** What a serve Command prints the moment it starts. */
|
|
8487
|
+
function startedOutput(outcome, format, spill) {
|
|
8488
|
+
return stdoutOf(outcome, {
|
|
8489
|
+
...format,
|
|
8490
|
+
fields: void 0
|
|
8491
|
+
}, spill);
|
|
8492
|
+
}
|
|
8493
|
+
/** A serve Command stopped after it started: stopping it is how it is meant to end. */
|
|
8494
|
+
const STOPPED_RESULT = {
|
|
8495
|
+
stdout: "",
|
|
8496
|
+
stderr: "",
|
|
8497
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8498
|
+
};
|
|
8499
|
+
function errorResult(error, format) {
|
|
8012
8500
|
return {
|
|
8013
|
-
|
|
8014
|
-
|
|
8501
|
+
stdout: "",
|
|
8502
|
+
stderr: errorText(error, format),
|
|
8503
|
+
exitCode: exitCodeOf(error, format.errors, format.stop)
|
|
8015
8504
|
};
|
|
8016
8505
|
}
|
|
8017
|
-
function
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8506
|
+
async function commandResult(settled, format, spill) {
|
|
8507
|
+
if (settled.ok) try {
|
|
8508
|
+
return {
|
|
8509
|
+
stdout: await stdoutOf(settled.outcome, format, spill),
|
|
8510
|
+
stderr: "",
|
|
8511
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8512
|
+
};
|
|
8513
|
+
} catch (spillError) {
|
|
8514
|
+
return errorResult(spillError, format);
|
|
8515
|
+
}
|
|
8516
|
+
const { error, delivered } = settled;
|
|
8517
|
+
const result = errorResult(error, format);
|
|
8518
|
+
if (delivered === void 0) return result;
|
|
8024
8519
|
try {
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8520
|
+
return {
|
|
8521
|
+
...result,
|
|
8522
|
+
stdout: await stdoutOf(delivered, format, spill)
|
|
8523
|
+
};
|
|
8524
|
+
} catch (spillError) {
|
|
8525
|
+
const both = new AggregateError([...errorsOf(error), spillError]);
|
|
8526
|
+
return {
|
|
8527
|
+
...result,
|
|
8528
|
+
stderr: errorText(both, format)
|
|
8529
|
+
};
|
|
8033
8530
|
}
|
|
8034
|
-
return {
|
|
8035
|
-
row: {
|
|
8036
|
-
check: check.name,
|
|
8037
|
-
...finding
|
|
8038
|
-
},
|
|
8039
|
-
advisory: check.advisory === true
|
|
8040
|
-
};
|
|
8041
8531
|
}
|
|
8042
|
-
function
|
|
8043
|
-
|
|
8532
|
+
function textHelp(node, root, cli, style) {
|
|
8533
|
+
if (node === root) return cliHelp(cli, node, style);
|
|
8534
|
+
return node.kind === "command" ? commandHelp(node, style) : groupHelp(node, style);
|
|
8044
8535
|
}
|
|
8045
|
-
function
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
return
|
|
8049
|
-
const label = state === "problem" ? style.red(state) : state;
|
|
8050
|
-
return `${check.padEnd(width)}${label}${" ".repeat(stateWidth - state.length)}${message}`;
|
|
8051
|
-
}), ...next.map((fix) => `${"next".padEnd(width)}${fix}`)].join("\n");
|
|
8536
|
+
function helpOf(node, root, cli, style, json) {
|
|
8537
|
+
if (!json) return textHelp(node, root, cli, style);
|
|
8538
|
+
if (node === root) return cliHelpJson(cli, node);
|
|
8539
|
+
return node.kind === "command" ? commandHelpJson(node) : groupHelpJson(node);
|
|
8052
8540
|
}
|
|
8053
|
-
function
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
}
|
|
8059
|
-
return new AggregateError(errors);
|
|
8541
|
+
function helpResult(node, root, cli, { style, json }) {
|
|
8542
|
+
return {
|
|
8543
|
+
stdout: helpOf(node, root, cli, style, json),
|
|
8544
|
+
stderr: "",
|
|
8545
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8546
|
+
};
|
|
8060
8547
|
}
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
command: `${cli.name} doctor`,
|
|
8068
|
-
note: "check the setup and list the commands that fix it"
|
|
8069
|
-
}, {
|
|
8070
|
-
command: `${cli.name} doctor --json`,
|
|
8071
|
-
note: "get the rows and fixes as data"
|
|
8072
|
-
}],
|
|
8073
|
-
effect: "read",
|
|
8074
|
-
output: reportSchema,
|
|
8075
|
-
run: async (_input, ctx) => {
|
|
8076
|
-
const checked = (await Promise.all(doctorChecks(cli, launch).map((check) => rowOf(check, ctx)))).filter((row) => row !== void 0);
|
|
8077
|
-
const rows = checked.map(({ row }) => row);
|
|
8078
|
-
const report = {
|
|
8079
|
-
rows,
|
|
8080
|
-
next: nextOf(rows)
|
|
8081
|
-
};
|
|
8082
|
-
if (ctx.signal.aborted) {
|
|
8083
|
-
ctx.deliver(report);
|
|
8084
|
-
ctx.signal.throwIfAborted();
|
|
8085
|
-
}
|
|
8086
|
-
const problems = checked.filter(({ row, advisory }) => row.state === "problem" && !advisory).map(({ row }) => row);
|
|
8087
|
-
if (problems.length > 0) {
|
|
8088
|
-
ctx.deliver(report);
|
|
8089
|
-
throw failure(cli.name, problems);
|
|
8090
|
-
}
|
|
8091
|
-
return report;
|
|
8092
|
-
},
|
|
8093
|
-
render
|
|
8094
|
-
});
|
|
8548
|
+
function versionResult(cli, packageRoot) {
|
|
8549
|
+
return {
|
|
8550
|
+
stdout: `${(cli.build === void 0 ? [versionLine(cli)] : [versionLine(cli), `changelog ${join(packageRoot, "CHANGELOG.md")}`]).join("\n")}\n`,
|
|
8551
|
+
stderr: "",
|
|
8552
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8553
|
+
};
|
|
8095
8554
|
}
|
|
8096
8555
|
//#endregion
|
|
8097
|
-
//#region ../agent-cli/dist/
|
|
8098
|
-
const RELEASE_HEADING = /^## v?(\S+)/;
|
|
8099
|
-
function releasesIn(changelog) {
|
|
8100
|
-
const releases = [];
|
|
8101
|
-
let current;
|
|
8102
|
-
for (const line of changelog.split(/\r?\n/)) {
|
|
8103
|
-
const heading = RELEASE_HEADING.exec(line);
|
|
8104
|
-
if (heading !== null) {
|
|
8105
|
-
const version = heading[1] ?? "";
|
|
8106
|
-
current = isVersion(version) ? {
|
|
8107
|
-
version,
|
|
8108
|
-
lines: []
|
|
8109
|
-
} : void 0;
|
|
8110
|
-
if (current !== void 0) releases.push(current);
|
|
8111
|
-
} else current?.lines.push(line);
|
|
8112
|
-
}
|
|
8113
|
-
return releases.map(({ version, lines }) => ({
|
|
8114
|
-
version,
|
|
8115
|
-
notes: lines.join("\n").trim()
|
|
8116
|
-
}));
|
|
8117
|
-
}
|
|
8556
|
+
//#region ../agent-cli/dist/package-root.js
|
|
8118
8557
|
/**
|
|
8119
|
-
*
|
|
8120
|
-
* `
|
|
8558
|
+
* The nearest folder holding a `package.json`, searched upward from the bin or, run without one,
|
|
8559
|
+
* from `cwd`; the search's start when none holds one. The bin is resolved through links first,
|
|
8560
|
+
* since npm's global bin is a link to it.
|
|
8121
8561
|
*/
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
if (isMissingFile(error)) return [];
|
|
8128
|
-
throw error;
|
|
8562
|
+
function packageRootOf(bin, cwd) {
|
|
8563
|
+
const start = bin === void 0 ? resolve(cwd) : dirname(realpathSync(bin));
|
|
8564
|
+
for (let dir = start;; dir = dirname(dir)) {
|
|
8565
|
+
if (existsSync(join(dir, "package.json"))) return dir;
|
|
8566
|
+
if (dirname(dir) === dir) return start;
|
|
8129
8567
|
}
|
|
8130
|
-
return releasesIn(changelog).filter(({ version }) => compareVersions(version, from) > 0 && compareVersions(version, to) <= 0).sort((a, b) => compareVersions(a.version, b.version));
|
|
8131
8568
|
}
|
|
8132
8569
|
//#endregion
|
|
8133
|
-
//#region ../agent-cli/dist/
|
|
8134
|
-
const
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8570
|
+
//#region ../agent-cli/dist/suggest.js
|
|
8571
|
+
const MAX_DISTANCE = 3;
|
|
8572
|
+
const MIN_SIMILARITY = .4;
|
|
8573
|
+
function distance(a, b) {
|
|
8574
|
+
const width = b.length + 1;
|
|
8575
|
+
const d = Array.from({ length: (a.length + 1) * width }, (_, k) => {
|
|
8576
|
+
const i = Math.floor(k / width);
|
|
8577
|
+
const j = k % width;
|
|
8578
|
+
return i === 0 || j === 0 ? i + j : 0;
|
|
8579
|
+
});
|
|
8580
|
+
const at = (i, j) => d[i * width + j] ?? 0;
|
|
8581
|
+
for (let i = 1; i <= a.length; i++) for (let j = 1; j <= b.length; j++) {
|
|
8582
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
8583
|
+
const edit = Math.min(at(i - 1, j) + 1, at(i, j - 1) + 1, at(i - 1, j - 1) + cost);
|
|
8584
|
+
const transposed = i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1];
|
|
8585
|
+
d[i * width + j] = transposed ? Math.min(edit, at(i - 2, j - 2) + 1) : edit;
|
|
8586
|
+
}
|
|
8587
|
+
return at(a.length, b.length);
|
|
8149
8588
|
}
|
|
8150
|
-
function
|
|
8151
|
-
const
|
|
8152
|
-
|
|
8153
|
-
return
|
|
8154
|
-
`installed ${install.package}@${installed.version} with the npm under ${installed.prefix}, replacing ${update.from}`,
|
|
8155
|
-
...update.upgrades.map(({ version, notes }) => `\nchanges in ${version}:\n${notes}`),
|
|
8156
|
-
"",
|
|
8157
|
-
...update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${installed.version}`)
|
|
8158
|
-
].join("\n");
|
|
8589
|
+
function isClose(word, candidate) {
|
|
8590
|
+
const length = Math.max(word.length, candidate.length);
|
|
8591
|
+
const edits = distance(word, candidate);
|
|
8592
|
+
return candidate.length > 1 && edits < MAX_DISTANCE && (length - edits) / length > MIN_SIMILARITY;
|
|
8159
8593
|
}
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
});
|
|
8594
|
+
/** The names closest to `word`, sorted, several when they tie, or none when nothing is close. */
|
|
8595
|
+
function closestNames(word, names) {
|
|
8596
|
+
const close = [...new Set(names)].filter((candidate) => isClose(word, candidate));
|
|
8597
|
+
const best = Math.min(...close.map((candidate) => distance(word, candidate)));
|
|
8598
|
+
return close.filter((candidate) => distance(word, candidate) === best).sort((a, b) => a.localeCompare(b));
|
|
8166
8599
|
}
|
|
8167
|
-
/** The
|
|
8168
|
-
function
|
|
8169
|
-
return
|
|
8170
|
-
|
|
8171
|
-
|
|
8172
|
-
examples: [{
|
|
8173
|
-
command: `${cli.name} update`,
|
|
8174
|
-
note: "install the latest version and show what changed"
|
|
8175
|
-
}, {
|
|
8176
|
-
command: `${cli.name} update --dry-run`,
|
|
8177
|
-
note: "show the version it would install"
|
|
8178
|
-
}],
|
|
8179
|
-
effect: "write",
|
|
8180
|
-
output: updateSchema,
|
|
8181
|
-
plan: async (_input, ctx) => {
|
|
8182
|
-
const npm = npmContext(cli, install, ctx, node);
|
|
8183
|
-
const copy = await globalInstallOf(bin, npm);
|
|
8184
|
-
return {
|
|
8185
|
-
package: install.package,
|
|
8186
|
-
from: cli.version,
|
|
8187
|
-
latest: await latestVersion(npm),
|
|
8188
|
-
prefix: copy.prefix,
|
|
8189
|
-
packageDir: copy.packageDir
|
|
8190
|
-
};
|
|
8191
|
-
},
|
|
8192
|
-
apply: async (plan, ctx) => {
|
|
8193
|
-
const { from, latest, prefix } = plan;
|
|
8194
|
-
if (standingOf(from, latest) !== "behind") return {
|
|
8195
|
-
from,
|
|
8196
|
-
latest,
|
|
8197
|
-
installed: null,
|
|
8198
|
-
upgrades: [],
|
|
8199
|
-
next: []
|
|
8200
|
-
};
|
|
8201
|
-
ctx.signal.throwIfAborted();
|
|
8202
|
-
ctx.progress(`installing ${plan.package}@${latest} with the npm under ${prefix}…`);
|
|
8203
|
-
await ctx.runToEnd(`installing ${plan.package}@${latest}`, () => installGlobally(latest, npmContext(cli, install, ctx, node)));
|
|
8204
|
-
const update = {
|
|
8205
|
-
from,
|
|
8206
|
-
latest,
|
|
8207
|
-
installed: {
|
|
8208
|
-
version: latest,
|
|
8209
|
-
prefix
|
|
8210
|
-
},
|
|
8211
|
-
upgrades: await upgradeNotes(plan.packageDir, from, latest),
|
|
8212
|
-
next: [skillUpdateCommand(cli.name)]
|
|
8213
|
-
};
|
|
8214
|
-
if (ctx.signal.aborted) {
|
|
8215
|
-
ctx.deliver(update);
|
|
8216
|
-
throw interruptedAfterInstall(plan);
|
|
8217
|
-
}
|
|
8218
|
-
return update;
|
|
8219
|
-
},
|
|
8220
|
-
render: (update) => renderUpdate(cli, install, update),
|
|
8221
|
-
renderPlan: (plan) => standingOf(plan.from, plan.latest) === "behind" ? `would install ${plan.package}@${plan.latest} with the npm under ${plan.prefix}, replacing ${plan.from}` : nothingToInstall(plan)
|
|
8222
|
-
});
|
|
8600
|
+
/** The long flags closest to `flag`, sorted, or none for a short flag or when nothing is close. */
|
|
8601
|
+
function closestFlags(flag, flags) {
|
|
8602
|
+
if (!flag.startsWith("--")) return [];
|
|
8603
|
+
const names = flags.map((candidate) => candidate.slice(2));
|
|
8604
|
+
return closestNames(flag.slice(2), names).map((name) => `--${name}`);
|
|
8223
8605
|
}
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
return {
|
|
8229
|
-
doctor: doctorCommand(cli, launch),
|
|
8230
|
-
...cli.install === void 0 ? {} : { update: updateCommand(cli, cli.install, launch) }
|
|
8231
|
-
};
|
|
8606
|
+
/** The one long flag closest to `flag`, or none when nothing is close or several tie. */
|
|
8607
|
+
function closestFlag(flag, flags) {
|
|
8608
|
+
const closest = closestFlags(flag, flags);
|
|
8609
|
+
return closest.length === 1 ? closest[0] : void 0;
|
|
8232
8610
|
}
|
|
8233
8611
|
//#endregion
|
|
8234
|
-
//#region ../agent-cli/dist/
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8612
|
+
//#region ../agent-cli/dist/route.js
|
|
8613
|
+
const GROUP_FLAGS = [
|
|
8614
|
+
HELP_FLAG,
|
|
8615
|
+
VERSION_FLAG,
|
|
8616
|
+
JSON_FLAG.flag
|
|
8617
|
+
];
|
|
8618
|
+
function beforeEnd(words) {
|
|
8619
|
+
const end = words.indexOf("--");
|
|
8620
|
+
return end === -1 ? words : words.slice(0, end);
|
|
8238
8621
|
}
|
|
8239
|
-
function
|
|
8240
|
-
|
|
8241
|
-
if (cli.commands === void 0) return cli;
|
|
8242
|
-
const { commands } = cli;
|
|
8243
|
-
const taken = Object.keys(builtInCommands(cli, {
|
|
8244
|
-
bin: void 0,
|
|
8245
|
-
node: void 0
|
|
8246
|
-
})).filter((name) => commands[name] !== void 0);
|
|
8247
|
-
if (taken.length > 0) throw new Error(`${cli.name} defines ${taken.join(", ")}, a built-in Command it cannot replace`);
|
|
8248
|
-
return cli;
|
|
8622
|
+
function wantsHelp(words) {
|
|
8623
|
+
return beforeEnd(words).some((word) => word === "--help" || word === "-h");
|
|
8249
8624
|
}
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8625
|
+
function childOf(group, name) {
|
|
8626
|
+
return Object.hasOwn(group.commands, name) ? group.commands[name] : void 0;
|
|
8627
|
+
}
|
|
8628
|
+
function isFlagLike(word) {
|
|
8629
|
+
return word.length > 1 && word[0] === "-";
|
|
8630
|
+
}
|
|
8631
|
+
function walk(node, words, json, invocation) {
|
|
8632
|
+
const help = {
|
|
8633
|
+
kind: "help",
|
|
8634
|
+
node,
|
|
8635
|
+
json
|
|
8636
|
+
};
|
|
8637
|
+
if (node.kind === "command") return wantsHelp(words) ? help : {
|
|
8638
|
+
kind: "command",
|
|
8639
|
+
spec: node,
|
|
8640
|
+
words,
|
|
8641
|
+
json
|
|
8258
8642
|
};
|
|
8643
|
+
const [first, ...rest] = words;
|
|
8644
|
+
if (first === void 0) return help;
|
|
8645
|
+
const child = childOf(node, first);
|
|
8646
|
+
if (child !== void 0) return walk(child, rest, json, invocation);
|
|
8647
|
+
if (first === "--") {
|
|
8648
|
+
const [name, ...after] = rest;
|
|
8649
|
+
if (name === void 0) return help;
|
|
8650
|
+
const named = childOf(node, name);
|
|
8651
|
+
if (named !== void 0) return walk(named, ["--", ...after], json, invocation);
|
|
8652
|
+
return unknownCommand(node, name, json);
|
|
8653
|
+
}
|
|
8654
|
+
if (wantsHelp(words)) return help;
|
|
8655
|
+
if (isFlagLike(first)) {
|
|
8656
|
+
const suggestions = closestFlags(first, GROUP_FLAGS);
|
|
8657
|
+
return {
|
|
8658
|
+
kind: "usage error",
|
|
8659
|
+
error: unknownOptionError(node.commandLine, invocation, first, suggestions),
|
|
8660
|
+
node,
|
|
8661
|
+
json
|
|
8662
|
+
};
|
|
8663
|
+
}
|
|
8664
|
+
return unknownCommand(node, first, json);
|
|
8259
8665
|
}
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8666
|
+
function unknownCommand(group, name, json) {
|
|
8667
|
+
const suggestions = closestNames(name, Object.keys(visibleCommands(group)));
|
|
8668
|
+
return {
|
|
8669
|
+
kind: "usage error",
|
|
8670
|
+
error: unknownCommandError(group.commandLine, name, suggestions),
|
|
8671
|
+
node: group,
|
|
8672
|
+
json
|
|
8673
|
+
};
|
|
8265
8674
|
}
|
|
8266
|
-
/**
|
|
8267
|
-
function
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8675
|
+
/** Walks the caller's command line through the Commands to the one it names, or to a stop. */
|
|
8676
|
+
function route(root, invocation) {
|
|
8677
|
+
const { argv } = invocation;
|
|
8678
|
+
const options = beforeEnd(argv);
|
|
8679
|
+
const json = options.includes(JSON_FLAG.flag);
|
|
8680
|
+
if (options.includes("--version")) return {
|
|
8681
|
+
kind: "version",
|
|
8682
|
+
json
|
|
8683
|
+
};
|
|
8684
|
+
return walk(root, argv.filter((word, index) => !(index < options.length && word === JSON_FLAG.flag)), json, invocation);
|
|
8272
8685
|
}
|
|
8273
8686
|
//#endregion
|
|
8274
8687
|
//#region ../agent-cli/dist/execute.js
|
|
@@ -8341,67 +8754,12 @@ async function execute(command, input, ctx, { dryRun, confirm, yes, page, invoca
|
|
|
8341
8754
|
}, outputs);
|
|
8342
8755
|
if (!ctx.force) guardOutputs(outputs, ctx.commandLine({ add: [FORCE_FLAG.flag] }));
|
|
8343
8756
|
}
|
|
8344
|
-
return outcomeOf(await command.apply(plan, ctx), (data, style) => command.render(data, style));
|
|
8345
|
-
}
|
|
8346
|
-
//#endregion
|
|
8347
|
-
//#region ../agent-cli/dist/package-root.js
|
|
8348
|
-
/**
|
|
8349
|
-
* The nearest folder holding a `package.json`, searched upward from the bin or, run without one,
|
|
8350
|
-
* from `cwd`; the search's start when none holds one. The bin is resolved through links first,
|
|
8351
|
-
* since npm's global bin is a link to it.
|
|
8352
|
-
*/
|
|
8353
|
-
function packageRootOf(bin, cwd) {
|
|
8354
|
-
const start = bin === void 0 ? resolve(cwd) : dirname(realpathSync(bin));
|
|
8355
|
-
for (let dir = start;; dir = dirname(dir)) {
|
|
8356
|
-
if (existsSync(join(dir, "package.json"))) return dir;
|
|
8357
|
-
if (dirname(dir) === dir) return start;
|
|
8358
|
-
}
|
|
8359
|
-
}
|
|
8360
|
-
//#endregion
|
|
8361
|
-
//#region ../agent-cli/dist/suggest.js
|
|
8362
|
-
const MAX_DISTANCE = 3;
|
|
8363
|
-
const MIN_SIMILARITY = .4;
|
|
8364
|
-
function distance(a, b) {
|
|
8365
|
-
const width = b.length + 1;
|
|
8366
|
-
const d = Array.from({ length: (a.length + 1) * width }, (_, k) => {
|
|
8367
|
-
const i = Math.floor(k / width);
|
|
8368
|
-
const j = k % width;
|
|
8369
|
-
return i === 0 || j === 0 ? i + j : 0;
|
|
8370
|
-
});
|
|
8371
|
-
const at = (i, j) => d[i * width + j] ?? 0;
|
|
8372
|
-
for (let i = 1; i <= a.length; i++) for (let j = 1; j <= b.length; j++) {
|
|
8373
|
-
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
8374
|
-
const edit = Math.min(at(i - 1, j) + 1, at(i, j - 1) + 1, at(i - 1, j - 1) + cost);
|
|
8375
|
-
const transposed = i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1];
|
|
8376
|
-
d[i * width + j] = transposed ? Math.min(edit, at(i - 2, j - 2) + 1) : edit;
|
|
8377
|
-
}
|
|
8378
|
-
return at(a.length, b.length);
|
|
8379
|
-
}
|
|
8380
|
-
function isClose(word, candidate) {
|
|
8381
|
-
const length = Math.max(word.length, candidate.length);
|
|
8382
|
-
const edits = distance(word, candidate);
|
|
8383
|
-
return candidate.length > 1 && edits < MAX_DISTANCE && (length - edits) / length > MIN_SIMILARITY;
|
|
8384
|
-
}
|
|
8385
|
-
/** The names closest to `word`, sorted, several when they tie, or none when nothing is close. */
|
|
8386
|
-
function closestNames(word, names) {
|
|
8387
|
-
const close = [...new Set(names)].filter((candidate) => isClose(word, candidate));
|
|
8388
|
-
const best = Math.min(...close.map((candidate) => distance(word, candidate)));
|
|
8389
|
-
return close.filter((candidate) => distance(word, candidate) === best).sort((a, b) => a.localeCompare(b));
|
|
8390
|
-
}
|
|
8391
|
-
/** The long flags closest to `flag`, sorted, or none for a short flag or when nothing is close. */
|
|
8392
|
-
function closestFlags(flag, flags) {
|
|
8393
|
-
if (!flag.startsWith("--")) return [];
|
|
8394
|
-
const names = flags.map((candidate) => candidate.slice(2));
|
|
8395
|
-
return closestNames(flag.slice(2), names).map((name) => `--${name}`);
|
|
8396
|
-
}
|
|
8397
|
-
/** The one long flag closest to `flag`, or none when nothing is close or several tie. */
|
|
8398
|
-
function closestFlag(flag, flags) {
|
|
8399
|
-
const closest = closestFlags(flag, flags);
|
|
8400
|
-
return closest.length === 1 ? closest[0] : void 0;
|
|
8757
|
+
return outcomeOf(await command.apply(plan, ctx), (data, style) => command.render(data, style));
|
|
8401
8758
|
}
|
|
8402
8759
|
//#endregion
|
|
8403
8760
|
//#region ../agent-cli/dist/parse-input.js
|
|
8404
8761
|
const NO_INPUT = object({});
|
|
8762
|
+
const WHITESPACE = /\s/;
|
|
8405
8763
|
function knownFlags(spec) {
|
|
8406
8764
|
return [...spec.options.map((field) => ({
|
|
8407
8765
|
flag: field.label,
|
|
@@ -8538,6 +8896,8 @@ async function parseInput(spec, words, invocation, readStdin) {
|
|
|
8538
8896
|
page: page.data,
|
|
8539
8897
|
values
|
|
8540
8898
|
};
|
|
8899
|
+
const [onlyWord] = unknownOptions;
|
|
8900
|
+
if (onlyWord !== void 0 && unknownOptions.length === 1 && WHITESPACE.test(onlyWord) && argFields.some((field) => field.stdin && argValues.get(field) === void 0)) throw stdinTextError(spec.commandLine, invocation, onlyWord);
|
|
8541
8901
|
const [only] = unknown;
|
|
8542
8902
|
if (only !== void 0 && unknown.length === 1 && otherLines.length === 0) throw unknownOptionError(spec.commandLine, invocation, only.flag, only.suggestion === void 0 ? [] : [only.suggestion]);
|
|
8543
8903
|
throw invalidInput(spec.commandLine, invocation, unknown, otherLines);
|
|
@@ -8563,83 +8923,9 @@ async function parseCommand({ spec, words, json }, invocation, readStdin) {
|
|
|
8563
8923
|
};
|
|
8564
8924
|
}
|
|
8565
8925
|
//#endregion
|
|
8566
|
-
//#region ../agent-cli/dist/route.js
|
|
8567
|
-
const GROUP_FLAGS = [
|
|
8568
|
-
HELP_FLAG,
|
|
8569
|
-
VERSION_FLAG,
|
|
8570
|
-
JSON_FLAG.flag
|
|
8571
|
-
];
|
|
8572
|
-
function beforeEnd(words) {
|
|
8573
|
-
const end = words.indexOf("--");
|
|
8574
|
-
return end === -1 ? words : words.slice(0, end);
|
|
8575
|
-
}
|
|
8576
|
-
function wantsHelp(words) {
|
|
8577
|
-
return beforeEnd(words).some((word) => word === "--help" || word === "-h");
|
|
8578
|
-
}
|
|
8579
|
-
function childOf(group, name) {
|
|
8580
|
-
return Object.hasOwn(group.commands, name) ? group.commands[name] : void 0;
|
|
8581
|
-
}
|
|
8582
|
-
function isFlagLike(word) {
|
|
8583
|
-
return word.length > 1 && word[0] === "-";
|
|
8584
|
-
}
|
|
8585
|
-
function walk(node, words, json, invocation) {
|
|
8586
|
-
const help = {
|
|
8587
|
-
kind: "help",
|
|
8588
|
-
node,
|
|
8589
|
-
json
|
|
8590
|
-
};
|
|
8591
|
-
if (node.kind === "command") return wantsHelp(words) ? help : {
|
|
8592
|
-
kind: "command",
|
|
8593
|
-
spec: node,
|
|
8594
|
-
words,
|
|
8595
|
-
json
|
|
8596
|
-
};
|
|
8597
|
-
const [first, ...rest] = words;
|
|
8598
|
-
if (first === void 0) return help;
|
|
8599
|
-
const child = childOf(node, first);
|
|
8600
|
-
if (child !== void 0) return walk(child, rest, json, invocation);
|
|
8601
|
-
if (first === "--") {
|
|
8602
|
-
const [name, ...after] = rest;
|
|
8603
|
-
if (name === void 0) return help;
|
|
8604
|
-
const named = childOf(node, name);
|
|
8605
|
-
if (named !== void 0) return walk(named, ["--", ...after], json, invocation);
|
|
8606
|
-
return unknownCommand(node, name, json);
|
|
8607
|
-
}
|
|
8608
|
-
if (wantsHelp(words)) return help;
|
|
8609
|
-
if (isFlagLike(first)) {
|
|
8610
|
-
const suggestions = closestFlags(first, GROUP_FLAGS);
|
|
8611
|
-
return {
|
|
8612
|
-
kind: "usage error",
|
|
8613
|
-
error: unknownOptionError(node.commandLine, invocation, first, suggestions),
|
|
8614
|
-
node,
|
|
8615
|
-
json
|
|
8616
|
-
};
|
|
8617
|
-
}
|
|
8618
|
-
return unknownCommand(node, first, json);
|
|
8619
|
-
}
|
|
8620
|
-
function unknownCommand(group, name, json) {
|
|
8621
|
-
const suggestions = closestNames(name, Object.keys(visibleCommands(group)));
|
|
8622
|
-
return {
|
|
8623
|
-
kind: "usage error",
|
|
8624
|
-
error: unknownCommandError(group.commandLine, name, suggestions),
|
|
8625
|
-
node: group,
|
|
8626
|
-
json
|
|
8627
|
-
};
|
|
8628
|
-
}
|
|
8629
|
-
/** Walks the caller's command line through the Commands to the one it names, or to a stop. */
|
|
8630
|
-
function route(root, invocation) {
|
|
8631
|
-
const { argv } = invocation;
|
|
8632
|
-
const options = beforeEnd(argv);
|
|
8633
|
-
const json = options.includes(JSON_FLAG.flag);
|
|
8634
|
-
if (options.includes("--version")) return {
|
|
8635
|
-
kind: "version",
|
|
8636
|
-
json
|
|
8637
|
-
};
|
|
8638
|
-
return walk(root, argv.filter((word, index) => !(index < options.length && word === JSON_FLAG.flag)), json, invocation);
|
|
8639
|
-
}
|
|
8640
|
-
//#endregion
|
|
8641
8926
|
//#region ../agent-cli/dist/secrets.js
|
|
8642
|
-
|
|
8927
|
+
/** `$XDG_CONFIG_HOME/<cli>/.env`, with `~/.config` when the variable is unset or empty. */
|
|
8928
|
+
function envFileOf(cliName, env) {
|
|
8643
8929
|
const config = env.XDG_CONFIG_HOME || join(env.HOME || homedir(), ".config");
|
|
8644
8930
|
return join(config, cliName, ".env");
|
|
8645
8931
|
}
|
|
@@ -8656,24 +8942,50 @@ function readDotenv(path, fileError) {
|
|
|
8656
8942
|
}
|
|
8657
8943
|
return parseEnv(text);
|
|
8658
8944
|
}
|
|
8659
|
-
/** Looks `name` up in the env, then in
|
|
8660
|
-
function secretOf({
|
|
8945
|
+
/** Looks `name` up in the env, then in `envFile`; an empty value counts as unset. */
|
|
8946
|
+
function secretOf({ envFile, env, fileError }, name) {
|
|
8661
8947
|
const fromEnv = env[name];
|
|
8662
8948
|
if (fromEnv) return {
|
|
8663
8949
|
value: fromEnv,
|
|
8664
8950
|
origin: { kind: "env" }
|
|
8665
8951
|
};
|
|
8666
|
-
const
|
|
8667
|
-
const fromFile = readDotenv(path, fileError)[name];
|
|
8952
|
+
const fromFile = readDotenv(envFile, fileError)[name];
|
|
8668
8953
|
return fromFile ? {
|
|
8669
8954
|
value: fromFile,
|
|
8670
8955
|
origin: {
|
|
8671
8956
|
kind: "file",
|
|
8672
|
-
path
|
|
8957
|
+
path: envFile
|
|
8673
8958
|
}
|
|
8674
8959
|
} : void 0;
|
|
8675
8960
|
}
|
|
8676
8961
|
//#endregion
|
|
8962
|
+
//#region ../agent-cli/dist/side-task.js
|
|
8963
|
+
/** How long a run waits for its Side task once its output is written. */
|
|
8964
|
+
const SIDE_TASK_WAIT_MS = 1e3;
|
|
8965
|
+
const noSideTask = async () => {};
|
|
8966
|
+
function waitOver() {
|
|
8967
|
+
return new DOMException(`the side task ran past its ${SIDE_TASK_WAIT_MS} ms wait`, "TimeoutError");
|
|
8968
|
+
}
|
|
8969
|
+
function startSideTask(sideTask, runWith, { clock, failed }) {
|
|
8970
|
+
if (sideTask === void 0) return noSideTask;
|
|
8971
|
+
const controller = new AbortController();
|
|
8972
|
+
const { signal } = controller;
|
|
8973
|
+
const running = (async () => sideTask(runWith(signal)))().catch((error) => {
|
|
8974
|
+
if (!(signal.aborted && error === signal.reason)) failed(error);
|
|
8975
|
+
});
|
|
8976
|
+
return async () => {
|
|
8977
|
+
const waited = new AbortController();
|
|
8978
|
+
const capped = new Promise((resolve) => after(clock, SIDE_TASK_WAIT_MS, waited.signal, () => {
|
|
8979
|
+
const over = waitOver();
|
|
8980
|
+
failed(over);
|
|
8981
|
+
controller.abort(over);
|
|
8982
|
+
resolve();
|
|
8983
|
+
}));
|
|
8984
|
+
await Promise.race([running, capped]);
|
|
8985
|
+
waited.abort();
|
|
8986
|
+
};
|
|
8987
|
+
}
|
|
8988
|
+
//#endregion
|
|
8677
8989
|
//#region ../agent-cli/dist/spill.js
|
|
8678
8990
|
const STDOUT_BUDGET_CHARS = 3e4;
|
|
8679
8991
|
const SPILL_RETENTION_MS = 6048e5;
|
|
@@ -8726,47 +9038,91 @@ function spillTo(target) {
|
|
|
8726
9038
|
};
|
|
8727
9039
|
}
|
|
8728
9040
|
//#endregion
|
|
8729
|
-
//#region ../agent-cli/dist/
|
|
8730
|
-
function
|
|
8731
|
-
|
|
8732
|
-
return env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "" && env.FORCE_COLOR !== "0" || stdoutIsTTY && !isAgent(env);
|
|
9041
|
+
//#region ../agent-cli/dist/run-command.js
|
|
9042
|
+
function stdinNeverEndedHint(callerLine) {
|
|
9043
|
+
return `stdin never ended: pipe the text into \`${callerLine}\`, or redirect a file into it`;
|
|
8733
9044
|
}
|
|
8734
|
-
function
|
|
8735
|
-
return
|
|
9045
|
+
function selfOf(name, bin) {
|
|
9046
|
+
return bin === void 0 ? [name] : [
|
|
9047
|
+
process.execPath,
|
|
9048
|
+
...process.execArgv,
|
|
9049
|
+
bin
|
|
9050
|
+
];
|
|
8736
9051
|
}
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
8740
|
-
red: sgr(31, 39),
|
|
8741
|
-
green: sgr(32, 39),
|
|
8742
|
-
yellow: sgr(33, 39),
|
|
8743
|
-
cyan: sgr(36, 39)
|
|
8744
|
-
};
|
|
8745
|
-
const plain = (text) => text;
|
|
8746
|
-
const PLAIN = {
|
|
8747
|
-
bold: plain,
|
|
8748
|
-
dim: plain,
|
|
8749
|
-
red: plain,
|
|
8750
|
-
green: plain,
|
|
8751
|
-
yellow: plain,
|
|
8752
|
-
cyan: plain
|
|
8753
|
-
};
|
|
8754
|
-
function styleFor(env, stdoutIsTTY) {
|
|
8755
|
-
return colourEnabled(env, stdoutIsTTY) ? COLOURED : PLAIN;
|
|
9052
|
+
function portsOf(cli, replacement) {
|
|
9053
|
+
if (replacement !== void 0) return () => replacement;
|
|
9054
|
+
return cli.ports ?? (() => ({}));
|
|
8756
9055
|
}
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
9056
|
+
function portsBaseOf(scope, signal) {
|
|
9057
|
+
const { cli, options, packageRoot, progress, fileError, clock, files } = scope;
|
|
9058
|
+
const { cwd, env } = options;
|
|
9059
|
+
const envFile = envFileOf(cli.name, env);
|
|
9060
|
+
return {
|
|
9061
|
+
cwd,
|
|
9062
|
+
env,
|
|
9063
|
+
packageRoot,
|
|
9064
|
+
progress,
|
|
9065
|
+
secret: (name) => secretOf({
|
|
9066
|
+
envFile,
|
|
9067
|
+
env,
|
|
9068
|
+
fileError
|
|
9069
|
+
}, name),
|
|
9070
|
+
envFile,
|
|
9071
|
+
fileError,
|
|
9072
|
+
version: cli.version,
|
|
9073
|
+
build: cli.build,
|
|
9074
|
+
self: selfOf(cli.name, options.bin),
|
|
9075
|
+
signal,
|
|
9076
|
+
clock,
|
|
9077
|
+
files,
|
|
9078
|
+
spawn: contextSpawn(options.spawn ?? realSpawn, {
|
|
9079
|
+
cwd,
|
|
9080
|
+
env,
|
|
9081
|
+
signal,
|
|
9082
|
+
progress
|
|
9083
|
+
}, fileError)
|
|
9084
|
+
};
|
|
9085
|
+
}
|
|
9086
|
+
function contextOf(portsBase, control, parts) {
|
|
9087
|
+
const { ports, project, force, commandLine, deliver } = parts;
|
|
9088
|
+
return {
|
|
9089
|
+
...portsBase,
|
|
9090
|
+
deadline: (ms) => control.deadline(ms),
|
|
9091
|
+
timeout: (ms) => control.timeout(ms),
|
|
9092
|
+
runToEnd: (name, work) => control.runToEnd(name, work),
|
|
9093
|
+
get ports() {
|
|
9094
|
+
return ports();
|
|
9095
|
+
},
|
|
9096
|
+
project,
|
|
9097
|
+
force,
|
|
9098
|
+
commandLine,
|
|
9099
|
+
poll: (check, { intervalMs, signal: stop }) => poll(portsBase.clock, check, intervalMs, stop === void 0 ? control.signal : AbortSignal.any([control.signal, stop])),
|
|
9100
|
+
deliver
|
|
9101
|
+
};
|
|
8761
9102
|
}
|
|
8762
|
-
|
|
8763
|
-
|
|
9103
|
+
/** Leaves the Side task running, so the caller writes the result before it waits for it. */
|
|
9104
|
+
async function runCommand(cli, routed, options, write, baseFormat) {
|
|
9105
|
+
const { command, commandLine, builtIn } = routed.spec;
|
|
9106
|
+
const { cwd, env } = options;
|
|
9107
|
+
const clock = options.clock ?? realClock;
|
|
9108
|
+
const files = options.files ?? realFiles();
|
|
9109
|
+
const stdin = options.stdin ?? "";
|
|
9110
|
+
const platform = options.platform ?? process.platform;
|
|
9111
|
+
const ports = portsOf(cli, options.ports);
|
|
9112
|
+
const packageRoot = packageRootOf(options.bin, cwd);
|
|
9113
|
+
const fileError = fileErrorOf({
|
|
9114
|
+
callerLine: commandLineOf(baseFormat.invocation),
|
|
9115
|
+
env,
|
|
9116
|
+
platform
|
|
9117
|
+
});
|
|
9118
|
+
const progress = (message) => write.stderr(progressLine(message, routed.json));
|
|
8764
9119
|
const invocation = {
|
|
8765
9120
|
...baseFormat.invocation,
|
|
8766
9121
|
flags: knownFlags(routed.spec)
|
|
8767
9122
|
};
|
|
8768
9123
|
const format = {
|
|
8769
9124
|
...baseFormat,
|
|
9125
|
+
bugs: () => manifestAt(packageRoot).bugs,
|
|
8770
9126
|
json: routed.json,
|
|
8771
9127
|
invocation
|
|
8772
9128
|
};
|
|
@@ -8774,71 +9130,91 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8774
9130
|
let resumeHint;
|
|
8775
9131
|
const control = new RunControl({
|
|
8776
9132
|
commandLine,
|
|
8777
|
-
outer: signal,
|
|
9133
|
+
outer: options.signal,
|
|
8778
9134
|
clock,
|
|
8779
|
-
progress
|
|
9135
|
+
progress,
|
|
8780
9136
|
runDeadline: command.deadline === void 0 ? void 0 : {
|
|
8781
9137
|
ms: command.deadline.ms,
|
|
8782
9138
|
hint: () => resumeHint ?? stdinNeverEndedHint(typedLine())
|
|
8783
9139
|
}
|
|
8784
9140
|
});
|
|
9141
|
+
const failed = (error, finishSideTask) => {
|
|
9142
|
+
control.close();
|
|
9143
|
+
return {
|
|
9144
|
+
result: errorResult(error, format),
|
|
9145
|
+
finishSideTask
|
|
9146
|
+
};
|
|
9147
|
+
};
|
|
8785
9148
|
let parsed;
|
|
8786
|
-
let project;
|
|
8787
9149
|
try {
|
|
8788
|
-
checkOperator(routed.spec,
|
|
9150
|
+
checkOperator(routed.spec, env, typedLine());
|
|
8789
9151
|
parsed = await parseCommand(routed, invocation, (field) => {
|
|
8790
|
-
if (isTerminal(stdin))
|
|
8791
|
-
return readStdin(stdin, control.signal
|
|
9152
|
+
if (isTerminal(stdin)) progress(readingLine(field.name, platform));
|
|
9153
|
+
return readStdin(stdin, control.signal, {
|
|
9154
|
+
clock,
|
|
9155
|
+
stalled: () => stdinStalled(typedLine())
|
|
9156
|
+
});
|
|
8792
9157
|
});
|
|
8793
|
-
project = projectFile === void 0 ? void 0 : projectOf(projectFile, base.cwd);
|
|
8794
9158
|
} catch (error) {
|
|
8795
|
-
|
|
8796
|
-
return errorResult(error, format);
|
|
9159
|
+
return failed(error, noSideTask);
|
|
8797
9160
|
}
|
|
8798
9161
|
const { input, flags } = parsed;
|
|
8799
9162
|
resumeHint = command.deadline?.resume(input, typedLine);
|
|
8800
|
-
let delivered;
|
|
8801
|
-
const { fileError } = base;
|
|
8802
9163
|
const outputs = outputsGuard(classifiedFiles(files, {
|
|
8803
|
-
cwd
|
|
8804
|
-
fileError
|
|
8805
|
-
}), base.cwd);
|
|
8806
|
-
const spill = spillTo({
|
|
8807
|
-
cliName: format.cliName,
|
|
8808
|
-
commandName: command.name,
|
|
8809
|
-
env: base.env,
|
|
8810
|
-
clock,
|
|
8811
|
-
files: outputs.files,
|
|
9164
|
+
cwd,
|
|
8812
9165
|
fileError
|
|
8813
|
-
});
|
|
8814
|
-
const
|
|
8815
|
-
|
|
8816
|
-
|
|
9166
|
+
}), cwd);
|
|
9167
|
+
const scope = {
|
|
9168
|
+
cli,
|
|
9169
|
+
options,
|
|
9170
|
+
packageRoot,
|
|
9171
|
+
progress,
|
|
9172
|
+
fileError,
|
|
8817
9173
|
clock,
|
|
8818
|
-
files: outputs.files
|
|
8819
|
-
spawn: contextSpawn(spawn, {
|
|
8820
|
-
cwd: base.cwd,
|
|
8821
|
-
env: base.env,
|
|
8822
|
-
signal: control.signal,
|
|
8823
|
-
progress: base.progress
|
|
8824
|
-
}, fileError)
|
|
9174
|
+
files: outputs.files
|
|
8825
9175
|
};
|
|
8826
|
-
const
|
|
8827
|
-
const
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
9176
|
+
const portsBase = portsBaseOf(scope, control.signal);
|
|
9177
|
+
const finishSideTask = startSideTask(builtIn ? void 0 : cli.sideTask?.bind(cli), (sideSignal) => {
|
|
9178
|
+
const sideBase = portsBaseOf(scope, sideSignal);
|
|
9179
|
+
const sidePorts = once(() => ports(sideBase));
|
|
9180
|
+
return {
|
|
9181
|
+
...sideBase,
|
|
9182
|
+
command: routed.spec.path,
|
|
9183
|
+
dryRun: flags.dryRun,
|
|
9184
|
+
get ports() {
|
|
9185
|
+
return sidePorts();
|
|
9186
|
+
}
|
|
9187
|
+
};
|
|
9188
|
+
}, {
|
|
9189
|
+
clock,
|
|
9190
|
+
failed: (error) => {
|
|
9191
|
+
if (isDebug(baseFormat)) progress(`side task failed: ${traceOf(error)}`);
|
|
9192
|
+
}
|
|
9193
|
+
});
|
|
9194
|
+
let project;
|
|
9195
|
+
try {
|
|
9196
|
+
project = builtIn || cli.project === void 0 ? void 0 : projectOf(cli.project, cwd, fileError);
|
|
9197
|
+
} catch (error) {
|
|
9198
|
+
return failed(error, finishSideTask);
|
|
9199
|
+
}
|
|
9200
|
+
let delivered;
|
|
9201
|
+
const ctx = contextOf(portsBase, control, {
|
|
9202
|
+
ports: once(() => ports(portsBase)),
|
|
8834
9203
|
project,
|
|
8835
9204
|
force: flags.force,
|
|
8836
9205
|
commandLine: typedLine,
|
|
8837
|
-
poll: (check, { intervalMs, signal: stop }) => poll(clock, check, intervalMs, stop === void 0 ? control.signal : AbortSignal.any([control.signal, stop])),
|
|
8838
9206
|
deliver: (data) => {
|
|
8839
9207
|
delivered = deliveredOutcome(command, data);
|
|
8840
9208
|
}
|
|
8841
|
-
};
|
|
9209
|
+
});
|
|
9210
|
+
const spill = spillTo({
|
|
9211
|
+
cliName: format.cliName,
|
|
9212
|
+
commandName: command.name,
|
|
9213
|
+
env,
|
|
9214
|
+
clock,
|
|
9215
|
+
files: outputs.files,
|
|
9216
|
+
fileError
|
|
9217
|
+
});
|
|
8842
9218
|
let served = false;
|
|
8843
9219
|
let settled;
|
|
8844
9220
|
try {
|
|
@@ -8852,7 +9228,7 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8852
9228
|
invocation,
|
|
8853
9229
|
commandLine,
|
|
8854
9230
|
started: async (outcome) => {
|
|
8855
|
-
|
|
9231
|
+
write.stdout(await startedOutput(outcome, format, spill));
|
|
8856
9232
|
served = true;
|
|
8857
9233
|
},
|
|
8858
9234
|
files,
|
|
@@ -8860,17 +9236,23 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8860
9236
|
}))
|
|
8861
9237
|
};
|
|
8862
9238
|
} catch (error) {
|
|
8863
|
-
if (served && control.signal.aborted) return
|
|
9239
|
+
if (served && control.signal.aborted) return {
|
|
9240
|
+
result: STOPPED_RESULT,
|
|
9241
|
+
finishSideTask
|
|
9242
|
+
};
|
|
8864
9243
|
settled = {
|
|
8865
9244
|
ok: false,
|
|
8866
9245
|
error: control.errorAfter(error),
|
|
8867
9246
|
delivered
|
|
8868
9247
|
};
|
|
8869
9248
|
}
|
|
8870
|
-
return
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
9249
|
+
return {
|
|
9250
|
+
result: await commandResult(settled, {
|
|
9251
|
+
...format,
|
|
9252
|
+
fields: flags.fields
|
|
9253
|
+
}, spill),
|
|
9254
|
+
finishSideTask
|
|
9255
|
+
};
|
|
8874
9256
|
}
|
|
8875
9257
|
/** `build` runs on the first call; later calls give its value or throw its error again. */
|
|
8876
9258
|
function once(build) {
|
|
@@ -8891,17 +9273,37 @@ function once(build) {
|
|
|
8891
9273
|
throw outcome.error;
|
|
8892
9274
|
};
|
|
8893
9275
|
}
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
];
|
|
9276
|
+
//#endregion
|
|
9277
|
+
//#region ../agent-cli/dist/style.js
|
|
9278
|
+
function colourEnabled(env, stdoutIsTTY) {
|
|
9279
|
+
if (env.NO_COLOR !== void 0 && env.NO_COLOR !== "") return false;
|
|
9280
|
+
return env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "" && env.FORCE_COLOR !== "0" || stdoutIsTTY && !isAgent(env);
|
|
8900
9281
|
}
|
|
8901
|
-
function
|
|
8902
|
-
|
|
8903
|
-
|
|
9282
|
+
function sgr(open, close) {
|
|
9283
|
+
return (text) => `\u001b[${open}m${text}\u001b[${close}m`;
|
|
9284
|
+
}
|
|
9285
|
+
const COLOURED = {
|
|
9286
|
+
bold: sgr(1, 22),
|
|
9287
|
+
dim: sgr(2, 22),
|
|
9288
|
+
red: sgr(31, 39),
|
|
9289
|
+
green: sgr(32, 39),
|
|
9290
|
+
yellow: sgr(33, 39),
|
|
9291
|
+
cyan: sgr(36, 39)
|
|
9292
|
+
};
|
|
9293
|
+
const plain = (text) => text;
|
|
9294
|
+
const PLAIN = {
|
|
9295
|
+
bold: plain,
|
|
9296
|
+
dim: plain,
|
|
9297
|
+
red: plain,
|
|
9298
|
+
green: plain,
|
|
9299
|
+
yellow: plain,
|
|
9300
|
+
cyan: plain
|
|
9301
|
+
};
|
|
9302
|
+
function styleFor(env, stdoutIsTTY) {
|
|
9303
|
+
return colourEnabled(env, stdoutIsTTY) ? COLOURED : PLAIN;
|
|
8904
9304
|
}
|
|
9305
|
+
//#endregion
|
|
9306
|
+
//#region ../agent-cli/dist/run-cli.js
|
|
8905
9307
|
function stopLine(notice, json) {
|
|
8906
9308
|
return json ? progressLine(notice, true) : `\n${notice}\n`;
|
|
8907
9309
|
}
|
|
@@ -8915,7 +9317,14 @@ async function whileStopping(signal, onStop, work) {
|
|
|
8915
9317
|
signal.removeEventListener("abort", onStop);
|
|
8916
9318
|
}
|
|
8917
9319
|
}
|
|
9320
|
+
/** Runs the CLI, writes its output, then waits for the Side task it started. */
|
|
8918
9321
|
async function runWithProgress(cli, argv, options, write, stopNotice) {
|
|
9322
|
+
const { result, finishSideTask } = await routeAndRun(cli, argv, options, write, stopNotice);
|
|
9323
|
+
await write.result(result);
|
|
9324
|
+
await finishSideTask();
|
|
9325
|
+
return result;
|
|
9326
|
+
}
|
|
9327
|
+
async function routeAndRun(cli, argv, options, write, stopNotice) {
|
|
8919
9328
|
const format = {
|
|
8920
9329
|
cliName: cli.name,
|
|
8921
9330
|
env: options.env,
|
|
@@ -8929,64 +9338,37 @@ async function runWithProgress(cli, argv, options, write, stopNotice) {
|
|
|
8929
9338
|
errors: cli.errors ?? {},
|
|
8930
9339
|
stop: options.signal
|
|
8931
9340
|
};
|
|
8932
|
-
const
|
|
9341
|
+
const root = cli.commands === void 0 ? {
|
|
9342
|
+
...commandSpec(cli.name, cli.command),
|
|
9343
|
+
description: cli.description
|
|
9344
|
+
} : groupSpec(cli.name, cli.commands, builtInCommands(cli, {
|
|
8933
9345
|
bin: options.bin,
|
|
8934
9346
|
node: options.node
|
|
8935
|
-
});
|
|
8936
|
-
const root = cli.commands === void 0 ? commandSpec(cli.name, cli.command) : groupSpec(cli.name, {
|
|
8937
|
-
...cli.commands,
|
|
8938
|
-
...builtIns
|
|
8939
|
-
});
|
|
9347
|
+
}));
|
|
8940
9348
|
const routed = route(root, format.invocation);
|
|
8941
|
-
const platform = options.platform ?? process.platform;
|
|
8942
|
-
const fileError = fileErrorOf({
|
|
8943
|
-
callerLine: commandLineOf(format.invocation),
|
|
8944
|
-
env: options.env,
|
|
8945
|
-
platform
|
|
8946
|
-
});
|
|
8947
9349
|
const misused = (node) => isAgent(options.env) ? {
|
|
8948
9350
|
...format,
|
|
8949
9351
|
usageHelp: textHelp(node, root, cli, format.style)
|
|
8950
9352
|
} : format;
|
|
8951
9353
|
switch (routed.kind) {
|
|
8952
|
-
case "version": return versionResult(cli, packageRootOf(options.bin, options.cwd));
|
|
8953
|
-
case "help": return helpResult(routed.node, root, cli, {
|
|
9354
|
+
case "version": return ranAlone(versionResult(cli, packageRootOf(options.bin, options.cwd)));
|
|
9355
|
+
case "help": return ranAlone(helpResult(routed.node, root, cli, {
|
|
8954
9356
|
...format,
|
|
8955
9357
|
json: routed.json
|
|
8956
|
-
});
|
|
8957
|
-
case "usage error": return errorResult(routed.error, {
|
|
9358
|
+
}));
|
|
9359
|
+
case "usage error": return ranAlone(errorResult(routed.error, {
|
|
8958
9360
|
...misused(routed.node),
|
|
8959
9361
|
json: routed.json
|
|
8960
|
-
});
|
|
8961
|
-
case "command": return whileStopping(options.signal, stopNotice === void 0 ? void 0 : () => write.stderr(stopLine(stopNotice, routed.json)), () => runCommand(routed, {
|
|
8962
|
-
base: {
|
|
8963
|
-
cwd: options.cwd,
|
|
8964
|
-
env: options.env,
|
|
8965
|
-
packageRoot: packageRootOf(options.bin, options.cwd),
|
|
8966
|
-
progress: (message) => write.stderr(progressLine(message, routed.json)),
|
|
8967
|
-
secret: (name) => secretOf({
|
|
8968
|
-
cliName: cli.name,
|
|
8969
|
-
env: options.env,
|
|
8970
|
-
fileError
|
|
8971
|
-
}, name),
|
|
8972
|
-
fileError,
|
|
8973
|
-
version: cli.version,
|
|
8974
|
-
build: cli.build,
|
|
8975
|
-
self: selfOf(cli.name, options.bin)
|
|
8976
|
-
},
|
|
8977
|
-
writeStdout: (text) => write.stdout(text),
|
|
8978
|
-
signal: options.signal,
|
|
8979
|
-
format: misused(routed.spec),
|
|
8980
|
-
ports: portsOf(cli, options.ports),
|
|
8981
|
-
clock: options.clock ?? realClock,
|
|
8982
|
-
files: options.files ?? realFiles(),
|
|
8983
|
-
spawn: options.spawn ?? realSpawn,
|
|
8984
|
-
projectFile: Object.values(builtIns).includes(routed.spec.command) ? void 0 : cli.project,
|
|
8985
|
-
stdin: options.stdin ?? "",
|
|
8986
|
-
platform
|
|
8987
9362
|
}));
|
|
9363
|
+
case "command": return whileStopping(options.signal, stopNotice === void 0 ? void 0 : () => write.stderr(stopLine(stopNotice, routed.json)), () => runCommand(cli, routed, options, write, misused(routed.spec)));
|
|
8988
9364
|
}
|
|
8989
9365
|
}
|
|
9366
|
+
async function ranAlone(result) {
|
|
9367
|
+
return {
|
|
9368
|
+
result: await result,
|
|
9369
|
+
finishSideTask: noSideTask
|
|
9370
|
+
};
|
|
9371
|
+
}
|
|
8990
9372
|
//#endregion
|
|
8991
9373
|
//#region ../agent-cli/dist/run-process.js
|
|
8992
9374
|
function written(stream, text) {
|
|
@@ -9011,10 +9393,12 @@ async function runProcess(cli) {
|
|
|
9011
9393
|
stdin: process.stdin
|
|
9012
9394
|
}, {
|
|
9013
9395
|
stdout: (text) => process.stdout.write(text),
|
|
9014
|
-
stderr: (text) => process.stderr.write(text)
|
|
9396
|
+
stderr: (text) => process.stderr.write(text),
|
|
9397
|
+
result: async ({ stdout, stderr }) => {
|
|
9398
|
+
await written(process.stdout, stdout);
|
|
9399
|
+
await written(process.stderr, stderr);
|
|
9400
|
+
}
|
|
9015
9401
|
}, "stopping… (Ctrl-C again to quit now)");
|
|
9016
|
-
await written(process.stdout, result.stdout);
|
|
9017
|
-
await written(process.stderr, result.stderr);
|
|
9018
9402
|
process.exitCode = result.exitCode;
|
|
9019
9403
|
} finally {
|
|
9020
9404
|
process.off("SIGINT", onSignal);
|
|
@@ -9023,11 +9407,15 @@ async function runProcess(cli) {
|
|
|
9023
9407
|
process.exit();
|
|
9024
9408
|
}
|
|
9025
9409
|
//#endregion
|
|
9410
|
+
//#region package.json
|
|
9411
|
+
var version$1 = "0.7.0";
|
|
9412
|
+
var description = "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.";
|
|
9413
|
+
//#endregion
|
|
9026
9414
|
//#region src/build.ts
|
|
9027
9415
|
const build = {
|
|
9028
|
-
"sha": "
|
|
9416
|
+
"sha": "10574f5",
|
|
9029
9417
|
"dirty": false,
|
|
9030
|
-
"builtAt": "2026-10-
|
|
9418
|
+
"builtAt": "2026-10-20T03:42:41.670Z"
|
|
9031
9419
|
};
|
|
9032
9420
|
//#endregion
|
|
9033
9421
|
//#region src/steps.ts
|
|
@@ -9156,11 +9544,13 @@ async function writeTemplate(root, files, values) {
|
|
|
9156
9544
|
}
|
|
9157
9545
|
//#endregion
|
|
9158
9546
|
//#region src/version.ts
|
|
9159
|
-
const version =
|
|
9547
|
+
const version = version$1;
|
|
9160
9548
|
//#endregion
|
|
9161
9549
|
//#region src/create.ts
|
|
9162
9550
|
const { defineCommand } = agentCli();
|
|
9163
9551
|
const PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?([a-z0-9][a-z0-9._-]*)$/;
|
|
9552
|
+
const RELEASE_BRANCH = "release";
|
|
9553
|
+
const NO_REPOSITORY = "<!-- Set `repository` in package.json, then put here the `! npx -y skills add` line that `node dist/bin.js doctor` gives as the `skill` row's fix. -->";
|
|
9164
9554
|
function errorCode(error) {
|
|
9165
9555
|
return error instanceof Error && "code" in error ? error.code : void 0;
|
|
9166
9556
|
}
|
|
@@ -9173,6 +9563,17 @@ async function isFree(path) {
|
|
|
9173
9563
|
throw error;
|
|
9174
9564
|
}
|
|
9175
9565
|
}
|
|
9566
|
+
function skillInstallLine(repository, binName) {
|
|
9567
|
+
if (repository === void 0) return NO_REPOSITORY;
|
|
9568
|
+
return `\`! npx -y skills add ${`${repository.endsWith(".git") ? repository : `${repository}.git`}#${RELEASE_BRANCH}`} --skill ${binName} -g\``;
|
|
9569
|
+
}
|
|
9570
|
+
const MANIFEST = record(string(), unknown());
|
|
9571
|
+
async function setRepository(root, repository) {
|
|
9572
|
+
const path = join(root, "package.json");
|
|
9573
|
+
const manifest = MANIFEST.parse(JSON.parse(await readFile(path, "utf8")));
|
|
9574
|
+
const entries = Object.entries(manifest).flatMap((entry) => entry[0] === "description" ? [entry, ["repository", repository]] : [entry]);
|
|
9575
|
+
await writeFile(path, `${JSON.stringify(Object.fromEntries(entries), null, 2)}\n`);
|
|
9576
|
+
}
|
|
9176
9577
|
async function ensureFree(path) {
|
|
9177
9578
|
if (!await isFree(path)) throw new UsageError({
|
|
9178
9579
|
code: "TARGET_NOT_EMPTY",
|
|
@@ -9192,9 +9593,10 @@ const create = defineCommand({
|
|
|
9192
9593
|
options: object({
|
|
9193
9594
|
description: string().default("An Agent CLI.").describe("one line saying what the CLI does"),
|
|
9194
9595
|
install: boolean().default(true).describe("run pnpm install"),
|
|
9195
|
-
git: boolean().default(true).describe("create a git repository with an initial commit")
|
|
9596
|
+
git: boolean().default(true).describe("create a git repository with an initial commit"),
|
|
9597
|
+
repository: url({ protocol: /^https$/ }).optional().describe("the https URL of the CLI's git repository, where its skill is installed from")
|
|
9196
9598
|
}),
|
|
9197
|
-
plan: async ({ name, description, install, git }, ctx) => {
|
|
9599
|
+
plan: async ({ name, description, install, git, repository }, ctx) => {
|
|
9198
9600
|
const binName = PACKAGE_NAME.exec(name)?.[1] ?? name;
|
|
9199
9601
|
const path = resolve(ctx.cwd, binName);
|
|
9200
9602
|
await ensureFree(path);
|
|
@@ -9203,7 +9605,8 @@ const create = defineCommand({
|
|
|
9203
9605
|
binName,
|
|
9204
9606
|
description,
|
|
9205
9607
|
debugVariable: debugVariable(binName),
|
|
9206
|
-
runtimeVersion: version
|
|
9608
|
+
runtimeVersion: version,
|
|
9609
|
+
skillInstall: skillInstallLine(repository, binName)
|
|
9207
9610
|
};
|
|
9208
9611
|
return {
|
|
9209
9612
|
path,
|
|
@@ -9213,12 +9616,14 @@ const create = defineCommand({
|
|
|
9213
9616
|
install,
|
|
9214
9617
|
git
|
|
9215
9618
|
}),
|
|
9216
|
-
install
|
|
9619
|
+
install,
|
|
9620
|
+
repository
|
|
9217
9621
|
};
|
|
9218
9622
|
},
|
|
9219
9623
|
apply: async (plan, ctx) => {
|
|
9220
9624
|
await mkdir(plan.path, { recursive: true });
|
|
9221
9625
|
await writeTemplate(plan.path, plan.files, plan.values);
|
|
9626
|
+
if (plan.repository !== void 0) await setRepository(plan.path, plan.repository);
|
|
9222
9627
|
await runSteps(plan.steps, plan.path, ctx);
|
|
9223
9628
|
return {
|
|
9224
9629
|
path: plan.path,
|
|
@@ -9240,6 +9645,7 @@ const { defineCli } = agentCli();
|
|
|
9240
9645
|
await runProcess(defineCli({
|
|
9241
9646
|
name: "create-agent-cli",
|
|
9242
9647
|
version,
|
|
9648
|
+
description,
|
|
9243
9649
|
build,
|
|
9244
9650
|
errors: stepErrors,
|
|
9245
9651
|
command: create
|