stitchkit 0.90.2 → 0.90.3
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 +55 -0
- package/dist/cli.js +1 -1
- package/dist/{index-8dph3pw6.js → index-1923shw9.js} +191 -28
- package/dist/tools/cli-args.d.ts +27 -0
- package/dist/tools/cli-args.d.ts.map +1 -1
- package/dist/tools/cli-command.d.ts +8 -1
- package/dist/tools/cli-command.d.ts.map +1 -1
- package/dist/tools/cli-policy.d.ts +6 -1
- package/dist/tools/cli-policy.d.ts.map +1 -1
- package/dist/tools/cli.d.ts +20 -5
- package/dist/tools/cli.d.ts.map +1 -1
- package/dist/tools.js +1 -1
- package/llms-full.txt +90 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -15,6 +15,61 @@ additive**; the first breaking change landed in 0.10.0. Grep the file for
|
|
|
15
15
|
|
|
16
16
|
## [Unreleased]
|
|
17
17
|
|
|
18
|
+
## [0.90.3] — 2026-09-15
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **A trailing positional may be a list.** When the last field of a command's
|
|
23
|
+
declared `positionals` is an array, it takes every remaining argv token,
|
|
24
|
+
coerced by the element type: `myapp handoff proj a.md b.md` instead of
|
|
25
|
+
`--files '["a.md","b.md"]'`. One token is a one-element list, so the parsed
|
|
26
|
+
shape never depends on how many a caller happened to pass, and command help
|
|
27
|
+
says which field is the list (`<to> <files...>`). The flag form still works;
|
|
28
|
+
passing both forms in one call is an argument error rather than a silent
|
|
29
|
+
merge. Only the trailing position is variadic — an array declared earlier
|
|
30
|
+
keeps taking exactly one JSON token, unchanged.
|
|
31
|
+
- **`globalOptions` — the application's own invocation context.** A CLI's
|
|
32
|
+
globals were only ever the framework's (`--json`, `--wait`, …), so an app that
|
|
33
|
+
needed `--caller <key>` or `--root <dir>` had to read an environment variable
|
|
34
|
+
or parse argv itself, next to the parser it already had. Declare them as a Zod
|
|
35
|
+
object and `createCli` lifts them out of argv wherever they stand — before or
|
|
36
|
+
after the command name — validates them, keeps them out of every operation's
|
|
37
|
+
arguments, and hands them to `resolveAuth(globals)`, `context(auth, globals)`
|
|
38
|
+
and a native command's `globals`. A name that collides with a framework option
|
|
39
|
+
or with a field of any command is refused at startup instead of shadowing it
|
|
40
|
+
silently, and both help levels list them under `Application options:`.
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **Output past the pipe buffer is no longer lost to a slow reader.** The
|
|
45
|
+
default writer called `writeSync` and ignored the byte count it returns. Once
|
|
46
|
+
anything in the process has touched `process.stdout` the descriptor is
|
|
47
|
+
non-blocking, so a write into a pipe whose reader has not started yet stores
|
|
48
|
+
what the 64 KB buffer takes, returns that count and throws nothing: the tail
|
|
49
|
+
vanished with exit code `0`, at exactly 65536 bytes — the same number as the
|
|
50
|
+
truncation the synchronous writer had been introduced to fix, which is why it
|
|
51
|
+
read as already fixed for so long. A consuming CLI saw `… | jq` fail with
|
|
52
|
+
"Unfinished string at column 65536" while the same command redirected to a
|
|
53
|
+
file wrote the whole result. The writer now loops on the returned count and
|
|
54
|
+
treats a full buffer (`EAGAIN`) as a wait rather than a failure, which is what
|
|
55
|
+
a blocking write into an undrained pipe is supposed to do; where an exotic
|
|
56
|
+
descriptor still forces the async fallback, the default `exit` waits for that
|
|
57
|
+
write instead of cutting it off, and output that could not be delivered at all
|
|
58
|
+
now exits non-zero.
|
|
59
|
+
- **Help survives a managed surface that cannot resolve.** A CLI whose commands
|
|
60
|
+
come from a running server declares them with a factory, and the factory needs
|
|
61
|
+
an identity. When `resolveAuth` failed — server down, key file missing — the
|
|
62
|
+
rejection escaped `createCli` and `--help` printed *nothing*: not the native
|
|
63
|
+
commands, which never depended on identity, and not the reason. Calling such a
|
|
64
|
+
name was worse than silence, because the surface never resolved and the answer
|
|
65
|
+
would have been `Unknown command` — a claim that the name does not exist when
|
|
66
|
+
the truth is that it could not be looked up. Top-level help now lists the
|
|
67
|
+
native commands and one line naming the refusal (`Managed commands are
|
|
68
|
+
unavailable: UNREACHABLE: socket closed`), and an unresolvable name answers
|
|
69
|
+
with that refusal and the exit code its error class declares through
|
|
70
|
+
`exitCodes`. Identity is still resolved at most once per invocation, failure
|
|
71
|
+
included.
|
|
72
|
+
|
|
18
73
|
## [0.90.2] — 2026-09-15
|
|
19
74
|
|
|
20
75
|
### Fixed
|
package/dist/cli.js
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
formatToolError
|
|
10
10
|
} from "./index-2hrfpw2c.js";
|
|
11
11
|
import {
|
|
12
|
+
toolErrorFromResult,
|
|
12
13
|
toolResultFromError
|
|
13
14
|
} from "./index-44ht2790.js";
|
|
14
15
|
import {
|
|
@@ -434,10 +435,19 @@ function parseCliArgs(argv, schema, config = {}) {
|
|
|
434
435
|
}
|
|
435
436
|
const toolArgs = {};
|
|
436
437
|
const fillable = config.positionals === undefined ? [...fields.entries()].filter(([, info]) => info.kind !== "boolean").map(([name]) => name) : [...config.positionals];
|
|
438
|
+
const variadicTail = config.positionals !== undefined && fields.get(fillable[fillable.length - 1] ?? "")?.kind === "array" ? fillable[fillable.length - 1] : undefined;
|
|
437
439
|
let pi = 0;
|
|
438
440
|
for (const key of fillable) {
|
|
439
441
|
if (pi >= positionals.length)
|
|
440
442
|
break;
|
|
443
|
+
if (key === variadicTail) {
|
|
444
|
+
if (flags.has(key)) {
|
|
445
|
+
throw new CliArgumentError(`--${key} conflicts with the positional values for "${key}" — pass one form, not both`);
|
|
446
|
+
}
|
|
447
|
+
toolArgs[key] = coerceField(fields.get(key), positionals.slice(pi));
|
|
448
|
+
pi = positionals.length;
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
441
451
|
if (flags.has(key))
|
|
442
452
|
continue;
|
|
443
453
|
const value = positionals[pi++];
|
|
@@ -477,6 +487,55 @@ function parseCliArgs(argv, schema, config = {}) {
|
|
|
477
487
|
}
|
|
478
488
|
return { toolArgs, options };
|
|
479
489
|
}
|
|
490
|
+
function extractCliGlobalOptions(argv, schema) {
|
|
491
|
+
if (schema === undefined)
|
|
492
|
+
return { argv: [...argv], globals: {} };
|
|
493
|
+
const fields = describeSchemaFields(schema);
|
|
494
|
+
const rest = [];
|
|
495
|
+
const raw = new Map;
|
|
496
|
+
let ended = false;
|
|
497
|
+
for (let i = 0;i < argv.length; i++) {
|
|
498
|
+
const token = argv[i];
|
|
499
|
+
if (token === undefined)
|
|
500
|
+
continue;
|
|
501
|
+
if (!ended && token === "--")
|
|
502
|
+
ended = true;
|
|
503
|
+
const option = ended ? undefined : classifyLongOptionToken(token);
|
|
504
|
+
const info = option && option.globalKind === undefined ? fields.get(option.name) : undefined;
|
|
505
|
+
if (!option || !info) {
|
|
506
|
+
rest.push(token);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
let { value } = option;
|
|
510
|
+
if (value === undefined && info.kind === "boolean") {
|
|
511
|
+
value = "true";
|
|
512
|
+
} else if (value === undefined) {
|
|
513
|
+
const next = argv[i + 1];
|
|
514
|
+
if (next !== undefined && (!next.startsWith("-") || NUMERIC_VALUE.test(next))) {
|
|
515
|
+
value = next;
|
|
516
|
+
i++;
|
|
517
|
+
} else {
|
|
518
|
+
throw new CliArgumentError(`--${option.name} requires a value`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
const existing = raw.get(option.name);
|
|
522
|
+
if (existing)
|
|
523
|
+
existing.push(value);
|
|
524
|
+
else
|
|
525
|
+
raw.set(option.name, [value]);
|
|
526
|
+
}
|
|
527
|
+
const args = {};
|
|
528
|
+
for (const [name, values] of raw)
|
|
529
|
+
args[name] = coerceField(fields.get(name), values);
|
|
530
|
+
const parsed = schema.safeParse(coerceJsonArgs(args, schema));
|
|
531
|
+
if (!parsed.success) {
|
|
532
|
+
const issue = parsed.error.issues[0];
|
|
533
|
+
const field = issue?.path[0];
|
|
534
|
+
const where = typeof field === "string" ? `--${field}` : "application option";
|
|
535
|
+
throw new CliArgumentError(`${where}: ${issue?.message ?? "invalid value"}`);
|
|
536
|
+
}
|
|
537
|
+
return { argv: rest, globals: parsed.data };
|
|
538
|
+
}
|
|
480
539
|
|
|
481
540
|
// src/tools/cli-command.ts
|
|
482
541
|
function defineCliCommand(definition) {
|
|
@@ -509,7 +568,7 @@ function cliCommandPresentationSchema(definition) {
|
|
|
509
568
|
unrepresentable: "any"
|
|
510
569
|
});
|
|
511
570
|
}
|
|
512
|
-
async function executeCliCommand(definition, rawArgs, options, writers, coerceJson) {
|
|
571
|
+
async function executeCliCommand(definition, rawArgs, options, writers, coerceJson, globals = {}) {
|
|
513
572
|
let parsed;
|
|
514
573
|
try {
|
|
515
574
|
parsed = definition.input.safeParse(coerceJson ? coerceJsonArgs(rawArgs, definition.input) : rawArgs);
|
|
@@ -527,6 +586,7 @@ async function executeCliCommand(definition, rawArgs, options, writers, coerceJs
|
|
|
527
586
|
const data = await definition.handler({
|
|
528
587
|
input: parsed.data,
|
|
529
588
|
options,
|
|
589
|
+
globals,
|
|
530
590
|
...writers
|
|
531
591
|
});
|
|
532
592
|
const checked = validateDeclaredOutput(definition.output, data);
|
|
@@ -1190,7 +1250,19 @@ function collectPassthrough(toolArgs, field, knownKeys) {
|
|
|
1190
1250
|
const base = passthroughBase(toolArgs[field]);
|
|
1191
1251
|
toolArgs[field] = base ? { ...base, ...bag } : bag;
|
|
1192
1252
|
}
|
|
1193
|
-
function
|
|
1253
|
+
function applicationOptionLines(fields) {
|
|
1254
|
+
if (fields.length === 0)
|
|
1255
|
+
return [];
|
|
1256
|
+
const labels = new Map(fields.map((field) => [field.name, `--${field.name} <${typeLabel(field.schema)}>`]));
|
|
1257
|
+
const width = Math.max(...fields.map((field) => labels.get(field.name)?.length ?? 0));
|
|
1258
|
+
return [
|
|
1259
|
+
"",
|
|
1260
|
+
"Application options:",
|
|
1261
|
+
...fields.map((field) => ` ${padRight(labels.get(field.name) ?? `--${field.name}`, width)} ${field.description ?? ""}`.trimEnd())
|
|
1262
|
+
];
|
|
1263
|
+
}
|
|
1264
|
+
function renderTopHelp(input) {
|
|
1265
|
+
const { name, version, commands, defaultCommand } = input;
|
|
1194
1266
|
const lines = [
|
|
1195
1267
|
`${name} ${version}`,
|
|
1196
1268
|
"",
|
|
@@ -1202,29 +1274,35 @@ function renderTopHelp(name, version, commands, defaultCommand) {
|
|
|
1202
1274
|
for (const [command, descriptor] of commands) {
|
|
1203
1275
|
lines.push(` ${padRight(command, width)} ${summarize(descriptor.description)}${command === defaultCommand ? " (default)" : ""}`);
|
|
1204
1276
|
}
|
|
1277
|
+
if (input.unavailable !== undefined) {
|
|
1278
|
+
lines.push("", `Managed commands are unavailable: ${input.unavailable}`);
|
|
1279
|
+
}
|
|
1205
1280
|
lines.push("", "Global options:");
|
|
1206
1281
|
const optWidth = Math.max(...GLOBAL_OPTIONS.map(([flag]) => flag.length));
|
|
1207
1282
|
for (const [flag, desc] of GLOBAL_OPTIONS)
|
|
1208
1283
|
lines.push(` ${padRight(flag, optWidth)} ${desc}`);
|
|
1284
|
+
lines.push(...applicationOptionLines(input.applicationOptions));
|
|
1209
1285
|
lines.push("", `Run "${name} <command> --help" for command-specific flags.`);
|
|
1210
1286
|
return `${lines.join(`
|
|
1211
1287
|
`)}
|
|
1212
1288
|
`;
|
|
1213
1289
|
}
|
|
1214
|
-
function renderCommandHelp(name, command, descriptor) {
|
|
1290
|
+
function renderCommandHelp(name, command, descriptor, applicationOptions = []) {
|
|
1215
1291
|
const fields = jsonSchemaFields(descriptor.presentationSchema);
|
|
1216
1292
|
const fieldsByName = new Map(fields.map((field) => [field.name, field]));
|
|
1293
|
+
const kinds = describeSchemaFields(descriptor.argumentSchema);
|
|
1217
1294
|
const positionals = [];
|
|
1218
|
-
const positionalNames = descriptor.positionals ?? [...
|
|
1295
|
+
const positionalNames = descriptor.positionals ?? [...kinds].filter(([, info]) => info.kind !== "boolean").map(([fieldName]) => fieldName);
|
|
1219
1296
|
for (const fieldName of positionalNames) {
|
|
1220
1297
|
const field = fieldsByName.get(fieldName);
|
|
1221
1298
|
if (field)
|
|
1222
1299
|
positionals.push(field);
|
|
1223
1300
|
}
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1226
|
-
field.
|
|
1227
|
-
|
|
1301
|
+
const variadicTail = descriptor.positionals !== undefined && kinds.get(descriptor.positionals[descriptor.positionals.length - 1] ?? "")?.kind === "array" ? descriptor.positionals[descriptor.positionals.length - 1] : undefined;
|
|
1302
|
+
const positionalSyntax = new Map(positionals.map((field) => {
|
|
1303
|
+
const label = field.name === variadicTail ? `${field.name}...` : field.name;
|
|
1304
|
+
return [field.name, field.required ? `<${label}>` : `[${label}]`];
|
|
1305
|
+
}));
|
|
1228
1306
|
const usage = [
|
|
1229
1307
|
`Usage: ${name} ${command}`,
|
|
1230
1308
|
...positionals.map((field) => positionalSyntax.get(field.name) ?? field.name),
|
|
@@ -1248,6 +1326,9 @@ function renderCommandHelp(name, command, descriptor) {
|
|
|
1248
1326
|
}
|
|
1249
1327
|
lines.push("");
|
|
1250
1328
|
}
|
|
1329
|
+
const applicationLines = applicationOptionLines(applicationOptions);
|
|
1330
|
+
if (applicationLines.length > 0)
|
|
1331
|
+
lines.push(...applicationLines.slice(1), "");
|
|
1251
1332
|
return `${lines.join(`
|
|
1252
1333
|
`)}
|
|
1253
1334
|
`;
|
|
@@ -1266,15 +1347,20 @@ function nativeDescriptor(definition) {
|
|
|
1266
1347
|
presentationSchema: cliCommandPresentationSchema(definition)
|
|
1267
1348
|
};
|
|
1268
1349
|
}
|
|
1269
|
-
function assertCommandShape(name, descriptor, exists, passthroughField) {
|
|
1350
|
+
function assertCommandShape(name, descriptor, exists, passthroughField, applicationGlobals = new Set) {
|
|
1270
1351
|
assertUniqueToolName(name, exists, "CLI command");
|
|
1271
1352
|
if (name === "help" || name === "version") {
|
|
1272
1353
|
throw new Error(`[stitchkit] CLI command "${name}" is reserved`);
|
|
1273
1354
|
}
|
|
1274
|
-
const
|
|
1355
|
+
const fieldNames = jsonSchemaFields(descriptor.presentationSchema).map((field) => field.name);
|
|
1356
|
+
const conflicting = fieldNames.filter((field) => RESERVED_CLI_OPTIONS.has(field));
|
|
1275
1357
|
if (conflicting.length > 0) {
|
|
1276
1358
|
throw new Error(`[stitchkit] CLI command "${name}" declares reserved option field(s): ${conflicting.join(", ")}`);
|
|
1277
1359
|
}
|
|
1360
|
+
const shadowed = fieldNames.filter((field) => applicationGlobals.has(field));
|
|
1361
|
+
if (shadowed.length > 0) {
|
|
1362
|
+
throw new Error(`[stitchkit] CLI command "${name}" declares field(s) shadowed by application global options: ${shadowed.join(", ")}`);
|
|
1363
|
+
}
|
|
1278
1364
|
if (passthroughField !== undefined && descriptor.aliases.has(passthroughField)) {
|
|
1279
1365
|
throw new Error(`[stitchkit] CLI command "${name}" cannot alias passthrough field "${passthroughField}"`);
|
|
1280
1366
|
}
|
|
@@ -1338,30 +1424,78 @@ async function downloadResults(files, dir, stderr, quiet, allowPrivate, maxBytes
|
|
|
1338
1424
|
return succeeded;
|
|
1339
1425
|
}
|
|
1340
1426
|
async function createCli(config) {
|
|
1427
|
+
let pendingWrite;
|
|
1428
|
+
let writeFailed = false;
|
|
1341
1429
|
const writeFd = (fd, text) => {
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1430
|
+
const bytes = Buffer.from(text, "utf8");
|
|
1431
|
+
let offset = 0;
|
|
1432
|
+
while (offset < bytes.length) {
|
|
1433
|
+
try {
|
|
1434
|
+
offset += writeSync(fd, bytes, offset, bytes.length - offset);
|
|
1435
|
+
} catch (error) {
|
|
1436
|
+
if (isRecord(error) && error.code === "EAGAIN") {
|
|
1437
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 1);
|
|
1438
|
+
continue;
|
|
1439
|
+
}
|
|
1440
|
+
const stream = fd === 1 ? process.stdout : process.stderr;
|
|
1441
|
+
const rest = bytes.subarray(offset);
|
|
1442
|
+
pendingWrite = new Promise((resolve2) => {
|
|
1443
|
+
stream.write(rest, (failure) => {
|
|
1444
|
+
if (failure)
|
|
1445
|
+
writeFailed = true;
|
|
1446
|
+
resolve2();
|
|
1447
|
+
});
|
|
1448
|
+
});
|
|
1449
|
+
return;
|
|
1450
|
+
}
|
|
1346
1451
|
}
|
|
1347
1452
|
};
|
|
1348
1453
|
const stdout = config.stdout ?? ((text) => writeFd(1, text));
|
|
1349
1454
|
const stderr = config.stderr ?? ((text) => writeFd(2, text));
|
|
1350
|
-
const exit = config.exit ?? ((code) =>
|
|
1455
|
+
const exit = config.exit ?? ((code) => {
|
|
1456
|
+
if (pendingWrite === undefined)
|
|
1457
|
+
process.exit(code);
|
|
1458
|
+
else
|
|
1459
|
+
pendingWrite.then(() => process.exit(writeFailed ? 1 : code));
|
|
1460
|
+
});
|
|
1351
1461
|
const argv = config.argv ?? process.argv.slice(2);
|
|
1352
1462
|
const readStdin = config.stdin ?? readPipedStdin;
|
|
1353
1463
|
if (config.auth !== undefined && config.resolveAuth !== undefined) {
|
|
1354
1464
|
throw new Error("[stitchkit] createCli: use either auth or resolveAuth, not both");
|
|
1355
1465
|
}
|
|
1466
|
+
const applicationOptions = config.globalOptions ? jsonSchemaFields(buildToolPresentationSchema({
|
|
1467
|
+
inputSchema: config.globalOptions,
|
|
1468
|
+
unrepresentable: "any"
|
|
1469
|
+
})) : [];
|
|
1470
|
+
const applicationGlobalNames = new Set(applicationOptions.map((field) => field.name));
|
|
1471
|
+
for (const name of applicationGlobalNames) {
|
|
1472
|
+
if (RESERVED_CLI_OPTIONS.has(name)) {
|
|
1473
|
+
throw new Error(`[stitchkit] CLI global option "--${name}" is reserved by the framework`);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1356
1476
|
const nativeCommands = new Map;
|
|
1357
1477
|
const nativeHelp = new Map;
|
|
1358
1478
|
for (const definition of config.commands ?? []) {
|
|
1359
1479
|
const descriptor2 = applyCliPresentationPolicy(definition.name, nativeDescriptor(definition), config);
|
|
1360
|
-
assertCommandShape(definition.name, descriptor2, nativeCommands.has(definition.name), config.passthrough?.[definition.name]);
|
|
1480
|
+
assertCommandShape(definition.name, descriptor2, nativeCommands.has(definition.name), config.passthrough?.[definition.name], applicationGlobalNames);
|
|
1361
1481
|
nativeCommands.set(definition.name, definition);
|
|
1362
1482
|
nativeHelp.set(definition.name, descriptor2);
|
|
1363
1483
|
}
|
|
1364
|
-
|
|
1484
|
+
let globals;
|
|
1485
|
+
let routableArgv;
|
|
1486
|
+
try {
|
|
1487
|
+
const lifted = extractCliGlobalOptions(argv, config.globalOptions);
|
|
1488
|
+
globals = lifted.globals;
|
|
1489
|
+
routableArgv = lifted.argv;
|
|
1490
|
+
} catch (error) {
|
|
1491
|
+
if (!(error instanceof CliArgumentError))
|
|
1492
|
+
throw error;
|
|
1493
|
+
stderr(`${error.message}
|
|
1494
|
+
`);
|
|
1495
|
+
return exit(2);
|
|
1496
|
+
}
|
|
1497
|
+
const typedGlobals = globals;
|
|
1498
|
+
const route = routeCliArgv(routableArgv, config.defaultCommand);
|
|
1365
1499
|
if (route.error) {
|
|
1366
1500
|
stderr(`${route.error}
|
|
1367
1501
|
`);
|
|
@@ -1381,7 +1515,7 @@ async function createCli(config) {
|
|
|
1381
1515
|
if (!descriptor2)
|
|
1382
1516
|
throw new Error("[stitchkit] native CLI descriptor invariant failed");
|
|
1383
1517
|
if (helpRequested) {
|
|
1384
|
-
stdout(renderCommandHelp(config.name, command, descriptor2));
|
|
1518
|
+
stdout(renderCommandHelp(config.name, command, descriptor2, applicationOptions));
|
|
1385
1519
|
return exit(0);
|
|
1386
1520
|
}
|
|
1387
1521
|
const prepared2 = await prepareInvocation(command, commandArgv, descriptor2, config, readStdin);
|
|
@@ -1392,7 +1526,7 @@ async function createCli(config) {
|
|
|
1392
1526
|
}
|
|
1393
1527
|
const { toolArgs: toolArgs2, options: options2 } = prepared2;
|
|
1394
1528
|
if (options2.help) {
|
|
1395
|
-
stdout(renderCommandHelp(config.name, command, descriptor2));
|
|
1529
|
+
stdout(renderCommandHelp(config.name, command, descriptor2, applicationOptions));
|
|
1396
1530
|
return exit(0);
|
|
1397
1531
|
}
|
|
1398
1532
|
if (options2.wait) {
|
|
@@ -1415,7 +1549,7 @@ async function createCli(config) {
|
|
|
1415
1549
|
`);
|
|
1416
1550
|
return exit(0);
|
|
1417
1551
|
}
|
|
1418
|
-
const result2 = await executeCliCommand(native, toolArgs2, options2, { stdout, stderr }, config.coerceJsonArgs ?? true);
|
|
1552
|
+
const result2 = await executeCliCommand(native, toolArgs2, options2, { stdout, stderr }, config.coerceJsonArgs ?? true, globals);
|
|
1419
1553
|
const emission = prepareCliCommandEmission(native, result2, options2);
|
|
1420
1554
|
let emittedExitCode;
|
|
1421
1555
|
if (emission.result.ok && emission.presentation !== undefined) {
|
|
@@ -1433,12 +1567,26 @@ async function createCli(config) {
|
|
|
1433
1567
|
}
|
|
1434
1568
|
let authPromise;
|
|
1435
1569
|
const resolveIdentity = () => {
|
|
1436
|
-
authPromise ??=
|
|
1570
|
+
authPromise ??= (async () => config.resolveAuth ? await config.resolveAuth(typedGlobals) : await config.auth)();
|
|
1437
1571
|
return authPromise;
|
|
1438
1572
|
};
|
|
1439
1573
|
const dynamicSurface = typeof config.services === "function" || typeof config.runtimeTools === "function";
|
|
1440
1574
|
const buildManagedSurface = async (forExecution) => {
|
|
1441
|
-
|
|
1575
|
+
let auth;
|
|
1576
|
+
if (dynamicSurface || forExecution) {
|
|
1577
|
+
try {
|
|
1578
|
+
auth = await resolveIdentity();
|
|
1579
|
+
} catch (error) {
|
|
1580
|
+
const failure = toolResultFromError(error);
|
|
1581
|
+
const normalized = toolErrorFromResult(failure);
|
|
1582
|
+
return {
|
|
1583
|
+
resolved: false,
|
|
1584
|
+
failure,
|
|
1585
|
+
reason: `${normalized.code}: ${normalized.message}`,
|
|
1586
|
+
help: new Map(nativeHelp)
|
|
1587
|
+
};
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1442
1590
|
const services = typeof config.services === "function" ? config.services(auth) : config.services ?? [];
|
|
1443
1591
|
const runtimeTools = typeof config.runtimeTools === "function" ? config.runtimeTools(auth) : config.runtimeTools ?? [];
|
|
1444
1592
|
const tools = new Map;
|
|
@@ -1448,19 +1596,34 @@ async function createCli(config) {
|
|
|
1448
1596
|
transport: "CLI"
|
|
1449
1597
|
})) {
|
|
1450
1598
|
const descriptor2 = applyCliPresentationPolicy(mountable.name, managedDescriptor(mountable), config);
|
|
1451
|
-
assertCommandShape(mountable.name, descriptor2, help.has(mountable.name), config.passthrough?.[mountable.name]);
|
|
1599
|
+
assertCommandShape(mountable.name, descriptor2, help.has(mountable.name), config.passthrough?.[mountable.name], applicationGlobalNames);
|
|
1452
1600
|
tools.set(mountable.name, mountable);
|
|
1453
1601
|
help.set(mountable.name, descriptor2);
|
|
1454
1602
|
}
|
|
1455
1603
|
assertCliPoliciesResolved(help, config);
|
|
1456
|
-
return { auth, help, tools };
|
|
1604
|
+
return { resolved: true, auth, help, tools };
|
|
1457
1605
|
};
|
|
1458
1606
|
const topLevelHelp = route.topLevelHelp || command === undefined || command === "help" || command === "--help" || command === "-h";
|
|
1459
1607
|
const managed = await buildManagedSurface(!topLevelHelp && !helpRequested);
|
|
1460
1608
|
if (topLevelHelp) {
|
|
1461
|
-
stdout(renderTopHelp(
|
|
1609
|
+
stdout(renderTopHelp({
|
|
1610
|
+
name: config.name,
|
|
1611
|
+
version: config.version,
|
|
1612
|
+
commands: managed.help,
|
|
1613
|
+
defaultCommand: config.defaultCommand,
|
|
1614
|
+
applicationOptions,
|
|
1615
|
+
...managed.resolved ? {} : { unavailable: managed.reason }
|
|
1616
|
+
}));
|
|
1462
1617
|
return exit(0);
|
|
1463
1618
|
}
|
|
1619
|
+
if (!managed.resolved) {
|
|
1620
|
+
return exit(emitResult(managed.failure, { stdout, stderr }, {
|
|
1621
|
+
json: beforeSeparator.includes("--json"),
|
|
1622
|
+
toolName: command ?? config.name,
|
|
1623
|
+
errorHint: config.errorHint,
|
|
1624
|
+
exitCodes: { ...DEFAULT_EXIT_CODES, ...config.exitCodes }
|
|
1625
|
+
}));
|
|
1626
|
+
}
|
|
1464
1627
|
const tool = managed.tools.get(command);
|
|
1465
1628
|
if (!tool) {
|
|
1466
1629
|
stderr(`Unknown command "${command}". Run "${config.name} --help" for the command list.
|
|
@@ -1471,7 +1634,7 @@ async function createCli(config) {
|
|
|
1471
1634
|
if (!descriptor)
|
|
1472
1635
|
throw new Error("[stitchkit] managed CLI descriptor invariant failed");
|
|
1473
1636
|
if (helpRequested) {
|
|
1474
|
-
stdout(renderCommandHelp(config.name, command, descriptor));
|
|
1637
|
+
stdout(renderCommandHelp(config.name, command, descriptor, applicationOptions));
|
|
1475
1638
|
return exit(0);
|
|
1476
1639
|
}
|
|
1477
1640
|
const prepared = await prepareInvocation(command, commandArgv, descriptor, config, readStdin);
|
|
@@ -1497,7 +1660,7 @@ async function createCli(config) {
|
|
|
1497
1660
|
return exit(2);
|
|
1498
1661
|
}
|
|
1499
1662
|
if (options.help) {
|
|
1500
|
-
stdout(renderCommandHelp(config.name, command, descriptor));
|
|
1663
|
+
stdout(renderCommandHelp(config.name, command, descriptor, applicationOptions));
|
|
1501
1664
|
return exit(0);
|
|
1502
1665
|
}
|
|
1503
1666
|
if (options.dryRun) {
|
|
@@ -1507,7 +1670,7 @@ async function createCli(config) {
|
|
|
1507
1670
|
}
|
|
1508
1671
|
const runTool = createToolRunner({
|
|
1509
1672
|
source: "cli",
|
|
1510
|
-
context: { ...config.context?.(managed.auth), signal: config.signal },
|
|
1673
|
+
context: { ...config.context?.(managed.auth, typedGlobals), signal: config.signal },
|
|
1511
1674
|
hooks: config.hooks,
|
|
1512
1675
|
lifecycle: config.lifecycle,
|
|
1513
1676
|
errorHint: config.errorHint,
|
package/dist/tools/cli-args.d.ts
CHANGED
|
@@ -88,5 +88,32 @@ export declare function parseCliArgs(argv: string[], schema: z.ZodType | undefin
|
|
|
88
88
|
optionAliases?: ReadonlyMap<string, string>;
|
|
89
89
|
positionals?: readonly string[];
|
|
90
90
|
}): ParsedCliArgs;
|
|
91
|
+
/** The application's own global options, lifted out of one invocation's argv. */
|
|
92
|
+
export interface CliGlobalOptionsParse {
|
|
93
|
+
/** argv with the application-global tokens removed, ready for routing. */
|
|
94
|
+
argv: string[];
|
|
95
|
+
/** The validated values, as the application's own schema types them. */
|
|
96
|
+
globals: Record<string, unknown>;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Lift the APPLICATION's global options out of argv, wherever they stand.
|
|
100
|
+
*
|
|
101
|
+
* These are not arguments of any operation: which identity key to use, which
|
|
102
|
+
* checkout a call speaks for, which profile. They belong to the invocation, so
|
|
103
|
+
* they may precede the command name as easily as follow it — and a command's
|
|
104
|
+
* own parser must never see them, or an app-global would read as an unknown
|
|
105
|
+
* flag on every operation that does not declare it.
|
|
106
|
+
*
|
|
107
|
+
* Stripping them BEFORE routing is what keeps this one grammar rather than two:
|
|
108
|
+
* `routeCliArgv` then sees a command where a command is, `parseCliArgs` sees
|
|
109
|
+
* only operation arguments, and `passthrough` cannot swallow an app-global into
|
|
110
|
+
* a freeform bag. The token shape is the same `classifyLongOptionToken` the
|
|
111
|
+
* framework's own globals use, so `--root /x`, `--root=/x` and a bare boolean
|
|
112
|
+
* `--verbose` all behave as they do everywhere else.
|
|
113
|
+
*
|
|
114
|
+
* `--` ends the sweep: past it every token is a literal value, so a positional
|
|
115
|
+
* that happens to read as `--root` survives intact.
|
|
116
|
+
*/
|
|
117
|
+
export declare function extractCliGlobalOptions(argv: readonly string[], schema: z.ZodObject | undefined): CliGlobalOptionsParse;
|
|
91
118
|
export {};
|
|
92
119
|
//# sourceMappingURL=cli-args.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../../src/tools/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-args.d.ts","sourceRoot":"","sources":["../../src/tools/cli-args.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,IAAI,EAAE,OAAO,CAAC;IACd,iEAAiE;IACjE,IAAI,EAAE,OAAO,CAAC;IACd,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wEAAwE;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,KAAK,EAAE,OAAO,CAAC;IACf,qEAAqE;IACrE,MAAM,EAAE,OAAO,CAAC;IAChB,qDAAqD;IACrD,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,mEAAmE;IACnE,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,+BAA+B;IAC/B,OAAO,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,KAAK,SAAS,GACV,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,QAAQ,GACR,MAAM,GACN,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ,UAAU,SAAS;IACjB,IAAI,EAAE,SAAS,CAAC;IAChB,uEAAuE;IACvE,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB;AAOD,eAAO,MAAM,oBAAoB,aAA+C,CAAC;AA0BjF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,YAAY,CAsFlF;AAED,qBAAa,gBAAiB,SAAQ,KAAK;IAChC,IAAI,SAAsB;CACpC;AAuED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAI1F;AA8FD;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EAAE,EACd,MAAM,EAAE,CAAC,CAAC,OAAO,GAAG,SAAS,EAC7B,MAAM,GAAE;IACN,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAChC,aAAa,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,GACL,aAAa,CA+Nf;AAED,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,wEAAwE;IACxE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,MAAM,EAAE,CAAC,CAAC,SAAS,GAAG,SAAS,GAC9B,qBAAqB,CA8CvB"}
|
|
@@ -5,6 +5,13 @@ import { type ToolResult } from './execute.js';
|
|
|
5
5
|
export interface CliCommandContext<TInput extends ZodObject> extends CliWriters {
|
|
6
6
|
input: z.output<TInput>;
|
|
7
7
|
options: Readonly<CliRunOptions>;
|
|
8
|
+
/**
|
|
9
|
+
* The application's own global options for this invocation, already validated
|
|
10
|
+
* against `CliConfig.globalOptions`. Empty when the CLI declares none. Typed
|
|
11
|
+
* loosely because a command is defined independently of the CLI it is mounted
|
|
12
|
+
* on — read it through the same schema the application declared.
|
|
13
|
+
*/
|
|
14
|
+
globals: Readonly<Record<string, unknown>>;
|
|
8
15
|
}
|
|
9
16
|
export interface CliCommandDefinitionBase<TInput extends ZodObject> {
|
|
10
17
|
name: string;
|
|
@@ -41,5 +48,5 @@ export interface PreparedCliCommandEmission {
|
|
|
41
48
|
export declare function prepareCliCommandEmission(definition: CliCommandDefinition, result: ToolResult, options: Readonly<CliRunOptions>): PreparedCliCommandEmission;
|
|
42
49
|
export declare function cliCommandPresentationSchema(definition: CliCommandDefinition): Record<string, unknown>;
|
|
43
50
|
/** Execute a CLI-only definition without inventing a tool operation identity. */
|
|
44
|
-
export declare function executeCliCommand(definition: CliCommandDefinition, rawArgs: Record<string, unknown>, options: CliRunOptions, writers: CliWriters, coerceJson: boolean): Promise<ToolResult>;
|
|
51
|
+
export declare function executeCliCommand(definition: CliCommandDefinition, rawArgs: Record<string, unknown>, options: CliRunOptions, writers: CliWriters, coerceJson: boolean, globals?: Readonly<Record<string, unknown>>): Promise<ToolResult>;
|
|
45
52
|
//# sourceMappingURL=cli-command.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-command.d.ts","sourceRoot":"","sources":["../../src/tools/cli-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAEjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EAAE,KAAK,UAAU,EAAuB,MAAM,WAAW,CAAC;AAGjE,MAAM,WAAW,iBAAiB,CAAC,MAAM,SAAS,SAAS,CAAE,SAAQ,UAAU;IAC7E,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-command.d.ts","sourceRoot":"","sources":["../../src/tools/cli-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,7 +13,12 @@ export interface CliCommandPresentation {
|
|
|
13
13
|
presentationSchema: Record<string, unknown>;
|
|
14
14
|
/** Canonical field name → one short alias. */
|
|
15
15
|
aliases: ReadonlyMap<string, string>;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* `undefined` retains automatic non-boolean schema order. A trailing ARRAY
|
|
18
|
+
* field is variadic — it takes every remaining token. An array declared
|
|
19
|
+
* anywhere else keeps taking exactly one (a JSON-array token), and command
|
|
20
|
+
* help says which is which: only the variadic tail renders as `<name...>`.
|
|
21
|
+
*/
|
|
17
22
|
positionals?: readonly string[];
|
|
18
23
|
}
|
|
19
24
|
export declare function applyCliPresentationPolicy(command: string, descriptor: Omit<CliCommandPresentation, 'aliases' | 'positionals'>, config: CliPresentationPolicyConfig): CliCommandPresentation;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-policy.d.ts","sourceRoot":"","sources":["../../src/tools/cli-policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,2BAA2B;IAC1C,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,6FAA6F;IAC7F,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,8CAA8C;IAC9C,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC
|
|
1
|
+
{"version":3,"file":"cli-policy.d.ts","sourceRoot":"","sources":["../../src/tools/cli-policy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGlD,MAAM,WAAW,2BAA2B;IAC1C,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+EAA+E;IAC/E,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,6FAA6F;IAC7F,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC5C,8CAA8C;IAC9C,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACjC;AAkFD,wBAAgB,0BAA0B,CACxC,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,IAAI,CAAC,sBAAsB,EAAE,SAAS,GAAG,aAAa,CAAC,EACnE,MAAM,EAAE,2BAA2B,GAClC,sBAAsB,CAexB;AAED,wFAAwF;AACxF,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,sBAAsB,CAAC,EACrD,MAAM,EAAE,2BAA2B,GAClC,IAAI,CAWN"}
|
package/dist/tools/cli.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ZodObject, z } from 'zod';
|
|
1
2
|
import type { ServiceDef, StitchLogger } from '../server/types.js';
|
|
2
3
|
import { type CliCommandDefinition } from './cli-command.js';
|
|
3
4
|
import { type ExitCodeMap } from './cli-format.js';
|
|
@@ -6,7 +7,7 @@ import { type CliWaitConfig } from './cli-wait.js';
|
|
|
6
7
|
import { type ErrorHintFn, type ToolCallHooks, type ToolLifecycle } from './execute.js';
|
|
7
8
|
import type { RuntimeToolDefinition } from './runtime-tool.js';
|
|
8
9
|
export type CliSurfaceSource<TAuth, TValue> = readonly TValue[] | ((auth: Awaited<TAuth> | undefined) => readonly TValue[]);
|
|
9
|
-
export interface CliConfig<TAuth = unknown, TContext extends Record<string, unknown> = Record<string, unknown
|
|
10
|
+
export interface CliConfig<TAuth = unknown, TContext extends Record<string, unknown> = Record<string, unknown>, TGlobals extends ZodObject = ZodObject> extends CliPresentationPolicyConfig {
|
|
10
11
|
/** Program name — shown in help and unknown-command messages. */
|
|
11
12
|
name: string;
|
|
12
13
|
/** Program version — printed by `--version`. */
|
|
@@ -23,13 +24,27 @@ export interface CliConfig<TAuth = unknown, TContext extends Record<string, unkn
|
|
|
23
24
|
* promise of one.
|
|
24
25
|
*/
|
|
25
26
|
auth?: TAuth | Promise<TAuth>;
|
|
26
|
-
/**
|
|
27
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Lazily resolve identity only when a managed command/surface actually needs
|
|
29
|
+
* it. Receives the application's global options, so `--caller <key>` can
|
|
30
|
+
* select WHICH identity this invocation speaks as.
|
|
31
|
+
*/
|
|
32
|
+
resolveAuth?: (globals: z.output<TGlobals>) => TAuth | Promise<TAuth>;
|
|
33
|
+
/**
|
|
34
|
+
* The application's OWN global options — invocation context that belongs to
|
|
35
|
+
* no single operation: which identity key, which checkout, which profile.
|
|
36
|
+
* Declared as a Zod object of optional fields; `createCli` lifts these flags
|
|
37
|
+
* out of argv wherever they stand (before or after the command name),
|
|
38
|
+
* validates them against this schema and keeps them out of every operation's
|
|
39
|
+
* arguments. A name that collides with a framework option or with a field of
|
|
40
|
+
* any command is a startup error, never silent shadowing.
|
|
41
|
+
*/
|
|
42
|
+
globalOptions?: TGlobals;
|
|
28
43
|
/**
|
|
29
44
|
* Context merged into every handler. Typed against the app's context shape
|
|
30
45
|
* when the CLI is built via `createToolkit<AppContext>()`.
|
|
31
46
|
*/
|
|
32
|
-
context?: (auth: Awaited<TAuth> | undefined) => TContext;
|
|
47
|
+
context?: (auth: Awaited<TAuth> | undefined, globals: z.output<TGlobals>) => TContext;
|
|
33
48
|
/** Explicit cancellation for this invocation; applications may bind SIGINT to it. */
|
|
34
49
|
signal?: AbortSignal;
|
|
35
50
|
/** Tool-call observability hooks — `afterToolCall` fires for every result,
|
|
@@ -87,5 +102,5 @@ export interface CliConfig<TAuth = unknown, TContext extends Record<string, unkn
|
|
|
87
102
|
stdin?: () => Promise<string | null>;
|
|
88
103
|
}
|
|
89
104
|
/** Build and run one mixed contract/runtime/native CLI surface, then exit. */
|
|
90
|
-
export declare function createCli<TAuth = unknown, TContext extends Record<string, unknown> = Record<string, unknown
|
|
105
|
+
export declare function createCli<TAuth = unknown, TContext extends Record<string, unknown> = Record<string, unknown>, TGlobals extends ZodObject = ZodObject>(config: CliConfig<TAuth, TContext, TGlobals>): Promise<void>;
|
|
91
106
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/tools/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/tools/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/tools/cli.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxC,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAShE,OAAO,EACL,KAAK,oBAAoB,EAI1B,MAAM,eAAe,CAAC;AACvB,OAAO,EAAsB,KAAK,WAAW,EAAc,MAAM,cAAc,CAAC;AAChF,OAAO,EAIL,KAAK,2BAA2B,EACjC,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,KAAK,aAAa,EAAiB,MAAM,YAAY,CAAC;AAC/D,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAInB,MAAM,WAAW,CAAC;AAKnB,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAI5D,MAAM,MAAM,gBAAgB,CAAC,KAAK,EAAE,MAAM,IACtC,SAAS,MAAM,EAAE,GACjB,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,KAAK,SAAS,MAAM,EAAE,CAAC,CAAC;AAE9D,MAAM,WAAW,SAAS,CACxB,KAAK,GAAG,OAAO,EACf,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,QAAQ,SAAS,SAAS,GAAG,SAAS,CACtC,SAAQ,2BAA2B;IACnC,iEAAiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAC/C,uFAAuF;IACvF,YAAY,CAAC,EAAE,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC;IAC9D,0FAA0F;IAC1F,QAAQ,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAC3C;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACtE;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,QAAQ,CAAC;IACzB;;;OAGG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,QAAQ,CAAC;IACtF,qFAAqF;IACrF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;+DAC2D;IAC3D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,wEAAwE;IACxE,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB,2EAA2E;IAC3E,SAAS,CAAC,EAAE,WAAW,CAAC;IACxB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrC,wEAAwE;IACxE,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrE;;;OAGG;IACH,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oEAAoE;IACpE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,oEAAoE;IACpE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,gEAAgE;IAChE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACtC;AAkXD,8EAA8E;AAC9E,wBAAsB,SAAS,CAC7B,KAAK,GAAG,OAAO,EACf,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,QAAQ,SAAS,SAAS,GAAG,SAAS,EACtC,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CA2b7D"}
|
package/dist/tools.js
CHANGED
package/llms-full.txt
CHANGED
|
@@ -7443,6 +7443,30 @@ command schema. `-f` / `-f=false` are boolean forms; values accept `-n 100` and
|
|
|
7443
7443
|
bundles such as `-fn`, attached values such as `-n100`, `--no-f` and unknown
|
|
7444
7444
|
short flags are rejected. Canonical `--no-follow` remains available.
|
|
7445
7445
|
|
|
7446
|
+
### A trailing list
|
|
7447
|
+
|
|
7448
|
+
When the LAST declared positional is an array field, it takes every remaining
|
|
7449
|
+
token, each coerced by the array's element type:
|
|
7450
|
+
|
|
7451
|
+
```ts
|
|
7452
|
+
positionals: { handoff: ['to', 'files'] } // files: z.array(z.string())
|
|
7453
|
+
```
|
|
7454
|
+
|
|
7455
|
+
```
|
|
7456
|
+
myapp handoff proj a.md b.md → { to: 'proj', files: ['a.md', 'b.md'] }
|
|
7457
|
+
myapp handoff proj a.md → { to: 'proj', files: ['a.md'] }
|
|
7458
|
+
```
|
|
7459
|
+
|
|
7460
|
+
One token is a one-element list, not a scalar, so the parsed shape never depends
|
|
7461
|
+
on how many a caller happened to pass. Command help marks it:
|
|
7462
|
+
`Usage: myapp handoff <to> <files...>`. The flag form still works
|
|
7463
|
+
(`--files '["a.md","b.md"]'`, or a repeated `--files`) — but passing both forms
|
|
7464
|
+
in one call is an argument error rather than a silent merge.
|
|
7465
|
+
|
|
7466
|
+
Only the trailing position is variadic. An array declared anywhere else in the
|
|
7467
|
+
list keeps taking exactly one token (a JSON array), and its help stays `<tags>`,
|
|
7468
|
+
so the usage line always says which field is the list.
|
|
7469
|
+
|
|
7446
7470
|
`positionals` replaces automatic schema-order selection only for the named
|
|
7447
7471
|
command. An empty array disables argv positionals. Fields remain available as
|
|
7448
7472
|
long/short options and stdin still fills the first required unset field with the
|
|
@@ -7474,6 +7498,68 @@ diagnostics remain ordinary stderr text. This keeps stdout pipeable and
|
|
|
7474
7498
|
`VALIDATION_ERROR → 1`, `UNAUTHORIZED → 2`, `FORBIDDEN → 3`, `NOT_FOUND → 4`,
|
|
7475
7499
|
…) — override per app with `exitCodes`.
|
|
7476
7500
|
|
|
7501
|
+
## Application global options
|
|
7502
|
+
|
|
7503
|
+
`--json` and friends above are the framework's. An application usually has
|
|
7504
|
+
globals of its own — which identity key to use, which checkout a call speaks
|
|
7505
|
+
for, which profile — and they belong to no single operation:
|
|
7506
|
+
|
|
7507
|
+
```ts
|
|
7508
|
+
await createCli({
|
|
7509
|
+
name: 'myapp',
|
|
7510
|
+
version: '1.0.0',
|
|
7511
|
+
globalOptions: z.object({
|
|
7512
|
+
caller: z.string().optional().describe('Identity key file'),
|
|
7513
|
+
root: z.string().optional().describe('Checkout the call speaks for'),
|
|
7514
|
+
}),
|
|
7515
|
+
resolveAuth: (globals) => loadIdentity(globals.caller),
|
|
7516
|
+
context: (auth, globals) => ({ auth, root: globals.root }),
|
|
7517
|
+
runtimeTools: (auth) => catalogFor(auth),
|
|
7518
|
+
})
|
|
7519
|
+
```
|
|
7520
|
+
|
|
7521
|
+
```
|
|
7522
|
+
myapp --root /srv/app handoff_read --handoffId u
|
|
7523
|
+
myapp handoff_read --root /srv/app --handoffId u # the same call
|
|
7524
|
+
```
|
|
7525
|
+
|
|
7526
|
+
These flags are lifted out of argv wherever they stand — before or after the
|
|
7527
|
+
command name — validated against the declared schema, and kept out of every
|
|
7528
|
+
operation's arguments: `handoff_read` above receives `{ handoffId: 'u' }` and
|
|
7529
|
+
nothing else. The values reach `resolveAuth(globals)`, `context(auth, globals)`
|
|
7530
|
+
and a native command's `globals`. An invalid value is an argument error naming
|
|
7531
|
+
the flag; a name that collides with a framework option, or with a field of any
|
|
7532
|
+
command, is refused at startup rather than shadowing it silently. Past a bare
|
|
7533
|
+
`--` every token is a literal, so a positional value that reads like a global
|
|
7534
|
+
survives intact.
|
|
7535
|
+
|
|
7536
|
+
Both help levels list them under `Application options:`.
|
|
7537
|
+
|
|
7538
|
+
## When the managed surface cannot resolve
|
|
7539
|
+
|
|
7540
|
+
A CLI whose commands come from a running server declares them with a factory,
|
|
7541
|
+
and that factory needs an identity. When `resolveAuth` fails — the server is
|
|
7542
|
+
down, the key file is missing — the commands it would have named are unknown to
|
|
7543
|
+
the CLI, but the native ones are not:
|
|
7544
|
+
|
|
7545
|
+
```
|
|
7546
|
+
$ myapp --help
|
|
7547
|
+
myapp 1.0.0
|
|
7548
|
+
...
|
|
7549
|
+
Commands:
|
|
7550
|
+
serve Run the server
|
|
7551
|
+
|
|
7552
|
+
Managed commands are unavailable: UNREACHABLE: socket closed
|
|
7553
|
+
```
|
|
7554
|
+
|
|
7555
|
+
Help still lists what does not depend on identity and says, in one line, why the
|
|
7556
|
+
rest is missing. Calling a name the CLI cannot resolve answers with that same
|
|
7557
|
+
refusal and the exit code its error class declares through `exitCodes` — never
|
|
7558
|
+
`Unknown command`, which would claim the name does not exist when the truth is
|
|
7559
|
+
that it could not be looked up. A native command and its help still run: they
|
|
7560
|
+
never needed an identity. Identity is still resolved at most once per
|
|
7561
|
+
invocation, failure included.
|
|
7562
|
+
|
|
7477
7563
|
Per-command help derives the positional form from the same resolved policy as
|
|
7478
7564
|
the argv parser. For example, a required `action` and optional `profile` render as
|
|
7479
7565
|
`Usage: myapp skill <action> [profile] [--flags]`; the argument table also shows
|
|
@@ -16443,14 +16529,14 @@ payload.
|
|
|
16443
16529
|
| `AgentToolRegistry` / `AgentToolRegistryBuilder` / `AgentToolRegistryInput` | _type_ | the composed runtime surface and its builder: declared defaults, `replace`/`disable` by name, and the exact `{ tools, names }` a mount receives |
|
|
16444
16530
|
| `defineToolRegistry` | function | compose runtime tools over one declared default set; an unknown `replace`/`disable` name is refused instead of silently leaving the default in place |
|
|
16445
16531
|
| `AgentContext` | _type_ | the context merged into agent tool handlers |
|
|
16446
|
-
| `CliConfig` | _type_ | config for `createCli`, including program-level `defaultCommand` selection and command-scoped `optionAliases` / `positionals` policy |
|
|
16532
|
+
| `CliConfig` | _type_ | config for `createCli`, including program-level `defaultCommand` selection, application-wide `globalOptions` and command-scoped `optionAliases` / `positionals` policy |
|
|
16447
16533
|
| `CliPresentationPolicyConfig` | _type_ | reusable default-command, short-alias and explicit-positional policy inherited by `CliConfig` |
|
|
16448
16534
|
| `CliSurfaceSource` | _type_ | static managed surface or identity-dependent surface factory for `createCli` |
|
|
16449
16535
|
| `CliCommandDefinition` | _type_ | Zod-first CLI-only command union |
|
|
16450
16536
|
| `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
|
|
16451
16537
|
| `CliCommandDefinitionWithOutput` | _type_ | native command with declared output schema, validated handler result and typed optional `present` / `exitCode` callbacks |
|
|
16452
16538
|
| `CliCommandDefinitionWithoutOutput` | _type_ | void native command with no output schema |
|
|
16453
|
-
| `CliCommandContext` | _type_ | parsed native command input,
|
|
16539
|
+
| `CliCommandContext` | _type_ | parsed native command input, framework run options, the application's `globals` and injected writers |
|
|
16454
16540
|
| `CliWaitConfig` | _type_ | `--wait` polling config |
|
|
16455
16541
|
| `ExitCodeMap` | _type_ | `ToolResult.code` → process exit code |
|
|
16456
16542
|
| `Toolkit` | _type_ | the context-pinned tool surface from `createToolkit` |
|
|
@@ -16949,14 +17035,14 @@ SDK nor the `ai` peer.
|
|
|
16949
17035
|
| `pollUntilDone` | function | the generic `--wait` poller (advanced) |
|
|
16950
17036
|
| `emitResult` | function | write a pretty or compact `ToolResult` record to stdout/stderr + exit code (advanced) |
|
|
16951
17037
|
| `DEFAULT_EXIT_CODES` | const | the default `ToolResult.code` → exit-code map |
|
|
16952
|
-
| `CliConfig` | _type_ | config for `createCli`; `defaultCommand`, `optionAliases` and `positionals` define the shared command presentation policy |
|
|
17038
|
+
| `CliConfig` | _type_ | config for `createCli`; `defaultCommand`, `globalOptions`, `optionAliases` and `positionals` define the shared command presentation policy |
|
|
16953
17039
|
| `CliPresentationPolicyConfig` | _type_ | shared command presentation-policy subset of `CliConfig` |
|
|
16954
17040
|
| `CliSurfaceSource` | _type_ | static service/runtime array or identity-dependent factory |
|
|
16955
17041
|
| `CliCommandDefinition` | _type_ | native command definition union |
|
|
16956
17042
|
| `CliCommandDefinitionBase` | _type_ | native command name, description and input schema |
|
|
16957
17043
|
| `CliCommandDefinitionWithOutput` | _type_ | native command with validated declared output and typed optional `present` / successful `exitCode` callbacks |
|
|
16958
17044
|
| `CliCommandDefinitionWithoutOutput` | _type_ | native void command without an output contract |
|
|
16959
|
-
| `CliCommandContext` | _type_ | parsed input,
|
|
17045
|
+
| `CliCommandContext` | _type_ | parsed input, framework run options, the application's `globals` and stdout/stderr writers |
|
|
16960
17046
|
| `CliRunOptions` | _type_ | parsed global flags (`--json` compacts success/error records, `--wait`, …) |
|
|
16961
17047
|
| `ParsedCliArgs` | _type_ | result of `parseCliArgs` |
|
|
16962
17048
|
| `CliWaitConfig` | _type_ | per-command `--wait` polling config; optional `failed(result)` maps a terminal domain failure to `WAIT_FAILED` and a non-zero exit |
|
package/package.json
CHANGED