@duyquangnvx/create-agent-cli 0.5.0 → 0.6.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 +34 -0
- package/README.md +2 -2
- package/dist/bin.js +1705 -1320
- 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_CODE = "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_CODE,
|
|
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,116 +6055,19 @@ 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;
|
|
5760
|
-
}
|
|
5761
|
-
function isMissingFile(error) {
|
|
5762
|
-
return errnoOf(error) === "ENOENT";
|
|
5763
|
-
}
|
|
5764
|
-
function isNothingThere(error) {
|
|
5765
|
-
return isMissingFile(error) || errnoOf(error) === "ENOTDIR";
|
|
5766
|
-
}
|
|
5767
|
-
function debugVariable(cliName) {
|
|
5768
|
-
return `${cliName.toUpperCase().replace(/[^A-Z0-9]/g, "_")}_DEBUG`;
|
|
5769
|
-
}
|
|
5770
|
-
function messageOf(error) {
|
|
5771
|
-
return error instanceof Error ? error.message : String(error);
|
|
5772
|
-
}
|
|
5773
|
-
function isDebug({ env, cliName }) {
|
|
5774
|
-
return Boolean(env[debugVariable(cliName)]);
|
|
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);
|
|
5775
6062
|
}
|
|
5776
|
-
function
|
|
5777
|
-
return
|
|
6063
|
+
function parseArgsOptions(known) {
|
|
6064
|
+
return Object.fromEntries(known.map(({ flag, takes }) => [flag.slice(2), { type: takes === "value" ? "string" : "boolean" }]));
|
|
5778
6065
|
}
|
|
5779
|
-
function
|
|
5780
|
-
if (
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
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
|
|
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
|
|
5845
6071
|
};
|
|
5846
6072
|
const took = token.index + 1;
|
|
5847
6073
|
const next = words[took];
|
|
@@ -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,7 +6770,68 @@ function contextSpawn(run, defaults, fileError) {
|
|
|
6537
6770
|
};
|
|
6538
6771
|
}
|
|
6539
6772
|
//#endregion
|
|
6540
|
-
//#region ../agent-cli/dist/
|
|
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);
|
|
6778
|
+
}
|
|
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;
|
|
6786
|
+
}
|
|
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
|
|
6541
6835
|
const REGISTRY_UNREACHABLE = "REGISTRY_UNREACHABLE";
|
|
6542
6836
|
const REGISTRY_AUTH = "REGISTRY_AUTH";
|
|
6543
6837
|
const INSTALL_FAILED = "INSTALL_FAILED";
|
|
@@ -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,46 +7049,671 @@ 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
|
-
});
|
|
6777
|
-
}
|
|
6778
|
-
//#endregion
|
|
6779
|
-
//#region ../agent-cli/dist/cost.js
|
|
6780
|
-
const NOT_CONFIRMED = "NOT_CONFIRMED";
|
|
6781
|
-
/** Refuses a run whose Plan states a cost the caller has not approved with `--yes`. */
|
|
6782
|
-
function checkCost({ invocation, commandLine, yes }, cost) {
|
|
6783
|
-
if (cost === void 0 || yes) return;
|
|
6784
|
-
throw new CliError({
|
|
6785
|
-
code: NOT_CONFIRMED,
|
|
6786
|
-
message: `\`${commandLine}\` needs ${YES_FLAG.flag}: ${cost}`,
|
|
6787
|
-
hint: `to approve the cost, run \`${commandLineOf(invocation, { add: [YES_FLAG.flag] })}\``
|
|
6788
|
-
});
|
|
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;
|
|
6789
7068
|
}
|
|
6790
7069
|
//#endregion
|
|
6791
|
-
//#region ../agent-cli/dist/
|
|
6792
|
-
const
|
|
6793
|
-
|
|
6794
|
-
const
|
|
6795
|
-
const
|
|
6796
|
-
|
|
6797
|
-
|
|
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];
|
|
7088
|
+
}
|
|
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
|
+
};
|
|
7156
|
+
}
|
|
7157
|
+
//#endregion
|
|
7158
|
+
//#region ../agent-cli/dist/built-ins/doctor-rows.js
|
|
7159
|
+
function ok(message) {
|
|
7160
|
+
return {
|
|
7161
|
+
state: "ok",
|
|
7162
|
+
message
|
|
7163
|
+
};
|
|
7164
|
+
}
|
|
7165
|
+
function buildRow(cli) {
|
|
7166
|
+
return {
|
|
7167
|
+
name: "build",
|
|
7168
|
+
run: () => ok(versionLine(cli))
|
|
7169
|
+
};
|
|
7170
|
+
}
|
|
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
|
+
function projectRow(projectFile) {
|
|
7194
|
+
const { file } = projectFile;
|
|
7195
|
+
return {
|
|
7196
|
+
name: "project",
|
|
7197
|
+
run: (ctx) => {
|
|
7198
|
+
let project;
|
|
7199
|
+
try {
|
|
7200
|
+
project = projectOf(projectFile, ctx.cwd, ctx.fileError);
|
|
7201
|
+
} catch (error) {
|
|
7202
|
+
if (error instanceof CliError && error.code === "PROJECT_INVALID") return {
|
|
7203
|
+
state: "problem",
|
|
7204
|
+
message: error.message
|
|
7205
|
+
};
|
|
7206
|
+
throw error;
|
|
7207
|
+
}
|
|
7208
|
+
return ok(project === void 0 ? `none found: no ${file} at or above ${ctx.cwd}` : join(project.root, file));
|
|
7209
|
+
}
|
|
7210
|
+
};
|
|
7211
|
+
}
|
|
7212
|
+
function installRow(cli, { bin, node }) {
|
|
7213
|
+
return {
|
|
7214
|
+
name: "install",
|
|
7215
|
+
advisory: true,
|
|
7216
|
+
run: async (ctx) => {
|
|
7217
|
+
const { install } = cli;
|
|
7218
|
+
if (install === void 0) return ok(`${cli.name} declares no install, so it has no \`update\``);
|
|
7219
|
+
try {
|
|
7220
|
+
return ok(`a global npm install under ${(await globalInstallOf(bin, npmContext(cli, install, ctx, node))).prefix}`);
|
|
7221
|
+
} catch (error) {
|
|
7222
|
+
if (error instanceof CliError && error.code === "NOT_GLOBAL_INSTALL") return {
|
|
7223
|
+
state: "problem",
|
|
7224
|
+
message: error.message,
|
|
7225
|
+
fix: installCommandLine(install)
|
|
7226
|
+
};
|
|
7227
|
+
throw error;
|
|
7228
|
+
}
|
|
7229
|
+
}
|
|
7230
|
+
};
|
|
7231
|
+
}
|
|
7232
|
+
function registryRow(cli, node) {
|
|
7233
|
+
return {
|
|
7234
|
+
name: "registry",
|
|
7235
|
+
advisory: true,
|
|
7236
|
+
run: async (ctx) => {
|
|
7237
|
+
const { install } = cli;
|
|
7238
|
+
if (install === void 0) return ok(`${cli.name} declares no registry to compare this build with`);
|
|
7239
|
+
const latest = await latestVersion(npmContext(cli, install, ctx, node));
|
|
7240
|
+
const standing = standingOf(cli.version, latest);
|
|
7241
|
+
const head = `${install.registry} has ${latest} as latest: this build`;
|
|
7242
|
+
if (standing === "behind") return {
|
|
7243
|
+
state: "problem",
|
|
7244
|
+
message: `${head} (${cli.version}) is older`,
|
|
7245
|
+
fix: `${cli.name} update`
|
|
7246
|
+
};
|
|
7247
|
+
return ok(`${head} is ${standing === "current" ? "current" : `newer (${cli.version})`}`);
|
|
7248
|
+
}
|
|
7249
|
+
};
|
|
7250
|
+
}
|
|
7251
|
+
const SKILL_STATE_NOTES = {
|
|
7252
|
+
current: "the same as this build",
|
|
7253
|
+
behind: "older than this build",
|
|
7254
|
+
ahead: "newer than this build",
|
|
7255
|
+
unversioned: "states no metadata.version",
|
|
7256
|
+
unreadable: "could not be read"
|
|
7257
|
+
};
|
|
7258
|
+
function describeCopy({ path, version, state }) {
|
|
7259
|
+
return `${path}${version === void 0 ? "" : ` ${version}`} (${SKILL_STATE_NOTES[state]})`;
|
|
7260
|
+
}
|
|
7261
|
+
function skillRow(cli) {
|
|
7262
|
+
return {
|
|
7263
|
+
name: "skill",
|
|
7264
|
+
run: async (ctx) => {
|
|
7265
|
+
const { copies, fix } = await skillReport(cli, cli.version, ctx);
|
|
7266
|
+
const message = copies.length === 0 ? `no copy of the ${cli.name} skill is installed` : copies.map(describeCopy).join("; ");
|
|
7267
|
+
return fix === void 0 ? ok(message) : {
|
|
7268
|
+
state: "ok",
|
|
7269
|
+
message,
|
|
7270
|
+
fix
|
|
7271
|
+
};
|
|
7272
|
+
}
|
|
7273
|
+
};
|
|
7274
|
+
}
|
|
7275
|
+
/** Every row `doctor` reports, in order: the fixed rows around the CLI's own and its tools'. */
|
|
7276
|
+
function doctorChecks(cli, launch) {
|
|
7277
|
+
return [
|
|
7278
|
+
buildRow(cli),
|
|
7279
|
+
nodeRow(cli),
|
|
7280
|
+
...cli.project === void 0 ? [] : [projectRow(cli.project)],
|
|
7281
|
+
...cli.doctor ?? [],
|
|
7282
|
+
...toolRows(cli.tools ?? [], cli.commands),
|
|
7283
|
+
installRow(cli, launch),
|
|
7284
|
+
registryRow(cli, launch.node),
|
|
7285
|
+
skillRow(cli)
|
|
7286
|
+
];
|
|
7287
|
+
}
|
|
7288
|
+
//#endregion
|
|
7289
|
+
//#region ../agent-cli/dist/built-ins/doctor.js
|
|
7290
|
+
const DOCTOR_PROBLEMS = "DOCTOR_PROBLEMS";
|
|
7291
|
+
const DEFAULT_DEADLINE_MS = 1e4;
|
|
7292
|
+
const MS_PER_SECOND = 1e3;
|
|
7293
|
+
const MIN_LABEL_WIDTH = 8;
|
|
7294
|
+
const reportSchema = object({
|
|
7295
|
+
rows: array(object({
|
|
7296
|
+
check: string(),
|
|
7297
|
+
state: _enum([
|
|
7298
|
+
"ok",
|
|
7299
|
+
"problem",
|
|
7300
|
+
"skipped"
|
|
7301
|
+
]),
|
|
7302
|
+
message: string(),
|
|
7303
|
+
fix: string().optional(),
|
|
7304
|
+
code: string().optional()
|
|
7305
|
+
})),
|
|
7306
|
+
next: array(string())
|
|
7307
|
+
});
|
|
7308
|
+
function problemOf(check, error, { signal, deadline, ms }) {
|
|
7309
|
+
if (!signal.aborted && deadline.aborted && error === deadline.reason) return {
|
|
7310
|
+
state: "problem",
|
|
7311
|
+
message: `${check.name} did not answer within ${ms / MS_PER_SECOND} s`
|
|
7312
|
+
};
|
|
7313
|
+
if (error instanceof CliError) return {
|
|
7314
|
+
state: "problem",
|
|
7315
|
+
message: `${error.message}; ${error.hint}`,
|
|
7316
|
+
code: error.code
|
|
7317
|
+
};
|
|
7318
|
+
return {
|
|
7319
|
+
state: "problem",
|
|
7320
|
+
message: `the ${check.name} row hit a bug: ${messageOf(error)}`
|
|
7321
|
+
};
|
|
7322
|
+
}
|
|
7323
|
+
function withSignal(ctx, signal) {
|
|
7324
|
+
return Object.create(ctx, { signal: { value: signal } });
|
|
7325
|
+
}
|
|
7326
|
+
async function rowOf(check, ctx) {
|
|
7327
|
+
const ms = check.deadlineMs ?? DEFAULT_DEADLINE_MS;
|
|
7328
|
+
const signal = ctx.deadline(ms);
|
|
7329
|
+
let finding;
|
|
7330
|
+
try {
|
|
7331
|
+
finding = await Promise.race([Promise.resolve().then(() => check.run(withSignal(ctx, signal))), untilAborted(signal)]);
|
|
7332
|
+
} catch (error) {
|
|
7333
|
+
if (ctx.signal.aborted) return void 0;
|
|
7334
|
+
finding = problemOf(check, error, {
|
|
7335
|
+
signal: ctx.signal,
|
|
7336
|
+
deadline: signal,
|
|
7337
|
+
ms
|
|
7338
|
+
});
|
|
7339
|
+
}
|
|
7340
|
+
return {
|
|
7341
|
+
row: {
|
|
7342
|
+
check: check.name,
|
|
7343
|
+
...finding
|
|
7344
|
+
},
|
|
7345
|
+
advisory: check.advisory === true
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
function nextOf(rows) {
|
|
7349
|
+
return [...new Set(rows.flatMap(({ fix }) => fix === void 0 ? [] : [fix]))];
|
|
7350
|
+
}
|
|
7351
|
+
function render({ rows, next }, style) {
|
|
7352
|
+
const width = Math.max(MIN_LABEL_WIDTH, ...rows.map(({ check }) => check.length)) + 2;
|
|
7353
|
+
const stateWidth = Math.max(...rows.map(({ state }) => state.length)) + 2;
|
|
7354
|
+
return [...rows.map(({ check, state, message }) => {
|
|
7355
|
+
const label = state === "problem" ? style.red(state) : state;
|
|
7356
|
+
return `${check.padEnd(width)}${label}${" ".repeat(stateWidth - state.length)}${message}`;
|
|
7357
|
+
}), ...next.map((fix) => `${"next".padEnd(width)}${fix}`)].join("\n");
|
|
7358
|
+
}
|
|
7359
|
+
function failure(cliName, problems) {
|
|
7360
|
+
const errors = problems.map(({ check, message, fix, code }) => new CliError({
|
|
7361
|
+
code: code ?? "DOCTOR_PROBLEMS",
|
|
7362
|
+
message: `${cliName} doctor found a problem in ${check}: ${message}`,
|
|
7363
|
+
hint: fix === void 0 ? "the row says what is wrong" : `run ${fix}, then run doctor again`
|
|
7364
|
+
}));
|
|
7365
|
+
return new AggregateError(errors);
|
|
7366
|
+
}
|
|
7367
|
+
/** The built-in `doctor`: the fixed rows around the CLI's own, each under its own deadline. */
|
|
7368
|
+
function doctorCommand(cli, launch) {
|
|
7369
|
+
return defineCommand$1({
|
|
7370
|
+
name: "doctor",
|
|
7371
|
+
description: "check the setup and say what fixes each problem",
|
|
7372
|
+
examples: [{
|
|
7373
|
+
command: `${cli.name} doctor`,
|
|
7374
|
+
note: "check the setup and list the commands that fix it"
|
|
7375
|
+
}, {
|
|
7376
|
+
command: `${cli.name} doctor --json`,
|
|
7377
|
+
note: "get the rows and fixes as data"
|
|
7378
|
+
}],
|
|
7379
|
+
effect: "read",
|
|
7380
|
+
output: reportSchema,
|
|
7381
|
+
run: async (_input, ctx) => {
|
|
7382
|
+
const checked = (await Promise.all(doctorChecks(cli, launch).map((check) => rowOf(check, ctx)))).filter((row) => row !== void 0);
|
|
7383
|
+
const rows = checked.map(({ row }) => row);
|
|
7384
|
+
const report = {
|
|
7385
|
+
rows,
|
|
7386
|
+
next: nextOf(rows)
|
|
7387
|
+
};
|
|
7388
|
+
if (ctx.signal.aborted) {
|
|
7389
|
+
ctx.deliver(report);
|
|
7390
|
+
ctx.signal.throwIfAborted();
|
|
7391
|
+
}
|
|
7392
|
+
const problems = checked.filter(({ row, advisory }) => row.state === "problem" && !advisory).map(({ row }) => row);
|
|
7393
|
+
if (problems.length > 0) {
|
|
7394
|
+
ctx.deliver(report);
|
|
7395
|
+
throw failure(cli.name, problems);
|
|
7396
|
+
}
|
|
7397
|
+
return report;
|
|
7398
|
+
},
|
|
7399
|
+
render
|
|
7400
|
+
});
|
|
7401
|
+
}
|
|
7402
|
+
//#endregion
|
|
7403
|
+
//#region ../agent-cli/dist/interrupts.js
|
|
7404
|
+
const INTERRUPTED = "INTERRUPTED";
|
|
7405
|
+
const DEADLINE_EXCEEDED = "DEADLINE_EXCEEDED";
|
|
7406
|
+
/** How long an interrupted Command may take to settle before the run ends without it. */
|
|
7407
|
+
const GRACE_MS = 3e3;
|
|
7408
|
+
const GRACE_OVER = Symbol("grace over");
|
|
7409
|
+
function interruptedError() {
|
|
7410
|
+
return new CliError({
|
|
7411
|
+
code: INTERRUPTED,
|
|
7412
|
+
message: "interrupted before it finished",
|
|
7413
|
+
hint: "run the command again"
|
|
7414
|
+
});
|
|
7415
|
+
}
|
|
7416
|
+
const WAIT_HINT = "run it again later, when the service it waits on may answer faster";
|
|
7417
|
+
function deadlineError(commandLine, ms, hint, bound = "deadline") {
|
|
7418
|
+
return new CliError({
|
|
7419
|
+
code: DEADLINE_EXCEEDED,
|
|
7420
|
+
message: `${commandLine} ran past its ${ms} ms ${bound}`,
|
|
7421
|
+
hint
|
|
7422
|
+
});
|
|
7423
|
+
}
|
|
7424
|
+
/** One Command run's cancellation: its signal, its deadlines and the steps it must finish. */
|
|
7425
|
+
var RunControl = class {
|
|
7426
|
+
signal;
|
|
7427
|
+
#controller = new AbortController();
|
|
7428
|
+
#commandLine;
|
|
7429
|
+
#outer;
|
|
7430
|
+
#onOuterAbort = () => this.#controller.abort(interruptedError());
|
|
7431
|
+
/** Each running must-finish step, tracked until it settles, with its name. */
|
|
7432
|
+
#steps = /* @__PURE__ */ new Map();
|
|
7433
|
+
#progress;
|
|
7434
|
+
#clock;
|
|
7435
|
+
#disposed = new AbortController();
|
|
7436
|
+
/** The reasons this run's deadlines and timeouts aborted with, to tell them in a Command's error. */
|
|
7437
|
+
#abortReasons = /* @__PURE__ */ new WeakSet();
|
|
7438
|
+
#graceCancel = new AbortController();
|
|
7439
|
+
#endGrace = () => {};
|
|
7440
|
+
#graceOver = new Promise((resolve) => {
|
|
7441
|
+
this.#endGrace = resolve;
|
|
7442
|
+
});
|
|
7443
|
+
constructor({ commandLine, outer, clock, progress, runDeadline }) {
|
|
7444
|
+
this.#commandLine = commandLine;
|
|
7445
|
+
this.#outer = outer;
|
|
7446
|
+
this.#clock = clock;
|
|
7447
|
+
this.#progress = progress;
|
|
7448
|
+
this.signal = this.#controller.signal;
|
|
7449
|
+
this.signal.addEventListener("abort", () => this.#onStop(), { once: true });
|
|
7450
|
+
if (outer?.aborted === true) this.#onOuterAbort();
|
|
7451
|
+
else outer?.addEventListener("abort", this.#onOuterAbort, { once: true });
|
|
7452
|
+
if (runDeadline !== void 0) {
|
|
7453
|
+
const { ms, hint } = runDeadline;
|
|
7454
|
+
after(clock, ms, this.#disposed.signal, () => this.#controller.abort(deadlineError(commandLine, ms, hint())));
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7457
|
+
deadline(ms) {
|
|
7458
|
+
return AbortSignal.any([this.signal, this.#abortsAfter(ms, "deadline")]);
|
|
7459
|
+
}
|
|
7460
|
+
timeout(ms) {
|
|
7461
|
+
return this.#abortsAfter(ms, "timeout");
|
|
7462
|
+
}
|
|
7463
|
+
#abortsAfter(ms, bound) {
|
|
7464
|
+
const controller = new AbortController();
|
|
7465
|
+
after(this.#clock, ms, this.#disposed.signal, () => {
|
|
7466
|
+
const reason = deadlineError(this.#commandLine, ms, WAIT_HINT, bound);
|
|
7467
|
+
this.#abortReasons.add(reason);
|
|
7468
|
+
controller.abort(reason);
|
|
7469
|
+
});
|
|
7470
|
+
return controller.signal;
|
|
7471
|
+
}
|
|
7472
|
+
async runToEnd(name, work) {
|
|
7473
|
+
this.#graceCancel.abort();
|
|
7474
|
+
if (this.signal.aborted) this.#finishing(name);
|
|
7475
|
+
const step = work();
|
|
7476
|
+
const settled = step.then(() => {}, () => {});
|
|
7477
|
+
this.#steps.set(settled, name);
|
|
7478
|
+
try {
|
|
7479
|
+
return await step;
|
|
7480
|
+
} finally {
|
|
7481
|
+
this.#steps.delete(settled);
|
|
7482
|
+
this.#startGrace();
|
|
7483
|
+
}
|
|
7484
|
+
}
|
|
7485
|
+
/** Waits for the Command, its must-finish steps, and no longer than the grace once interrupted. */
|
|
7486
|
+
async settle(work) {
|
|
7487
|
+
try {
|
|
7488
|
+
const value = await Promise.race([work, this.#graceOver]);
|
|
7489
|
+
if (this.signal.aborted || value === GRACE_OVER) throw this.signal.reason;
|
|
7490
|
+
return value;
|
|
7491
|
+
} finally {
|
|
7492
|
+
await this.#stepsDone();
|
|
7493
|
+
this.close();
|
|
7494
|
+
}
|
|
7495
|
+
}
|
|
7496
|
+
/**
|
|
7497
|
+
* The error a run ends with: an interrupt or the run deadline outranks what the Command threw,
|
|
7498
|
+
* unless the Command threw its own `INTERRUPTED`, saying what it finished before it stopped.
|
|
7499
|
+
* Otherwise each leaf that is not a `CliError` and whose cause chain holds a deadline's or timeout's
|
|
7500
|
+
* abort is reported as that abort, so a declared error keeps its own code.
|
|
7501
|
+
*/
|
|
7502
|
+
errorAfter(error) {
|
|
7503
|
+
if (this.signal.aborted) return error instanceof CliError && error.code === "INTERRUPTED" ? error : this.signal.reason;
|
|
7504
|
+
const leaves = errorsOf(error).map((leaf) => this.#abortIn(leaf) ?? leaf);
|
|
7505
|
+
return leaves.length === 1 ? leaves[0] : new AggregateError(leaves);
|
|
7506
|
+
}
|
|
7507
|
+
#abortIn(error) {
|
|
7508
|
+
if (error instanceof CliError) return void 0;
|
|
7509
|
+
return causesOf(error).find((each) => each instanceof CliError && this.#abortReasons.has(each));
|
|
7510
|
+
}
|
|
7511
|
+
#onStop() {
|
|
7512
|
+
for (const name of this.#steps.values()) this.#finishing(name);
|
|
7513
|
+
this.#startGrace();
|
|
7514
|
+
}
|
|
7515
|
+
#finishing(name) {
|
|
7516
|
+
this.#progress(`finishing ${name}`);
|
|
7517
|
+
}
|
|
7518
|
+
#startGrace() {
|
|
7519
|
+
if (this.signal.aborted && this.#steps.size === 0) {
|
|
7520
|
+
this.#graceCancel.abort();
|
|
7521
|
+
this.#graceCancel = new AbortController();
|
|
7522
|
+
after(this.#clock, GRACE_MS, this.#graceCancel.signal, () => this.#endGrace(GRACE_OVER));
|
|
7523
|
+
}
|
|
7524
|
+
}
|
|
7525
|
+
async #stepsDone() {
|
|
7526
|
+
while (this.#steps.size > 0) await Promise.all(this.#steps.keys());
|
|
7527
|
+
}
|
|
7528
|
+
/** Stops the run's timers and its hold on the caller's signal, for a run that never settles. */
|
|
7529
|
+
close() {
|
|
7530
|
+
this.#graceCancel.abort();
|
|
7531
|
+
this.#disposed.abort();
|
|
7532
|
+
this.#outer?.removeEventListener("abort", this.#onOuterAbort);
|
|
7533
|
+
}
|
|
7534
|
+
};
|
|
7535
|
+
//#endregion
|
|
7536
|
+
//#region ../agent-cli/dist/built-ins/upgrade-notes.js
|
|
7537
|
+
const RELEASE_HEADING = /^## v?(\S+)/;
|
|
7538
|
+
function releasesIn(changelog) {
|
|
7539
|
+
const releases = [];
|
|
7540
|
+
let current;
|
|
7541
|
+
for (const line of changelog.split(/\r?\n/)) {
|
|
7542
|
+
const heading = RELEASE_HEADING.exec(line);
|
|
7543
|
+
if (heading !== null) {
|
|
7544
|
+
const version = heading[1] ?? "";
|
|
7545
|
+
current = isVersion(version) ? {
|
|
7546
|
+
version,
|
|
7547
|
+
lines: []
|
|
7548
|
+
} : void 0;
|
|
7549
|
+
if (current !== void 0) releases.push(current);
|
|
7550
|
+
} else current?.lines.push(line);
|
|
7551
|
+
}
|
|
7552
|
+
return releases.map(({ version, lines }) => ({
|
|
7553
|
+
version,
|
|
7554
|
+
notes: lines.join("\n").trim()
|
|
7555
|
+
}));
|
|
7556
|
+
}
|
|
7557
|
+
/**
|
|
7558
|
+
* What changed in each release after `from` up to `to`, oldest first, from the CHANGELOG.md in
|
|
7559
|
+
* `packageDir`; none when the package ships no CHANGELOG.
|
|
7560
|
+
*/
|
|
7561
|
+
async function upgradeNotes(packageDir, from, to) {
|
|
7562
|
+
let changelog;
|
|
7563
|
+
try {
|
|
7564
|
+
changelog = await readFile(join(packageDir, "CHANGELOG.md"), "utf8");
|
|
7565
|
+
} catch (error) {
|
|
7566
|
+
if (isMissingFile(error)) return [];
|
|
7567
|
+
throw error;
|
|
7568
|
+
}
|
|
7569
|
+
return releasesIn(changelog).filter(({ version }) => compareVersions(version, from) > 0 && compareVersions(version, to) <= 0).sort((a, b) => compareVersions(a.version, b.version));
|
|
7570
|
+
}
|
|
7571
|
+
//#endregion
|
|
7572
|
+
//#region ../agent-cli/dist/built-ins/update.js
|
|
7573
|
+
const updateSchema = object({
|
|
7574
|
+
from: string(),
|
|
7575
|
+
latest: string(),
|
|
7576
|
+
installed: object({
|
|
7577
|
+
version: string(),
|
|
7578
|
+
prefix: string()
|
|
7579
|
+
}).nullable(),
|
|
7580
|
+
upgrades: array(object({
|
|
7581
|
+
version: string(),
|
|
7582
|
+
notes: string()
|
|
7583
|
+
})),
|
|
7584
|
+
next: array(string())
|
|
7585
|
+
});
|
|
7586
|
+
function nothingToInstall({ from, latest }) {
|
|
7587
|
+
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`;
|
|
7588
|
+
}
|
|
7589
|
+
function renderUpdate(cli, install, update) {
|
|
7590
|
+
const { installed } = update;
|
|
7591
|
+
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}`)];
|
|
7592
|
+
const next = update.next.map((command) => `next: ${command}, so the ${cli.name} skill describes ${update.latest}`);
|
|
7593
|
+
return (next.length === 0 ? head : [
|
|
7594
|
+
...head,
|
|
7595
|
+
"",
|
|
7596
|
+
...next
|
|
7597
|
+
]).join("\n");
|
|
7598
|
+
}
|
|
7599
|
+
async function skillNext(cli, latest, ctx) {
|
|
7600
|
+
const { fix } = await skillReport(cli, latest, ctx);
|
|
7601
|
+
return fix === void 0 ? [] : [fix];
|
|
7602
|
+
}
|
|
7603
|
+
function interruptedAfterInstall(plan) {
|
|
7604
|
+
return new CliError({
|
|
7605
|
+
code: INTERRUPTED,
|
|
7606
|
+
message: `interrupted, but ${plan.package}@${plan.latest} had already been installed with the npm under ${plan.prefix}, replacing ${plan.from}`,
|
|
7607
|
+
hint: "nothing to run again: run the commands under next"
|
|
7608
|
+
});
|
|
7609
|
+
}
|
|
7610
|
+
/** The built-in `update`, for a CLI installed globally with npm. */
|
|
7611
|
+
function updateCommand(cli, install, { bin, node }) {
|
|
7612
|
+
return defineCommand$1({
|
|
7613
|
+
name: "update",
|
|
7614
|
+
description: "install the latest version of this CLI from its registry",
|
|
7615
|
+
examples: [{
|
|
7616
|
+
command: `${cli.name} update`,
|
|
7617
|
+
note: "install the latest version and show what changed"
|
|
7618
|
+
}, {
|
|
7619
|
+
command: `${cli.name} update --dry-run`,
|
|
7620
|
+
note: "show the version it would install"
|
|
7621
|
+
}],
|
|
7622
|
+
effect: "write",
|
|
7623
|
+
output: updateSchema,
|
|
7624
|
+
plan: async (_input, ctx) => {
|
|
7625
|
+
const npm = npmContext(cli, install, ctx, node);
|
|
7626
|
+
const copy = await globalInstallOf(bin, npm);
|
|
7627
|
+
return {
|
|
7628
|
+
package: install.package,
|
|
7629
|
+
from: cli.version,
|
|
7630
|
+
latest: await latestVersion(npm),
|
|
7631
|
+
prefix: copy.prefix,
|
|
7632
|
+
packageDir: copy.packageDir
|
|
7633
|
+
};
|
|
7634
|
+
},
|
|
7635
|
+
apply: async (plan, ctx) => {
|
|
7636
|
+
const { from, latest, prefix } = plan;
|
|
7637
|
+
if (standingOf(from, latest) !== "behind") return {
|
|
7638
|
+
from,
|
|
7639
|
+
latest,
|
|
7640
|
+
installed: null,
|
|
7641
|
+
upgrades: [],
|
|
7642
|
+
next: await skillNext(cli, latest, ctx)
|
|
7643
|
+
};
|
|
7644
|
+
ctx.signal.throwIfAborted();
|
|
7645
|
+
ctx.progress(`installing ${plan.package}@${latest} with the npm under ${prefix}…`);
|
|
7646
|
+
await ctx.runToEnd(`installing ${plan.package}@${latest}`, () => installGlobally(latest, npmContext(cli, install, ctx, node)));
|
|
7647
|
+
const update = {
|
|
7648
|
+
from,
|
|
7649
|
+
latest,
|
|
7650
|
+
installed: {
|
|
7651
|
+
version: latest,
|
|
7652
|
+
prefix
|
|
7653
|
+
},
|
|
7654
|
+
upgrades: await upgradeNotes(plan.packageDir, from, latest),
|
|
7655
|
+
next: await skillNext(cli, latest, ctx)
|
|
7656
|
+
};
|
|
7657
|
+
if (ctx.signal.aborted) {
|
|
7658
|
+
ctx.deliver(update);
|
|
7659
|
+
throw interruptedAfterInstall(plan);
|
|
7660
|
+
}
|
|
7661
|
+
return update;
|
|
7662
|
+
},
|
|
7663
|
+
render: (update) => renderUpdate(cli, install, update),
|
|
7664
|
+
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)
|
|
7665
|
+
});
|
|
7666
|
+
}
|
|
7667
|
+
//#endregion
|
|
7668
|
+
//#region ../agent-cli/dist/built-ins/commands.js
|
|
7669
|
+
/** The Commands the Runtime adds to a multi-Command CLI: `update` only when it declares an install. */
|
|
7670
|
+
function builtInCommands(cli, launch) {
|
|
7671
|
+
return {
|
|
7672
|
+
doctor: doctorCommand(cli, launch),
|
|
7673
|
+
...cli.install === void 0 ? {} : { update: updateCommand(cli, cli.install, launch) }
|
|
7674
|
+
};
|
|
7675
|
+
}
|
|
7676
|
+
//#endregion
|
|
7677
|
+
//#region ../agent-cli/dist/confirm.js
|
|
7678
|
+
const CONFIRMATION_REQUIRED = "CONFIRMATION_REQUIRED";
|
|
7679
|
+
const CONFIRMATION_MISMATCH = "CONFIRMATION_MISMATCH";
|
|
7680
|
+
function checkConfirmation({ invocation, commandLine, given }, expected) {
|
|
7681
|
+
if (given === expected) return;
|
|
7682
|
+
const hint = `to confirm, run \`${commandLineOf(invocation, {
|
|
7683
|
+
remove: [CONFIRM_FLAG.flag],
|
|
7684
|
+
add: [CONFIRM_FLAG.flag, expected]
|
|
7685
|
+
})}\``;
|
|
7686
|
+
if (given === void 0) throw new UsageError({
|
|
7687
|
+
code: CONFIRMATION_REQUIRED,
|
|
7688
|
+
message: `\`${commandLine}\` is destructive and needs ${CONFIRM_FLAG.flag}`,
|
|
7689
|
+
hint
|
|
7690
|
+
});
|
|
7691
|
+
throw new UsageError({
|
|
7692
|
+
code: CONFIRMATION_MISMATCH,
|
|
7693
|
+
message: `${CONFIRM_FLAG.flag} ${JSON.stringify(given)} does not match the target of \`${commandLine}\``,
|
|
7694
|
+
hint
|
|
7695
|
+
});
|
|
7696
|
+
}
|
|
7697
|
+
//#endregion
|
|
7698
|
+
//#region ../agent-cli/dist/cost.js
|
|
7699
|
+
const NOT_CONFIRMED = "NOT_CONFIRMED";
|
|
7700
|
+
/** Refuses a run whose Plan states a cost the caller has not approved with `--yes`. */
|
|
7701
|
+
function checkCost({ invocation, commandLine, yes }, cost) {
|
|
7702
|
+
if (cost === void 0 || yes) return;
|
|
7703
|
+
throw new CliError({
|
|
7704
|
+
code: NOT_CONFIRMED,
|
|
7705
|
+
message: `\`${commandLine}\` needs ${YES_FLAG.flag}: ${cost}`,
|
|
7706
|
+
hint: `to approve the cost, run \`${commandLineOf(invocation, { add: [YES_FLAG.flag] })}\``
|
|
7707
|
+
});
|
|
7708
|
+
}
|
|
7709
|
+
//#endregion
|
|
7710
|
+
//#region ../agent-cli/dist/agent.js
|
|
7711
|
+
const AGENT_NAME = /^[a-zA-Z0-9_-]+$/u;
|
|
7712
|
+
const isSet = (name) => (env) => (env[name] ?? "") !== "";
|
|
7713
|
+
const equals = (name, value) => (env) => env[name] === value;
|
|
7714
|
+
const MARKERS = [
|
|
7715
|
+
(env) => AGENT_NAME.test(env.AI_AGENT ?? ""),
|
|
7716
|
+
equals("AGENT", "amp"),
|
|
6798
7717
|
isSet("CODEX_SANDBOX"),
|
|
6799
7718
|
isSet("CODEX_CI"),
|
|
6800
7719
|
isSet("CODEX_THREAD_ID"),
|
|
@@ -6877,159 +7796,6 @@ function classifyErrno(error, context) {
|
|
|
6877
7796
|
}
|
|
6878
7797
|
}
|
|
6879
7798
|
//#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
7799
|
//#region ../agent-cli/dist/operator.js
|
|
7034
7800
|
const NEEDS_OPERATOR = "NEEDS_OPERATOR";
|
|
7035
7801
|
/** Fails with `NEEDS_OPERATOR` when a Coding agent runs an Operator Command. */
|
|
@@ -7160,12 +7926,19 @@ function realFiles() {
|
|
|
7160
7926
|
force: true
|
|
7161
7927
|
}),
|
|
7162
7928
|
mkdir: async (path, options) => {
|
|
7929
|
+
const mode = options?.mode;
|
|
7163
7930
|
if (options?.exclusive !== true) {
|
|
7164
|
-
await mkdir(path, {
|
|
7931
|
+
await mkdir(path, {
|
|
7932
|
+
recursive: true,
|
|
7933
|
+
mode
|
|
7934
|
+
});
|
|
7165
7935
|
return;
|
|
7166
7936
|
}
|
|
7167
|
-
await mkdir(dirname(path), {
|
|
7168
|
-
|
|
7937
|
+
await mkdir(dirname(path), {
|
|
7938
|
+
recursive: true,
|
|
7939
|
+
mode
|
|
7940
|
+
});
|
|
7941
|
+
await mkdir(path, { mode });
|
|
7169
7942
|
},
|
|
7170
7943
|
stat: async (path) => {
|
|
7171
7944
|
try {
|
|
@@ -7277,52 +8050,6 @@ async function probeOutputs({ files, cwd, fileError }, outputs) {
|
|
|
7277
8050
|
}));
|
|
7278
8051
|
}
|
|
7279
8052
|
//#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));
|
|
7324
|
-
}
|
|
7325
|
-
//#endregion
|
|
7326
8053
|
//#region ../agent-cli/dist/exit-classes.js
|
|
7327
8054
|
const SIGNAL_EXIT_CODES = {
|
|
7328
8055
|
SIGINT: 130,
|
|
@@ -7335,46 +8062,44 @@ const EXIT_CODES = {
|
|
|
7335
8062
|
wait: 75,
|
|
7336
8063
|
bug: 70
|
|
7337
8064
|
};
|
|
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
|
-
}
|
|
8065
|
+
const RUNTIME_EXIT_CLASSES = {
|
|
8066
|
+
[INVALID_INPUT]: "caller",
|
|
8067
|
+
[UNKNOWN_OPTION]: "caller",
|
|
8068
|
+
[UNKNOWN_COMMAND]: "caller",
|
|
8069
|
+
[UNKNOWN_FIELD]: "caller",
|
|
8070
|
+
[CONFIRMATION_REQUIRED]: "caller",
|
|
8071
|
+
[CONFIRMATION_MISMATCH]: "caller",
|
|
8072
|
+
[NOT_CONFIRMED]: "operator",
|
|
8073
|
+
[NEEDS_OPERATOR]: "operator",
|
|
8074
|
+
[OUTPUT_EXISTS]: "caller",
|
|
8075
|
+
[STDIN_STALLED]: "caller",
|
|
8076
|
+
[INTERRUPTED]: "interrupted",
|
|
8077
|
+
[DEADLINE_EXCEEDED]: "wait",
|
|
8078
|
+
[INTERNAL_CODE]: "bug",
|
|
8079
|
+
[PERMISSION_DENIED]: "operator",
|
|
8080
|
+
[DISK_FULL]: "operator",
|
|
8081
|
+
[NOT_FOUND]: "caller",
|
|
8082
|
+
[ALREADY_EXISTS]: "caller",
|
|
8083
|
+
[NOT_A_FILE]: "caller",
|
|
8084
|
+
[TOOL_FAILED]: "operator",
|
|
8085
|
+
[TOOL_MISSING]: "operator",
|
|
8086
|
+
[PROJECT_INVALID]: "operator",
|
|
8087
|
+
[DOCTOR_PROBLEMS]: "operator",
|
|
8088
|
+
[NOT_GLOBAL_INSTALL]: "operator",
|
|
8089
|
+
[REGISTRY_UNREACHABLE]: "operator",
|
|
8090
|
+
[REGISTRY_AUTH]: "operator",
|
|
8091
|
+
[INSTALL_FAILED]: "operator",
|
|
8092
|
+
[NPM_FAILED]: "operator",
|
|
8093
|
+
[NO_LATEST]: "source"
|
|
8094
|
+
};
|
|
7370
8095
|
/** The codes of `errors` that the Runtime already declares, which a CLI cannot redeclare. */
|
|
7371
8096
|
function runtimeCodesIn(errors) {
|
|
7372
|
-
return Object.keys(errors).filter((code) => Object.hasOwn(
|
|
8097
|
+
return Object.keys(errors).filter((code) => Object.hasOwn(RUNTIME_EXIT_CLASSES, code));
|
|
7373
8098
|
}
|
|
7374
8099
|
function exitClassOfOne(error, errors) {
|
|
7375
8100
|
if (!(error instanceof CliError)) return "bug";
|
|
7376
8101
|
if (error instanceof UsageError) return "caller";
|
|
7377
|
-
return
|
|
8102
|
+
return RUNTIME_EXIT_CLASSES[error.code] ?? errors[error.code]?.class ?? "bug";
|
|
7378
8103
|
}
|
|
7379
8104
|
function isBug(error, errors) {
|
|
7380
8105
|
return exitClassOfOne(error, errors) === "bug";
|
|
@@ -7418,6 +8143,50 @@ function exitCodeOf(error, errors, stop) {
|
|
|
7418
8143
|
return exitClass === "interrupted" ? SIGNAL_EXIT_CODES[stopSignalOf(stop?.reason)] : EXIT_CODES[exitClass];
|
|
7419
8144
|
}
|
|
7420
8145
|
//#endregion
|
|
8146
|
+
//#region ../agent-cli/dist/agent-cli.js
|
|
8147
|
+
function checkOwnCodes(cli) {
|
|
8148
|
+
const redeclared = runtimeCodesIn(cli.errors ?? {});
|
|
8149
|
+
if (redeclared.length > 0) throw new Error(`${cli.name} declares ${redeclared.join(", ")}, an error code the Runtime already declares`);
|
|
8150
|
+
}
|
|
8151
|
+
function defineCli$1(cli) {
|
|
8152
|
+
checkOwnCodes(cli);
|
|
8153
|
+
if (cli.commands === void 0) return cli;
|
|
8154
|
+
const { commands } = cli;
|
|
8155
|
+
const taken = Object.keys(builtInCommands(cli, {
|
|
8156
|
+
bin: void 0,
|
|
8157
|
+
node: void 0
|
|
8158
|
+
})).filter((name) => commands[name] !== void 0);
|
|
8159
|
+
if (taken.length > 0) throw new Error(`${cli.name} defines ${taken.join(", ")}, a built-in Command it cannot replace`);
|
|
8160
|
+
return cli;
|
|
8161
|
+
}
|
|
8162
|
+
/**
|
|
8163
|
+
* Declares the CLI's ports and its Project file's settings once; the `defineCommand` and
|
|
8164
|
+
* `defineCli` it returns type `ctx.ports` and `ctx.project`.
|
|
8165
|
+
*/
|
|
8166
|
+
function agentCli() {
|
|
8167
|
+
return {
|
|
8168
|
+
defineCommand: defineCommandFor(),
|
|
8169
|
+
defineCli: defineCli$1
|
|
8170
|
+
};
|
|
8171
|
+
}
|
|
8172
|
+
//#endregion
|
|
8173
|
+
//#region ../agent-cli/dist/error-table.js
|
|
8174
|
+
/** Keeps each code's literal class and `details` schema, so `cliError` can type its throw sites. */
|
|
8175
|
+
function defineErrors(table) {
|
|
8176
|
+
return table;
|
|
8177
|
+
}
|
|
8178
|
+
/**
|
|
8179
|
+
* A `CliError` for a code of `table`, whose `details` must match the code's schema. The `hint`
|
|
8180
|
+
* names the next command to run and says whether running it again can help; `retryAt` (ISO 8601)
|
|
8181
|
+
* is allowed only on a wait-class code.
|
|
8182
|
+
*/
|
|
8183
|
+
function cliError(_table, code, init, options) {
|
|
8184
|
+
return new CliError({
|
|
8185
|
+
...init,
|
|
8186
|
+
code
|
|
8187
|
+
}, options);
|
|
8188
|
+
}
|
|
8189
|
+
//#endregion
|
|
7421
8190
|
//#region ../agent-cli/dist/command-spec.js
|
|
7422
8191
|
/** The group's Commands and groups that help and suggestions may name: hidden Commands left out. */
|
|
7423
8192
|
function visibleCommands({ commands }) {
|
|
@@ -7435,12 +8204,18 @@ function declaredOf(command) {
|
|
|
7435
8204
|
cost: command.cost !== void 0
|
|
7436
8205
|
};
|
|
7437
8206
|
}
|
|
7438
|
-
|
|
8207
|
+
const SINGLE_COMMAND = {
|
|
8208
|
+
path: [],
|
|
8209
|
+
builtIn: false
|
|
8210
|
+
};
|
|
8211
|
+
function commandSpec(commandLine, command, { path, builtIn } = SINGLE_COMMAND) {
|
|
7439
8212
|
const list = command.rows === void 0 ? void 0 : listSpec(command.rows);
|
|
7440
8213
|
return {
|
|
7441
8214
|
kind: "command",
|
|
7442
8215
|
commandLine,
|
|
8216
|
+
path,
|
|
7443
8217
|
command,
|
|
8218
|
+
builtIn,
|
|
7444
8219
|
description: command.description,
|
|
7445
8220
|
help: command.help,
|
|
7446
8221
|
hidden: command.hidden === true,
|
|
@@ -7454,15 +8229,34 @@ function commandSpec(commandLine, command) {
|
|
|
7454
8229
|
output: list?.output ?? command.output
|
|
7455
8230
|
};
|
|
7456
8231
|
}
|
|
7457
|
-
function
|
|
8232
|
+
function group(commandLine, commands) {
|
|
7458
8233
|
return {
|
|
7459
8234
|
kind: "group",
|
|
7460
8235
|
commandLine,
|
|
7461
|
-
commands
|
|
8236
|
+
commands
|
|
7462
8237
|
};
|
|
7463
8238
|
}
|
|
7464
|
-
|
|
7465
|
-
|
|
8239
|
+
/** The root group of a multi-Command CLI: the author's Commands, then the Built-in Commands. */
|
|
8240
|
+
function groupSpec(commandLine, commands, builtIns) {
|
|
8241
|
+
return group(commandLine, {
|
|
8242
|
+
...specsOf(commandLine, commands, {
|
|
8243
|
+
path: [],
|
|
8244
|
+
builtIn: false
|
|
8245
|
+
}),
|
|
8246
|
+
...specsOf(commandLine, builtIns, {
|
|
8247
|
+
path: [],
|
|
8248
|
+
builtIn: true
|
|
8249
|
+
})
|
|
8250
|
+
});
|
|
8251
|
+
}
|
|
8252
|
+
function specsOf(commandLine, commands, { path, builtIn }) {
|
|
8253
|
+
return Object.fromEntries(Object.entries(commands).map(([key, node]) => [key, specOf(`${commandLine} ${key}`, node, {
|
|
8254
|
+
path: [...path, key],
|
|
8255
|
+
builtIn
|
|
8256
|
+
})]));
|
|
8257
|
+
}
|
|
8258
|
+
function specOf(commandLine, node, place) {
|
|
8259
|
+
return isCommand(node) ? commandSpec(commandLine, node, place) : group(commandLine, specsOf(commandLine, node, place));
|
|
7466
8260
|
}
|
|
7467
8261
|
//#endregion
|
|
7468
8262
|
//#region ../agent-cli/dist/help.js
|
|
@@ -7487,9 +8281,10 @@ function commandRows(group) {
|
|
|
7487
8281
|
function lines(...parts) {
|
|
7488
8282
|
return `${parts.join("\n")}\n`;
|
|
7489
8283
|
}
|
|
7490
|
-
function listingLines(heading, group, style) {
|
|
8284
|
+
function listingLines(heading, group, style, description) {
|
|
7491
8285
|
return [
|
|
7492
8286
|
style.bold(heading),
|
|
8287
|
+
...description === void 0 ? [] : [description],
|
|
7493
8288
|
...section("Commands", commandRows(group), style),
|
|
7494
8289
|
"",
|
|
7495
8290
|
`Run \`${group.commandLine} <command> --help\` for its examples and input.`
|
|
@@ -7522,7 +8317,7 @@ function examplesSection(examples, style) {
|
|
|
7522
8317
|
}
|
|
7523
8318
|
/** The CLI's own help: a listing or its single Command's help, ending with exit codes and examples. */
|
|
7524
8319
|
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));
|
|
8320
|
+
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
8321
|
}
|
|
7527
8322
|
function groupHelp(group, style) {
|
|
7528
8323
|
return lines(...listingLines(group.commandLine, group, style));
|
|
@@ -7620,10 +8415,11 @@ function errorsData(errors) {
|
|
|
7620
8415
|
details: declaration.details === void 0 ? null : toJSONSchema(declaration.details, { unrepresentable: "any" })
|
|
7621
8416
|
}]));
|
|
7622
8417
|
}
|
|
7623
|
-
function cliHelpJson({ version, errors }, root) {
|
|
8418
|
+
function cliHelpJson({ version, description, errors }, root) {
|
|
7624
8419
|
return printed$1({
|
|
7625
8420
|
name: root.commandLine,
|
|
7626
8421
|
version,
|
|
8422
|
+
description,
|
|
7627
8423
|
...nodeData(root),
|
|
7628
8424
|
errors: errorsData(errors ?? {})
|
|
7629
8425
|
});
|
|
@@ -7656,619 +8452,215 @@ function progressLine(message, json) {
|
|
|
7656
8452
|
}
|
|
7657
8453
|
function errorText(error, format) {
|
|
7658
8454
|
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
|
-
};
|
|
7730
|
-
}
|
|
7731
|
-
/** The first line of `--version`: the version, and the commit and time of a stamped build. */
|
|
7732
|
-
function versionLine({ version, build }) {
|
|
7733
|
-
return build === void 0 ? version : `${version} (${build.sha}${build.dirty ? "+dirty" : ""}) built ${build.builtAt}`;
|
|
7734
|
-
}
|
|
7735
|
-
function versionResult(cli, packageRoot) {
|
|
7736
|
-
return {
|
|
7737
|
-
stdout: `${(cli.build === void 0 ? [versionLine(cli)] : [versionLine(cli), `changelog ${join(packageRoot, "CHANGELOG.md")}`]).join("\n")}\n`,
|
|
7738
|
-
stderr: "",
|
|
7739
|
-
exitCode: SUCCESS_EXIT_CODE
|
|
7740
|
-
};
|
|
7741
|
-
}
|
|
7742
|
-
//#endregion
|
|
7743
|
-
//#region ../agent-cli/dist/skill-source.js
|
|
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}`;
|
|
7760
|
-
}
|
|
7761
|
-
async function repositoryAt(packageRoot) {
|
|
7762
|
-
let manifest;
|
|
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;
|
|
7771
|
-
}
|
|
7772
|
-
/** What `npx skills add` installs the CLI's skill from: the declared source, else the package's repository. */
|
|
7773
|
-
async function skillSource(declared, packageRoot) {
|
|
7774
|
-
if (declared !== void 0) return declared.source;
|
|
7775
|
-
const repository = await repositoryAt(packageRoot);
|
|
7776
|
-
return repository === void 0 ? void 0 : sourceFromRepository(repository);
|
|
7777
|
-
}
|
|
7778
|
-
//#endregion
|
|
7779
|
-
//#region ../agent-cli/dist/skills.js
|
|
7780
|
-
/** Where the skills CLI (`npx skills add`) puts a skill, under a project and under home. */
|
|
7781
|
-
const SKILL_DIRS = [[".claude", "skills"], [".agents", "skills"]];
|
|
7782
|
-
function skillUpdateCommand(cliName) {
|
|
7783
|
-
return `npx -y skills update ${cliName}`;
|
|
7784
|
-
}
|
|
7785
|
-
function skillAddCommand(source, cliName) {
|
|
7786
|
-
return `npx -y skills add ${source} --skill ${cliName} -g`;
|
|
7787
|
-
}
|
|
7788
|
-
const FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
7789
|
-
const METADATA_VERSION = /^metadata:[ \t]*\r?\n(?:[ \t]+.*\r?\n)*?[ \t]+version:[ \t]*["']?([^"'\s]+)["']?[ \t]*$/m;
|
|
7790
|
-
/** The version a SKILL.md's frontmatter `metadata.version` states. */
|
|
7791
|
-
function skillVersionIn(skill) {
|
|
7792
|
-
const frontmatter = FRONTMATTER.exec(skill)?.[1];
|
|
7793
|
-
return frontmatter === void 0 ? void 0 : METADATA_VERSION.exec(`${frontmatter}\n`)?.[1];
|
|
7794
|
-
}
|
|
7795
|
-
function homeOf(env) {
|
|
7796
|
-
return env.HOME ?? env.USERPROFILE ?? homedir();
|
|
7797
|
-
}
|
|
7798
|
-
async function copyAt(path, cliVersion) {
|
|
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
|
-
};
|
|
7816
|
-
return {
|
|
7817
|
-
path,
|
|
7818
|
-
version,
|
|
7819
|
-
state: standingOf(version, cliVersion)
|
|
7820
|
-
};
|
|
7821
|
-
}
|
|
7822
|
-
/** Every installed copy of the skill named after the CLI, in the project first, then under home. */
|
|
7823
|
-
async function skillCopies(skillName, cliVersion, cwd, env) {
|
|
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;
|
|
7836
|
-
}
|
|
7837
|
-
//#endregion
|
|
7838
|
-
//#region ../agent-cli/dist/doctor-rows.js
|
|
7839
|
-
function ok(message) {
|
|
7840
|
-
return {
|
|
7841
|
-
state: "ok",
|
|
7842
|
-
message
|
|
7843
|
-
};
|
|
7844
|
-
}
|
|
7845
|
-
function buildRow(cli) {
|
|
7846
|
-
return {
|
|
7847
|
-
name: "build",
|
|
7848
|
-
run: () => ok(versionLine(cli))
|
|
7849
|
-
};
|
|
7850
|
-
}
|
|
7851
|
-
function nodeRow(cli) {
|
|
7852
|
-
return {
|
|
7853
|
-
name: "node",
|
|
7854
|
-
run: () => {
|
|
7855
|
-
const found = process.versions.node;
|
|
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
|
-
};
|
|
7872
|
-
}
|
|
7873
|
-
function projectRow(projectFile) {
|
|
7874
|
-
const { file } = projectFile;
|
|
7875
|
-
return {
|
|
7876
|
-
name: "project",
|
|
7877
|
-
run: (ctx) => {
|
|
7878
|
-
let project;
|
|
7879
|
-
try {
|
|
7880
|
-
project = projectOf(projectFile, ctx.cwd);
|
|
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
|
-
};
|
|
7891
|
-
}
|
|
7892
|
-
function installRow(cli, { bin, node }) {
|
|
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
|
-
};
|
|
7911
|
-
}
|
|
7912
|
-
function registryRow(cli, node) {
|
|
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
|
-
};
|
|
7930
|
-
}
|
|
7931
|
-
const SKILL_STATE_NOTES = {
|
|
7932
|
-
current: "the same as this build",
|
|
7933
|
-
behind: "older than this build",
|
|
7934
|
-
ahead: "newer than this build",
|
|
7935
|
-
unversioned: "states no metadata.version",
|
|
7936
|
-
unreadable: "could not be read"
|
|
7937
|
-
};
|
|
7938
|
-
function describeCopy({ path, version, state }) {
|
|
7939
|
-
return `${path}${version === void 0 ? "" : ` ${version}`} (${SKILL_STATE_NOTES[state]})`;
|
|
7940
|
-
}
|
|
7941
|
-
function skillFix(cli, copies) {
|
|
7942
|
-
if (copies.some(({ state }) => state === "behind" || state === "unversioned")) return skillUpdateCommand(cli.name);
|
|
7943
|
-
return copies.some(({ state }) => state === "ahead") ? `${cli.name} update` : void 0;
|
|
8455
|
+
...format,
|
|
8456
|
+
isBug: (each) => isBug(each, format.errors)
|
|
8457
|
+
});
|
|
8458
|
+
const { usageHelp, json } = format;
|
|
8459
|
+
return usageHelp !== void 0 && !json && error instanceof UsageError ? `${text}\n${usageHelp}` : text;
|
|
7944
8460
|
}
|
|
7945
|
-
function
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
run: async (ctx) => {
|
|
7949
|
-
const copies = await skillCopies(cli.name, cli.version, ctx.cwd, ctx.env);
|
|
7950
|
-
if (copies.length === 0) {
|
|
7951
|
-
const message = `no copy of the ${cli.name} skill is installed`;
|
|
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
|
-
};
|
|
8461
|
+
function stdoutOf({ value, render }, format, spill) {
|
|
8462
|
+
const text = printed(value, render, format);
|
|
8463
|
+
return value instanceof Page ? text : spill(text, format.json);
|
|
7968
8464
|
}
|
|
7969
|
-
/**
|
|
7970
|
-
function
|
|
7971
|
-
return
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
...cli.doctor ?? [],
|
|
7976
|
-
...toolRows(cli.tools ?? [], cli.commands),
|
|
7977
|
-
installRow(cli, launch),
|
|
7978
|
-
registryRow(cli, launch.node),
|
|
7979
|
-
skillRow(cli)
|
|
7980
|
-
];
|
|
8465
|
+
/** What a serve Command prints the moment it starts. */
|
|
8466
|
+
function startedOutput(outcome, format, spill) {
|
|
8467
|
+
return stdoutOf(outcome, {
|
|
8468
|
+
...format,
|
|
8469
|
+
fields: void 0
|
|
8470
|
+
}, spill);
|
|
7981
8471
|
}
|
|
7982
|
-
|
|
7983
|
-
|
|
7984
|
-
|
|
7985
|
-
|
|
7986
|
-
|
|
7987
|
-
|
|
7988
|
-
|
|
7989
|
-
rows: array(object({
|
|
7990
|
-
check: string(),
|
|
7991
|
-
state: _enum([
|
|
7992
|
-
"ok",
|
|
7993
|
-
"problem",
|
|
7994
|
-
"skipped"
|
|
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
|
-
};
|
|
8472
|
+
/** A serve Command stopped after it started: stopping it is how it is meant to end. */
|
|
8473
|
+
const STOPPED_RESULT = {
|
|
8474
|
+
stdout: "",
|
|
8475
|
+
stderr: "",
|
|
8476
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8477
|
+
};
|
|
8478
|
+
function errorResult(error, format) {
|
|
8012
8479
|
return {
|
|
8013
|
-
|
|
8014
|
-
|
|
8480
|
+
stdout: "",
|
|
8481
|
+
stderr: errorText(error, format),
|
|
8482
|
+
exitCode: exitCodeOf(error, format.errors, format.stop)
|
|
8015
8483
|
};
|
|
8016
8484
|
}
|
|
8017
|
-
function
|
|
8018
|
-
|
|
8019
|
-
|
|
8020
|
-
|
|
8021
|
-
|
|
8022
|
-
|
|
8023
|
-
|
|
8485
|
+
async function commandResult(settled, format, spill) {
|
|
8486
|
+
if (settled.ok) try {
|
|
8487
|
+
return {
|
|
8488
|
+
stdout: await stdoutOf(settled.outcome, format, spill),
|
|
8489
|
+
stderr: "",
|
|
8490
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8491
|
+
};
|
|
8492
|
+
} catch (spillError) {
|
|
8493
|
+
return errorResult(spillError, format);
|
|
8494
|
+
}
|
|
8495
|
+
const { error, delivered } = settled;
|
|
8496
|
+
const result = errorResult(error, format);
|
|
8497
|
+
if (delivered === void 0) return result;
|
|
8024
8498
|
try {
|
|
8025
|
-
|
|
8026
|
-
|
|
8027
|
-
|
|
8028
|
-
|
|
8029
|
-
|
|
8030
|
-
|
|
8031
|
-
|
|
8032
|
-
|
|
8499
|
+
return {
|
|
8500
|
+
...result,
|
|
8501
|
+
stdout: await stdoutOf(delivered, format, spill)
|
|
8502
|
+
};
|
|
8503
|
+
} catch (spillError) {
|
|
8504
|
+
const both = new AggregateError([...errorsOf(error), spillError]);
|
|
8505
|
+
return {
|
|
8506
|
+
...result,
|
|
8507
|
+
stderr: errorText(both, format)
|
|
8508
|
+
};
|
|
8033
8509
|
}
|
|
8034
|
-
return {
|
|
8035
|
-
row: {
|
|
8036
|
-
check: check.name,
|
|
8037
|
-
...finding
|
|
8038
|
-
},
|
|
8039
|
-
advisory: check.advisory === true
|
|
8040
|
-
};
|
|
8041
8510
|
}
|
|
8042
|
-
function
|
|
8043
|
-
|
|
8511
|
+
function textHelp(node, root, cli, style) {
|
|
8512
|
+
if (node === root) return cliHelp(cli, node, style);
|
|
8513
|
+
return node.kind === "command" ? commandHelp(node, style) : groupHelp(node, style);
|
|
8044
8514
|
}
|
|
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");
|
|
8515
|
+
function helpOf(node, root, cli, style, json) {
|
|
8516
|
+
if (!json) return textHelp(node, root, cli, style);
|
|
8517
|
+
if (node === root) return cliHelpJson(cli, node);
|
|
8518
|
+
return node.kind === "command" ? commandHelpJson(node) : groupHelpJson(node);
|
|
8052
8519
|
}
|
|
8053
|
-
function
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
}
|
|
8059
|
-
return new AggregateError(errors);
|
|
8520
|
+
function helpResult(node, root, cli, { style, json }) {
|
|
8521
|
+
return {
|
|
8522
|
+
stdout: helpOf(node, root, cli, style, json),
|
|
8523
|
+
stderr: "",
|
|
8524
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8525
|
+
};
|
|
8060
8526
|
}
|
|
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
|
-
});
|
|
8527
|
+
function versionResult(cli, packageRoot) {
|
|
8528
|
+
return {
|
|
8529
|
+
stdout: `${(cli.build === void 0 ? [versionLine(cli)] : [versionLine(cli), `changelog ${join(packageRoot, "CHANGELOG.md")}`]).join("\n")}\n`,
|
|
8530
|
+
stderr: "",
|
|
8531
|
+
exitCode: SUCCESS_EXIT_CODE
|
|
8532
|
+
};
|
|
8095
8533
|
}
|
|
8096
8534
|
//#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
|
-
}
|
|
8535
|
+
//#region ../agent-cli/dist/package-root.js
|
|
8118
8536
|
/**
|
|
8119
|
-
*
|
|
8120
|
-
* `
|
|
8537
|
+
* The nearest folder holding a `package.json`, searched upward from the bin or, run without one,
|
|
8538
|
+
* from `cwd`; the search's start when none holds one. The bin is resolved through links first,
|
|
8539
|
+
* since npm's global bin is a link to it.
|
|
8121
8540
|
*/
|
|
8122
|
-
|
|
8123
|
-
|
|
8124
|
-
|
|
8125
|
-
|
|
8126
|
-
|
|
8127
|
-
if (isMissingFile(error)) return [];
|
|
8128
|
-
throw error;
|
|
8541
|
+
function packageRootOf(bin, cwd) {
|
|
8542
|
+
const start = bin === void 0 ? resolve(cwd) : dirname(realpathSync(bin));
|
|
8543
|
+
for (let dir = start;; dir = dirname(dir)) {
|
|
8544
|
+
if (existsSync(join(dir, "package.json"))) return dir;
|
|
8545
|
+
if (dirname(dir) === dir) return start;
|
|
8129
8546
|
}
|
|
8130
|
-
return releasesIn(changelog).filter(({ version }) => compareVersions(version, from) > 0 && compareVersions(version, to) <= 0).sort((a, b) => compareVersions(a.version, b.version));
|
|
8131
8547
|
}
|
|
8132
8548
|
//#endregion
|
|
8133
|
-
//#region ../agent-cli/dist/
|
|
8134
|
-
const
|
|
8135
|
-
|
|
8136
|
-
|
|
8137
|
-
|
|
8138
|
-
|
|
8139
|
-
|
|
8140
|
-
|
|
8141
|
-
|
|
8142
|
-
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8549
|
+
//#region ../agent-cli/dist/suggest.js
|
|
8550
|
+
const MAX_DISTANCE = 3;
|
|
8551
|
+
const MIN_SIMILARITY = .4;
|
|
8552
|
+
function distance(a, b) {
|
|
8553
|
+
const width = b.length + 1;
|
|
8554
|
+
const d = Array.from({ length: (a.length + 1) * width }, (_, k) => {
|
|
8555
|
+
const i = Math.floor(k / width);
|
|
8556
|
+
const j = k % width;
|
|
8557
|
+
return i === 0 || j === 0 ? i + j : 0;
|
|
8558
|
+
});
|
|
8559
|
+
const at = (i, j) => d[i * width + j] ?? 0;
|
|
8560
|
+
for (let i = 1; i <= a.length; i++) for (let j = 1; j <= b.length; j++) {
|
|
8561
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
8562
|
+
const edit = Math.min(at(i - 1, j) + 1, at(i, j - 1) + 1, at(i - 1, j - 1) + cost);
|
|
8563
|
+
const transposed = i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1];
|
|
8564
|
+
d[i * width + j] = transposed ? Math.min(edit, at(i - 2, j - 2) + 1) : edit;
|
|
8565
|
+
}
|
|
8566
|
+
return at(a.length, b.length);
|
|
8149
8567
|
}
|
|
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");
|
|
8568
|
+
function isClose(word, candidate) {
|
|
8569
|
+
const length = Math.max(word.length, candidate.length);
|
|
8570
|
+
const edits = distance(word, candidate);
|
|
8571
|
+
return candidate.length > 1 && edits < MAX_DISTANCE && (length - edits) / length > MIN_SIMILARITY;
|
|
8159
8572
|
}
|
|
8160
|
-
|
|
8161
|
-
|
|
8162
|
-
|
|
8163
|
-
|
|
8164
|
-
|
|
8165
|
-
});
|
|
8573
|
+
/** The names closest to `word`, sorted, several when they tie, or none when nothing is close. */
|
|
8574
|
+
function closestNames(word, names) {
|
|
8575
|
+
const close = [...new Set(names)].filter((candidate) => isClose(word, candidate));
|
|
8576
|
+
const best = Math.min(...close.map((candidate) => distance(word, candidate)));
|
|
8577
|
+
return close.filter((candidate) => distance(word, candidate) === best).sort((a, b) => a.localeCompare(b));
|
|
8166
8578
|
}
|
|
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
|
-
});
|
|
8579
|
+
/** The long flags closest to `flag`, sorted, or none for a short flag or when nothing is close. */
|
|
8580
|
+
function closestFlags(flag, flags) {
|
|
8581
|
+
if (!flag.startsWith("--")) return [];
|
|
8582
|
+
const names = flags.map((candidate) => candidate.slice(2));
|
|
8583
|
+
return closestNames(flag.slice(2), names).map((name) => `--${name}`);
|
|
8223
8584
|
}
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
return {
|
|
8229
|
-
doctor: doctorCommand(cli, launch),
|
|
8230
|
-
...cli.install === void 0 ? {} : { update: updateCommand(cli, cli.install, launch) }
|
|
8231
|
-
};
|
|
8585
|
+
/** The one long flag closest to `flag`, or none when nothing is close or several tie. */
|
|
8586
|
+
function closestFlag(flag, flags) {
|
|
8587
|
+
const closest = closestFlags(flag, flags);
|
|
8588
|
+
return closest.length === 1 ? closest[0] : void 0;
|
|
8232
8589
|
}
|
|
8233
8590
|
//#endregion
|
|
8234
|
-
//#region ../agent-cli/dist/
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8591
|
+
//#region ../agent-cli/dist/route.js
|
|
8592
|
+
const GROUP_FLAGS = [
|
|
8593
|
+
HELP_FLAG,
|
|
8594
|
+
VERSION_FLAG,
|
|
8595
|
+
JSON_FLAG.flag
|
|
8596
|
+
];
|
|
8597
|
+
function beforeEnd(words) {
|
|
8598
|
+
const end = words.indexOf("--");
|
|
8599
|
+
return end === -1 ? words : words.slice(0, end);
|
|
8238
8600
|
}
|
|
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;
|
|
8601
|
+
function wantsHelp(words) {
|
|
8602
|
+
return beforeEnd(words).some((word) => word === "--help" || word === "-h");
|
|
8249
8603
|
}
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8604
|
+
function childOf(group, name) {
|
|
8605
|
+
return Object.hasOwn(group.commands, name) ? group.commands[name] : void 0;
|
|
8606
|
+
}
|
|
8607
|
+
function isFlagLike(word) {
|
|
8608
|
+
return word.length > 1 && word[0] === "-";
|
|
8609
|
+
}
|
|
8610
|
+
function walk(node, words, json, invocation) {
|
|
8611
|
+
const help = {
|
|
8612
|
+
kind: "help",
|
|
8613
|
+
node,
|
|
8614
|
+
json
|
|
8615
|
+
};
|
|
8616
|
+
if (node.kind === "command") return wantsHelp(words) ? help : {
|
|
8617
|
+
kind: "command",
|
|
8618
|
+
spec: node,
|
|
8619
|
+
words,
|
|
8620
|
+
json
|
|
8258
8621
|
};
|
|
8622
|
+
const [first, ...rest] = words;
|
|
8623
|
+
if (first === void 0) return help;
|
|
8624
|
+
const child = childOf(node, first);
|
|
8625
|
+
if (child !== void 0) return walk(child, rest, json, invocation);
|
|
8626
|
+
if (first === "--") {
|
|
8627
|
+
const [name, ...after] = rest;
|
|
8628
|
+
if (name === void 0) return help;
|
|
8629
|
+
const named = childOf(node, name);
|
|
8630
|
+
if (named !== void 0) return walk(named, ["--", ...after], json, invocation);
|
|
8631
|
+
return unknownCommand(node, name, json);
|
|
8632
|
+
}
|
|
8633
|
+
if (wantsHelp(words)) return help;
|
|
8634
|
+
if (isFlagLike(first)) {
|
|
8635
|
+
const suggestions = closestFlags(first, GROUP_FLAGS);
|
|
8636
|
+
return {
|
|
8637
|
+
kind: "usage error",
|
|
8638
|
+
error: unknownOptionError(node.commandLine, invocation, first, suggestions),
|
|
8639
|
+
node,
|
|
8640
|
+
json
|
|
8641
|
+
};
|
|
8642
|
+
}
|
|
8643
|
+
return unknownCommand(node, first, json);
|
|
8259
8644
|
}
|
|
8260
|
-
|
|
8261
|
-
|
|
8262
|
-
|
|
8263
|
-
|
|
8264
|
-
|
|
8645
|
+
function unknownCommand(group, name, json) {
|
|
8646
|
+
const suggestions = closestNames(name, Object.keys(visibleCommands(group)));
|
|
8647
|
+
return {
|
|
8648
|
+
kind: "usage error",
|
|
8649
|
+
error: unknownCommandError(group.commandLine, name, suggestions),
|
|
8650
|
+
node: group,
|
|
8651
|
+
json
|
|
8652
|
+
};
|
|
8265
8653
|
}
|
|
8266
|
-
/**
|
|
8267
|
-
function
|
|
8268
|
-
|
|
8269
|
-
|
|
8270
|
-
|
|
8271
|
-
|
|
8654
|
+
/** Walks the caller's command line through the Commands to the one it names, or to a stop. */
|
|
8655
|
+
function route(root, invocation) {
|
|
8656
|
+
const { argv } = invocation;
|
|
8657
|
+
const options = beforeEnd(argv);
|
|
8658
|
+
const json = options.includes(JSON_FLAG.flag);
|
|
8659
|
+
if (options.includes("--version")) return {
|
|
8660
|
+
kind: "version",
|
|
8661
|
+
json
|
|
8662
|
+
};
|
|
8663
|
+
return walk(root, argv.filter((word, index) => !(index < options.length && word === JSON_FLAG.flag)), json, invocation);
|
|
8272
8664
|
}
|
|
8273
8665
|
//#endregion
|
|
8274
8666
|
//#region ../agent-cli/dist/execute.js
|
|
@@ -8341,67 +8733,12 @@ async function execute(command, input, ctx, { dryRun, confirm, yes, page, invoca
|
|
|
8341
8733
|
}, outputs);
|
|
8342
8734
|
if (!ctx.force) guardOutputs(outputs, ctx.commandLine({ add: [FORCE_FLAG.flag] }));
|
|
8343
8735
|
}
|
|
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;
|
|
8736
|
+
return outcomeOf(await command.apply(plan, ctx), (data, style) => command.render(data, style));
|
|
8401
8737
|
}
|
|
8402
8738
|
//#endregion
|
|
8403
8739
|
//#region ../agent-cli/dist/parse-input.js
|
|
8404
8740
|
const NO_INPUT = object({});
|
|
8741
|
+
const WHITESPACE = /\s/;
|
|
8405
8742
|
function knownFlags(spec) {
|
|
8406
8743
|
return [...spec.options.map((field) => ({
|
|
8407
8744
|
flag: field.label,
|
|
@@ -8538,6 +8875,8 @@ async function parseInput(spec, words, invocation, readStdin) {
|
|
|
8538
8875
|
page: page.data,
|
|
8539
8876
|
values
|
|
8540
8877
|
};
|
|
8878
|
+
const [onlyWord] = unknownOptions;
|
|
8879
|
+
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
8880
|
const [only] = unknown;
|
|
8542
8881
|
if (only !== void 0 && unknown.length === 1 && otherLines.length === 0) throw unknownOptionError(spec.commandLine, invocation, only.flag, only.suggestion === void 0 ? [] : [only.suggestion]);
|
|
8543
8882
|
throw invalidInput(spec.commandLine, invocation, unknown, otherLines);
|
|
@@ -8563,83 +8902,9 @@ async function parseCommand({ spec, words, json }, invocation, readStdin) {
|
|
|
8563
8902
|
};
|
|
8564
8903
|
}
|
|
8565
8904
|
//#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
8905
|
//#region ../agent-cli/dist/secrets.js
|
|
8642
|
-
|
|
8906
|
+
/** `$XDG_CONFIG_HOME/<cli>/.env`, with `~/.config` when the variable is unset or empty. */
|
|
8907
|
+
function envFileOf(cliName, env) {
|
|
8643
8908
|
const config = env.XDG_CONFIG_HOME || join(env.HOME || homedir(), ".config");
|
|
8644
8909
|
return join(config, cliName, ".env");
|
|
8645
8910
|
}
|
|
@@ -8656,24 +8921,50 @@ function readDotenv(path, fileError) {
|
|
|
8656
8921
|
}
|
|
8657
8922
|
return parseEnv(text);
|
|
8658
8923
|
}
|
|
8659
|
-
/** Looks `name` up in the env, then in
|
|
8660
|
-
function secretOf({
|
|
8924
|
+
/** Looks `name` up in the env, then in `envFile`; an empty value counts as unset. */
|
|
8925
|
+
function secretOf({ envFile, env, fileError }, name) {
|
|
8661
8926
|
const fromEnv = env[name];
|
|
8662
8927
|
if (fromEnv) return {
|
|
8663
8928
|
value: fromEnv,
|
|
8664
8929
|
origin: { kind: "env" }
|
|
8665
8930
|
};
|
|
8666
|
-
const
|
|
8667
|
-
const fromFile = readDotenv(path, fileError)[name];
|
|
8931
|
+
const fromFile = readDotenv(envFile, fileError)[name];
|
|
8668
8932
|
return fromFile ? {
|
|
8669
8933
|
value: fromFile,
|
|
8670
8934
|
origin: {
|
|
8671
8935
|
kind: "file",
|
|
8672
|
-
path
|
|
8936
|
+
path: envFile
|
|
8673
8937
|
}
|
|
8674
8938
|
} : void 0;
|
|
8675
8939
|
}
|
|
8676
8940
|
//#endregion
|
|
8941
|
+
//#region ../agent-cli/dist/side-task.js
|
|
8942
|
+
/** How long a run waits for its Side task once its output is written. */
|
|
8943
|
+
const SIDE_TASK_WAIT_MS = 1e3;
|
|
8944
|
+
const noSideTask = async () => {};
|
|
8945
|
+
function waitOver() {
|
|
8946
|
+
return new DOMException(`the side task ran past its ${SIDE_TASK_WAIT_MS} ms wait`, "TimeoutError");
|
|
8947
|
+
}
|
|
8948
|
+
function startSideTask(sideTask, runWith, { clock, failed }) {
|
|
8949
|
+
if (sideTask === void 0) return noSideTask;
|
|
8950
|
+
const controller = new AbortController();
|
|
8951
|
+
const { signal } = controller;
|
|
8952
|
+
const running = (async () => sideTask(runWith(signal)))().catch((error) => {
|
|
8953
|
+
if (!(signal.aborted && error === signal.reason)) failed(error);
|
|
8954
|
+
});
|
|
8955
|
+
return async () => {
|
|
8956
|
+
const waited = new AbortController();
|
|
8957
|
+
const capped = new Promise((resolve) => after(clock, SIDE_TASK_WAIT_MS, waited.signal, () => {
|
|
8958
|
+
const over = waitOver();
|
|
8959
|
+
failed(over);
|
|
8960
|
+
controller.abort(over);
|
|
8961
|
+
resolve();
|
|
8962
|
+
}));
|
|
8963
|
+
await Promise.race([running, capped]);
|
|
8964
|
+
waited.abort();
|
|
8965
|
+
};
|
|
8966
|
+
}
|
|
8967
|
+
//#endregion
|
|
8677
8968
|
//#region ../agent-cli/dist/spill.js
|
|
8678
8969
|
const STDOUT_BUDGET_CHARS = 3e4;
|
|
8679
8970
|
const SPILL_RETENTION_MS = 6048e5;
|
|
@@ -8726,47 +9017,91 @@ function spillTo(target) {
|
|
|
8726
9017
|
};
|
|
8727
9018
|
}
|
|
8728
9019
|
//#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);
|
|
9020
|
+
//#region ../agent-cli/dist/run-command.js
|
|
9021
|
+
function stdinNeverEndedHint(callerLine) {
|
|
9022
|
+
return `stdin never ended: pipe the text into \`${callerLine}\`, or redirect a file into it`;
|
|
8733
9023
|
}
|
|
8734
|
-
function
|
|
8735
|
-
return
|
|
9024
|
+
function selfOf(name, bin) {
|
|
9025
|
+
return bin === void 0 ? [name] : [
|
|
9026
|
+
process.execPath,
|
|
9027
|
+
...process.execArgv,
|
|
9028
|
+
bin
|
|
9029
|
+
];
|
|
8736
9030
|
}
|
|
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;
|
|
9031
|
+
function portsOf(cli, replacement) {
|
|
9032
|
+
if (replacement !== void 0) return () => replacement;
|
|
9033
|
+
return cli.ports ?? (() => ({}));
|
|
8756
9034
|
}
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
9035
|
+
function portsBaseOf(scope, signal) {
|
|
9036
|
+
const { cli, options, packageRoot, progress, fileError, clock, files } = scope;
|
|
9037
|
+
const { cwd, env } = options;
|
|
9038
|
+
const envFile = envFileOf(cli.name, env);
|
|
9039
|
+
return {
|
|
9040
|
+
cwd,
|
|
9041
|
+
env,
|
|
9042
|
+
packageRoot,
|
|
9043
|
+
progress,
|
|
9044
|
+
secret: (name) => secretOf({
|
|
9045
|
+
envFile,
|
|
9046
|
+
env,
|
|
9047
|
+
fileError
|
|
9048
|
+
}, name),
|
|
9049
|
+
envFile,
|
|
9050
|
+
fileError,
|
|
9051
|
+
version: cli.version,
|
|
9052
|
+
build: cli.build,
|
|
9053
|
+
self: selfOf(cli.name, options.bin),
|
|
9054
|
+
signal,
|
|
9055
|
+
clock,
|
|
9056
|
+
files,
|
|
9057
|
+
spawn: contextSpawn(options.spawn ?? realSpawn, {
|
|
9058
|
+
cwd,
|
|
9059
|
+
env,
|
|
9060
|
+
signal,
|
|
9061
|
+
progress
|
|
9062
|
+
}, fileError)
|
|
9063
|
+
};
|
|
9064
|
+
}
|
|
9065
|
+
function contextOf(portsBase, control, parts) {
|
|
9066
|
+
const { ports, project, force, commandLine, deliver } = parts;
|
|
9067
|
+
return {
|
|
9068
|
+
...portsBase,
|
|
9069
|
+
deadline: (ms) => control.deadline(ms),
|
|
9070
|
+
timeout: (ms) => control.timeout(ms),
|
|
9071
|
+
runToEnd: (name, work) => control.runToEnd(name, work),
|
|
9072
|
+
get ports() {
|
|
9073
|
+
return ports();
|
|
9074
|
+
},
|
|
9075
|
+
project,
|
|
9076
|
+
force,
|
|
9077
|
+
commandLine,
|
|
9078
|
+
poll: (check, { intervalMs, signal: stop }) => poll(portsBase.clock, check, intervalMs, stop === void 0 ? control.signal : AbortSignal.any([control.signal, stop])),
|
|
9079
|
+
deliver
|
|
9080
|
+
};
|
|
8761
9081
|
}
|
|
8762
|
-
|
|
8763
|
-
|
|
9082
|
+
/** Leaves the Side task running, so the caller writes the result before it waits for it. */
|
|
9083
|
+
async function runCommand(cli, routed, options, write, baseFormat) {
|
|
9084
|
+
const { command, commandLine, builtIn } = routed.spec;
|
|
9085
|
+
const { cwd, env } = options;
|
|
9086
|
+
const clock = options.clock ?? realClock;
|
|
9087
|
+
const files = options.files ?? realFiles();
|
|
9088
|
+
const stdin = options.stdin ?? "";
|
|
9089
|
+
const platform = options.platform ?? process.platform;
|
|
9090
|
+
const ports = portsOf(cli, options.ports);
|
|
9091
|
+
const packageRoot = packageRootOf(options.bin, cwd);
|
|
9092
|
+
const fileError = fileErrorOf({
|
|
9093
|
+
callerLine: commandLineOf(baseFormat.invocation),
|
|
9094
|
+
env,
|
|
9095
|
+
platform
|
|
9096
|
+
});
|
|
9097
|
+
const progress = (message) => write.stderr(progressLine(message, routed.json));
|
|
8764
9098
|
const invocation = {
|
|
8765
9099
|
...baseFormat.invocation,
|
|
8766
9100
|
flags: knownFlags(routed.spec)
|
|
8767
9101
|
};
|
|
8768
9102
|
const format = {
|
|
8769
9103
|
...baseFormat,
|
|
9104
|
+
bugs: () => manifestAt(packageRoot).bugs,
|
|
8770
9105
|
json: routed.json,
|
|
8771
9106
|
invocation
|
|
8772
9107
|
};
|
|
@@ -8774,71 +9109,91 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8774
9109
|
let resumeHint;
|
|
8775
9110
|
const control = new RunControl({
|
|
8776
9111
|
commandLine,
|
|
8777
|
-
outer: signal,
|
|
9112
|
+
outer: options.signal,
|
|
8778
9113
|
clock,
|
|
8779
|
-
progress
|
|
9114
|
+
progress,
|
|
8780
9115
|
runDeadline: command.deadline === void 0 ? void 0 : {
|
|
8781
9116
|
ms: command.deadline.ms,
|
|
8782
9117
|
hint: () => resumeHint ?? stdinNeverEndedHint(typedLine())
|
|
8783
9118
|
}
|
|
8784
9119
|
});
|
|
9120
|
+
const failed = (error, finishSideTask) => {
|
|
9121
|
+
control.close();
|
|
9122
|
+
return {
|
|
9123
|
+
result: errorResult(error, format),
|
|
9124
|
+
finishSideTask
|
|
9125
|
+
};
|
|
9126
|
+
};
|
|
8785
9127
|
let parsed;
|
|
8786
|
-
let project;
|
|
8787
9128
|
try {
|
|
8788
|
-
checkOperator(routed.spec,
|
|
9129
|
+
checkOperator(routed.spec, env, typedLine());
|
|
8789
9130
|
parsed = await parseCommand(routed, invocation, (field) => {
|
|
8790
|
-
if (isTerminal(stdin))
|
|
8791
|
-
return readStdin(stdin, control.signal
|
|
9131
|
+
if (isTerminal(stdin)) progress(readingLine(field.name, platform));
|
|
9132
|
+
return readStdin(stdin, control.signal, {
|
|
9133
|
+
clock,
|
|
9134
|
+
stalled: () => stdinStalled(typedLine())
|
|
9135
|
+
});
|
|
8792
9136
|
});
|
|
8793
|
-
project = projectFile === void 0 ? void 0 : projectOf(projectFile, base.cwd);
|
|
8794
9137
|
} catch (error) {
|
|
8795
|
-
|
|
8796
|
-
return errorResult(error, format);
|
|
9138
|
+
return failed(error, noSideTask);
|
|
8797
9139
|
}
|
|
8798
9140
|
const { input, flags } = parsed;
|
|
8799
9141
|
resumeHint = command.deadline?.resume(input, typedLine);
|
|
8800
|
-
let delivered;
|
|
8801
|
-
const { fileError } = base;
|
|
8802
9142
|
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,
|
|
9143
|
+
cwd,
|
|
8812
9144
|
fileError
|
|
8813
|
-
});
|
|
8814
|
-
const
|
|
8815
|
-
|
|
8816
|
-
|
|
9145
|
+
}), cwd);
|
|
9146
|
+
const scope = {
|
|
9147
|
+
cli,
|
|
9148
|
+
options,
|
|
9149
|
+
packageRoot,
|
|
9150
|
+
progress,
|
|
9151
|
+
fileError,
|
|
8817
9152
|
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)
|
|
9153
|
+
files: outputs.files
|
|
8825
9154
|
};
|
|
8826
|
-
const
|
|
8827
|
-
const
|
|
8828
|
-
|
|
8829
|
-
|
|
8830
|
-
|
|
8831
|
-
|
|
8832
|
-
|
|
8833
|
-
|
|
9155
|
+
const portsBase = portsBaseOf(scope, control.signal);
|
|
9156
|
+
const finishSideTask = startSideTask(builtIn ? void 0 : cli.sideTask?.bind(cli), (sideSignal) => {
|
|
9157
|
+
const sideBase = portsBaseOf(scope, sideSignal);
|
|
9158
|
+
const sidePorts = once(() => ports(sideBase));
|
|
9159
|
+
return {
|
|
9160
|
+
...sideBase,
|
|
9161
|
+
command: routed.spec.path,
|
|
9162
|
+
dryRun: flags.dryRun,
|
|
9163
|
+
get ports() {
|
|
9164
|
+
return sidePorts();
|
|
9165
|
+
}
|
|
9166
|
+
};
|
|
9167
|
+
}, {
|
|
9168
|
+
clock,
|
|
9169
|
+
failed: (error) => {
|
|
9170
|
+
if (isDebug(baseFormat)) progress(`side task failed: ${traceOf(error)}`);
|
|
9171
|
+
}
|
|
9172
|
+
});
|
|
9173
|
+
let project;
|
|
9174
|
+
try {
|
|
9175
|
+
project = builtIn || cli.project === void 0 ? void 0 : projectOf(cli.project, cwd, fileError);
|
|
9176
|
+
} catch (error) {
|
|
9177
|
+
return failed(error, finishSideTask);
|
|
9178
|
+
}
|
|
9179
|
+
let delivered;
|
|
9180
|
+
const ctx = contextOf(portsBase, control, {
|
|
9181
|
+
ports: once(() => ports(portsBase)),
|
|
8834
9182
|
project,
|
|
8835
9183
|
force: flags.force,
|
|
8836
9184
|
commandLine: typedLine,
|
|
8837
|
-
poll: (check, { intervalMs, signal: stop }) => poll(clock, check, intervalMs, stop === void 0 ? control.signal : AbortSignal.any([control.signal, stop])),
|
|
8838
9185
|
deliver: (data) => {
|
|
8839
9186
|
delivered = deliveredOutcome(command, data);
|
|
8840
9187
|
}
|
|
8841
|
-
};
|
|
9188
|
+
});
|
|
9189
|
+
const spill = spillTo({
|
|
9190
|
+
cliName: format.cliName,
|
|
9191
|
+
commandName: command.name,
|
|
9192
|
+
env,
|
|
9193
|
+
clock,
|
|
9194
|
+
files: outputs.files,
|
|
9195
|
+
fileError
|
|
9196
|
+
});
|
|
8842
9197
|
let served = false;
|
|
8843
9198
|
let settled;
|
|
8844
9199
|
try {
|
|
@@ -8852,7 +9207,7 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8852
9207
|
invocation,
|
|
8853
9208
|
commandLine,
|
|
8854
9209
|
started: async (outcome) => {
|
|
8855
|
-
|
|
9210
|
+
write.stdout(await startedOutput(outcome, format, spill));
|
|
8856
9211
|
served = true;
|
|
8857
9212
|
},
|
|
8858
9213
|
files,
|
|
@@ -8860,17 +9215,23 @@ async function runCommand(routed, { base, writeStdout, signal, format: baseForma
|
|
|
8860
9215
|
}))
|
|
8861
9216
|
};
|
|
8862
9217
|
} catch (error) {
|
|
8863
|
-
if (served && control.signal.aborted) return
|
|
9218
|
+
if (served && control.signal.aborted) return {
|
|
9219
|
+
result: STOPPED_RESULT,
|
|
9220
|
+
finishSideTask
|
|
9221
|
+
};
|
|
8864
9222
|
settled = {
|
|
8865
9223
|
ok: false,
|
|
8866
9224
|
error: control.errorAfter(error),
|
|
8867
9225
|
delivered
|
|
8868
9226
|
};
|
|
8869
9227
|
}
|
|
8870
|
-
return
|
|
8871
|
-
|
|
8872
|
-
|
|
8873
|
-
|
|
9228
|
+
return {
|
|
9229
|
+
result: await commandResult(settled, {
|
|
9230
|
+
...format,
|
|
9231
|
+
fields: flags.fields
|
|
9232
|
+
}, spill),
|
|
9233
|
+
finishSideTask
|
|
9234
|
+
};
|
|
8874
9235
|
}
|
|
8875
9236
|
/** `build` runs on the first call; later calls give its value or throw its error again. */
|
|
8876
9237
|
function once(build) {
|
|
@@ -8891,17 +9252,37 @@ function once(build) {
|
|
|
8891
9252
|
throw outcome.error;
|
|
8892
9253
|
};
|
|
8893
9254
|
}
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
];
|
|
9255
|
+
//#endregion
|
|
9256
|
+
//#region ../agent-cli/dist/style.js
|
|
9257
|
+
function colourEnabled(env, stdoutIsTTY) {
|
|
9258
|
+
if (env.NO_COLOR !== void 0 && env.NO_COLOR !== "") return false;
|
|
9259
|
+
return env.FORCE_COLOR !== void 0 && env.FORCE_COLOR !== "" && env.FORCE_COLOR !== "0" || stdoutIsTTY && !isAgent(env);
|
|
8900
9260
|
}
|
|
8901
|
-
function
|
|
8902
|
-
|
|
8903
|
-
|
|
9261
|
+
function sgr(open, close) {
|
|
9262
|
+
return (text) => `\u001b[${open}m${text}\u001b[${close}m`;
|
|
9263
|
+
}
|
|
9264
|
+
const COLOURED = {
|
|
9265
|
+
bold: sgr(1, 22),
|
|
9266
|
+
dim: sgr(2, 22),
|
|
9267
|
+
red: sgr(31, 39),
|
|
9268
|
+
green: sgr(32, 39),
|
|
9269
|
+
yellow: sgr(33, 39),
|
|
9270
|
+
cyan: sgr(36, 39)
|
|
9271
|
+
};
|
|
9272
|
+
const plain = (text) => text;
|
|
9273
|
+
const PLAIN = {
|
|
9274
|
+
bold: plain,
|
|
9275
|
+
dim: plain,
|
|
9276
|
+
red: plain,
|
|
9277
|
+
green: plain,
|
|
9278
|
+
yellow: plain,
|
|
9279
|
+
cyan: plain
|
|
9280
|
+
};
|
|
9281
|
+
function styleFor(env, stdoutIsTTY) {
|
|
9282
|
+
return colourEnabled(env, stdoutIsTTY) ? COLOURED : PLAIN;
|
|
8904
9283
|
}
|
|
9284
|
+
//#endregion
|
|
9285
|
+
//#region ../agent-cli/dist/run-cli.js
|
|
8905
9286
|
function stopLine(notice, json) {
|
|
8906
9287
|
return json ? progressLine(notice, true) : `\n${notice}\n`;
|
|
8907
9288
|
}
|
|
@@ -8915,7 +9296,14 @@ async function whileStopping(signal, onStop, work) {
|
|
|
8915
9296
|
signal.removeEventListener("abort", onStop);
|
|
8916
9297
|
}
|
|
8917
9298
|
}
|
|
9299
|
+
/** Runs the CLI, writes its output, then waits for the Side task it started. */
|
|
8918
9300
|
async function runWithProgress(cli, argv, options, write, stopNotice) {
|
|
9301
|
+
const { result, finishSideTask } = await routeAndRun(cli, argv, options, write, stopNotice);
|
|
9302
|
+
await write.result(result);
|
|
9303
|
+
await finishSideTask();
|
|
9304
|
+
return result;
|
|
9305
|
+
}
|
|
9306
|
+
async function routeAndRun(cli, argv, options, write, stopNotice) {
|
|
8919
9307
|
const format = {
|
|
8920
9308
|
cliName: cli.name,
|
|
8921
9309
|
env: options.env,
|
|
@@ -8929,64 +9317,37 @@ async function runWithProgress(cli, argv, options, write, stopNotice) {
|
|
|
8929
9317
|
errors: cli.errors ?? {},
|
|
8930
9318
|
stop: options.signal
|
|
8931
9319
|
};
|
|
8932
|
-
const
|
|
9320
|
+
const root = cli.commands === void 0 ? {
|
|
9321
|
+
...commandSpec(cli.name, cli.command),
|
|
9322
|
+
description: cli.description
|
|
9323
|
+
} : groupSpec(cli.name, cli.commands, builtInCommands(cli, {
|
|
8933
9324
|
bin: options.bin,
|
|
8934
9325
|
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
|
-
});
|
|
9326
|
+
}));
|
|
8940
9327
|
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
9328
|
const misused = (node) => isAgent(options.env) ? {
|
|
8948
9329
|
...format,
|
|
8949
9330
|
usageHelp: textHelp(node, root, cli, format.style)
|
|
8950
9331
|
} : format;
|
|
8951
9332
|
switch (routed.kind) {
|
|
8952
|
-
case "version": return versionResult(cli, packageRootOf(options.bin, options.cwd));
|
|
8953
|
-
case "help": return helpResult(routed.node, root, cli, {
|
|
9333
|
+
case "version": return ranAlone(versionResult(cli, packageRootOf(options.bin, options.cwd)));
|
|
9334
|
+
case "help": return ranAlone(helpResult(routed.node, root, cli, {
|
|
8954
9335
|
...format,
|
|
8955
9336
|
json: routed.json
|
|
8956
|
-
});
|
|
8957
|
-
case "usage error": return errorResult(routed.error, {
|
|
9337
|
+
}));
|
|
9338
|
+
case "usage error": return ranAlone(errorResult(routed.error, {
|
|
8958
9339
|
...misused(routed.node),
|
|
8959
9340
|
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
9341
|
}));
|
|
9342
|
+
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
9343
|
}
|
|
8989
9344
|
}
|
|
9345
|
+
async function ranAlone(result) {
|
|
9346
|
+
return {
|
|
9347
|
+
result: await result,
|
|
9348
|
+
finishSideTask: noSideTask
|
|
9349
|
+
};
|
|
9350
|
+
}
|
|
8990
9351
|
//#endregion
|
|
8991
9352
|
//#region ../agent-cli/dist/run-process.js
|
|
8992
9353
|
function written(stream, text) {
|
|
@@ -9011,10 +9372,12 @@ async function runProcess(cli) {
|
|
|
9011
9372
|
stdin: process.stdin
|
|
9012
9373
|
}, {
|
|
9013
9374
|
stdout: (text) => process.stdout.write(text),
|
|
9014
|
-
stderr: (text) => process.stderr.write(text)
|
|
9375
|
+
stderr: (text) => process.stderr.write(text),
|
|
9376
|
+
result: async ({ stdout, stderr }) => {
|
|
9377
|
+
await written(process.stdout, stdout);
|
|
9378
|
+
await written(process.stderr, stderr);
|
|
9379
|
+
}
|
|
9015
9380
|
}, "stopping… (Ctrl-C again to quit now)");
|
|
9016
|
-
await written(process.stdout, result.stdout);
|
|
9017
|
-
await written(process.stderr, result.stderr);
|
|
9018
9381
|
process.exitCode = result.exitCode;
|
|
9019
9382
|
} finally {
|
|
9020
9383
|
process.off("SIGINT", onSignal);
|
|
@@ -9023,11 +9386,15 @@ async function runProcess(cli) {
|
|
|
9023
9386
|
process.exit();
|
|
9024
9387
|
}
|
|
9025
9388
|
//#endregion
|
|
9389
|
+
//#region package.json
|
|
9390
|
+
var version$1 = "0.6.0";
|
|
9391
|
+
var description = "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.";
|
|
9392
|
+
//#endregion
|
|
9026
9393
|
//#region src/build.ts
|
|
9027
9394
|
const build = {
|
|
9028
|
-
"sha": "
|
|
9395
|
+
"sha": "6821473",
|
|
9029
9396
|
"dirty": false,
|
|
9030
|
-
"builtAt": "2026-10-
|
|
9397
|
+
"builtAt": "2026-10-20T02:08:46.888Z"
|
|
9031
9398
|
};
|
|
9032
9399
|
//#endregion
|
|
9033
9400
|
//#region src/steps.ts
|
|
@@ -9156,11 +9523,13 @@ async function writeTemplate(root, files, values) {
|
|
|
9156
9523
|
}
|
|
9157
9524
|
//#endregion
|
|
9158
9525
|
//#region src/version.ts
|
|
9159
|
-
const version =
|
|
9526
|
+
const version = version$1;
|
|
9160
9527
|
//#endregion
|
|
9161
9528
|
//#region src/create.ts
|
|
9162
9529
|
const { defineCommand } = agentCli();
|
|
9163
9530
|
const PACKAGE_NAME = /^(?:@[a-z0-9][a-z0-9._-]*\/)?([a-z0-9][a-z0-9._-]*)$/;
|
|
9531
|
+
const RELEASE_BRANCH = "release";
|
|
9532
|
+
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
9533
|
function errorCode(error) {
|
|
9165
9534
|
return error instanceof Error && "code" in error ? error.code : void 0;
|
|
9166
9535
|
}
|
|
@@ -9173,6 +9542,17 @@ async function isFree(path) {
|
|
|
9173
9542
|
throw error;
|
|
9174
9543
|
}
|
|
9175
9544
|
}
|
|
9545
|
+
function skillInstallLine(repository, binName) {
|
|
9546
|
+
if (repository === void 0) return NO_REPOSITORY;
|
|
9547
|
+
return `\`! npx -y skills add ${`${repository.endsWith(".git") ? repository : `${repository}.git`}#${RELEASE_BRANCH}`} --skill ${binName} -g\``;
|
|
9548
|
+
}
|
|
9549
|
+
const MANIFEST = record(string(), unknown());
|
|
9550
|
+
async function setRepository(root, repository) {
|
|
9551
|
+
const path = join(root, "package.json");
|
|
9552
|
+
const manifest = MANIFEST.parse(JSON.parse(await readFile(path, "utf8")));
|
|
9553
|
+
const entries = Object.entries(manifest).flatMap((entry) => entry[0] === "description" ? [entry, ["repository", repository]] : [entry]);
|
|
9554
|
+
await writeFile(path, `${JSON.stringify(Object.fromEntries(entries), null, 2)}\n`);
|
|
9555
|
+
}
|
|
9176
9556
|
async function ensureFree(path) {
|
|
9177
9557
|
if (!await isFree(path)) throw new UsageError({
|
|
9178
9558
|
code: "TARGET_NOT_EMPTY",
|
|
@@ -9192,9 +9572,10 @@ const create = defineCommand({
|
|
|
9192
9572
|
options: object({
|
|
9193
9573
|
description: string().default("An Agent CLI.").describe("one line saying what the CLI does"),
|
|
9194
9574
|
install: boolean().default(true).describe("run pnpm install"),
|
|
9195
|
-
git: boolean().default(true).describe("create a git repository with an initial commit")
|
|
9575
|
+
git: boolean().default(true).describe("create a git repository with an initial commit"),
|
|
9576
|
+
repository: url({ protocol: /^https$/ }).optional().describe("the https URL of the CLI's git repository, where its skill is installed from")
|
|
9196
9577
|
}),
|
|
9197
|
-
plan: async ({ name, description, install, git }, ctx) => {
|
|
9578
|
+
plan: async ({ name, description, install, git, repository }, ctx) => {
|
|
9198
9579
|
const binName = PACKAGE_NAME.exec(name)?.[1] ?? name;
|
|
9199
9580
|
const path = resolve(ctx.cwd, binName);
|
|
9200
9581
|
await ensureFree(path);
|
|
@@ -9203,7 +9584,8 @@ const create = defineCommand({
|
|
|
9203
9584
|
binName,
|
|
9204
9585
|
description,
|
|
9205
9586
|
debugVariable: debugVariable(binName),
|
|
9206
|
-
runtimeVersion: version
|
|
9587
|
+
runtimeVersion: version,
|
|
9588
|
+
skillInstall: skillInstallLine(repository, binName)
|
|
9207
9589
|
};
|
|
9208
9590
|
return {
|
|
9209
9591
|
path,
|
|
@@ -9213,12 +9595,14 @@ const create = defineCommand({
|
|
|
9213
9595
|
install,
|
|
9214
9596
|
git
|
|
9215
9597
|
}),
|
|
9216
|
-
install
|
|
9598
|
+
install,
|
|
9599
|
+
repository
|
|
9217
9600
|
};
|
|
9218
9601
|
},
|
|
9219
9602
|
apply: async (plan, ctx) => {
|
|
9220
9603
|
await mkdir(plan.path, { recursive: true });
|
|
9221
9604
|
await writeTemplate(plan.path, plan.files, plan.values);
|
|
9605
|
+
if (plan.repository !== void 0) await setRepository(plan.path, plan.repository);
|
|
9222
9606
|
await runSteps(plan.steps, plan.path, ctx);
|
|
9223
9607
|
return {
|
|
9224
9608
|
path: plan.path,
|
|
@@ -9240,6 +9624,7 @@ const { defineCli } = agentCli();
|
|
|
9240
9624
|
await runProcess(defineCli({
|
|
9241
9625
|
name: "create-agent-cli",
|
|
9242
9626
|
version,
|
|
9627
|
+
description,
|
|
9243
9628
|
build,
|
|
9244
9629
|
errors: stepErrors,
|
|
9245
9630
|
command: create
|