@lousy-agents/cli 5.8.1 → 5.8.2

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.
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "ghcr.io/devcontainers/features/copilot-cli:1.0.0": {},
12
12
  "ghcr.io/anthropics/devcontainer-features/claude-code:1": {
13
- "version": "v2.1.86"
13
+ "version": "v2.1.90"
14
14
  },
15
15
  "ghcr.io/rocker-org/devcontainer-features/apt-packages:1.0.2": {
16
16
  "packages": "yamllint, shellcheck",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "ghcr.io/devcontainers/features/copilot-cli:1.0.0": {},
12
12
  "ghcr.io/anthropics/devcontainer-features/claude-code:1": {
13
- "version": "v2.1.86"
13
+ "version": "v2.1.90"
14
14
  },
15
15
  "ghcr.io/rocker-org/devcontainer-features/apt-packages:1.0.2": {
16
16
  "packages": "yamllint, shellcheck",
@@ -14,7 +14,7 @@
14
14
  "lint:yaml": "yamllint ."
15
15
  },
16
16
  "dependencies": {
17
- "citty": "0.2.1",
17
+ "citty": "0.2.2",
18
18
  "consola": "3.4.2",
19
19
  "zod": "4.3.6"
20
20
  },
package/dist/index.js CHANGED
@@ -9694,6 +9694,7 @@ __webpack_require__.d(constructs_namespaceObject, {
9694
9694
 
9695
9695
 
9696
9696
  ;// CONCATENATED MODULE: ../../node_modules/citty/dist/_chunks/libs/scule.mjs
9697
+ //#region node_modules/.pnpm/scule@1.3.0/node_modules/scule/dist/index.mjs
9697
9698
  const NUMBER_CHAR_RE = /\d/;
9698
9699
  const STR_SPLITTERS = [
9699
9700
  "-",
@@ -9758,6 +9759,10 @@ function camelCase(str, opts) {
9758
9759
  function kebabCase(str, joiner) {
9759
9760
  return str ? (Array.isArray(str) ? str : splitByCase(str)).map((p) => p.toLowerCase()).join(joiner ?? "-") : "";
9760
9761
  }
9762
+ function snakeCase(str) {
9763
+ return kebabCase(str || "", "_");
9764
+ }
9765
+ //#endregion
9761
9766
 
9762
9767
 
9763
9768
  // EXTERNAL MODULE: external "node:util"
@@ -9765,6 +9770,7 @@ var external_node_util_ = __webpack_require__(7975);
9765
9770
  ;// CONCATENATED MODULE: ../../node_modules/citty/dist/index.mjs
9766
9771
 
9767
9772
 
9773
+ //#region src/_utils.ts
9768
9774
  function toArray(val) {
9769
9775
  if (Array.isArray(val)) return val;
9770
9776
  return val === void 0 ? [] : [val];
@@ -9785,6 +9791,8 @@ var CLIError = class extends Error {
9785
9791
  this.code = code;
9786
9792
  }
9787
9793
  };
9794
+ //#endregion
9795
+ //#region src/_parser.ts
9788
9796
  function parseRawArgs(args = [], opts = {}) {
9789
9797
  const booleans = new Set(opts.boolean || []);
9790
9798
  const strings = new Set(opts.string || []);
@@ -9810,6 +9818,12 @@ function parseRawArgs(args = [], opts = {}) {
9810
9818
  for (const alias of aliases) if (booleans.has(alias)) return "boolean";
9811
9819
  return "string";
9812
9820
  }
9821
+ function isStringType(name) {
9822
+ if (strings.has(name)) return true;
9823
+ const aliases = mainToAliases.get(name) || [];
9824
+ for (const alias of aliases) if (strings.has(alias)) return true;
9825
+ return false;
9826
+ }
9813
9827
  const allOptions = new Set([
9814
9828
  ...booleans,
9815
9829
  ...strings,
@@ -9853,7 +9867,12 @@ function parseRawArgs(args = [], opts = {}) {
9853
9867
  }
9854
9868
  const out = { _: [] };
9855
9869
  out._ = parsed.positionals;
9856
- for (const [key, value] of Object.entries(parsed.values)) out[key] = value;
9870
+ for (const [key, value] of Object.entries(parsed.values)) {
9871
+ let coerced = value;
9872
+ if (getType(key) === "boolean" && typeof value === "string") coerced = value !== "false";
9873
+ else if (isStringType(key) && typeof value === "boolean") coerced = "";
9874
+ out[key] = coerced;
9875
+ }
9857
9876
  for (const [name] of Object.entries(negatedFlags)) {
9858
9877
  out[name] = false;
9859
9878
  const mainName = aliasToMain.get(name);
@@ -9864,9 +9883,12 @@ function parseRawArgs(args = [], opts = {}) {
9864
9883
  for (const [alias, main] of aliasToMain.entries()) {
9865
9884
  if (out[alias] !== void 0 && out[main] === void 0) out[main] = out[alias];
9866
9885
  if (out[main] !== void 0 && out[alias] === void 0) out[alias] = out[main];
9886
+ if (out[alias] !== out[main] && defaults[main] === out[main]) out[main] = out[alias];
9867
9887
  }
9868
9888
  return out;
9869
9889
  }
9890
+ //#endregion
9891
+ //#region src/_color.ts
9870
9892
  const noColor = /* @__PURE__ */ (() => {
9871
9893
  const env = globalThis.process?.env ?? {};
9872
9894
  return env.NO_COLOR === "1" || env.TERM === "dumb" || env.TEST || env.CI;
@@ -9876,6 +9898,8 @@ const bold = /* @__PURE__ */ _c(1, 22);
9876
9898
  const cyan = /* @__PURE__ */ _c(36);
9877
9899
  const gray = /* @__PURE__ */ _c(90);
9878
9900
  const underline = /* @__PURE__ */ _c(4, 24);
9901
+ //#endregion
9902
+ //#region src/args.ts
9879
9903
  function parseArgs(rawArgs, argsDef) {
9880
9904
  const parseOptions = {
9881
9905
  boolean: [],
@@ -9925,6 +9949,16 @@ function resolveArgs(argsDef) {
9925
9949
  });
9926
9950
  return args;
9927
9951
  }
9952
+ //#endregion
9953
+ //#region src/plugin.ts
9954
+ function defineCittyPlugin(plugin) {
9955
+ return plugin;
9956
+ }
9957
+ async function resolvePlugins(plugins) {
9958
+ return Promise.all(plugins.map((p) => resolveValue(p)));
9959
+ }
9960
+ //#endregion
9961
+ //#region src/command.ts
9928
9962
  function defineCommand(def) {
9929
9963
  return def;
9930
9964
  }
@@ -9937,35 +9971,94 @@ async function dist_runCommand(cmd, opts) {
9937
9971
  data: opts.data,
9938
9972
  cmd
9939
9973
  };
9940
- if (typeof cmd.setup === "function") await cmd.setup(context);
9974
+ const plugins = await resolvePlugins(cmd.plugins ?? []);
9941
9975
  let result;
9976
+ let runError;
9942
9977
  try {
9978
+ for (const plugin of plugins) await plugin.setup?.(context);
9979
+ if (typeof cmd.setup === "function") await cmd.setup(context);
9943
9980
  const subCommands = await resolveValue(cmd.subCommands);
9944
9981
  if (subCommands && Object.keys(subCommands).length > 0) {
9945
- const subCommandArgIndex = opts.rawArgs.findIndex((arg) => !arg.startsWith("-"));
9946
- const subCommandName = opts.rawArgs[subCommandArgIndex];
9947
- if (subCommandName) {
9948
- if (!subCommands[subCommandName]) throw new CLIError(`Unknown command ${cyan(subCommandName)}`, "E_UNKNOWN_COMMAND");
9949
- const subCommand = await resolveValue(subCommands[subCommandName]);
9950
- if (subCommand) await dist_runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
9951
- } else if (!cmd.run) throw new CLIError(`No command specified.`, "E_NO_COMMAND");
9982
+ const subCommandArgIndex = findSubCommandIndex(opts.rawArgs, cmdArgs);
9983
+ const explicitName = opts.rawArgs[subCommandArgIndex];
9984
+ if (explicitName) {
9985
+ const subCommand = await _findSubCommand(subCommands, explicitName);
9986
+ if (!subCommand) throw new CLIError(`Unknown command ${cyan(explicitName)}`, "E_UNKNOWN_COMMAND");
9987
+ await dist_runCommand(subCommand, { rawArgs: opts.rawArgs.slice(subCommandArgIndex + 1) });
9988
+ } else {
9989
+ const defaultSubCommand = await resolveValue(cmd.default);
9990
+ if (defaultSubCommand) {
9991
+ if (cmd.run) throw new CLIError(`Cannot specify both 'run' and 'default' on the same command.`, "E_DEFAULT_CONFLICT");
9992
+ const subCommand = await _findSubCommand(subCommands, defaultSubCommand);
9993
+ if (!subCommand) throw new CLIError(`Default sub command ${cyan(defaultSubCommand)} not found in subCommands.`, "E_UNKNOWN_COMMAND");
9994
+ await dist_runCommand(subCommand, { rawArgs: opts.rawArgs });
9995
+ } else if (!cmd.run) throw new CLIError(`No command specified.`, "E_NO_COMMAND");
9996
+ }
9952
9997
  }
9953
9998
  if (typeof cmd.run === "function") result = await cmd.run(context);
9954
- } finally {
9955
- if (typeof cmd.cleanup === "function") await cmd.cleanup(context);
9999
+ } catch (error) {
10000
+ runError = error;
10001
+ }
10002
+ const cleanupErrors = [];
10003
+ if (typeof cmd.cleanup === "function") try {
10004
+ await cmd.cleanup(context);
10005
+ } catch (error) {
10006
+ cleanupErrors.push(error);
10007
+ }
10008
+ for (const plugin of [...plugins].reverse()) try {
10009
+ await plugin.cleanup?.(context);
10010
+ } catch (error) {
10011
+ cleanupErrors.push(error);
9956
10012
  }
10013
+ if (runError) throw runError;
10014
+ if (cleanupErrors.length === 1) throw cleanupErrors[0];
10015
+ if (cleanupErrors.length > 1) throw new Error("Multiple cleanup errors", { cause: cleanupErrors });
9957
10016
  return { result };
9958
10017
  }
9959
10018
  async function resolveSubCommand(cmd, rawArgs, parent) {
9960
10019
  const subCommands = await resolveValue(cmd.subCommands);
9961
10020
  if (subCommands && Object.keys(subCommands).length > 0) {
9962
- const subCommandArgIndex = rawArgs.findIndex((arg) => !arg.startsWith("-"));
10021
+ const subCommandArgIndex = findSubCommandIndex(rawArgs, await resolveValue(cmd.args || {}));
9963
10022
  const subCommandName = rawArgs[subCommandArgIndex];
9964
- const subCommand = await resolveValue(subCommands[subCommandName]);
10023
+ const subCommand = await _findSubCommand(subCommands, subCommandName);
9965
10024
  if (subCommand) return resolveSubCommand(subCommand, rawArgs.slice(subCommandArgIndex + 1), cmd);
9966
10025
  }
9967
10026
  return [cmd, parent];
9968
10027
  }
10028
+ async function _findSubCommand(subCommands, name) {
10029
+ if (name in subCommands) return resolveValue(subCommands[name]);
10030
+ for (const sub of Object.values(subCommands)) {
10031
+ const resolved = await resolveValue(sub);
10032
+ const meta = await resolveValue(resolved?.meta);
10033
+ if (meta?.alias) {
10034
+ if (toArray(meta.alias).includes(name)) return resolved;
10035
+ }
10036
+ }
10037
+ }
10038
+ function findSubCommandIndex(rawArgs, argsDef) {
10039
+ for (let i = 0; i < rawArgs.length; i++) {
10040
+ const arg = rawArgs[i];
10041
+ if (arg === "--") return -1;
10042
+ if (arg.startsWith("-")) {
10043
+ if (!arg.includes("=") && _isValueFlag(arg, argsDef)) i++;
10044
+ continue;
10045
+ }
10046
+ return i;
10047
+ }
10048
+ return -1;
10049
+ }
10050
+ function _isValueFlag(flag, argsDef) {
10051
+ const name = flag.replace(/^-{1,2}/, "");
10052
+ const normalized = camelCase(name);
10053
+ for (const [key, def] of Object.entries(argsDef)) {
10054
+ if (def.type !== "string" && def.type !== "enum") continue;
10055
+ if (normalized === camelCase(key)) return true;
10056
+ if ((Array.isArray(def.alias) ? def.alias : def.alias ? [def.alias] : []).includes(name)) return true;
10057
+ }
10058
+ return false;
10059
+ }
10060
+ //#endregion
10061
+ //#region src/usage.ts
9969
10062
  async function showUsage(cmd, parent) {
9970
10063
  try {
9971
10064
  console.log(await renderUsage(cmd, parent) + "\n");
@@ -9986,22 +10079,22 @@ async function renderUsage(cmd, parent) {
9986
10079
  for (const arg of cmdArgs) if (arg.type === "positional") {
9987
10080
  const name = arg.name.toUpperCase();
9988
10081
  const isRequired = arg.required !== false && arg.default === void 0;
9989
- const defaultHint = arg.default ? `="${arg.default}"` : "";
9990
- posLines.push([
9991
- cyan(name + defaultHint),
9992
- arg.description || "",
9993
- arg.valueHint ? `<${arg.valueHint}>` : ""
9994
- ]);
10082
+ posLines.push([cyan(name + renderValueHint(arg)), renderDescription(arg, isRequired)]);
9995
10083
  usageLine.push(isRequired ? `<${name}>` : `[${name}]`);
9996
10084
  } else {
9997
10085
  const isRequired = arg.required === true && arg.default === void 0;
9998
- const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + (arg.type === "string" && (arg.valueHint || arg.default) ? `=${arg.valueHint ? `<${arg.valueHint}>` : `"${arg.default || ""}"`}` : "") + (arg.type === "enum" && arg.options ? `=<${arg.options.join("|")}>` : "");
9999
- argLines.push([cyan(argStr + (isRequired ? " (required)" : "")), arg.description || ""]);
10086
+ const argStr = [...(arg.alias || []).map((a) => `-${a}`), `--${arg.name}`].join(", ") + renderValueHint(arg);
10087
+ argLines.push([cyan(argStr), renderDescription(arg, isRequired)]);
10088
+ /**
10089
+ * print negative boolean arg variant usage when
10090
+ * - enabled by default or has `negativeDescription`
10091
+ * - not prefixed with `no-` or `no[A-Z]`
10092
+ */
10000
10093
  if (arg.type === "boolean" && (arg.default === true || arg.negativeDescription) && !negativePrefixRe.test(arg.name)) {
10001
10094
  const negativeArgStr = [...(arg.alias || []).map((a) => `--no-${a}`), `--no-${arg.name}`].join(", ");
10002
- argLines.push([cyan(negativeArgStr + (isRequired ? " (required)" : "")), arg.negativeDescription || ""]);
10095
+ argLines.push([cyan(negativeArgStr), [arg.negativeDescription, isRequired ? gray("(Required)") : ""].filter(Boolean).join(" ")]);
10003
10096
  }
10004
- if (isRequired) usageLine.push(argStr);
10097
+ if (isRequired) usageLine.push(`--${arg.name}` + renderValueHint(arg));
10005
10098
  }
10006
10099
  if (cmd.subCommands) {
10007
10100
  const commandNames = [];
@@ -10009,8 +10102,10 @@ async function renderUsage(cmd, parent) {
10009
10102
  for (const [name, sub] of Object.entries(subCommands)) {
10010
10103
  const meta = await resolveValue((await resolveValue(sub))?.meta);
10011
10104
  if (meta?.hidden) continue;
10012
- commandsLines.push([cyan(name), meta?.description || ""]);
10013
- commandNames.push(name);
10105
+ const aliases = toArray(meta?.alias);
10106
+ const label = [name, ...aliases].join(", ");
10107
+ commandsLines.push([cyan(label), meta?.description || ""]);
10108
+ commandNames.push(name, ...aliases);
10014
10109
  }
10015
10110
  usageLine.push(commandNames.join("|"));
10016
10111
  }
@@ -10036,14 +10131,33 @@ async function renderUsage(cmd, parent) {
10036
10131
  }
10037
10132
  return usageLines.filter((l) => typeof l === "string").join("\n");
10038
10133
  }
10134
+ function renderValueHint(arg) {
10135
+ const valueHint = arg.valueHint ? `=<${arg.valueHint}>` : "";
10136
+ const fallbackValueHint = valueHint || `=<${snakeCase(arg.name)}>`;
10137
+ if (!arg.type || arg.type === "positional" || arg.type === "boolean") return valueHint;
10138
+ if (arg.type === "enum" && arg.options?.length) return `=<${arg.options.join("|")}>`;
10139
+ return fallbackValueHint;
10140
+ }
10141
+ function renderDescription(arg, required) {
10142
+ const requiredHint = required ? gray("(Required)") : "";
10143
+ const defaultHint = arg.default === void 0 ? "" : gray(`(Default: ${arg.default})`);
10144
+ return [
10145
+ arg.description,
10146
+ requiredHint,
10147
+ defaultHint
10148
+ ].filter(Boolean).join(" ");
10149
+ }
10150
+ //#endregion
10151
+ //#region src/main.ts
10039
10152
  async function runMain(cmd, opts = {}) {
10040
10153
  const rawArgs = opts.rawArgs || process.argv.slice(2);
10041
10154
  const showUsage$1 = opts.showUsage || showUsage;
10042
10155
  try {
10043
- if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
10156
+ const builtinFlags = await _resolveBuiltinFlags(cmd);
10157
+ if (builtinFlags.help.length > 0 && rawArgs.some((arg) => builtinFlags.help.includes(arg))) {
10044
10158
  await showUsage$1(...await resolveSubCommand(cmd, rawArgs));
10045
10159
  process.exit(0);
10046
- } else if (rawArgs.length === 1 && rawArgs[0] === "--version") {
10160
+ } else if (rawArgs.length === 1 && builtinFlags.version.includes(rawArgs[0])) {
10047
10161
  const meta = typeof cmd.meta === "function" ? await cmd.meta() : await cmd.meta;
10048
10162
  if (!meta?.version) throw new CLIError("No version specified", "E_NO_VERSION");
10049
10163
  console.log(meta.version);
@@ -10059,6 +10173,25 @@ async function runMain(cmd, opts = {}) {
10059
10173
  function createMain(cmd) {
10060
10174
  return (opts = {}) => runMain(cmd, opts);
10061
10175
  }
10176
+ async function _resolveBuiltinFlags(cmd) {
10177
+ const argsDef = await resolveValue(cmd.args || {});
10178
+ const userNames = /* @__PURE__ */ new Set();
10179
+ const userAliases = /* @__PURE__ */ new Set();
10180
+ for (const [name, def] of Object.entries(argsDef)) {
10181
+ userNames.add(name);
10182
+ for (const alias of toArray(def.alias)) userAliases.add(alias);
10183
+ }
10184
+ return {
10185
+ help: _getBuiltinFlags("help", "h", userNames, userAliases),
10186
+ version: _getBuiltinFlags("version", "v", userNames, userAliases)
10187
+ };
10188
+ }
10189
+ function _getBuiltinFlags(long, short, userNames, userAliases) {
10190
+ if (userNames.has(long) || userAliases.has(long)) return [];
10191
+ if (userNames.has(short) || userAliases.has(short)) return [`--${long}`];
10192
+ return [`--${long}`, `-${short}`];
10193
+ }
10194
+ //#endregion
10062
10195
 
10063
10196
 
10064
10197
  // EXTERNAL MODULE: external "node:fs/promises"
@@ -13378,7 +13511,7 @@ function partial(Class, schema, mask) {
13378
13511
  });
13379
13512
  return clone(schema, def);
13380
13513
  }
13381
- function required(Class, schema, mask) {
13514
+ function util_required(Class, schema, mask) {
13382
13515
  const def = mergeDefs(schema._zod.def, {
13383
13516
  get shape() {
13384
13517
  const oldShape = schema._zod.def.shape;
@@ -25300,7 +25433,7 @@ const ZodObject = /*@__PURE__*/ $constructor("ZodObject", (inst, def) => {
25300
25433
  inst.pick = (mask) => pick(inst, mask);
25301
25434
  inst.omit = (mask) => omit(inst, mask);
25302
25435
  inst.partial = (...args) => partial(ZodOptional, inst, args[0]);
25303
- inst.required = (...args) => required(ZodNonOptional, inst, args[0]);
25436
+ inst.required = (...args) => util_required(ZodNonOptional, inst, args[0]);
25304
25437
  });
25305
25438
  function schemas_object(shape, params) {
25306
25439
  const def = {