dataiku-sdk 3.0.0 → 3.1.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.
Files changed (79) hide show
  1. package/README.md +132 -17
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +39 -4
  4. package/dist/packages/types/src/index.js +31 -2
  5. package/dist/src/cli/commands/api-service.js +62 -16
  6. package/dist/src/cli/commands/bundle.js +49 -15
  7. package/dist/src/cli/commands/code-env.js +210 -49
  8. package/dist/src/cli/commands/code.d.ts +19 -0
  9. package/dist/src/cli/commands/code.js +87 -15
  10. package/dist/src/cli/commands/dataset.js +8 -3
  11. package/dist/src/cli/commands/flow-zone.js +33 -5
  12. package/dist/src/cli/commands/notebook.js +72 -41
  13. package/dist/src/cli/commands/project-git.js +8 -5
  14. package/dist/src/cli/commands/project-library.d.ts +21 -0
  15. package/dist/src/cli/commands/project-library.js +121 -50
  16. package/dist/src/cli/commands/project.js +16 -2
  17. package/dist/src/cli/commands/recipe.js +37 -12
  18. package/dist/src/cli/commands/sql.d.ts +10 -0
  19. package/dist/src/cli/commands/sql.js +39 -17
  20. package/dist/src/cli/commands/webapp.js +67 -13
  21. package/dist/src/cli/contract.d.ts +15 -0
  22. package/dist/src/cli/contract.js +870 -107
  23. package/dist/src/cli/env.d.ts +9 -0
  24. package/dist/src/cli/env.js +20 -2
  25. package/dist/src/cli/flags.js +9 -0
  26. package/dist/src/cli/helpers/cleanup.js +104 -3
  27. package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
  28. package/dist/src/cli/helpers/flow-zone.js +33 -3
  29. package/dist/src/cli/helpers/recipe.d.ts +20 -0
  30. package/dist/src/cli/helpers/recipe.js +158 -3
  31. package/dist/src/cli/output.d.ts +2 -0
  32. package/dist/src/cli/output.js +33 -6
  33. package/dist/src/cli/runtime.d.ts +35 -1
  34. package/dist/src/cli/runtime.js +125 -18
  35. package/dist/src/cli/types.d.ts +7 -0
  36. package/dist/src/cli.js +135 -28
  37. package/dist/src/client.d.ts +60 -0
  38. package/dist/src/client.js +237 -42
  39. package/dist/src/errors.d.ts +8 -2
  40. package/dist/src/errors.js +40 -0
  41. package/dist/src/index.d.ts +4 -3
  42. package/dist/src/index.js +2 -1
  43. package/dist/src/resources/api-services.d.ts +48 -6
  44. package/dist/src/resources/api-services.js +54 -8
  45. package/dist/src/resources/bundles.d.ts +51 -6
  46. package/dist/src/resources/bundles.js +39 -9
  47. package/dist/src/resources/code-envs.d.ts +25 -3
  48. package/dist/src/resources/code-envs.js +104 -2
  49. package/dist/src/resources/datasets.d.ts +20 -0
  50. package/dist/src/resources/datasets.js +232 -52
  51. package/dist/src/resources/jobs.d.ts +35 -10
  52. package/dist/src/resources/jobs.js +92 -17
  53. package/dist/src/resources/notebooks.d.ts +77 -7
  54. package/dist/src/resources/notebooks.js +143 -19
  55. package/dist/src/resources/project-git.d.ts +12 -0
  56. package/dist/src/resources/project-git.js +39 -8
  57. package/dist/src/resources/project-library.d.ts +122 -7
  58. package/dist/src/resources/project-library.js +494 -25
  59. package/dist/src/resources/projects.d.ts +5 -2
  60. package/dist/src/resources/projects.js +18 -2
  61. package/dist/src/resources/scenarios.d.ts +30 -0
  62. package/dist/src/resources/scenarios.js +73 -27
  63. package/dist/src/resources/sql.d.ts +6 -0
  64. package/dist/src/resources/sql.js +22 -2
  65. package/dist/src/resources/webapps.d.ts +35 -4
  66. package/dist/src/resources/webapps.js +54 -5
  67. package/dist/src/schemas.d.ts +2 -2
  68. package/dist/src/schemas.js +1 -1
  69. package/dist/src/skill.d.ts +9 -0
  70. package/dist/src/skill.js +37 -4
  71. package/dist/src/utils/flow-analysis.d.ts +53 -0
  72. package/dist/src/utils/flow-analysis.js +382 -0
  73. package/dist/src/utils/project-archive.d.ts +41 -2
  74. package/dist/src/utils/project-archive.js +159 -16
  75. package/package.json +4 -4
  76. package/packages/types/dist/index.d.ts +39 -4
  77. package/packages/types/dist/index.js +31 -2
  78. package/plugin.json +1 -1
  79. package/skills/dataiku-dss/SKILL.md +74 -47
