@agentuity/cli 1.0.34 → 1.0.35

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.
Files changed (53) hide show
  1. package/dist/ai-help.js +60 -0
  2. package/dist/ai-help.js.map +1 -1
  3. package/dist/cache/agent-intro.d.ts +10 -0
  4. package/dist/cache/agent-intro.d.ts.map +1 -1
  5. package/dist/cache/agent-intro.js +50 -0
  6. package/dist/cache/agent-intro.js.map +1 -1
  7. package/dist/cache/index.d.ts +1 -1
  8. package/dist/cache/index.d.ts.map +1 -1
  9. package/dist/cache/index.js +1 -1
  10. package/dist/cache/index.js.map +1 -1
  11. package/dist/cli.d.ts.map +1 -1
  12. package/dist/cli.js +50 -7
  13. package/dist/cli.js.map +1 -1
  14. package/dist/cmd/ai/intro.d.ts.map +1 -1
  15. package/dist/cmd/ai/intro.js +26 -6
  16. package/dist/cmd/ai/intro.js.map +1 -1
  17. package/dist/cmd/cloud/deploy.d.ts.map +1 -1
  18. package/dist/cmd/cloud/deploy.js +4 -0
  19. package/dist/cmd/cloud/deploy.js.map +1 -1
  20. package/dist/cmd/project/domain/check.d.ts.map +1 -1
  21. package/dist/cmd/project/domain/check.js +1 -5
  22. package/dist/cmd/project/domain/check.js.map +1 -1
  23. package/dist/domain.d.ts +9 -8
  24. package/dist/domain.d.ts.map +1 -1
  25. package/dist/domain.js +19 -62
  26. package/dist/domain.js.map +1 -1
  27. package/dist/output.d.ts.map +1 -1
  28. package/dist/output.js +45 -1
  29. package/dist/output.js.map +1 -1
  30. package/dist/schema-generator.d.ts +9 -1
  31. package/dist/schema-generator.d.ts.map +1 -1
  32. package/dist/schema-generator.js +57 -24
  33. package/dist/schema-generator.js.map +1 -1
  34. package/dist/schema-parser.d.ts +2 -2
  35. package/dist/schema-parser.d.ts.map +1 -1
  36. package/dist/schema-parser.js +44 -3
  37. package/dist/schema-parser.js.map +1 -1
  38. package/dist/types.d.ts +3 -0
  39. package/dist/types.d.ts.map +1 -1
  40. package/dist/types.js.map +1 -1
  41. package/package.json +6 -6
  42. package/src/ai-help.ts +61 -0
  43. package/src/cache/agent-intro.ts +54 -0
  44. package/src/cache/index.ts +6 -1
  45. package/src/cli.ts +84 -11
  46. package/src/cmd/ai/intro.ts +26 -6
  47. package/src/cmd/cloud/deploy.ts +5 -0
  48. package/src/cmd/project/domain/check.ts +0 -4
  49. package/src/domain.ts +28 -72
  50. package/src/output.ts +46 -1
  51. package/src/schema-generator.ts +62 -27
  52. package/src/schema-parser.ts +57 -3
  53. package/src/types.ts +3 -0
@@ -31,6 +31,7 @@ The Agentuity CLI is designed to be agent-friendly. Here are the key commands:
31
31
 
32
32
  ### Discovery & Introspection
