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/bin/apcore-cli.js
CHANGED
|
@@ -35,6 +35,12 @@ function exitCodeForError(error) {
|
|
|
35
35
|
if (error instanceof SchemaValidationError) {
|
|
36
36
|
return EXIT_CODES.SCHEMA_VALIDATION_ERROR;
|
|
37
37
|
}
|
|
38
|
+
if (error instanceof MaxDepthExceededError || error instanceof CircularRefError) {
|
|
39
|
+
return EXIT_CODES.SCHEMA_CIRCULAR_REF;
|
|
40
|
+
}
|
|
41
|
+
if (error instanceof UnresolvableRefError) {
|
|
42
|
+
return EXIT_CODES.SCHEMA_VALIDATION_ERROR;
|
|
43
|
+
}
|
|
38
44
|
if (error instanceof ModuleNotFoundError) {
|
|
39
45
|
return EXIT_CODES.MODULE_NOT_FOUND;
|
|
40
46
|
}
|
|
@@ -74,7 +80,7 @@ function exitCodeForError(error) {
|
|
|
74
80
|
}
|
|
75
81
|
return EXIT_CODES.MODULE_EXECUTE_ERROR;
|
|
76
82
|
}
|
|
77
|
-
var ApprovalTimeoutError, AuthenticationError, ConfigDecryptionError, ModuleExecutionError, ApprovalDeniedError, SchemaValidationError, ModuleNotFoundError, EXIT_CODES;
|
|
83
|
+
var ApprovalTimeoutError, AuthenticationError, ConfigDecryptionError, ModuleExecutionError, ApprovalDeniedError, SchemaValidationError, MaxDepthExceededError, CircularRefError, UnresolvableRefError, ModuleNotFoundError, EXIT_CODES;
|
|
78
84
|
var init_errors = __esm({
|
|
79
85
|
"src/errors.ts"() {
|
|
80
86
|
"use strict";
|
|
@@ -115,6 +121,24 @@ var init_errors = __esm({
|
|
|
115
121
|
this.name = "SchemaValidationError";
|
|
116
122
|
}
|
|
117
123
|
};
|
|
124
|
+
MaxDepthExceededError = class extends Error {
|
|
125
|
+
constructor(message = "Schema $ref resolution depth exceeded") {
|
|
126
|
+
super(message);
|
|
127
|
+
this.name = "MaxDepthExceededError";
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
CircularRefError = class extends Error {
|
|
131
|
+
constructor(message = "Circular $ref detected in schema") {
|
|
132
|
+
super(message);
|
|
133
|
+
this.name = "CircularRefError";
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
UnresolvableRefError = class extends Error {
|
|
137
|
+
constructor(message = "Unresolvable $ref in schema") {
|
|
138
|
+
super(message);
|
|
139
|
+
this.name = "UnresolvableRefError";
|
|
140
|
+
}
|
|
141
|
+
};
|
|
118
142
|
ModuleNotFoundError = class extends Error {
|
|
119
143
|
constructor(message = "Module not found") {
|
|
120
144
|
super(message);
|
|
@@ -155,8 +179,13 @@ var init_errors = __esm({
|
|
|
155
179
|
var sandbox_exports = {};
|
|
156
180
|
__export(sandbox_exports, {
|
|
157
181
|
Sandbox: () => Sandbox,
|
|
182
|
+
_buildSandboxEnvForTesting: () => _buildSandboxEnvForTesting,
|
|
158
183
|
runSandboxRunner: () => runSandboxRunner
|
|
159
184
|
});
|
|
185
|
+
import { spawn } from "child_process";
|
|
186
|
+
import { mkdtempSync, rmSync } from "fs";
|
|
187
|
+
import { tmpdir } from "os";
|
|
188
|
+
import { join, resolve as resolvePath } from "path";
|
|
160
189
|
async function runSandboxRunner(moduleId) {
|
|
161
190
|
const extensionsRoot = process.env.APCORE_EXTENSIONS_ROOT ?? "./extensions";
|
|
162
191
|
const apcore = await import("apcore-js").catch(() => {
|
|
@@ -191,10 +220,13 @@ async function runSandboxRunner(moduleId) {
|
|
|
191
220
|
process.exit(1);
|
|
192
221
|
}
|
|
193
222
|
}
|
|
223
|
+
function _buildSandboxEnvForTesting(tmpDir) {
|
|
224
|
+
return buildSandboxEnv(tmpDir);
|
|
225
|
+
}
|
|
194
226
|
function buildSandboxEnv(tmpDir) {
|
|
195
227
|
const env = {};
|
|
196
228
|
for (const key of SANDBOX_ALLOW_KEYS) {
|
|
197
|
-
if (process.env[key]) env[key] = process.env[key];
|
|
229
|
+
if (process.env[key] !== void 0) env[key] = process.env[key];
|
|
198
230
|
}
|
|
199
231
|
for (const [key, val] of Object.entries(process.env)) {
|
|
200
232
|
if (key.startsWith(SANDBOX_ALLOW_PREFIX) && !key.startsWith(SANDBOX_DENY_PREFIX) && !SANDBOX_DENY_KEYS.includes(key)) {
|
|
@@ -260,13 +292,8 @@ var init_sandbox = __esm({
|
|
|
260
292
|
return this._sandboxedExecute(moduleId, inputData);
|
|
261
293
|
}
|
|
262
294
|
async _sandboxedExecute(moduleId, inputData) {
|
|
263
|
-
const
|
|
264
|
-
const { tmpdir } = await import("os");
|
|
265
|
-
const { join: join4 } = await import("path");
|
|
266
|
-
const { mkdtempSync, rmSync } = await import("fs");
|
|
267
|
-
const tmpDir = mkdtempSync(join4(tmpdir(), "apcore_sandbox_"));
|
|
295
|
+
const tmpDir = mkdtempSync(join(tmpdir(), "apcore_sandbox_"));
|
|
268
296
|
const env = buildSandboxEnv(tmpDir);
|
|
269
|
-
const { resolve: resolvePath } = await import("path");
|
|
270
297
|
if (this.extensionsRoot !== null) {
|
|
271
298
|
env.APCORE_EXTENSIONS_ROOT = resolvePath(this.extensionsRoot);
|
|
272
299
|
} else if (env.APCORE_EXTENSIONS_ROOT) {
|
|
@@ -304,11 +331,20 @@ var init_sandbox = __esm({
|
|
|
304
331
|
}
|
|
305
332
|
stderr += chunk.toString();
|
|
306
333
|
});
|
|
334
|
+
child.stdin.on("error", () => {
|
|
335
|
+
});
|
|
307
336
|
child.stdin.write(JSON.stringify(inputData));
|
|
308
337
|
child.stdin.end();
|
|
309
338
|
return new Promise((resolve2, reject) => {
|
|
339
|
+
const cleanup = () => {
|
|
340
|
+
try {
|
|
341
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
342
|
+
} catch {
|
|
343
|
+
}
|
|
344
|
+
};
|
|
310
345
|
const timer = setTimeout(() => {
|
|
311
346
|
child.kill("SIGKILL");
|
|
347
|
+
cleanup();
|
|
312
348
|
reject(
|
|
313
349
|
new ModuleExecutionError(
|
|
314
350
|
`Sandbox module '${moduleId}' timed out after ${this.timeoutSeconds}s.`
|
|
@@ -317,10 +353,7 @@ var init_sandbox = __esm({
|
|
|
317
353
|
}, this.timeoutSeconds * 1e3);
|
|
318
354
|
child.on("close", (code) => {
|
|
319
355
|
clearTimeout(timer);
|
|
320
|
-
|
|
321
|
-
rmSync(tmpDir, { recursive: true, force: true });
|
|
322
|
-
} catch {
|
|
323
|
-
}
|
|
356
|
+
cleanup();
|
|
324
357
|
if (sizeExceeded) {
|
|
325
358
|
const limitMiB = Math.floor(outputCap / (1024 * 1024));
|
|
326
359
|
reject(new ModuleExecutionError(
|
|
@@ -344,6 +377,7 @@ var init_sandbox = __esm({
|
|
|
344
377
|
});
|
|
345
378
|
child.on("error", (err) => {
|
|
346
379
|
clearTimeout(timer);
|
|
380
|
+
cleanup();
|
|
347
381
|
reject(new ModuleExecutionError(`Failed to spawn sandbox process: ${err.message}`));
|
|
348
382
|
});
|
|
349
383
|
});
|
|
@@ -376,27 +410,21 @@ function resolveNode(node, defs, visited, depth, maxDepth, moduleId) {
|
|
|
376
410
|
if ("$ref" in obj) {
|
|
377
411
|
const refPath = obj.$ref;
|
|
378
412
|
if (depth >= maxDepth) {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
`
|
|
413
|
+
throw new MaxDepthExceededError(
|
|
414
|
+
`$ref resolution depth exceeded maximum of ${maxDepth} for module '${moduleId}'.`
|
|
382
415
|
);
|
|
383
|
-
process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
|
|
384
416
|
}
|
|
385
417
|
if (visited.has(refPath)) {
|
|
386
|
-
|
|
387
|
-
`
|
|
388
|
-
`
|
|
418
|
+
throw new CircularRefError(
|
|
419
|
+
`Circular $ref detected in schema for module '${moduleId}' at path '${refPath}'.`
|
|
389
420
|
);
|
|
390
|
-
process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
|
|
391
421
|
}
|
|
392
422
|
const parts = refPath.split("/");
|
|
393
423
|
const key = parts[parts.length - 1];
|
|
394
424
|
if (!(key in defs)) {
|
|
395
|
-
|
|
396
|
-
`
|
|
397
|
-
`
|
|
425
|
+
throw new UnresolvableRefError(
|
|
426
|
+
`Unresolvable $ref '${refPath}' in schema for module '${moduleId}'.`
|
|
398
427
|
);
|
|
399
|
-
process.exit(EXIT_CODES.SCHEMA_VALIDATION_ERROR);
|
|
400
428
|
}
|
|
401
429
|
const newVisited = new Set(visited);
|
|
402
430
|
newVisited.add(refPath);
|
|
@@ -497,17 +525,12 @@ function resolveNode(node, defs, visited, depth, maxDepth, moduleId) {
|
|
|
497
525
|
return merged;
|
|
498
526
|
}
|
|
499
527
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
visited,
|
|
507
|
-
depth,
|
|
508
|
-
maxDepth,
|
|
509
|
-
moduleId
|
|
510
|
-
);
|
|
528
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
529
|
+
if (k === "allOf" || k === "anyOf" || k === "oneOf" || k === "$ref") {
|
|
530
|
+
continue;
|
|
531
|
+
}
|
|
532
|
+
if (typeof v === "object" && v !== null && !Array.isArray(v)) {
|
|
533
|
+
obj[k] = resolveNode(v, defs, visited, depth, maxDepth, moduleId);
|
|
511
534
|
}
|
|
512
535
|
}
|
|
513
536
|
return obj;
|
|
@@ -704,7 +727,7 @@ var init_schema_parser = __esm({
|
|
|
704
727
|
"format",
|
|
705
728
|
"fields",
|
|
706
729
|
"sandbox",
|
|
707
|
-
"
|
|
730
|
+
"all_options",
|
|
708
731
|
"dry_run",
|
|
709
732
|
"trace",
|
|
710
733
|
"stream",
|
|
@@ -817,6 +840,14 @@ var init_approval = __esm({
|
|
|
817
840
|
}
|
|
818
841
|
async requestApproval(request) {
|
|
819
842
|
const moduleId = request.module_id ?? "unknown";
|
|
843
|
+
if (request.requires_approval === false) {
|
|
844
|
+
return { status: "approved", approved_by: "not_required" };
|
|
845
|
+
}
|
|
846
|
+
const moduleDef = request.module_def;
|
|
847
|
+
const annotationsForCheck = moduleDef?.annotations;
|
|
848
|
+
if (annotationsForCheck && annotationsForCheck.requires_approval === false) {
|
|
849
|
+
return { status: "approved", approved_by: "not_required" };
|
|
850
|
+
}
|
|
820
851
|
if (this.autoApprove) {
|
|
821
852
|
return { status: "approved", approved_by: "auto_approve" };
|
|
822
853
|
}
|
|
@@ -853,6 +884,7 @@ var init_approval = __esm({
|
|
|
853
884
|
|
|
854
885
|
// src/output.ts
|
|
855
886
|
import yaml from "js-yaml";
|
|
887
|
+
import { formatCsv, formatJsonl } from "apcore-toolkit";
|
|
856
888
|
function descriptorToScanned(m) {
|
|
857
889
|
const metadata = m.metadata ?? {};
|
|
858
890
|
const display = metadata["display"] ?? null;
|
|
@@ -873,11 +905,6 @@ function descriptorToScanned(m) {
|
|
|
873
905
|
warnings: []
|
|
874
906
|
};
|
|
875
907
|
}
|
|
876
|
-
function csvCellString(value) {
|
|
877
|
-
if (value === null || value === void 0) return "";
|
|
878
|
-
if (typeof value === "object") return JSON.stringify(value);
|
|
879
|
-
return String(value);
|
|
880
|
-
}
|
|
881
908
|
function resolveFormat(explicitFormat) {
|
|
882
909
|
if (explicitFormat !== void 0) {
|
|
883
910
|
return explicitFormat;
|
|
@@ -1080,30 +1107,18 @@ function formatExecResult(result, format, fields) {
|
|
|
1080
1107
|
}
|
|
1081
1108
|
const effective = resolveFormat(format);
|
|
1082
1109
|
if (effective === "csv") {
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
const header = keys.map(escapeCsvField).join(",");
|
|
1087
|
-
const row = keys.map((k) => escapeCsvField(csvCellString(obj[k]))).join(",");
|
|
1088
|
-
process.stdout.write(header + "\n" + row + "\n");
|
|
1089
|
-
} else if (Array.isArray(effective_result) && effective_result.length > 0 && typeof effective_result[0] === "object") {
|
|
1090
|
-
const keys = Object.keys(effective_result[0]);
|
|
1091
|
-
const header = keys.map(escapeCsvField).join(",");
|
|
1092
|
-
const rows = effective_result.map((item) => {
|
|
1093
|
-
const obj = item;
|
|
1094
|
-
return keys.map((k) => escapeCsvField(csvCellString(obj[k]))).join(",");
|
|
1095
|
-
});
|
|
1096
|
-
process.stdout.write(header + "\n" + rows.join("\n") + "\n");
|
|
1110
|
+
const rows = toRowsForTabular(effective_result);
|
|
1111
|
+
if (rows !== null) {
|
|
1112
|
+
process.stdout.write(formatCsv(rows));
|
|
1097
1113
|
} else {
|
|
1098
1114
|
process.stdout.write(JSON.stringify(effective_result) + "\n");
|
|
1099
1115
|
}
|
|
1100
1116
|
} else if (effective === "yaml") {
|
|
1101
1117
|
process.stdout.write(yaml.dump(effective_result, { lineWidth: -1 }));
|
|
1102
1118
|
} else if (effective === "jsonl") {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
}
|
|
1119
|
+
const rows = toRowsForTabular(effective_result);
|
|
1120
|
+
if (rows !== null) {
|
|
1121
|
+
process.stdout.write(formatJsonl(rows));
|
|
1107
1122
|
} else {
|
|
1108
1123
|
process.stdout.write(JSON.stringify(effective_result) + "\n");
|
|
1109
1124
|
}
|
|
@@ -1120,11 +1135,19 @@ function formatExecResult(result, format, fields) {
|
|
|
1120
1135
|
process.stdout.write(String(effective_result) + "\n");
|
|
1121
1136
|
}
|
|
1122
1137
|
}
|
|
1123
|
-
function
|
|
1124
|
-
if (value
|
|
1125
|
-
|
|
1138
|
+
function toRowsForTabular(value) {
|
|
1139
|
+
if (value === null || value === void 0) return null;
|
|
1140
|
+
if (Array.isArray(value)) {
|
|
1141
|
+
if (value.length === 0) return null;
|
|
1142
|
+
if (!value.every((item) => typeof item === "object" && item !== null && !Array.isArray(item))) {
|
|
1143
|
+
return null;
|
|
1144
|
+
}
|
|
1145
|
+
return value;
|
|
1146
|
+
}
|
|
1147
|
+
if (typeof value === "object") {
|
|
1148
|
+
return [value];
|
|
1126
1149
|
}
|
|
1127
|
-
return
|
|
1150
|
+
return null;
|
|
1128
1151
|
}
|
|
1129
1152
|
function formatPreflightResult(result, format) {
|
|
1130
1153
|
const resolved = resolveFormat(format);
|
|
@@ -1205,7 +1228,7 @@ var init_output = __esm({
|
|
|
1205
1228
|
"use strict";
|
|
1206
1229
|
init_esm_shims();
|
|
1207
1230
|
init_errors();
|
|
1208
|
-
TOOLKIT_MISSING_HINT = "The 'markdown' and 'skill' output formats require the apcore-toolkit peer dependency. Install with: npm install apcore-toolkit@^0.
|
|
1231
|
+
TOOLKIT_MISSING_HINT = "The 'markdown' and 'skill' output formats require the apcore-toolkit peer dependency. Install with: npm install apcore-toolkit@^0.7";
|
|
1209
1232
|
}
|
|
1210
1233
|
});
|
|
1211
1234
|
|
|
@@ -1236,7 +1259,7 @@ function renderTemplate(template, context) {
|
|
|
1236
1259
|
return result;
|
|
1237
1260
|
}
|
|
1238
1261
|
function registerInitCommand(cli) {
|
|
1239
|
-
const initGroup = cli.command("init").description("Scaffold new
|
|
1262
|
+
const initGroup = cli.command("init").description("Scaffold new modules.");
|
|
1240
1263
|
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(
|
|
1241
1264
|
"--style <style>",
|
|
1242
1265
|
"Module style: decorator (@module), convention (plain function), or binding (YAML).",
|
|
@@ -1812,7 +1835,7 @@ function buildProgramManPage(program, progName, version, description, docsUrl2)
|
|
|
1812
1835
|
s.push(".SH ENVIRONMENT");
|
|
1813
1836
|
s.push(".TP");
|
|
1814
1837
|
s.push("\\fBAPCORE_EXTENSIONS_ROOT\\fR");
|
|
1815
|
-
s.push("Path to the
|
|
1838
|
+
s.push("Path to the extensions directory.");
|
|
1816
1839
|
s.push(".TP");
|
|
1817
1840
|
s.push("\\fBAPCORE_CLI_AUTO_APPROVE\\fR");
|
|
1818
1841
|
s.push("Set to \\fB1\\fR to bypass approval prompts.");
|
|
@@ -1837,7 +1860,7 @@ function buildProgramManPage(program, progName, version, description, docsUrl2)
|
|
|
1837
1860
|
${meaning}`);
|
|
1838
1861
|
}
|
|
1839
1862
|
s.push(".SH SEE ALSO");
|
|
1840
|
-
s.push(`\\fB${progName} \\-\\-help \\-\\-
|
|
1863
|
+
s.push(`\\fB${progName} \\-\\-help \\-\\-all\\-options\\fR for full option list.`);
|
|
1841
1864
|
if (docsUrl2) {
|
|
1842
1865
|
s.push(`.PP
|
|
1843
1866
|
Full documentation at \\fI${roffEscape(docsUrl2)}\\fR`);
|
|
@@ -2244,7 +2267,7 @@ var init_config_encryptor = __esm({
|
|
|
2244
2267
|
_ConfigEncryptor.weakFallbackWarned = true;
|
|
2245
2268
|
}
|
|
2246
2269
|
const hostname2 = os3.hostname();
|
|
2247
|
-
const username = process.env.USER ?? process.env.USERNAME ?? "unknown";
|
|
2270
|
+
const username = process.env.USER ?? process.env.LOGNAME ?? process.env.USERNAME ?? "unknown";
|
|
2248
2271
|
const material = `${hostname2}:${username}`;
|
|
2249
2272
|
return crypto2.pbkdf2Sync(material, salt, PBKDF2_ITERATIONS, 32, "sha256");
|
|
2250
2273
|
}
|
|
@@ -2276,7 +2299,7 @@ var init_config_encryptor = __esm({
|
|
|
2276
2299
|
const tag = data.subarray(12, 28);
|
|
2277
2300
|
const ct = data.subarray(28);
|
|
2278
2301
|
const hostname2 = os3.hostname();
|
|
2279
|
-
const username = process.env.USER ?? process.env.USERNAME ?? "unknown";
|
|
2302
|
+
const username = process.env.USER ?? process.env.LOGNAME ?? process.env.USERNAME ?? "unknown";
|
|
2280
2303
|
const passphrase = process.env.APCORE_CLI_CONFIG_PASSPHRASE;
|
|
2281
2304
|
const materials = passphrase ? [passphrase, `${hostname2}:${username}`] : [`${hostname2}:${username}`];
|
|
2282
2305
|
for (const material of materials) {
|
|
@@ -2306,10 +2329,26 @@ var init_auth = __esm({
|
|
|
2306
2329
|
init_config_encryptor();
|
|
2307
2330
|
AuthProvider = class {
|
|
2308
2331
|
config;
|
|
2309
|
-
|
|
2332
|
+
_encryptor;
|
|
2310
2333
|
constructor(config, encryptor) {
|
|
2311
2334
|
this.config = config;
|
|
2312
|
-
this.
|
|
2335
|
+
this._encryptor = encryptor;
|
|
2336
|
+
}
|
|
2337
|
+
/**
|
|
2338
|
+
* Resolve the active ConfigEncryptor instance.
|
|
2339
|
+
*
|
|
2340
|
+
* D11-005 (2026-05-12): three-tier fallback chain matching Python's
|
|
2341
|
+
* `_get_encryptor` (auth.py:33): explicit constructor arg > peer attribute
|
|
2342
|
+
* `config.encryptor` (set by embedders injecting forced-AES test fixtures
|
|
2343
|
+
* or shared instances) > fresh `new ConfigEncryptor()`. Previously TS
|
|
2344
|
+
* skipped the peer-attribute tier, silently giving embedders a different
|
|
2345
|
+
* encryptor than the one they wired on the config.
|
|
2346
|
+
*/
|
|
2347
|
+
getEncryptor() {
|
|
2348
|
+
if (this._encryptor) return this._encryptor;
|
|
2349
|
+
const fromConfig = this.config.encryptor;
|
|
2350
|
+
if (fromConfig) return fromConfig;
|
|
2351
|
+
return new ConfigEncryptor();
|
|
2313
2352
|
}
|
|
2314
2353
|
/**
|
|
2315
2354
|
* Retrieve the API key from the configured sources.
|
|
@@ -2327,11 +2366,11 @@ var init_auth = __esm({
|
|
|
2327
2366
|
const strResult = String(result);
|
|
2328
2367
|
if (strResult.startsWith("keyring:") || strResult.startsWith("enc:")) {
|
|
2329
2368
|
try {
|
|
2330
|
-
return await this.
|
|
2369
|
+
return await this.getEncryptor().retrieve(strResult, "auth.api_key");
|
|
2331
2370
|
} catch (err) {
|
|
2332
2371
|
if (err instanceof ConfigDecryptionError) {
|
|
2333
2372
|
throw new AuthenticationError(
|
|
2334
|
-
"Failed to decrypt stored API key. Re-
|
|
2373
|
+
"Failed to decrypt stored API key. Re-store with 'apcli config set auth.api_key'."
|
|
2335
2374
|
);
|
|
2336
2375
|
}
|
|
2337
2376
|
throw err;
|
|
@@ -2360,7 +2399,7 @@ var init_auth = __esm({
|
|
|
2360
2399
|
}
|
|
2361
2400
|
if (/[\r\n]/.test(key)) {
|
|
2362
2401
|
throw new AuthenticationError(
|
|
2363
|
-
"Malformed API key: contains invalid characters (CR/LF). Re-
|
|
2402
|
+
"Malformed API key: contains invalid characters (CR/LF). Re-store with 'apcli config set auth.api_key'."
|
|
2364
2403
|
);
|
|
2365
2404
|
}
|
|
2366
2405
|
headers.Authorization = `Bearer ${key.trim()}`;
|
|
@@ -2582,7 +2621,7 @@ function registerExecCommand(apcliGroup, registry, executor) {
|
|
|
2582
2621
|
return;
|
|
2583
2622
|
}
|
|
2584
2623
|
let result;
|
|
2585
|
-
if (opts.strategy && executor.callWithTrace) {
|
|
2624
|
+
if ((opts.trace || opts.strategy) && executor.callWithTrace) {
|
|
2586
2625
|
const [res] = await executor.callWithTrace(moduleId, merged, { strategy: opts.strategy });
|
|
2587
2626
|
result = res;
|
|
2588
2627
|
} else {
|
|
@@ -3698,6 +3737,7 @@ __export(main_exports, {
|
|
|
3698
3737
|
reconvertEnumValues: () => reconvertEnumValues,
|
|
3699
3738
|
resolveIntOption: () => resolveIntOption,
|
|
3700
3739
|
resolveStringOption: () => resolveStringOption,
|
|
3740
|
+
setAllOptionsHelp: () => setAllOptionsHelp,
|
|
3701
3741
|
setDocsUrl: () => setDocsUrl,
|
|
3702
3742
|
setVerboseHelp: () => setVerboseHelp,
|
|
3703
3743
|
validateModuleId: () => validateModuleId
|
|
@@ -3706,14 +3746,17 @@ import { readFileSync as readFileSync3 } from "fs";
|
|
|
3706
3746
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3707
3747
|
import * as path5 from "path";
|
|
3708
3748
|
import { Command as Command5, CommanderError, Option as Option4 } from "commander";
|
|
3749
|
+
function setAllOptionsHelp(allOptions) {
|
|
3750
|
+
verboseHelp = allOptions;
|
|
3751
|
+
}
|
|
3709
3752
|
function setVerboseHelp(verbose) {
|
|
3710
|
-
|
|
3753
|
+
setAllOptionsHelp(verbose);
|
|
3711
3754
|
}
|
|
3712
3755
|
function setDocsUrl(url) {
|
|
3713
3756
|
docsUrl = url;
|
|
3714
3757
|
}
|
|
3715
3758
|
function hasVerboseFlag() {
|
|
3716
|
-
return process.argv.includes("--
|
|
3759
|
+
return process.argv.includes("--all-options");
|
|
3717
3760
|
}
|
|
3718
3761
|
function resolveIntOption(cliValue, envValue, defaultValue) {
|
|
3719
3762
|
if (cliValue !== void 0 && Number.isFinite(cliValue) && cliValue > 0) {
|
|
@@ -3788,7 +3831,7 @@ function emitErrorTty(e, exitCode) {
|
|
|
3788
3831
|
Exit code: ${exitCode}
|
|
3789
3832
|
`);
|
|
3790
3833
|
}
|
|
3791
|
-
function createCli(extensionsDirOrOpts, progName,
|
|
3834
|
+
function createCli(extensionsDirOrOpts, progName, allOptions = false) {
|
|
3792
3835
|
let extensionsDir;
|
|
3793
3836
|
let registry;
|
|
3794
3837
|
let executor;
|
|
@@ -3803,7 +3846,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
|
|
|
3803
3846
|
if (typeof extensionsDirOrOpts === "object" && extensionsDirOrOpts !== null) {
|
|
3804
3847
|
extensionsDir = extensionsDirOrOpts.extensionsDir;
|
|
3805
3848
|
progName = extensionsDirOrOpts.progName ?? progName;
|
|
3806
|
-
|
|
3849
|
+
allOptions = extensionsDirOrOpts.allOptions ?? extensionsDirOrOpts.verbose ?? allOptions;
|
|
3807
3850
|
app = extensionsDirOrOpts.app;
|
|
3808
3851
|
registry = extensionsDirOrOpts.registry;
|
|
3809
3852
|
executor = extensionsDirOrOpts.executor;
|
|
@@ -3817,7 +3860,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
|
|
|
3817
3860
|
} else {
|
|
3818
3861
|
extensionsDir = extensionsDirOrOpts;
|
|
3819
3862
|
}
|
|
3820
|
-
verboseHelp =
|
|
3863
|
+
verboseHelp = allOptions;
|
|
3821
3864
|
registerConfigNamespace();
|
|
3822
3865
|
try {
|
|
3823
3866
|
const auditLogger = new AuditLogger();
|
|
@@ -3850,7 +3893,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
|
|
|
3850
3893
|
}
|
|
3851
3894
|
}
|
|
3852
3895
|
const registryInjected = registry !== void 0;
|
|
3853
|
-
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("--
|
|
3896
|
+
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)");
|
|
3854
3897
|
if (appVersion) {
|
|
3855
3898
|
program.version(appVersion, "-V, --version", "Print version");
|
|
3856
3899
|
}
|
|
@@ -3921,7 +3964,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
|
|
|
3921
3964
|
_registerApcliSubcommands(apcliGroup, apcliCfg, registry, executor, exposureFilter);
|
|
3922
3965
|
program.addHelpText("after", [
|
|
3923
3966
|
"",
|
|
3924
|
-
"Use --help --
|
|
3967
|
+
"Use --help --all-options to show all options (including built-in options).",
|
|
3925
3968
|
"Use --help --man to display a formatted man page."
|
|
3926
3969
|
].join("\n"));
|
|
3927
3970
|
configureManHelp(program, resolvedProgName, appVersion ?? VERSION);
|
|
@@ -3958,7 +4001,7 @@ function createCli(extensionsDirOrOpts, progName, verbose = false) {
|
|
|
3958
4001
|
function _registerApcliSubcommands(apcliGroup, apcliCfg, registry, executor, exposureFilter) {
|
|
3959
4002
|
const emitUnwiredError = () => {
|
|
3960
4003
|
process.stderr.write(
|
|
3961
|
-
"Error: no
|
|
4004
|
+
"Error: no module registry wired. In standalone mode, pass --extensions-dir <path> to enable module discovery.\n"
|
|
3962
4005
|
);
|
|
3963
4006
|
process.exit(EXIT_CODES.CONFIG_INVALID);
|
|
3964
4007
|
};
|
|
@@ -4072,9 +4115,9 @@ function main(progName) {
|
|
|
4072
4115
|
verboseHelp = hasVerboseFlag();
|
|
4073
4116
|
const program = createCli({
|
|
4074
4117
|
progName,
|
|
4075
|
-
|
|
4118
|
+
allOptions: verboseHelp,
|
|
4076
4119
|
version: VERSION,
|
|
4077
|
-
description: `${progName ?? "apcore-cli"} \u2014 execute
|
|
4120
|
+
description: `${progName ?? "apcore-cli"} \u2014 execute modules from the command line`
|
|
4078
4121
|
});
|
|
4079
4122
|
try {
|
|
4080
4123
|
program.parse(process.argv);
|
|
@@ -4102,7 +4145,17 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4102
4145
|
if (inputSchema && typeof inputSchema === "object" && inputSchema.properties) {
|
|
4103
4146
|
try {
|
|
4104
4147
|
resolvedSchema = resolveRefs(inputSchema, 32, moduleId);
|
|
4105
|
-
} catch {
|
|
4148
|
+
} catch (err) {
|
|
4149
|
+
if (err instanceof MaxDepthExceededError || err instanceof CircularRefError) {
|
|
4150
|
+
process.stderr.write(`Error: ${err.message}
|
|
4151
|
+
`);
|
|
4152
|
+
process.exit(EXIT_CODES.SCHEMA_CIRCULAR_REF);
|
|
4153
|
+
}
|
|
4154
|
+
if (err instanceof UnresolvableRefError) {
|
|
4155
|
+
process.stderr.write(`Error: ${err.message}
|
|
4156
|
+
`);
|
|
4157
|
+
process.exit(EXIT_CODES.SCHEMA_VALIDATION_ERROR);
|
|
4158
|
+
}
|
|
4106
4159
|
resolvedSchema = inputSchema;
|
|
4107
4160
|
}
|
|
4108
4161
|
schemaOptions = schemaToCliOptions(resolvedSchema, helpTextMaxLength);
|
|
@@ -4147,7 +4200,7 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4147
4200
|
cmd.addOption(approvalTokenOpt);
|
|
4148
4201
|
const footerParts = [];
|
|
4149
4202
|
if (!verbose) {
|
|
4150
|
-
footerParts.push("Use --
|
|
4203
|
+
footerParts.push("Use --all-options to show all options (including built-in options).");
|
|
4151
4204
|
}
|
|
4152
4205
|
if (docsUrl) {
|
|
4153
4206
|
footerParts.push(`Docs: ${docsUrl}/commands/${effectiveCmdName}`);
|
|
@@ -4156,7 +4209,15 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4156
4209
|
cmd.addHelpText("after", "\n" + footerParts.join("\n") + "\n");
|
|
4157
4210
|
}
|
|
4158
4211
|
for (const opt of schemaOptions) {
|
|
4159
|
-
if (opt.
|
|
4212
|
+
if (opt.isBooleanFlag) {
|
|
4213
|
+
const flagBase = opt.name.replace(/_/g, "-");
|
|
4214
|
+
cmd.addOption(
|
|
4215
|
+
new Option4(`--${flagBase}`, opt.description).default(
|
|
4216
|
+
opt.defaultValue
|
|
4217
|
+
)
|
|
4218
|
+
);
|
|
4219
|
+
cmd.addOption(new Option4(`--no-${flagBase}`).hideHelp());
|
|
4220
|
+
} else if (opt.parseArg) {
|
|
4160
4221
|
cmd.option(opt.flags, opt.description, opt.parseArg, opt.defaultValue);
|
|
4161
4222
|
} else {
|
|
4162
4223
|
cmd.option(opt.flags, opt.description, opt.defaultValue);
|
|
@@ -4180,24 +4241,12 @@ function buildModuleCommand(moduleDef, executor, helpTextMaxLength = 1e3, cmdNam
|
|
|
4180
4241
|
);
|
|
4181
4242
|
const approvalToken = options.approvalToken;
|
|
4182
4243
|
const schemaKwargs = {};
|
|
4183
|
-
const
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
"sandbox",
|
|
4190
|
-
"verbose",
|
|
4191
|
-
"dryRun",
|
|
4192
|
-
"trace",
|
|
4193
|
-
"stream",
|
|
4194
|
-
"strategy",
|
|
4195
|
-
"approvalTimeout",
|
|
4196
|
-
"approvalToken"
|
|
4197
|
-
]);
|
|
4198
|
-
for (const [k, v] of Object.entries(options)) {
|
|
4199
|
-
if (!builtinKeys.has(k)) {
|
|
4200
|
-
schemaKwargs[k] = v;
|
|
4244
|
+
for (const opt of schemaOptions) {
|
|
4245
|
+
const commanderKey = opt.name.replace(/_([a-z0-9])/g, (_, c) => c.toUpperCase());
|
|
4246
|
+
if (commanderKey in options) {
|
|
4247
|
+
schemaKwargs[opt.name] = options[commanderKey];
|
|
4248
|
+
} else if (opt.name in options) {
|
|
4249
|
+
schemaKwargs[opt.name] = options[opt.name];
|
|
4201
4250
|
}
|
|
4202
4251
|
}
|
|
4203
4252
|
let merged = {};
|