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/CHANGELOG.md +75 -0
- package/README.md +16 -12
- package/dist/bin/apcore-cli.js +155 -106
- package/dist/bin/apcore-cli.js.map +1 -1
- package/dist/index.d.ts +55 -6
- package/dist/index.js +155 -105
- package/dist/index.js.map +1 -1
- package/package.json +4 -9
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
|
-
|
|
495
|
+
_encryptor;
|
|
472
496
|
constructor(config, encryptor) {
|
|
473
497
|
this.config = config;
|
|
474
|
-
this.
|
|
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.
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
766
|
-
|
|
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
|
-
|
|
773
|
-
`
|
|
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
|
-
|
|
782
|
-
`
|
|
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
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
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
|
-
"
|
|
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
|
-
|
|
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
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
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
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
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
|
|
1470
|
-
if (value
|
|
1471
|
-
|
|
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
|
|
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
|
|
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
|
|
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 \\-\\-
|
|
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
|
-
|
|
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("--
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
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("--
|
|
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 --
|
|
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
|
|
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
|
-
|
|
3987
|
+
allOptions: verboseHelp,
|
|
3950
3988
|
version: VERSION,
|
|
3951
|
-
description: `${progName ?? "apcore-cli"} \u2014 execute
|
|
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 --
|
|
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.
|
|
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
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
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,
|