33
33
  \`\`\`bash
34
+ ${getCommand('<command> --describe')} # Get command schema as JSON (args, options, response)
34
35
  ${getCommand('--help=json')} # Get complete CLI schema as JSON
35
36
  ${getCommand('ai capabilities show')} # List all capabilities and workflows
36
37
  ${getCommand('ai schema show')} # Detailed command metadata
@@ -61,22 +62,41 @@ ${getCommand('env set KEY value --secret')} # Set secrets (encrypted)
61
62
 
62
63
  ## Best Practices for AI Agents
63
64
 
64
- 1. **Always use \`--json\` for machine-readable output**
65
+ 1. **Use \`--input <json>\` to pass arguments and options as a single JSON object**
65
66
  \`\`\`bash
66
- ${getCommand('--json project list')}
67
+ ${getCommand('cloud sandbox create --input \'{"runtime":"bun:1","memory":"1Gi","network":true}\'')}
68
+ ${getCommand('cloud kv set --input \'{"namespace":"ns","key":"k","value":"v","ttl":300}\'')}
69
+ \`\`\`
70
+ JSON keys must be the **camelCase schema keys** shown by \`--describe\` output (not kebab-case flag names). For example, the flag \`--dry-run\` becomes \`dryRun\` in JSON. CLI flags take precedence over --input values.
71
+
72
+ 2. **Use \`--describe\` to introspect what a command accepts before calling it**
73
+ \`\`\`bash
74
+ ${getCommand('cloud sandbox create --describe')}
67
75
  \`\`\`
76
+ Returns the full command schema as JSON: arguments, options (with types), response shape, requirements, and examples. No authentication required.
68
77
 
69
- 2. **Use \`--explain\` before destructive operations**
78
+ 3. **Use \`--fields\` with \`--json\` to limit output and protect your context window**
70
79
  \`\`\`bash
71
- ${getCommand('--explain cloud deployment delete <id>')}
80
+ ${getCommand('--json --fields "id,name,status" cloud deployment list')}
72
81
  \`\`\`
82
+ Comma-separated field names, supports dot notation for nested fields (e.g., \`properties.title\`).
73
83
 
74
- 3. **Use \`--dry-run\` to test commands safely**
84
+ 4. **Always use \`--json\` for machine-readable output**
85
+ \`\`\`bash
86
+ ${getCommand('--json project list')}
87
+ \`\`\`
88
+
89
+ 5. **Use \`--dry-run\` to test commands safely before mutating**
75
90
  \`\`\`bash
76
91
  ${getCommand('--dry-run cloud deploy')}
77
92
  \`\`\`
78
93
 
79
- 4. **Check requirements before running commands**
94
+ 6. **Use \`--validate\` to check inputs without executing**
95
+ \`\`\`bash
96
+ ${getCommand('--validate cloud kv set --input \'{"namespace":"ns","key":"k","value":"v"}\'')}
97
+ \`\`\`
98
+
99
+ 7. **Check requirements before running commands**
80
100
  - Many commands require authentication (\`${getCommand('auth login')}\`)
81
101
  - Project commands require an \`agentuity.json\` file in the current directory
82
102
 
@@ -1226,6 +1226,11 @@ export const deploySubcommand = createSubcommand({
1226
1226
  });
1227
1227
  }
1228
1228
 
1229
+ // Trigger TLS certificate provisioning for custom domains (fire-and-forget)
1230
+ if (project.deployment?.domains?.length) {
1231
+ void domain.triggerTLSProvisioning(project.deployment.domains);
1232
+ }
1233
+
1229
1234
  // Write final report on success
1230
1235
  if (opts.reportFile) {
1231
1236
  await collector.forceWrite();
@@ -7,7 +7,6 @@ import { isJSONMode } from '../../../output';
7
7
  import {
8
8
  checkCustomDomainForDNS,
9
9
  isSuccess,
10
- isPending,
11
10
  isMissing,
12
11
  isMisconfigured,
13
12
  isError,
@@ -92,9 +91,6 @@ export const checkSubcommand = createSubcommand({
92
91
  status = tui.colorSuccess(`${tui.ICONS.success} Configured`);
93
92
  statusRaw = 'configured';
94
93
  success = true;
95
- } else if (isPending(r)) {
96
- status = tui.colorWarning('⏳ Pending');
97
- statusRaw = 'pending';
98
94
  } else if (isMisconfigured(r)) {
99
95
  status = tui.colorWarning(`${tui.ICONS.warning} ${r.misconfigured}`);
100
96
  statusRaw = 'misconfigured';
package/src/domain.ts CHANGED
@@ -14,14 +14,8 @@ interface DNSSuccess extends BaseDNSResult {
14
14
  success: true;
15
15
  }
16
16
 
17
- interface DNSPending extends BaseDNSResult {
18
- success: true;
19
- pending: true;
20
- }
21
-
22
17
  interface DNSMissing extends BaseDNSResult {
23
18
  success: false;
24
- pending: false;
25
19
  }
26
20
 
27
21
  interface DNSError extends BaseDNSResult {
@@ -34,27 +28,23 @@ interface DNSMisconfigured extends BaseDNSResult {
34
28
  misconfigured: string;
35
29
  }
36
30
 
37
- export type DNSResult = DNSSuccess | DNSPending | DNSMissing | DNSError | DNSMisconfigured;
38
- export type DNSFailed = DNSPending | DNSMissing | DNSError | DNSMisconfigured;
31
+ export type DNSResult = DNSSuccess | DNSMissing | DNSError | DNSMisconfigured;
32
+ export type DNSFailed = DNSMissing | DNSError | DNSMisconfigured;
39
33
 
40
34
  export function isMisconfigured(x: DNSResult): x is DNSMisconfigured {
41
35
  return 'misconfigured' in x && !!x.misconfigured;
42
36
  }
43
37
 
44
38
  export function isMissing(x: DNSResult): x is DNSMissing {
45
- return 'pending' in x && x.pending === false && 'success' in x && x.success === false;
39
+ return x.success === false && !('error' in x) && !('misconfigured' in x);
46
40
  }
47
41
 
48
42
  export function isError(x: DNSResult): x is DNSError {
49
43
  return 'error' in x && !!x.error;
50
44
  }
51
45
 
52
- export function isPending(x: DNSResult): x is DNSPending {
53
- return 'pending' in x && x.pending === true && x.success === true;
54
- }
55
-
56
46
  export function isSuccess(x: DNSResult): x is DNSSuccess {
57
- return x.success === true && !('pending' in x) && !('error' in x) && !('misconfigured' in x);
47
+ return x.success === true;
58
48
  }
59
49
 
60
50
  const timeoutMs = 5000;
@@ -95,30 +85,6 @@ async function fetchDNSRecord(name: string, type: string): Promise<string | null
95
85
  return records[0] ?? null;
96
86
  }
97
87
 
98
- /**
99
- * Check if a domain has a valid TLS certificate by making a HEAD request.
100
- * This also triggers Let's Encrypt certificate provisioning on first access.
101
- * Returns true if the TLS certificate is valid (any HTTP status code received).
102
- * Returns false if the certificate is not yet provisioned (timeout or TLS error).
103
- */
104
- async function checkTLSCertificate(domain: string): Promise<boolean> {
105
- try {
106
- await fetch(`https://${domain}`, {
107
- method: 'HEAD',
108
- signal: AbortSignal.timeout(timeoutMs),
109
- redirect: 'manual',
110
- // @ts-expect-error - cache is supported by Bun's fetch at runtime but missing from type definitions
111
- cache: 'no-store',
112
- });
113
- // Any HTTP response means TLS handshake succeeded and certificate is valid
114
- return true;
115
- } catch {
116
- // Timeout, TLS certificate error, connection refused, etc.
117
- // All indicate the certificate is not yet provisioned
118
- return false;
119
- }
120
- }
121
-
122
88
  const LOCAL_DNS = 'agentuity.io';
