@duyquangnvx/create-agent-cli 0.26.0 → 0.27.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 CHANGED
@@ -4,6 +4,13 @@ What changed in each release of `@duyquangnvx/agent-cli` (the Runtime) and `@duy
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## v0.27.0 (2026-11-08)
8
+
9
+ ### Added
10
+
11
+ - A Secret declared `optional: true` is one the Command runs without, such as a token that overrides a saved login: it is read as any Secret is, `ctx.secret` types it `Secret | undefined`, and its absence fails nothing. Help JSON lists it with `"optional": true`, and `doctor` names it only when set; a name needed by any Command or by `defineCli({ secrets })` stays needed there.
12
+ - Each Command's text help lists its Secrets under `Secrets:`, each with where to get it.
13
+
7
14
  ## v0.26.0 (2026-11-06)
8
15
 
9
16
  ### Added
package/dist/bin.js CHANGED
@@ -7033,8 +7033,11 @@ function secretOf({ envFile, env, fileError }, name) {
7033
7033
  }
7034
7034
  } : void 0;
7035
7035
  }
7036
+ function isNeeded({ optional }) {
7037
+ return optional !== true;
7038
+ }
7036
7039
  function missingIn(scope, secrets) {
7037
- return secrets.filter(({ name }) => secretOf(scope, name) === void 0);
7040
+ return secrets.filter((secret) => isNeeded(secret) && secretOf(scope, secret.name) === void 0);
7038
7041
  }
7039
7042
  function getItFrom({ get }) {
7040
7043
  return `(get it from ${get})`;
@@ -7057,10 +7060,14 @@ function checkSecrets(secrets, scope, rerun) {
7057
7060
  function originOf({ origin }) {
7058
7061
  return origin.kind === "env" ? "the environment" : origin.path;
7059
7062
  }
7060
- /** The `doctor` row over every distinct Secret the CLI and its Commands declare; none without any. */
7063
+ /**
7064
+ * The `doctor` row over every distinct Secret the CLI and its Commands declare; none without any. A
7065
+ * name needed anywhere counts as needed, and an unset optional one goes unmentioned.
7066
+ */
7061
7067
  function secretRows(secrets, commands) {
7062
7068
  const declared = declaredIn(secrets, commands, (command) => command.secrets);
7063
7069
  if (declared.length === 0) return [];
7070
+ const needed = new Map(declaredIn(secrets.filter(isNeeded), commands, (command) => command.secrets?.filter(isNeeded)).map((declaration) => [declaration.name, declaration]));
7064
7071
  return [{
7065
7072
  name: "secrets",
7066
7073
  run: ({ env, envFile, fileError }) => {
@@ -7072,14 +7079,18 @@ function secretRows(secrets, commands) {
7072
7079
  fileError
7073
7080
  }, declaration.name)
7074
7081
  }));
7075
- const missing = read.filter(({ secret }) => secret === void 0);
7082
+ const missing = read.flatMap(({ declaration, secret }) => {
7083
+ const neededAs = needed.get(declaration.name);
7084
+ return secret === void 0 && neededAs !== void 0 ? [neededAs] : [];
7085
+ });
7076
7086
  if (missing.length > 0) return {
7077
7087
  state: "problem",
7078
- message: `${missing.map(({ declaration }) => `${declaration.name} is not set ${getItFrom(declaration)}`).join(", ")}; add ${missing.length === 1 ? "it" : "them"} to ${envFile} or the environment`
7088
+ message: `${missing.map((declaration) => `${declaration.name} is not set ${getItFrom(declaration)}`).join(", ")}; add ${missing.length === 1 ? "it" : "them"} to ${envFile} or the environment`
7079
7089
  };
7090
+ const found = read.flatMap(({ declaration, secret }) => secret === void 0 ? [] : [`${declaration.name} from ${originOf(secret)}`]);
7080
7091
  return {
7081
7092
  state: "ok",
7082
- message: read.flatMap(({ declaration, secret }) => secret === void 0 ? [] : [`${declaration.name} from ${originOf(secret)}`]).join(", ")
7093
+ message: found.length > 0 ? found.join(", ") : "no Secret is set, and none is needed"
7083
7094
  };
7084
7095
  }
7085
7096
  }];
@@ -7089,9 +7100,9 @@ function secretRows(secrets, commands) {
7089
7100
  /** The bundler's stamp, absent when the CLI runs unbundled. Read per call, so a test can define it. */
7090
7101
  function buildStamp() {
7091
7102
  return {
7092
- "sha": "ed7073b",
7103
+ "sha": "8ba1668",
7093
7104
  "dirty": false,
7094
- "builtAt": "2026-11-06T05:43:19.000Z"
7105
+ "builtAt": "2026-11-08T16:12:26.000Z"
7095
7106
  };
7096
7107
  }
7097
7108
  /** The first line of `--version`: the version, and the commit and time of a stamped build. */
@@ -10085,6 +10096,9 @@ function argRow(field) {
10085
10096
  function optionRow(field) {
10086
10097
  return fieldRow(field, defaultsOf(field));
10087
10098
  }
10099
+ function secretRow(declaration) {
10100
+ return [isNeeded(declaration) ? declaration.name : `${declaration.name} (optional)`, `get it from ${declaration.get}`];
10101
+ }
10088
10102
  function flagRow({ usage, description }) {
10089
10103
  return [usage, description];
10090
10104
  }
@@ -10095,6 +10109,7 @@ function commandLines(spec, style, { examples }) {
10095
10109
  ...examples ? examplesSection(spec.examples, style) : [],
10096
10110
  ...section("Arguments", spec.args.map(argRow), style),
10097
10111
  ...section("Options", spec.options.map(optionRow), style),
10112
+ ...section("Secrets", (spec.command.secrets ?? []).map(secretRow), style),
10098
10113
  ...spec.help === void 0 ? [] : ["", spec.help],
10099
10114
  "",
10100
10115
  `${style.bold("Effect:")} ${spec.effect} (${EFFECT_NOTES[spec.effect]})`,
@@ -11240,15 +11255,17 @@ function portsBaseOf(scope, signal) {
11240
11255
  }
11241
11256
  function contextOf(portsBase, control, parts) {
11242
11257
  const { ports, project, force, dryRun, secrets = [], rerun, deliver, notice } = parts;
11243
- const declared = new Set(secrets.map(({ name }) => name));
11258
+ const declared = new Map(secrets.map((declaration) => [declaration.name, declaration]));
11259
+ function secret(name) {
11260
+ const declaration = declared.get(name);
11261
+ if (declaration === void 0) throw new Error(`ctx.secret("${name}") names a Secret the Command does not declare`);
11262
+ const found = portsBase.secret(name);
11263
+ if (found === void 0 && isNeeded(declaration)) throw new Error(`ctx.secret("${name}") found no value`);
11264
+ return found;
11265
+ }
11244
11266
  return {
11245
11267
  ...portsBase,
11246
- secret: (name) => {
11247
- if (!declared.has(name)) throw new Error(`ctx.secret("${name}") names a Secret the Command does not declare`);
11248
- const secret = portsBase.secret(name);
11249
- if (secret === void 0) throw new Error(`ctx.secret("${name}") found no value`);
11250
- return secret;
11251
- },
11268
+ secret,
11252
11269
  fail: cliErrorOf,
11253
11270
  deadline: (ms, options) => control.deadline(ms, options),
11254
11271
  runToEnd: (name, work) => control.runToEnd(name, work),
@@ -11614,7 +11631,7 @@ async function runProcess(cli) {
11614
11631
  //#region package.json
11615
11632
  var package_default = {
11616
11633
  name: "@duyquangnvx/create-agent-cli",
11617
- version: "0.26.0",
11634
+ version: "0.27.0",
11618
11635
  description: "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.",
11619
11636
  type: "module",
11620
11637
  engines: { "node": ">=22.12.0" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@duyquangnvx/create-agent-cli",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Creates a new Agent CLI repository wired to @duyquangnvx/agent-cli.",
5
5
  "type": "module",
6
6
  "engines": {
@@ -21,7 +21,7 @@
21
21
  "access": "public"
22
22
  },
23
23
  "devDependencies": {
24
- "@duyquangnvx/agent-cli": "0.26.0",
24
+ "@duyquangnvx/agent-cli": "0.27.0",
25
25
  "tsdown": "0.23.0",
26
26
  "zod": "4.6.7"
27
27
  },