@@ -1,18 +1,42 @@
1
1
  import { readFileSync, } from "node:fs";
2
- import { mkdir, writeFile, } from "node:fs/promises";
2
+ import { writeFile, } from "node:fs/promises";
3
3
  import { join, } from "node:path";
4
4
  import { deepMerge, } from "../../utils/deep-merge.js";
5
5
  import { jobLogFilterFromFlag, jsonInput, maxLogLinesFromFlags, normalizeLineEndings, num, recipeInputDatasetsFromFlags, requiredStringFlag, rewritePairsFromFlags, sha256Hex, splitCsvFlag, stableHash, } from "../coerce.js";
6
6
  import { moveCreatedItemsToZone, resolveFlowZoneIdFromFlags, } from "../helpers/flow-zone.js";
7
- import { readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, } from "../helpers/recipe.js";
7
+ import { ensureRecipeBackupDir, readRecipeBackup, recipeBackupDocument, recipeBackupPath, recipeCodeEnv, recipeGraph, recipeInputItemRef, recipeRoleInputItems, recipeRunShouldWait, writeRecipeBackup, } from "../helpers/recipe.js";
8
8
  import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
9
9
  import { requireArgs, UsageError, } from "../usage.js";
10
+ /** Read a local recipe file before any DSS request, mapping read failures to usage validation. */
11
+ function readRecipeFile(filePath, flagName) {
12
+ try {
13
+ return readFileSync(filePath, "utf-8");
14
+ }
15
+ catch (error) {
16
+ const reason = error instanceof Error ? error.message : String(error);
17
+ throw new UsageError(`Could not read ${flagName} ${filePath}: ${reason}.`, "not_found", "Verify the file path and that it is readable.");
18
+ }
19
+ }
20
+ /** Read a set-payload backup file before any DSS request, mapping read failures to usage validation. */
21
+ function readRecipeBackupFile(backupPath) {
22
+ try {
23
+ return readRecipeBackup(backupPath);
24
+ }
25
+ catch (error) {
26
+ const reason = error instanceof Error ? error.message : String(error);
27
+ throw new UsageError(`Could not read --backup ${backupPath}: ${reason}.`, "not_found", "Verify the backup file path and that it is readable.");
28
+ }
29
+ }
10
30
  function formatLineDiff(remoteName, localPath, remoteContent, localContent) {
11
- if (localContent === remoteContent) {
31
+ // Line-ending differences are not content differences: compare and split on
32
+ // CRLF-normalized text, mirroring assert-unchanged's normalized payload hash.
33
+ const normalizedLocal = normalizeLineEndings(localContent);
34
+ const normalizedRemote = normalizeLineEndings(remoteContent);
35
+ if (normalizedLocal === normalizedRemote) {
12
36
  return "No differences.";
13
37
  }
14
- const localLines = localContent.split("\n");
15
- const remoteLines = remoteContent.split("\n");
38
+ const localLines = normalizedLocal.split("\n");
39
+ const remoteLines = normalizedRemote.split("\n");
16
40
  const lines = [`--- remote:${remoteName}`, `+++ local:${localPath}`, "",];
17
41
  const maxLen = Math.max(localLines.length, remoteLines.length);
18
42
  for (let i = 0; i < maxLen; i++) {
@@ -104,7 +128,7 @@ export const recipeCommands = {
104
128
  return c.recipes.run(a[0], options);
105
129
  },
106
130
  usage: "dss recipe run <name> [--wait|--no-wait] [--build-mode MODE] [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
107
- description: "Run a recipe by resolving its outputs and submitting the correct dataset or managed-folder build job.",
131
+ description: "Run a recipe by resolving its outputs and submitting the correct dataset or managed-folder build job. --timeout defaults to 120000 ms and --poll-interval to 2000 ms.",
108
132
  examples: [
109
133
  "dss recipe run compute_orders --wait",
110
134
  "dss recipe run compute_exports --include-logs --log-filter stdout --summary --timeout 600000",
@@ -344,6 +368,8 @@ export const recipeCommands = {
344
368
  if (!filePath) {
345
369
  throw new UsageError("--file is required. Usage: dss recipe diff <name> --file PATH");
346
370
  }
371
+ // Read and validate the local file before any DSS request.
372
+ const localContent = readRecipeFile(filePath, "--file");
347
373
  const result = await c.recipes.get(a[0], {
348
374
  includePayload: true,
349
375
  projectKey: f["project-key"],
@@ -351,7 +377,6 @@ export const recipeCommands = {
351
377
  if (!result.payload) {
352
378
  throw new Error(`Recipe "${a[0]}" has no code payload to diff.`);
353
379
  }
354
- const localContent = readFileSync(filePath, "utf-8");
355
380
  return formatLineDiff(a[0], filePath, result.payload, localContent);
356
381
  },
357
382
  usage: "dss recipe diff <name> --file PATH [--project-key KEY]",
@@ -506,7 +531,7 @@ export const recipeCommands = {
506
531
  const filePath = f["file"];
507
532
  if (!filePath)
508
533
  throw new UsageError("--file is required.");
509
- const content = readFileSync(filePath, "utf-8");
534
+ const content = readRecipeFile(filePath, "--file");
510
535
  const pk = f["project-key"];
511
536
  const shouldBackup = f["no-backup"] !== true;
512
537
  const backupDir = shouldBackup
@@ -530,8 +555,8 @@ export const recipeCommands = {
530
555
  };
531
556
  }
532
557
  if (backupDir && backupPath) {
533
- await mkdir(backupDir, { recursive: true, });
534
- await writeFile(backupPath, `${JSON.stringify(recipeBackupDocument(a[0], pk, current), null, 2)}\n`, "utf-8");
558
+ ensureRecipeBackupDir(backupDir);
559
+ writeRecipeBackup(backupPath, `${JSON.stringify(recipeBackupDocument(a[0], pk, current), null, 2)}\n`);
535
560
  }
536
561
  await c.recipes.replace(a[0], { ...current, payload: content, }, pk);
537
562
  return {
@@ -555,7 +580,7 @@ export const recipeCommands = {
555
580
  const usage = "dss recipe restore <name> --backup FILE [--payload-only] [--dry-run] [--project-key KEY]";
556
581
  requireArgs(a, 1, usage);
557
582
  const backupPath = requiredStringFlag(f, "backup", usage);
558
- const backup = readRecipeBackup(backupPath);
583
+ const backup = readRecipeBackupFile(backupPath);
559
584
  const payload = typeof backup.payload === "string" ? backup.payload : "";
560
585
  const pk = f["project-key"];
561
586
  const current = await c.recipes.get(a[0], { includePayload: true, projectKey: pk, });
@@ -598,7 +623,7 @@ export const recipeCommands = {
598
623
  const usage = "dss recipe assert-unchanged <name> --since BACKUP [--project-key KEY]";
599
624
  requireArgs(a, 1, usage);
600
625
  const backupPath = requiredStringFlag(f, "since", usage);
601
- const backup = readRecipeBackup(backupPath);
626
+ const backup = readRecipeBackupFile(backupPath);
602
627
  const current = await c.recipes.get(a[0], {
603
628
  includePayload: true,
604
629
  projectKey: f["project-key"],
@@ -1,2 +1,12 @@
1
1
  import type { CommandMeta } from "../types.js";
2
+ export declare function resolveSqlInput(args: string[], flags: Record<string, string | boolean>): string;
3
+ export interface SqlQueryInvocation {
4
+ query: string;
5
+ connection?: string;
6
+ datasetFullName?: string;
7
+ database?: string;
8
+ projectKey?: string;
9
+ type: "sql";
10
+ }
11
+ export declare function resolveSqlQueryInvocation(args: string[], flags: Record<string, string | boolean>, projectKeyOverride?: string): SqlQueryInvocation;
2
12
  export declare const sqlCommands: Record<string, CommandMeta>;
@@ -2,6 +2,7 @@ import { readFileSync, } from "node:fs";
2
2
  import { mkdir, writeFile, } from "node:fs/promises";
3
3
  import { dirname, resolve, } from "node:path";
4
4
  import { readStdinText, stripUtf8Bom, } from "../coerce.js";
5
+ import { enqueueCliWarning, } from "../output.js";
5
6
  import { UsageError, } from "../usage.js";
6
7
  const SQL_QUERY_USAGE = "dss sql query (SQL | --sql QUERY | --sql-file PATH | --sql - | --stdin) (--connection CONN | --dataset FULL_NAME) [--database DB] [--output PATH|--output-file PATH] [--preview N] [--start-retries N] [--request-timeout MS] [--project-key KEY]";
7
8
  const DEFAULT_SQL_PREVIEW_ROWS = 5;
@@ -34,7 +35,7 @@ function parseSqlStartRetries(value) {
34
35
  }
35
36
  return parsed;
36
37
  }
37
- function resolveSqlInput(args, flags) {
38
+ export function resolveSqlInput(args, flags) {
38
39
  const sources = [];
39
40
  if (typeof flags["sql"] === "string") {
40
41
  sources.push({
@@ -69,34 +70,55 @@ function resolveSqlInput(args, flags) {
69
70
  }
70
71
  return query;
71
72
  }
73
+ export function resolveSqlQueryInvocation(args, flags, projectKeyOverride) {
74
+ const connection = flags["connection"];
75
+ const datasetFullName = flags["dataset"];
76
+ if ((connection ? 1 : 0) + (datasetFullName ? 1 : 0) !== 1) {
77
+ throw new UsageError(`Pass exactly one of --connection or --dataset. Usage: ${SQL_QUERY_USAGE}`);
78
+ }
79
+ return {
80
+ query: resolveSqlInput(args, flags),
81
+ connection,
82
+ datasetFullName,
83
+ database: flags["database"],
84
+ projectKey: projectKeyOverride ?? flags["project-key"],
85
+ type: "sql",
86
+ };
87
+ }
72
88
  export const sqlCommands = {
73
89
  query: {
74
90
  handler: async (c, a, f) => {
75
- const connection = f["connection"];
76
- const datasetFullName = f["dataset"];
77
- if ((connection ? 1 : 0) + (datasetFullName ? 1 : 0) !== 1) {
78
- throw new UsageError(`Pass exactly one of --connection or --dataset. Usage: ${SQL_QUERY_USAGE}`);
79
- }
80
91
  const outputFile = f["output"]
81
92
  ?? f["output-file"];
82
93
  const previewProvided = f["preview"] !== undefined;
83
- if (previewProvided && !outputFile) {
84
- throw new UsageError(`--preview requires --output or --output-file. Usage: ${SQL_QUERY_USAGE}`, "validation_failed");
85
- }
86
94
  const previewCount = previewProvided
87
95
  ? parseSqlPreviewCount(f["preview"])
88
96
  : DEFAULT_SQL_PREVIEW_ROWS;
89
- const query = resolveSqlInput(a, f);
90
97
  const result = await c.sql.query({
91
- query,
92
- connection,
93
- datasetFullName,
94
- database: f["database"],
95
- projectKey: f["project-key"],
98
+ ...resolveSqlQueryInvocation(a, f),
96
99
  retryMaxAttempts: parseSqlStartRetries(f["start-retries"]),
97
100
  });
98
- if (!outputFile)
101
+ if (!outputFile && !previewProvided)
99
102
  return result;
103
+ if (!outputFile) {
104
+ const truncated = result.rows.length > previewCount;
105
+ if (truncated) {
106
+ enqueueCliWarning({
107
+ code: "sql_preview_truncated",
108
+ rowCount: result.rows.length,
109
+ previewRows: previewCount,
110
+ hint: "Use --output PATH to write the full result without placing it on stdout.",
111
+ });
112
+ }
113
+ return {
114
+ queryId: result.queryId,
115
+ schema: result.schema,
116
+ columns: result.columns ?? result.schema,
117
+ rowCount: result.rows.length,
118
+ preview: result.rows.slice(0, previewCount),
119
+ truncated,
120
+ };
121
+ }
100
122
  const outputPath = resolve(outputFile);
101
123
  await mkdir(dirname(outputPath), { recursive: true, });
102
124
  await writeFile(outputPath, `${JSON.stringify(result, null, 2)}\n`, "utf-8");
@@ -111,7 +133,7 @@ export const sqlCommands = {
111
133
  };
112
134
  },
113
135
  usage: SQL_QUERY_USAGE,
114
- description: "Run a SQL query against a DSS connection or dataset. --start-retries may execute the SQL more than once; use it only when repetition is safe.",
136
+ description: "Run potentially mutating SQL against a DSS connection or dataset. Use --preview N for bounded stdout or --output PATH for full rows. --start-retries may execute SQL more than once; use it only when repetition is safe.",
115
137
  examples: [
116
138
  "dss sql query 'SELECT * FROM orders LIMIT 10' --connection my_pg",
117
139
  "dss sql query --sql-file query.sql --connection my_pg",
@@ -1,5 +1,18 @@
1
- import { requiredJsonInput, } from "../coerce.js";
1
+ import { ClientValidationError, } from "../../errors.js";
2
+ import { deepMerge, } from "../../utils/deep-merge.js";
3
+ import { stableHash, } from "../../utils/stable-hash.js";
4
+ import { num, requiredJsonInput, } from "../coerce.js";
2
5
  import { requireArgs, } from "../usage.js";
6
+ const UPDATE_SETTINGS_USAGE = "dss webapp update-settings <webappId> (--data JSON|--data-file PATH|--stdin) [--expect-hash SHA256] [--dry-run] [--project-key KEY]";
7
+ const RESTART_USAGE = "dss webapp restart-backend <webappId> [--wait] [--timeout MS] [--poll-interval MS] [--project-key KEY]";
8
+ function validateExpectHash(value) {
9
+ if (value === undefined || value === false)
10
+ return undefined;
11
+ if (typeof value !== "string" || !/^[0-9a-fA-F]{64}$/.test(value)) {
12
+ throw new ClientValidationError("Expected webapp hash must be a 64-character SHA-256 hex digest.", "validation_failed", "Run this update with --dry-run and capture currentHash before retrying.");
13
+ }
14
+ return value;
15
+ }
3
16
  export const webappCommands = {
4
17
  list: {
5
18
  handler: (c, _a, f) => c.webapps.list(f["project-key"]),
@@ -26,14 +39,45 @@ export const webappCommands = {
26
39
  examples: ["dss webapp create --data-file webapp.json",],
27
40
  },
28
41
  "update-settings": {
29
- handler: (c, a, f) => {
30
- requireArgs(a, 1, "dss webapp update-settings <webappId> (--data JSON|--data-file PATH|--stdin) [--project-key KEY]");
42
+ handler: async (c, a, f) => {
43
+ requireArgs(a, 1, UPDATE_SETTINGS_USAGE);
31
44
  const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (webapp settings).");
32
- return c.webapps.updateSettings(a[0], body, f["project-key"]);
45
+ const projectKey = f["project-key"];
46
+ const expectHash = validateExpectHash(f["expect-hash"]);
47
+ if (f["dry-run"] === true) {
48
+ const current = await c.webapps.getSettings(a[0], projectKey);
49
+ const currentHash = stableHash(current);
50
+ if (expectHash !== undefined && currentHash !== expectHash.toLowerCase()) {
51
+ throw new ClientValidationError(`The webapp ${JSON.stringify(a[0])} changed since it was read.`, "validation_failed", "Re-read the webapp settings and retry with the current hash value.", {
52
+ id: a[0],
53
+ expectedHash: expectHash.toLowerCase(),
54
+ actualHash: currentHash,
55
+ });
56
+ }
57
+ const next = deepMerge(current, body);
58
+ return {
59
+ dryRun: true,
60
+ action: "update-settings",
61
+ resource: "webapp",
62
+ id: a[0],
63
+ current,
64
+ next,
65
+ currentHash,
66
+ nextHash: stableHash(next),
67
+ ...(expectHash !== undefined
68
+ ? { expectHash: expectHash.toLowerCase(), provenanceVerified: true, }
69
+ : {}),
70
+ };
71
+ }
72
+ const updated = await c.webapps.updateSettings(a[0], body, projectKey, { expectHash, });
73
+ return { updated: a[0], ...updated, };
33
74
  },
34
- usage: "dss webapp update-settings <webappId> (--data JSON|--data-file PATH|--stdin) [--project-key KEY]",
35
- description: "Replace a webapp's settings.",
36
- examples: ["dss webapp update-settings WEBAPP_ID --data-file webapp.json",],
75
+ usage: UPDATE_SETTINGS_USAGE,
76
+ description: "Merge supplied fields into a webapp's settings (GET-merge-PUT) and PUT the full object, so fields outside the patch are never dropped. --expect-hash refuses the write when the object changed since it was fetched; --dry-run reports current, next, and both hashes without writing.",
77
+ examples: [
78
+ "dss webapp update-settings WEBAPP_ID --data-file webapp.json",
79
+ 'dss webapp update-settings WEBAPP_ID --dry-run --data=\'{"params":{"designOptions":{"namingRule":"x"}}}\'',
80
+ ],
37
81
  },
38
82
  "stop-backend": {
39
83
  handler: async (c, a, f) => {
@@ -47,13 +91,23 @@ export const webappCommands = {
47
91
  },
48
92
  "restart-backend": {
49
93
  handler: async (c, a, f) => {
50
- requireArgs(a, 1, "dss webapp restart-backend <webappId> [--project-key KEY]");
51
- await c.webapps.startOrRestartBackend(a[0], f["project-key"]);
52
- return { restarted: true, };
94
+ requireArgs(a, 1, RESTART_USAGE);
95
+ const projectKey = f["project-key"];
96
+ if (f["wait"] === true) {
97
+ return c.webapps.restartBackendAndWait(a[0], projectKey, {
98
+ pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
99
+ timeoutMs: num(f["timeout"], "--timeout"),
100
+ });
101
+ }
102
+ const future = await c.webapps.startOrRestartBackend(a[0], projectKey);
103
+ return { restarted: true, future, };
53
104
  },
54
- usage: "dss webapp restart-backend <webappId> [--project-key KEY]",
55
- description: "Start or restart a webapp's backend.",
56
- examples: ["dss webapp restart-backend WEBAPP_ID",],
105
+ usage: RESTART_USAGE,
106
+ description: "Start or restart a webapp's backend. The documented endpoint returns a restart future; --wait settles it and returns the FutureWaitResult.",
107
+ examples: [
108
+ "dss webapp restart-backend WEBAPP_ID",
109
+ "dss webapp restart-backend WEBAPP_ID --wait --timeout=60000",
110
+ ],
57
111
  },
58
112
  "backend-state": {
59
113
  handler: (c, a, f) => {
@@ -32,6 +32,17 @@ export type CommandFlagMetadata = {
32
32
  aliases?: string[];
33
33
  allowEmptyValue?: boolean;
34
34
  };
35
+ export interface CommandPositionalMetadata {
36
+ name: string;
37
+ required: boolean;
38
+ }
39
+ export interface CommandRequiredInputAlternative {
40
+ flags?: string[];
41
+ positionals?: string[];
42
+ }
43
+ export interface CommandRequiredInputGroup {
44
+ oneOf: CommandRequiredInputAlternative[];
45
+ }
35
46
  export interface CommandStructuredExample {
36
47
  shell: string;
37
48
  argv?: string[];
@@ -57,6 +68,7 @@ export interface CommandRegistryEntry {
57
68
  structuredExamples: CommandStructuredExample[];
58
69
  flags: CommandFlagMetadata[];
59
70
  positionals: string[];
71
+ positionalArguments: CommandPositionalMetadata[];
60
72
  sideEffect: CommandSideEffect;
61
73
  requiresAuth: boolean;
62
74
  requiresProject: boolean;
@@ -70,6 +82,7 @@ export interface CommandRegistryEntry {
70
82
  dryRun: boolean;
71
83
  requiredFlags: string[];
72
84
  requiredOneOf?: CommandFlagChoice[];
85
+ requiredInputGroups?: CommandRequiredInputGroup[];
73
86
  optionalFlags: string[];
74
87
  payloadSchema?: CommandPayloadSchema;
75
88
  schemas: CommandAgentSchemas;
@@ -96,10 +109,12 @@ export declare function commandActionSummary(registry: Record<string, Record<str
96
109
  export declare function buildAgentContract(): Record<string, unknown>;
97
110
  export declare function commandPlanShape(resource: string, action: string, args: string[], flags: Record<string, string | boolean>, entry: CommandRegistryEntry, projectKey: string | undefined): {
98
111
  endpoint?: string;
112
+ exact?: boolean;
99
113
  identifiers?: Record<string, unknown>;
100
114
  method?: string;
101
115
  payload?: unknown;
102
116
  localWrites?: unknown;
117
+ reason?: string;
103
118
  wait?: unknown;
104
119
  requests?: unknown;
105
120
  };