123
89
  const PRODUCTION_DNS = 'agentuity.run';
124
90
 
@@ -197,25 +163,14 @@ export async function checkCustomDomainForDNS(
197
163
 
198
164
  if (result) {
199
165
  if (result === proxy) {
200
- // DNS is correct — verify TLS certificate (also triggers Let's Encrypt provisioning)
201
- const tlsValid = await checkTLSCertificate(domain);
202
- if (tlsValid) {
203
- return {
204
- domain,
205
- target: proxy,
206
- aRecordTarget,
207
- recordType: 'CNAME',
208
- success: true,
209
- } as DNSSuccess;
210
- }
166
+ // DNS is correctly configured
211
167
  return {
212
168
  domain,
213
169
  target: proxy,
214
170
  aRecordTarget,
215
171
  recordType: 'CNAME',
216
172
  success: true,
217
- pending: true,
218
- } as DNSPending;
173
+ } as DNSSuccess;
219
174
  }
220
175
  return {
221
176
  domain,
@@ -278,25 +233,14 @@ export async function checkCustomDomainForDNS(
278
233
  if (domainARecords.length > 0) {
279
234
  const matching = domainARecords.some((a) => ionIPs.includes(a));
280
235
  if (matching) {
281
- // DNS is correct — verify TLS certificate (also triggers Let's Encrypt provisioning)
282
- const tlsValid = await checkTLSCertificate(domain);
283
- if (tlsValid) {
284
- return {
285
- domain,
286
- target: proxy,
287
- aRecordTarget,
288
- recordType: 'A',
289
- success: true,
290
- } as DNSSuccess;
291
- }
236
+ // DNS is correctly configured
292
237
  return {
293
238
  domain,
294
239
  target: proxy,
295
240
  aRecordTarget,
296
241
  recordType: 'A',
297
242
  success: true,
298
- pending: true,
299
- } as DNSPending;
243
+ } as DNSSuccess;
300
244
  }
301
245
  return {
302
246
  domain,
@@ -318,7 +262,6 @@ export async function checkCustomDomainForDNS(
318
262
  target: proxy,
319
263
  aRecordTarget,
320
264
  recordType: 'CNAME',
321
- pending: false,
322
265
  } as DNSMissing;
323
266
  })
324
267
  );
@@ -371,13 +314,6 @@ export async function promptForDNS(
371
314
  aRecordTarget: r.aRecordTarget,
372
315
  status: tui.colorWarning(`${tui.ICONS.error} ${r.misconfigured}`),
373
316
  });
