apcore-cli 0.8.0 → 0.9.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/dist/index.js CHANGED
@@ -34,6 +34,12 @@ function exitCodeForError(error) {
34
34
  if (error instanceof SchemaValidationError) {
35
35
  return EXIT_CODES.SCHEMA_VALIDATION_ERROR;
36
36
  }
37
+ if (error instanceof MaxDepthExceededError || error instanceof CircularRefError) {
38
+ return EXIT_CODES.SCHEMA_CIRCULAR_REF;
39
+ }
40
+ if (error instanceof UnresolvableRefError) {
41
+ return EXIT_CODES.SCHEMA_VALIDATION_ERROR;
42
+ }
37
43
  if (error instanceof ModuleNotFoundError) {
38
44
  return EXIT_CODES.MODULE_NOT_FOUND;
39
45
  }
@@ -73,7 +79,7 @@ function exitCodeForError(error) {
73
79
  }
74
80
  return EXIT_CODES.MODULE_EXECUTE_ERROR;
75
81
  }
76
- var ApprovalTimeoutError, AuthenticationError, ConfigDecryptionError, ModuleExecutionError, ApprovalDeniedError, SchemaValidationError, ModuleNotFoundError, EXIT_CODES;
82
+ var ApprovalTimeoutError, AuthenticationError, ConfigDecryptionError, ModuleExecutionError, ApprovalDeniedError, SchemaValidationError, MaxDepthExceededError, CircularRefError, UnresolvableRefError, ModuleNotFoundError, EXIT_CODES;
77
83
  var init_errors = __esm({
78
84
  "src/errors.ts"() {
79
85
  "use strict";
@@ -114,6 +120,24 @@ var init_errors = __esm({
114
120
  this.name = "SchemaValidationError";
115
121
  }
116
122
  };
123
+ MaxDepthExceededError = class extends Error {
124
+ constructor(message = "Schema $ref resolution depth exceeded") {
125
+ super(message);
126
+ this.name = "MaxDepthExceededError";
127
+ }
128
+ };
129
+ CircularRefError = class extends Error {
130
+ constructor(message = "Circular $ref detected in schema") {
131
+ super(message);
132
+ this.name = "CircularRefError";
133
+ }
134
+ };
135
+ UnresolvableRefError = class extends Error {
136
+ constructor(message = "Unresolvable $ref in schema") {
137
+ super(message);
138
+ this.name = "UnresolvableRefError";
139
+ }
140
+ };
117
141
  ModuleNotFoundError = class extends Error {
118
142
  constructor(message = "Module not found") {
119
143
  super(message);
@@ -406,7 +430,7 @@ var init_config_encryptor = __esm({
406
430
  _ConfigEncryptor.weakFallbackWarned = true;
407
431
  }
408
432
  const hostname2 = os3.hostname();
409
- const username = process.env.USER ?? process.env.USERNAME ?? "unknown";
433
+ const username = process.env.USER ?? process.env.LOGNAME ?? process.env.USERNAME ?? "unknown";
410
434
  const material = `${hostname2}:${username}`;
411
435
  return crypto2.pbkdf2Sync(material, salt, PBKDF2_ITERATIONS, 32, "sha256");
412
436
  }
@@ -438,7 +462,7 @@ var init_config_encryptor = __esm({
438
462
  const tag = data.subarray(12, 28);
439
463
  const ct = data.subarray(28);
440
464
  const hostname2 = os3.hostname();
441
- const username = process.env.USER ?? process.env.USERNAME ?? "unknown";
465
+ const username = process.env.USER ?? process.env.LOGNAME ?? process.env.USERNAME ?? "unknown";
442
466
  const passphrase = process.env.APCORE_CLI_CONFIG_PASSPHRASE;
443
467
  const materials = passphrase ? [passphrase, `${hostname2}:${username}`] : [`${hostname2}:${username}`];
444
468
  for (const material of materials) {
@@ -468,10 +492,26 @@ var init_auth = __esm({
468
492
  init_config_encryptor();
469
493
  AuthProvider = class {
470
494
  config;
471
- encryptor;
495
+ _encryptor;
472
496
  constructor(config, encryptor) {
473
497
  this.config = config;
474
- this.encryptor = encryptor ?? new ConfigEncryptor();
498
+ this._encryptor = encryptor;
499
+ }
500
+ /**
501
+ * Resolve the active ConfigEncryptor instance.
502
+ *
503
+ * D11-005 (2026-05-12): three-tier fallback chain matching Python's
504
+ * `_get_encryptor` (auth.py:33): explicit constructor arg > peer attribute
505
+ * `config.encryptor` (set by embedders injecting forced-AES test fixtures
506
+ * or shared instances) > fresh `new ConfigEncryptor()`. Previously TS
507
+ * skipped the peer-attribute tier, silently giving embedders a different
508
+ * encryptor than the one they wired on the config.
509
+ */
510
+ getEncryptor() {
511
+ if (this._encryptor) return this._encryptor;
512
+ const fromConfig = this.config.encryptor;
513
+ if (fromConfig) return fromConfig;
514
+ return new ConfigEncryptor();
475
515
  }
476
516
  /**
477
517
  * Retrieve the API key from the configured sources.
@@ -489,11 +529,11 @@ var init_auth = __esm({
489
529
  const strResult = String(result);
490
530
  if (strResult.startsWith("keyring:") || strResult.startsWith("enc:")) {
491
531
  try {
492
- return await this.encryptor.retrieve(strResult, "auth.api_key");
532
+ return await this.getEncryptor().retrieve(strResult, "auth.api_key");
493
533
  } catch (err) {
494
534
  if (err instanceof ConfigDecryptionError) {
495
535
  throw new AuthenticationError(
496
- "Failed to decrypt stored API key. Re-configure with 'apcore-cli config set auth.api_key'."
536
+ "Failed to decrypt stored API key. Re-store with 'apcli config set auth.api_key'."
497
537
  );
498
538
  }
499
539
  throw err;
@@ -522,7 +562,7 @@ var init_auth = __esm({
522
562
  }
523
563
  if (/[\r\n]/.test(key)) {
524
564
  throw new AuthenticationError(
525
- "Malformed API key: contains invalid characters (CR/LF). Re-configure with 'apcore-cli config set auth.api_key'."
565
+ "Malformed API key: contains invalid characters (CR/LF). Re-store with 'apcli config set auth.api_key'."
526
566
  );
527
567
  }
528
568
  headers.Authorization = `Bearer ${key.trim()}`;
@@ -543,10 +583,14 @@ var init_auth = __esm({
543
583
  });
544
584
 
545
585
  // src/security/sandbox.ts
586
+ import { spawn } from "child_process";
587
+ import { mkdtempSync, rmSync } from "fs";
588
+ import { tmpdir } from "os";
589
+ import { join as join4, resolve as resolvePath } from "path";
546
590
  function buildSandboxEnv(tmpDir) {
547
591
  const env = {};
548
592
  for (const key of SANDBOX_ALLOW_KEYS) {
549
- if (process.env[key]) env[key] = process.env[key];
593
+ if (process.env[key] !== void 0) env[key] = process.env[key];
550
594
  }
551
595
  for (const [key, val] of Object.entries(process.env)) {
552
596
  if (key.startsWith(SANDBOX_ALLOW_PREFIX) && !key.startsWith(SANDBOX_DENY_PREFIX) && !SANDBOX_DENY_KEYS.includes(key)) {
@@ -612,13 +656,8 @@ var init_sandbox = __esm({
612
656
  return this._sandboxedExecute(moduleId, inputData);
613
657
  }
614
658
  async _sandboxedExecute(moduleId, inputData) {
615
- const { spawn } = await import("child_process");
616
- const { tmpdir } = await import("os");
617
- const { join: join4 } = await import("path");
618
- const { mkdtempSync, rmSync } = await import("fs");
619
659
  const tmpDir = mkdtempSync(join4(tmpdir(), "apcore_sandbox_"));
620
660
  const env = buildSandboxEnv(tmpDir);
621
- const { resolve: resolvePath } = await import("path");
622
661
  if (this.extensionsRoot !== null) {
623
662
  env.APCORE_EXTENSIONS_ROOT = resolvePath(this.extensionsRoot);
624
663
  } else if (env.APCORE_EXTENSIONS_ROOT) {
@@ -656,11 +695,20 @@ var init_sandbox = __esm({
656
695
  }
657
696
  stderr += chunk.toString();
658
697
  });
698
+ child.stdin.on("error", () => {
699
+ });
659
700
  child.stdin.write(JSON.stringify(inputData));
660
701
  child.stdin.end();
661
702
  return new Promise((resolve2, reject) => {
703
+ const cleanup = () => {
704
+ try {
705
+ rmSync(tmpDir, { recursive: true, force: true });
706
+ } catch {
707
+ }
708
+ };
662
709
  const timer = setTimeout(() => {
663
710
  child.kill("SIGKILL");
711
+ cleanup();
664
712
  reject(
665
713
  new ModuleExecutionError(
666
714
  `Sandbox module '${moduleId}' timed out after ${this.timeoutSeconds}s.`
@@ -669,10 +717,7 @@ var init_sandbox = __esm({
669
717
  }, this.timeoutSeconds * 1e3);
670
718
  child.on("close", (code) => {
671
719
  clearTimeout(timer);
672
- try {
673
- rmSync(tmpDir, { recursive: true, force: true });
674
- } catch {
675
- }
720
+ cleanup();
676
721
  if (sizeExceeded) {
677
722
  const limitMiB = Math.floor(outputCap / (1024 * 1024));
678
723
  reject(new ModuleExecutionError(
@@ -696,6 +741,7 @@ var init_sandbox = __esm({
696
741
  });
697
742
  child.on("error", (err) => {
698
743
  clearTimeout(timer);
744
+ cleanup();
699
745
  reject(new ModuleExecutionError(`Failed to spawn sandbox process: ${err.message}`));
700
746
  });
701
747
  });
@@ -762,27 +808,21 @@ function resolveNode(node, defs, visited, depth, maxDepth, moduleId) {
762
808
  if ("$ref" in obj) {
763
809
  const refPath = obj.$ref;
764
810
  if (depth >= maxDepth) {
765
- process.stderr.write(
766
- `Error: $ref resolution depth exceeded maximum of ${maxDepth} for module '${moduleId}'.
767
- `
811
+ throw new MaxDepthExceededError(
812
+ `$ref resolution depth exceeded maximum of ${maxDepth} for module '${moduleId}'.`
768
813
  );
769
- process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
770
814
  }
771
815
  if (visited.has(refPath)) {
772
- process.stderr.write(
773
- `Error: Circular $ref detected in schema for module '${moduleId}' at path '${refPath}'.
774
- `
816
+ throw new CircularRefError(
817
+ `Circular $ref detected in schema for module '${moduleId}' at path '${refPath}'.`
775
818
  );
776
- process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
777
819
  }
778
820
  const parts = refPath.split("/");
779
821
  const key = parts[parts.length - 1];
780
822
  if (!(key in defs)) {
781
- process.stderr.write(
782
- `Error: Unresolvable $ref '${refPath}' in schema for module '${moduleId}'.
783
- `
823
+ throw new UnresolvableRefError(
824
+ `Unresolvable $ref '${refPath}' in schema for module '${moduleId}'.`
784
825
  );
785
- process.exit(EXIT_CODES.SCHEMA_VALIDATION_ERROR);
786
826
  }
787
827
  const newVisited = new Set(visited);
788
828
  newVisited.add(refPath);
@@ -883,17 +923,12 @@ function resolveNode(node, defs, visited, depth, maxDepth, moduleId) {
883
923
  return merged;
884
924
  }
885
925
  }
886
- if ("properties" in obj && typeof obj.properties === "object" && obj.properties !== null) {
887
- const props = obj.properties;
888
- for (const [propName, propSchema] of Object.entries(props)) {
889
- props[propName] = resolveNode(
890
- propSchema,
891
- defs,
892
- visited,
893
- depth,
894
- maxDepth,
895
- moduleId
896
- );
926
+ for (const [k, v] of Object.entries(obj)) {
927
+ if (k === "allOf" || k === "anyOf" || k === "oneOf" || k === "$ref") {
928
+ continue;
929
+ }
930
+ if (typeof v === "object" && v !== null && !Array.isArray(v)) {
931
+ obj[k] = resolveNode(v, defs, visited, depth, maxDepth, moduleId);
897
932
  }
898
933
  }
899
934
  return obj;
@@ -942,7 +977,7 @@ var RESERVED_NAMES = /* @__PURE__ */ new Set([
942
977
  "format",
943
978
  "fields",
944
979
  "sandbox",
945
- "verbose",
980
+ "all_options",
946
981
  "dry_run",
947
982
  "trace",
948
983
  "stream",
@@ -1090,6 +1125,14 @@ var CliApprovalHandler = class {
1090
1125
  }
1091
1126
  async requestApproval(request) {
1092
1127
  const moduleId = request.module_id ?? "unknown";
1128
+ if (request.requires_approval === false) {
1129
+ return { status: "approved", approved_by: "not_required" };
1130
+ }
1131
+ const moduleDef = request.module_def;
1132
+ const annotationsForCheck = moduleDef?.annotations;
1133
+ if (annotationsForCheck && annotationsForCheck.requires_approval === false) {
1134
+ return { status: "approved", approved_by: "not_required" };
1135
+ }
1093
1136
  if (this.autoApprove) {
1094
1137
  return { status: "approved", approved_by: "auto_approve" };
1095
1138
  }
@@ -1198,7 +1241,8 @@ async function promptWithTimeout(moduleDef, timeout) {
1198
1241
  init_esm_shims();
1199
1242
  init_errors();
1200
1243
  import yaml from "js-yaml";
1201
- var TOOLKIT_MISSING_HINT = "The 'markdown' and 'skill' output formats require the apcore-toolkit peer dependency. Install with: npm install apcore-toolkit@^0.6";
1244
+ import { formatCsv, formatJsonl } from "apcore-toolkit";
1245
+ var TOOLKIT_MISSING_HINT = "The 'markdown' and 'skill' output formats require the apcore-toolkit peer dependency. Install with: npm install apcore-toolkit@^0.7";
1202
1246
  function descriptorToScanned(m) {
1203
1247
  const metadata = m.metadata ?? {};
1204
1248
  const display = metadata["display"] ?? null;
@@ -1219,11 +1263,6 @@ function descriptorToScanned(m) {
1219
1263
  warnings: []
1220
1264
  };
1221
1265
  }
1222
- function csvCellString(value) {
1223
- if (value === null || value === void 0) return "";
1224
- if (typeof value === "object") return JSON.stringify(value);
1225
- return String(value);
1226
- }
1227
1266
  function resolveFormat(explicitFormat) {
1228
1267
  if (explicitFormat !== void 0) {
1229
1268
  return explicitFormat;
@@ -1426,30 +1465,18 @@ function formatExecResult(result, format, fields) {
1426
1465
  }
1427
1466
  const effective = resolveFormat(format);
1428
1467
  if (effective === "csv") {
1429
- if (typeof effective_result === "object" && !Array.isArray(effective_result) && effective_result !== null) {
1430
- const obj = effective_result;
1431
- const keys = Object.keys(obj);
1432
- const header = keys.map(escapeCsvField).join(",");
1433
- const row = keys.map((k) => escapeCsvField(csvCellString(obj[k]))).join(",");
1434
- process.stdout.write(header + "\n" + row + "\n");
1435
- } else if (Array.isArray(effective_result) && effective_result.length > 0 && typeof effective_result[0] === "object") {
1436
- const keys = Object.keys(effective_result[0]);
1437
- const header = keys.map(escapeCsvField).join(",");
1438
- const rows = effective_result.map((item) => {
1439
- const obj = item;
1440
- return keys.map((k) => escapeCsvField(csvCellString(obj[k]))).join(",");
1441
- });
1442
- process.stdout.write(header + "\n" + rows.join("\n") + "\n");
1468
+ const rows = toRowsForTabular(effective_result);
1469
+ if (rows !== null) {
1470
+ process.stdout.write(formatCsv(rows));
1443
1471
  } else {
1444
1472
  process.stdout.write(JSON.stringify(effective_result) + "\n");
1445
1473
  }
1446
1474
  } else if (effective === "yaml") {
1447
1475
  process.stdout.write(yaml.dump(effective_result, { lineWidth: -1 }));
1448
1476
  } else if (effective === "jsonl") {
1449
- if (Array.isArray(effective_result)) {
1450
- for (const item of effective_result) {
1451
- process.stdout.write(JSON.stringify(item) + "\n");
1452
- }
1477
+ const rows = toRowsForTabular(effective_result);
1478
+ if (rows !== null) {
1479
+ process.stdout.write(formatJsonl(rows));
1453
1480
  } else {
1454
1481
  process.stdout.write(JSON.stringify(effective_result) + "\n");
1455
1482
  }
@@ -1466,11 +1493,19 @@ function formatExecResult(result, format, fields) {
1466
1493
  process.stdout.write(String(effective_result) + "\n");
1467
1494
  }
1468
1495
  }
1469
- function escapeCsvField(value) {
1470
- if (value.includes(",") || value.includes('"') || value.includes("\n") || value.includes("\r")) {
1471
- return '"' + value.replace(/"/g, '""') + '"';
1496
+ function toRowsForTabular(value) {
1497
+ if (value === null || value === void 0) return null;
1498
+ if (Array.isArray(value)) {
1499
+ if (value.length === 0) return null;
1500
+ if (!value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item))) {
1501
+ return null;
1502
+ }
1503
+ return value;
1504
+ }
1505
+ if (typeof value === "object") {
1506
+ return [value];
1472
1507
  }
1473
- return value;
1508
+ return null;
1474
1509
  }
1475
1510
  function formatPreflightResult(result, format) {
1476
1511
  const resolved = resolveFormat(format);
@@ -1608,7 +1643,7 @@ function renderTemplate(template, context) {
1608
1643
  return result;
1609
1644
  }
1610
1645
  function registerInitCommand(cli) {
1611
- const initGroup = cli.command("init").description("Scaffold new apcore modules.");
1646
+ const initGroup = cli.command("init").description("Scaffold new modules.");
1612
1647
  initGroup.command("module <module-id>").description("Create a new module from a template.\n\nMODULE_ID is the module identifier (e.g., ops.deploy, user.create).").option(
1613
1648
  "--style <style>",
1614
1649
  "Module style: decorator (@module), convention (plain function), or binding (YAML).",
@@ -2136,7 +2171,7 @@ function buildProgramManPage(program, progName, version, description, docsUrl2)
2136
2171
  s.push(".SH ENVIRONMENT");
2137
2172
  s.push(".TP");
2138
2173
  s.push("\\fBAPCORE_EXTENSIONS_ROOT\\fR");
2139
- s.push("Path to the apcore extensions directory.");
2174
+ s.push("Path to the extensions directory.");
2140
2175
  s.push(".TP");
2141
2176
  s.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
2142
2177
  s.push("Set to \\fB1\\fR to bypass approval prompts.");
@@ -2161,7 +2196,7 @@ function buildProgramManPage(program, progName, version, description, docsUrl2)
2161
2196
  ${meaning}`);
2162
2197
  }
2163
2198
  s.push(".SH SEE ALSO");
2164
- s.push(`\\fB${progName} \\-\\-help \\-\\-verbose\\fR for full option list.`);
2199
+ s.push(`\\fB${progName} \\-\\-help \\-\\-all\\-options\\fR for full option list.`);
2165
2200
  if (docsUrl2) {
2166
2201
  s.push(`.PP
2167
2202
  Full documentation at \\fI${roffEscape(docsUrl2)}\\fR`);
@@ -2513,7 +2548,7 @@ function registerExecCommand(apcliGroup, registry, executor) {
2513
2548
  return;
2514
2549
  }
2515
2550
  let result;
2516
- if (opts.strategy && executor.callWithTrace) {
2551
+ if ((opts.trace || opts.strategy) && executor.callWithTrace) {
2517
2552
  const [res] = await executor.callWithTrace(moduleId, merged, { strategy: opts.strategy });
2518
2553
  result = res;
2519
2554
  } else {
@@ -3574,15 +3609,18 @@ function validateModuleId(moduleId) {
3574
3609
  // src/main.ts
3575
3610
  var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
3576
3611
  var verboseHelp = false;
3612
+ function setAllOptionsHelp(allOptions) {
3613
+ verboseHelp = allOptions;
3614
+ }
3577
3615
  function setVerboseHelp(verbose) {
3578
- verboseHelp = verbose;
3616
+ setAllOptionsHelp(verbose);
3579
3617
  }
3580
3618
  var docsUrl = null;
3581
3619
  function setDocsUrl(url) {
3582
3620
  docsUrl = url;
3583
3621
  }
3584
3622
  function hasVerboseFlag() {
3585
- return process.argv.includes("--verbose");
3623
+ return process.argv.includes("--all-options");
3586
3624
  }
3587
3625
  function resolveIntOption(cliValue, envValue, defaultValue) {
3588
3626
  if (cliValue !== void 0 && Number.isFinite(cliValue) && cliValue > 0) {
@@ -3663,7 +3701,7 @@ function emitErrorTty(e, exitCode) {
3663
3701
  Exit code: ${exitCode}
3664
3702
  `);
3665
3703
  }
3666
- function createCli(extensionsDirOrOpts, progName, verbose = false) {
3704
+ function createCli(extensionsDirOrOpts, progName, allOptions = false) {
3667
3705
  let extensionsDir;
3668
3706
  let registry;
3669
3707
  let executor;
@@ -3678,7 +3716,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
3678
3716
  if (typeof extensionsDirOrOpts === "object" && extensionsDirOrOpts !== null) {
3679
3717
  extensionsDir = extensionsDirOrOpts.extensionsDir;
3680
3718
  progName = extensionsDirOrOpts.progName ?? progName;
3681
- verbose = extensionsDirOrOpts.verbose ?? verbose;
3719
+ allOptions = extensionsDirOrOpts.allOptions ?? extensionsDirOrOpts.verbose ?? allOptions;
3682
3720
  app = extensionsDirOrOpts.app;
3683
3721
  registry = extensionsDirOrOpts.registry;
3684
3722
  executor = extensionsDirOrOpts.executor;
@@ -3692,7 +3730,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
3692
3730
  } else {
3693
3731
  extensionsDir = extensionsDirOrOpts;
3694
3732
  }
3695
- verboseHelp = verbose;
3733
+ verboseHelp = allOptions;
3696
3734
  registerConfigNamespace();
3697
3735
  try {
3698
3736
  const auditLogger = new AuditLogger();
@@ -3725,7 +3763,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
3725
3763
  }
3726
3764
  }
3727
3765
  const registryInjected = registry !== void 0;
3728
- const program = new Command5(resolvedProgName).exitOverride().helpOption("-h, --help", "Print help").addHelpCommand("help [command]", "Print this message or the help of the given subcommand(s)").description(appDescription ?? `${resolvedProgName} CLI`).option("--log-level <level>", "Logging level (DEBUG|INFO|WARNING|ERROR)", "WARNING").option("--verbose", "Show all options in help output (including built-in options)");
3766
+ const program = new Command5(resolvedProgName).exitOverride().helpOption("-h, --help", "Print help").addHelpCommand("help [command]", "Print this message or the help of the given subcommand(s)").description(appDescription ?? `${resolvedProgName} CLI`).option("--log-level <level>", "Logging level (DEBUG|INFO|WARNING|ERROR)", "WARNING").option("--all-options", "Show all options in help output (including built-in options)");
3729
3767
  if (appVersion) {
3730
3768
  program.version(appVersion, "-V, --version", "Print version");
3731
3769
  }
@@ -3796,7 +3834,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
3796
3834
  _registerApcliSubcommands(apcliGroup, apcliCfg, registry, executor, exposureFilter);
3797
3835
  program.addHelpText("after", [
3798
3836
  "",
3799
- "Use --help --verbose to show all options (including built-in options).",
3837
+ "Use --help --all-options to show all options (including built-in options).",
3800
3838
  "Use --help --man to display a formatted man page."
3801
3839
  ].join("\n"));
3802
3840
  configureManHelp(program, resolvedProgName, appVersion ?? VERSION);
@@ -3834,7 +3872,7 @@ var _ALWAYS_REGISTERED = /* @__PURE__ */ new Set(["exec"]);
3834
3872
  function _registerApcliSubcommands(apcliGroup, apcliCfg, registry, executor, exposureFilter) {
3835
3873
  const emitUnwiredError = () => {
3836
3874
  process.stderr.write(
3837
- "Error: no apcore-js registry wired. In standalone mode, pass --extensions-dir <path> to enable module discovery.\n"
3875
+ "Error: no module registry wired. In standalone mode, pass --extensions-dir <path> to enable module discovery.\n"
3838
3876
  );
3839
3877
  process.exit(EXIT_CODES.CONFIG_INVALID);
3840
3878
  };
@@ -3946,9 +3984,9 @@ function main(progName) {
3946
3984
  verboseHelp = hasVerboseFlag();
3947
3985
  const program = createCli({
3948
3986
  progName,
3949
- verbose: verboseHelp,
3987
+ allOptions: verboseHelp,
3950
3988
  version: VERSION,
3951
- description: `${progName ?? "apcore-cli"} \u2014 execute apcore modules from the command line`
3989
+ description: `${progName ?? "apcore-cli"} \u2014 execute modules from the command line`
3952
3990
  });
3953
3991
  try {
3954
3992
  program.parse(process.argv);
@@ -3976,7 +4014,17 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
3976
4014
  if (inputSchema && typeof inputSchema === "object" && inputSchema.properties) {
3977
4015
  try {
3978
4016
  resolvedSchema = resolveRefs(inputSchema, 32, moduleId);
3979
- } catch {
4017
+ } catch (err) {
4018
+ if (err instanceof MaxDepthExceededError || err instanceof CircularRefError) {
4019
+ process.stderr.write(`Error: ${err.message}
4020
+ `);
4021
+ process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
4022
+ }
4023
+ if (err instanceof UnresolvableRefError) {
4024
+ process.stderr.write(`Error: ${err.message}
4025
+ `);
4026
+ process.exit(EXIT_CODES.SCHEMA_VALIDATION_ERROR);
4027
+ }
3980
4028
  resolvedSchema = inputSchema;
3981
4029
  }
3982
4030
  schemaOptions = schemaToCliOptions(resolvedSchema, helpTextMaxLength);
@@ -4021,7 +4069,7 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
4021
4069
  cmd.addOption(approvalTokenOpt);
4022
4070
  const footerParts = [];
4023
4071
  if (!verbose) {
4024
- footerParts.push("Use --verbose to show all options (including built-in apcore options).");
4072
+ footerParts.push("Use --all-options to show all options (including built-in options).");
4025
4073
  }
4026
4074
  if (docsUrl) {
4027
4075
  footerParts.push(`Docs: ${docsUrl}/commands/${effectiveCmdName}`);
@@ -4030,7 +4078,15 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
4030
4078
  cmd.addHelpText("after", "\n" + footerParts.join("\n") + "\n");
4031
4079
  }
4032
4080
  for (const opt of schemaOptions) {
4033
- if (opt.parseArg) {
4081
+ if (opt.isBooleanFlag) {
4082
+ const flagBase = opt.name.replace(/_/g, "-");
4083
+ cmd.addOption(
4084
+ new Option4(`--${flagBase}`, opt.description).default(
4085
+ opt.defaultValue
4086
+ )
4087
+ );
4088
+ cmd.addOption(new Option4(`--no-${flagBase}`).hideHelp());
4089
+ } else if (opt.parseArg) {
4034
4090
  cmd.option(opt.flags, opt.description, opt.parseArg, opt.defaultValue);
4035
4091
  } else {
4036
4092
  cmd.option(opt.flags, opt.description, opt.defaultValue);
@@ -4054,24 +4110,12 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
4054
4110
  );
4055
4111
  const approvalToken = options.approvalToken;
4056
4112
  const schemaKwargs = {};
4057
- const builtinKeys = /* @__PURE__ */ new Set([
4058
- "input",
4059
- "yes",
4060
- "largeInput",
4061
- "format",
4062
- "fields",
4063
- "sandbox",
4064
- "verbose",
4065
- "dryRun",
4066
- "trace",
4067
- "stream",
4068
- "strategy",
4069
- "approvalTimeout",
4070
- "approvalToken"
4071
- ]);
4072
- for (const [k, v] of Object.entries(options)) {
4073
- if (!builtinKeys.has(k)) {
4074
- schemaKwargs[k] = v;
4113
+ for (const opt of schemaOptions) {
4114
+ const commanderKey = opt.name.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
4115
+ if (commanderKey in options) {
4116
+ schemaKwargs[opt.name] = options[commanderKey];
4117
+ } else if (opt.name in options) {
4118
+ schemaKwargs[opt.name] = options[opt.name];
4075
4119
  }
4076
4120
  }
4077
4121
  let merged = {};
@@ -4674,6 +4718,7 @@ init_errors();
4674
4718
  init_logger();
4675
4719
  init_security();
4676
4720
  export {
4721
+ APCLI_SUBCOMMAND_NAMES,
4677
4722
  ApcliGroup,
4678
4723
  ApcliGroupError,
4679
4724
  ApprovalDeniedError,
@@ -4681,21 +4726,25 @@ export {
4681
4726
  AuditLogger,
4682
4727
  AuthProvider,
4683
4728
  AuthenticationError,
4729
+ CircularRefError,
4684
4730
  CliApprovalHandler,
4685
4731
  ConfigDecryptionError,
4686
4732
  ConfigEncryptor,
4687
4733
  ConfigResolver,
4688
4734
  DEFAULTS,
4735
+ DEFAULT_BUILTIN_GROUP_NAME,
4689
4736
  EXIT_CODES,
4690
4737
  ExposureFilter,
4691
4738
  GroupedModuleGroup,
4692
4739
  LazyGroup,
4693
4740
  LazyModuleGroup,
4741
+ MaxDepthExceededError,
4694
4742
  ModuleExecutionError,
4695
4743
  ModuleNotFoundError,
4696
4744
  RESERVED_GROUP_NAMES,
4697
4745
  Sandbox,
4698
4746
  SchemaValidationError,
4747
+ UnresolvableRefError,
4699
4748
  applyToolkitIntegration,
4700
4749
  buildModuleCommand,
4701
4750
  checkApproval,
@@ -4727,6 +4776,7 @@ export {
4727
4776
  resolveFormat,
4728
4777
  resolveRefs,
4729
4778
  schemaToCliOptions,
4779
+ setAllOptionsHelp,
4730
4780
  setAuditLogger,
4731
4781
  setDocsUrl,
4732
4782
  setLogLevel,