374
- } else if (isPending(r)) {
375
- records.push({
376
- domain: r.domain,
377
- cnameTarget: r.target,
378
- aRecordTarget: r.aRecordTarget,
379
- status: tui.colorWarning('⌛️ Pending'),
380
- });
381
317
  } else if (isMissing(r)) {
382
318
  records.push({
383
319
  domain: r.domain,
@@ -420,3 +356,23 @@ export async function promptForDNS(
420
356
  break;
421
357
  }
422
358
  }
359
+
360
+ /**
361
+ * Trigger TLS certificate provisioning for custom domains by making HTTPS requests.
362
+ * This causes the Ion proxy to initiate Let's Encrypt certificate issuance.
363
+ * Fire-and-forget — failures are silently ignored since certs will be provisioned
364
+ * on first real request if this doesn't succeed.
365
+ */
366
+ export async function triggerTLSProvisioning(domains: string[]): Promise<void> {
367
+ await Promise.allSettled(
368
+ domains.map((domain) =>
369
+ fetch(`https://${domain}`, {
370
+ method: 'HEAD',
371
+ signal: AbortSignal.timeout(10000),
372
+ redirect: 'manual',
373
+ }).catch(() => {
374
+ // Silently ignore — cert will be provisioned on first real request
375
+ })
376
+ )
377
+ );
378
+ }
package/src/output.ts CHANGED
@@ -63,11 +63,56 @@ export function shouldDisableColors(options: GlobalOptions): boolean {
63
63
  return options.json === true || options.quiet === true || !isTTYLike();
64
64
  }
65
65
 
66
+ /**
67
+ * Filter data to only include specified fields.
68
+ * Supports dot notation for nested fields (e.g., "id,name,properties.title").
69
+ * For arrays, applies the filter to each element.
70
+ */
71
+ function filterFields(data: unknown, fields: string[]): unknown {
72
+ if (Array.isArray(data)) {
73
+ return data.map((item) => filterFields(item, fields));
74
+ }
75
+ if (data && typeof data === 'object') {
76
+ const result: Record<string, unknown> = {};
77
+ for (const field of fields) {
78
+ const parts = field.split('.');
79
+ let current: unknown = data;
80
+ let target: Record<string, unknown> = result;
81
+ for (let i = 0; i < parts.length; i++) {
82
+ const part = parts[i] as string;
83
+ if (
84
+ current &&
85
+ typeof current === 'object' &&
86
+ part in (current as Record<string, unknown>)
87
+ ) {
88
+ if (i === parts.length - 1) {
89
+ target[part] = (current as Record<string, unknown>)[part];
90
+ } else {
91
+ target[part] = target[part] || {};
92
+ target = target[part] as Record<string, unknown>;
93
+ current = (current as Record<string, unknown>)[part];
94
+ }
95
+ } else {
96
+ break; // path segment not found — stop traversal for this field
97
+ }
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ return data;
103
+ }
104
+
66
105
  /**
67
106
  * Output JSON to stdout (for agent consumption)
68
107
  */
69
108
  export function outputJSON(data: unknown): void {
70
- console.log(JSON.stringify(data, null, 2));
109
+ let output = data;
110
+ const options = getOutputOptions();
111
+ if (options?.fields) {
112
+ const fields = options.fields.split(',').map((f) => f.trim());
113
+ output = filterFields(output, fields);
114
+ }
115
+ console.log(JSON.stringify(output, null, 2));
71
116
  }
72
117
 
73
118
  /**
@@ -75,10 +75,41 @@ export interface CLISchema {
75
75
  commands: SchemaCommand[];
76
76
  }
77
77
 
78
+ /**
79
+ * Apply args, options, and response from a CommandSchemas to a SchemaCommand.
80
+ * Shared by both extractCommandSchema and extractSubcommandSchema.
81
+ */
82
+ function applySchemaFields(schema: SchemaCommand, schemas: CommandSchemas): void {
83
+ if (schemas.args) {
84
+ const parsedArgs = parseArgsSchema(schemas.args);
85
+ schema.arguments = parsedArgs.metadata.map((arg) => ({
86
+ name: arg.name,
87
+ type: arg.variadic ? 'array' : 'string',
88
+ required: !arg.optional,
89
+ variadic: arg.variadic,
90
+ }));
91
+ }
92
+
93
+ if (schemas.options) {
94
+ const parsedOptions = parseOptionsSchema(schemas.options);
95
+ schema.options = parsedOptions.map((opt) => ({
96
+ name: opt.name,
97
+ type: opt.type,
98
+ required: !opt.hasDefault,
99
+ default: opt.defaultValue,
100
+ description: opt.description,
101
+ }));
102
+ }
103
+
104
+ if (schemas.response) {
105
+ schema.response = z.toJSONSchema(schemas.response);
106
+ }
107
+ }
108
+
78
109
  /**
79
110
  * Extract schema information from a CommandDefinition
80
111
  */
81
- function extractCommandSchema(def: CommandDefinition): SchemaCommand {
112
+ export function extractCommandSchema(def: CommandDefinition): SchemaCommand {
82
113
  const schema: SchemaCommand = {
83
114
  name: def.name,
84
115
  description: def.description,
@@ -151,6 +182,14 @@ function extractCommandSchema(def: CommandDefinition): SchemaCommand {
151
182
  };
152
183
  }
153
184
 
185
+ // Extract args and options from schema if available
186
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
187
+ if ((def as any).schema) {
188
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
189
+ const schemas = (def as any).schema as CommandSchemas;
190
+ applySchemaFields(schema, schemas);
191
+ }
192
+
154
193
  // Extract subcommands recursively
155
194
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
156
195
  if ((def as any).subcommands) {
@@ -166,7 +205,7 @@ function extractCommandSchema(def: CommandDefinition): SchemaCommand {
166
205
  /**
167
206
  * Extract schema information from a SubcommandDefinition
168
207
  */
169
- function extractSubcommandSchema(def: SubcommandDefinition): SchemaCommand {
208
+ export function extractSubcommandSchema(def: SubcommandDefinition): SchemaCommand {
170
209
  const schema: SchemaCommand = {
171
210
  name: def.name,
172
211
  description: def.description,
@@ -249,31 +288,7 @@ function extractSubcommandSchema(def: SubcommandDefinition): SchemaCommand {
249
288
  // Extract args and options from schema if available
250
289
  if (d.schema) {
251
290
  const schemas = d.schema as CommandSchemas;
252
-
253
- if (schemas.args) {
254
- const parsedArgs = parseArgsSchema(schemas.args);
255
- schema.arguments = parsedArgs.metadata.map((arg) => ({
256
- name: arg.name,
257
- type: arg.variadic ? 'array' : 'string',
258
- required: !arg.optional,
259
- variadic: arg.variadic,
260
- }));
261
- }
262
-
263
- if (schemas.options) {
264
- const parsedOptions = parseOptionsSchema(schemas.options);
265
- schema.options = parsedOptions.map((opt) => ({
266
- name: opt.name,
267
- type: opt.type,
268
- required: !opt.hasDefault,
269
- default: opt.defaultValue,
270
- description: opt.description,
271
- }));
272
- }
273
-
274
- if (schemas.response) {
275
- schema.response = z.toJSONSchema(schemas.response);
276
- }
291
+ applySchemaFields(schema, schemas);
277
292
  }
278
293
 
279
294
  // Extract nested subcommands recursively
@@ -410,6 +425,26 @@ export function generateCLISchema(
410
425
  default: false,
411
426
  description: 'Validate arguments and options without executing',
412
427
  },
428
+ {
429
+ name: 'input',
430
+ type: 'string',
431
+ required: false,
432
+ description: 'Pass arguments and options as a JSON object (for agents)',
433
+ },
434
+ {
435
+ name: 'describe',
436
+ type: 'boolean',
437
+ required: false,
438
+ default: false,
439
+ description: 'Output command schema as JSON for agent introspection',
440
+ },
441
+ {
442
+ name: 'fields',
443
+ type: 'string',
444
+ required: false,
445
+ description:
446
+ 'Filter JSON output to specified fields (comma-separated, dot notation for nested)',
447
+ },
413
448
  ],
414
449
  commands: commands.map(extractCommandSchema),
415
450
  };
@@ -1,5 +1,16 @@
1
1
  import type { ZodType } from 'zod';
2
2
  import type { CommandSchemas } from './types';
3
+ import { StructuredError } from '@agentuity/core';
4
+
5
+ const InputJSONParseError = StructuredError('InputJSONParseError')<{
6
+ flag: string;
7
+ errorType: string;
8
+ }>();
9
+ const InputJSONTypeError = StructuredError('InputJSONTypeError')<{
10
+ flag: string;
11
+ expected: string;
12
+ actual: string;
13
+ }>();
3
14
 
4
15
  export interface ParsedArgs {
5
16
  names: string[];
@@ -394,7 +405,8 @@ export function buildValidationInput(
394
405
  schemas: CommandSchemas,
395
406
  rawArgs: unknown[],
396
407
  rawOptions: Record<string, unknown>,
397
- _options?: { usesStdin?: boolean }
408
+ _options?: { usesStdin?: boolean },
409
+ inputJson?: string
398
410
  ): { args: Record<string, unknown>; options: Record<string, unknown> } {
399
411
  const result = { args: {} as Record<string, unknown>, options: {} as Record<string, unknown> };
400
412
 
@@ -442,6 +454,47 @@ export function buildValidationInput(
442
454
  }
443
455
  }
444
456
 
457
+ // Merge --input JSON values: CLI flags take precedence over --input values
458
+ if (inputJson !== undefined) {
459
+ let parsed: Record<string, unknown>;
460
+ try {
461
+ parsed = JSON.parse(inputJson) as Record<string, unknown>;
462
+ } catch (e) {
463
+ throw new InputJSONParseError({
464
+ message: `Invalid JSON in --input flag: ${e instanceof Error ? e.message : String(e)}`,
465
+ flag: '--input',
466
+ errorType: 'json_parse',
467
+ });
468
+ }
469
+
470
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
471
+ throw new InputJSONTypeError({
472
+ message: `Invalid JSON in --input flag: expected a JSON object, got ${parsed === null ? 'null' : Array.isArray(parsed) ? 'array' : typeof parsed}`,
473
+ flag: '--input',
474
+ expected: 'object',
475
+ actual: parsed === null ? 'null' : Array.isArray(parsed) ? 'array' : typeof parsed,
476
+ });
477
+ }
478
+
479
+ if (schemas.args) {
480
+ const argsMeta = parseArgsSchema(schemas.args);
481
+ for (const name of argsMeta.names) {
482
+ if (result.args[name] === undefined && parsed[name] !== undefined) {
483
+ result.args[name] = parsed[name];
484
+ }
485
+ }
486
+ }
487
+
488
+ if (schemas.options) {
489
+ const optsMeta = parseOptionsSchema(schemas.options);
490
+ for (const opt of optsMeta) {
491
+ if (result.options[opt.name] === undefined && parsed[opt.name] !== undefined) {
492
+ result.options[opt.name] = parsed[opt.name];
493
+ }
494
+ }
495
+ }
496
+ }
497
+
445
498
  return result;
446
499
  }
447
500
 
@@ -453,9 +506,10 @@ export async function buildValidationInputAsync(
453
506
  schemas: CommandSchemas,
454
507
  rawArgs: unknown[],
455
508
  rawOptions: Record<string, unknown>,
456
- options?: { usesStdin?: boolean }
509
+ options?: { usesStdin?: boolean },
510
+ inputJson?: string
457
511
  ): Promise<{ args: Record<string, unknown>; options: Record<string, unknown> }> {
458
- const result = buildValidationInput(schemas, rawArgs, rawOptions, options);
512
+ const result = buildValidationInput(schemas, rawArgs, rawOptions, options, inputJson);
459
513
 
460
514
  // Check for stdin confirmation if:
461
515
  // 1. Command has a confirm option in schema
package/src/types.ts CHANGED
@@ -310,6 +310,9 @@ export interface GlobalOptions {
310
310
  dryRun?: boolean;
311
311
  validate?: boolean;
312
312
  skipVersionCheck?: boolean;
313
+ input?: string;
314
+ describe?: boolean;
315
+ fields?: string;
313
316
  }
314
317
 
315
318
  export interface PaginationInfo {