dataiku-sdk 3.1.0 → 3.3.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 (149) hide show
  1. package/README.md +253 -38
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +102 -0
  4. package/dist/packages/types/src/index.js +76 -0
  5. package/dist/src/auth.js +1 -1
  6. package/dist/src/cli/coerce.js +11 -2
  7. package/dist/src/cli/commands/analysis.js +4 -3
  8. package/dist/src/cli/commands/api-service.js +5 -3
  9. package/dist/src/cli/commands/app.js +61 -18
  10. package/dist/src/cli/commands/bundle.js +3 -2
  11. package/dist/src/cli/commands/code-env.js +23 -16
  12. package/dist/src/cli/commands/connection.d.ts +9 -0
  13. package/dist/src/cli/commands/connection.js +267 -1
  14. package/dist/src/cli/commands/dashboard.js +7 -6
  15. package/dist/src/cli/commands/data-collection.d.ts +2 -0
  16. package/dist/src/cli/commands/data-collection.js +164 -0
  17. package/dist/src/cli/commands/data-quality.js +9 -8
  18. package/dist/src/cli/commands/dataset.js +170 -40
  19. package/dist/src/cli/commands/doctor.js +4 -2
  20. package/dist/src/cli/commands/flow-zone.js +9 -8
  21. package/dist/src/cli/commands/folder.js +9 -8
  22. package/dist/src/cli/commands/future.js +4 -3
  23. package/dist/src/cli/commands/group.d.ts +2 -0
  24. package/dist/src/cli/commands/group.js +109 -0
  25. package/dist/src/cli/commands/index.js +151 -78
  26. package/dist/src/cli/commands/insight.js +8 -7
  27. package/dist/src/cli/commands/job.js +4 -3
  28. package/dist/src/cli/commands/knowledge-bank.d.ts +2 -0
  29. package/dist/src/cli/commands/knowledge-bank.js +80 -0
  30. package/dist/src/cli/commands/llm.d.ts +2 -0
  31. package/dist/src/cli/commands/llm.js +93 -0
  32. package/dist/src/cli/commands/macro.d.ts +2 -0
  33. package/dist/src/cli/commands/macro.js +221 -0
  34. package/dist/src/cli/commands/meaning.js +5 -4
  35. package/dist/src/cli/commands/ml-task.js +21 -8
  36. package/dist/src/cli/commands/model-evaluation-store.js +4 -3
  37. package/dist/src/cli/commands/notebook.js +17 -12
  38. package/dist/src/cli/commands/plugin.d.ts +2 -0
  39. package/dist/src/cli/commands/plugin.js +799 -0
  40. package/dist/src/cli/commands/project-folder.d.ts +2 -0
  41. package/dist/src/cli/commands/project-folder.js +197 -0
  42. package/dist/src/cli/commands/project-git.js +14 -54
  43. package/dist/src/cli/commands/project-library.js +7 -6
  44. package/dist/src/cli/commands/project.js +55 -8
  45. package/dist/src/cli/commands/recipe.js +50 -14
  46. package/dist/src/cli/commands/saved-model.d.ts +5 -0
  47. package/dist/src/cli/commands/saved-model.js +392 -4
  48. package/dist/src/cli/commands/scenario.js +147 -9
  49. package/dist/src/cli/commands/sql.js +3 -2
  50. package/dist/src/cli/commands/statistics.js +7 -6
  51. package/dist/src/cli/commands/user.d.ts +8 -0
  52. package/dist/src/cli/commands/user.js +296 -0
  53. package/dist/src/cli/commands/variable.js +2 -1
  54. package/dist/src/cli/commands/webapp.js +2 -1
  55. package/dist/src/cli/commands/wiki.js +7 -6
  56. package/dist/src/cli/contract.d.ts +2 -3
  57. package/dist/src/cli/contract.js +1167 -163
  58. package/dist/src/cli/flags.d.ts +4 -0
  59. package/dist/src/cli/flags.js +50 -2
  60. package/dist/src/cli/helpers/app-successor.d.ts +19 -4
  61. package/dist/src/cli/helpers/app-successor.js +90 -30
  62. package/dist/src/cli/helpers/cleanup.js +3 -1
  63. package/dist/src/cli/helpers/flow-zone.js +1 -2
  64. package/dist/src/cli/output.d.ts +1 -1
  65. package/dist/src/cli/output.js +23 -10
  66. package/dist/src/cli/usage.d.ts +1 -0
  67. package/dist/src/cli/usage.js +47 -1
  68. package/dist/src/cli.js +225 -95
  69. package/dist/src/client.d.ts +86 -6
  70. package/dist/src/client.js +263 -50
  71. package/dist/src/errors.d.ts +3 -0
  72. package/dist/src/errors.js +4 -0
  73. package/dist/src/index.d.ts +16 -7
  74. package/dist/src/index.js +11 -2
  75. package/dist/src/resources/analyses.js +1 -8
  76. package/dist/src/resources/applications.d.ts +8 -6
  77. package/dist/src/resources/applications.js +21 -21
  78. package/dist/src/resources/base.d.ts +4 -0
  79. package/dist/src/resources/base.js +15 -0
  80. package/dist/src/resources/bundles.d.ts +9 -4
  81. package/dist/src/resources/bundles.js +10 -5
  82. package/dist/src/resources/connections.d.ts +78 -1
  83. package/dist/src/resources/connections.js +132 -1
  84. package/dist/src/resources/data-collections.d.ts +118 -0
  85. package/dist/src/resources/data-collections.js +49 -0
  86. package/dist/src/resources/datasets.d.ts +69 -0
  87. package/dist/src/resources/datasets.js +99 -1
  88. package/dist/src/resources/folders.js +2 -1
  89. package/dist/src/resources/futures.d.ts +4 -1
  90. package/dist/src/resources/futures.js +38 -6
  91. package/dist/src/resources/groups.d.ts +47 -0
  92. package/dist/src/resources/groups.js +56 -0
  93. package/dist/src/resources/jobs.d.ts +8 -13
  94. package/dist/src/resources/jobs.js +41 -16
  95. package/dist/src/resources/knowledge-banks.d.ts +58 -0
  96. package/dist/src/resources/knowledge-banks.js +61 -0
  97. package/dist/src/resources/llms.d.ts +92 -0
  98. package/dist/src/resources/llms.js +62 -0
  99. package/dist/src/resources/macros.d.ts +121 -0
  100. package/dist/src/resources/macros.js +231 -0
  101. package/dist/src/resources/ml-tasks.d.ts +37 -2
  102. package/dist/src/resources/ml-tasks.js +100 -20
  103. package/dist/src/resources/model-evaluation-stores.js +1 -8
  104. package/dist/src/resources/notebooks.d.ts +43 -7
  105. package/dist/src/resources/notebooks.js +53 -13
  106. package/dist/src/resources/plugins.d.ts +265 -0
  107. package/dist/src/resources/plugins.js +458 -0
  108. package/dist/src/resources/project-folders.d.ts +71 -0
  109. package/dist/src/resources/project-folders.js +57 -0
  110. package/dist/src/resources/project-git.d.ts +6 -0
  111. package/dist/src/resources/project-git.js +69 -42
  112. package/dist/src/resources/project-library.d.ts +0 -1
  113. package/dist/src/resources/project-library.js +1 -17
  114. package/dist/src/resources/projects.d.ts +19 -3
  115. package/dist/src/resources/projects.js +30 -18
  116. package/dist/src/resources/recipes.d.ts +15 -1
  117. package/dist/src/resources/recipes.js +73 -6
  118. package/dist/src/resources/saved-models.d.ts +134 -1
  119. package/dist/src/resources/saved-models.js +214 -6
  120. package/dist/src/resources/scenarios.d.ts +105 -0
  121. package/dist/src/resources/scenarios.js +232 -106
  122. package/dist/src/resources/sql.js +5 -1
  123. package/dist/src/resources/users.d.ts +129 -0
  124. package/dist/src/resources/users.js +128 -0
  125. package/dist/src/resources/webapps.d.ts +15 -2
  126. package/dist/src/resources/webapps.js +18 -4
  127. package/dist/src/schemas.d.ts +2 -2
  128. package/dist/src/schemas.js +1 -1
  129. package/dist/src/skill.d.ts +13 -4
  130. package/dist/src/skill.js +75 -24
  131. package/dist/src/utils/deep-merge.d.ts +1 -1
  132. package/dist/src/utils/polling.d.ts +20 -0
  133. package/dist/src/utils/polling.js +27 -0
  134. package/dist/src/utils/response-file.d.ts +2 -0
  135. package/dist/src/utils/response-file.js +34 -0
  136. package/dist/src/utils/secret-sanitize.d.ts +54 -0
  137. package/dist/src/utils/secret-sanitize.js +101 -0
  138. package/package.json +8 -5
  139. package/packages/types/dist/index.d.ts +102 -0
  140. package/packages/types/dist/index.js +76 -0
  141. package/plugin.json +1 -1
  142. package/skills/dataiku-dss/SKILL.md +47 -225
  143. package/skills/dataiku-dss/references/app-releases.md +28 -0
  144. package/skills/dataiku-dss/references/authentication.md +39 -0
  145. package/skills/dataiku-dss/references/coding.md +8 -0
  146. package/skills/dataiku-dss/references/discovery.md +30 -0
  147. package/skills/dataiku-dss/references/flow-maps.md +12 -0
  148. package/skills/dataiku-dss/references/mutations.md +33 -0
  149. package/skills/dataiku-dss/references/troubleshooting.md +29 -0
@@ -0,0 +1,221 @@
1
+ import { macroResultMaxBytes, } from "../../resources/macros.js";
2
+ import { jsonInput, num, } from "../coerce.js";
3
+ import { executionMode, } from "../flags.js";
4
+ import { encodedProjectEndpoint, } from "../output.js";
5
+ import { requireArgs, UsageError, } from "../usage.js";
6
+ const MACRO_RUN_USAGE = "dss macro run <macro_id> [--wait] [--timeout MS (default 120000)] [--poll-interval MS] [--data JSON] [--dry-run] [--project-key KEY]";
7
+ /**
8
+ * Flags accepted by run/run-and-wait; validated identically for live, dry-run,
9
+ * and --plan so a plan that would fail cannot be "fixed" by dropping flags.
10
+ * Returns undefined rather than a partial options object so callers can spread
11
+ * it only when the macro actually has parameters.
12
+ */
13
+ function macroWaitOptionsFromFlags(flags) {
14
+ const timeoutMs = num(flags["timeout"], "--timeout");
15
+ const pollIntervalMs = num(flags["poll-interval"], "--poll-interval");
16
+ if (timeoutMs !== undefined && timeoutMs < 0) {
17
+ throw new UsageError("--timeout must be >= 0.", "invalid_flag_value", undefined, {
18
+ flag: "--timeout",
19
+ });
20
+ }
21
+ if (pollIntervalMs !== undefined && pollIntervalMs < 1) {
22
+ throw new UsageError("--poll-interval must be >= 1.", "invalid_flag_value", undefined, { flag: "--poll-interval", });
23
+ }
24
+ return { timeoutMs, pollIntervalMs, };
25
+ }
26
+ /**
27
+ * Macro parameter payload from --data/--data-file/--stdin. The JSON object is
28
+ * passed through as the POST body: `{ "params": {...}, "adminParams": {...} }`.
29
+ * Values may carry credentials; the plan redacts nothing beyond DSS's own
30
+ * response echo, so callers must not log payloads.
31
+ */
32
+ function macroRunParamsFromFlags(flags) {
33
+ const input = jsonInput(flags);
34
+ if (input === undefined)
35
+ return {};
36
+ const body = {};
37
+ if (input["params"] !== undefined) {
38
+ if (input["params"] === null || typeof input["params"] !== "object") {
39
+ throw new UsageError("Macro run payload params must be an object keyed by macro parameter names.", "invalid_flag_value", undefined, { flag: "--data", });
40
+ }
41
+ body.params = input["params"];
42
+ }
43
+ if (input["adminParams"] !== undefined) {
44
+ if (input["adminParams"] === null || typeof input["adminParams"] !== "object") {
45
+ throw new UsageError("Macro run payload adminParams must be an object.", "invalid_flag_value", undefined, { flag: "--data", });
46
+ }
47
+ body.adminParams = input["adminParams"];
48
+ }
49
+ return body;
50
+ }
51
+ /** Exact POST body a run will send; empty object when no parameters. */
52
+ function macroRunDryRunPayload(runParams) {
53
+ const payload = {};
54
+ if (runParams.params !== undefined)
55
+ payload["params"] = runParams.params;
56
+ if (runParams.adminParams !== undefined)
57
+ payload["adminParams"] = runParams.adminParams;
58
+ return payload;
59
+ }
60
+ /**
61
+ * Reject blank/whitespace positional ids as a usage error BEFORE any request:
62
+ * an empty macro/run id would hit the list route or an unresolvable path.
63
+ */
64
+ function requireNotBlankId(value, usage) {
65
+ if (value.trim().length === 0) {
66
+ throw new UsageError(`Macro/run id must be non-empty. Usage: ${usage}`);
67
+ }
68
+ }
69
+ export const macroCommands = {
70
+ list: {
71
+ handler: (c, _a, f) => c.macros.list(f["project-key"]),
72
+ usage: "dss macro list [--project-key KEY]",
73
+ description: "List the macros (runnables) available in a project.",
74
+ examples: ["dss macro list",],
75
+ },
76
+ get: {
77
+ handler: (c, a, f) => {
78
+ requireArgs(a, 1, "dss macro get <macro_id>");
79
+ requireNotBlankId(a[0], "dss macro get <macro_id>");
80
+ return c.macros.definition(a[0], {
81
+ projectKey: f["project-key"],
82
+ });
83
+ },
84
+ usage: "dss macro get <macro_id> [--project-key KEY]",
85
+ description: "Get a macro's definition: parameters, result type, owning plugin, labels.",
86
+ examples: ["dss macro get compute_orders",],
87
+ },
88
+ run: {
89
+ handler: async (c, a, f) => {
90
+ requireArgs(a, 1, "dss macro run <macro_id>");
91
+ const pk = f["project-key"];
92
+ const waitOptions = macroWaitOptionsFromFlags(f);
93
+ const runParams = macroRunParamsFromFlags(f);
94
+ if (executionMode(f).dryRun) {
95
+ return {
96
+ dryRun: true,
97
+ action: "run",
98
+ resource: "macro",
99
+ id: a[0],
100
+ ...waitOptions,
101
+ ...(runParams.params !== undefined ? { params: runParams.params, } : {}),
102
+ ...(runParams.adminParams !== undefined
103
+ ? { adminParams: runParams.adminParams, }
104
+ : {}),
105
+ endpoint: encodedProjectEndpoint(c, pk, `/runnables/${encodeURIComponent(a[0])}?wait=false`),
106
+ method: "POST",
107
+ payload: macroRunDryRunPayload(runParams),
108
+ warning: "Macro runs execute arbitrary plugin code on the DSS backend; review the macro definition before running.",
109
+ };
110
+ }
111
+ if (f["wait"] === true) {
112
+ return c.macros.runAndWait(a[0], {
113
+ ...waitOptions,
114
+ ...runParams,
115
+ projectKey: pk,
116
+ });
117
+ }
118
+ return c.macros.run(a[0], { ...runParams, projectKey: pk, });
119
+ },
120
+ usage: MACRO_RUN_USAGE,
121
+ description: "Start a macro run. Macros execute arbitrary plugin code and are classified destructive. --wait polls to completion and exits 4 on failure; without it only the runId is returned. --data JSON may carry { params: {...}, adminParams: {...} } for parameterized macros.",
122
+ examples: [
123
+ "dss macro run compute_orders",
124
+ "dss macro run compute_orders --wait",
125
+ 'dss macro run compute_orders --data \'{"params":{"region":"EU"}}\'',
126
+ "dss macro run compute_orders --wait --timeout 300000",
127
+ ],
128
+ },
129
+ "run-and-wait": {
130
+ handler: async (c, a, f) => {
131
+ requireArgs(a, 1, "dss macro run-and-wait <macro_id>");
132
+ const pk = f["project-key"];
133
+ const waitOptions = macroWaitOptionsFromFlags(f);
134
+ const runParams = macroRunParamsFromFlags(f);
135
+ if (executionMode(f).dryRun) {
136
+ return {
137
+ dryRun: true,
138
+ action: "run-and-wait",
139
+ resource: "macro",
140
+ id: a[0],
141
+ ...waitOptions,
142
+ ...(runParams.params !== undefined ? { params: runParams.params, } : {}),
143
+ ...(runParams.adminParams !== undefined
144
+ ? { adminParams: runParams.adminParams, }
145
+ : {}),
146
+ endpoint: encodedProjectEndpoint(c, pk, `/runnables/${encodeURIComponent(a[0])}?wait=false`),
147
+ method: "POST",
148
+ payload: macroRunDryRunPayload(runParams),
149
+ warning: "Macro runs execute arbitrary plugin code on the DSS backend; review the macro definition before running.",
150
+ };
151
+ }
152
+ return c.macros.runAndWait(a[0], {
153
+ ...waitOptions,
154
+ ...runParams,
155
+ projectKey: pk,
156
+ });
157
+ },
158
+ usage: "dss macro run-and-wait <macro_id> [--timeout MS (default 120000)] [--poll-interval MS] [--data JSON] [--dry-run] [--project-key KEY]",
159
+ description: "Run a macro and poll its state until it finishes. Exits 4 on failure; returns { success: false, timedOut: true } on timeout.",
160
+ examples: [
161
+ "dss macro run-and-wait compute_orders",
162
+ "dss macro run-and-wait compute_orders --timeout 60000 --poll-interval 500",
163
+ ],
164
+ },
165
+ abort: {
166
+ handler: async (c, a, f) => {
167
+ requireArgs(a, 2, "dss macro abort <macro_id> <run_id>");
168
+ requireNotBlankId(a[0], "dss macro abort <macro_id> <run_id>");
169
+ requireNotBlankId(a[1], "dss macro abort <macro_id> <run_id>");
170
+ const pk = f["project-key"];
171
+ if (executionMode(f).dryRun) {
172
+ return {
173
+ dryRun: true,
174
+ action: "abort",
175
+ resource: "macro",
176
+ id: a[0],
177
+ runId: a[1],
178
+ endpoint: encodedProjectEndpoint(c, pk, `/runnables/${encodeURIComponent(a[0])}/abort/${encodeURIComponent(a[1])}`),
179
+ method: "POST",
180
+ };
181
+ }
182
+ await c.macros.abort(a[0], a[1], pk);
183
+ return { aborted: a[1], runId: a[1], resource: "macro", };
184
+ },
185
+ usage: "dss macro abort <macro_id> <run_id> [--dry-run] [--project-key KEY]",
186
+ description: "Request abort of a running macro run.",
187
+ examples: ["dss macro abort compute_orders run_42",],
188
+ },
189
+ state: {
190
+ handler: (c, a, f) => {
191
+ requireArgs(a, 2, "dss macro state <macro_id> <run_id>");
192
+ requireNotBlankId(a[0], "dss macro state <macro_id> <run_id>");
193
+ requireNotBlankId(a[1], "dss macro state <macro_id> <run_id>");
194
+ return c.macros.state(a[0], a[1], {
195
+ projectKey: f["project-key"],
196
+ });
197
+ },
198
+ usage: "dss macro state <macro_id> <run_id> [--project-key KEY]",
199
+ description: "Get the poll state of a macro run: running flag, progress stack, failure details.",
200
+ examples: ["dss macro state compute_orders run_42",],
201
+ },
202
+ result: {
203
+ handler: async (c, a, f) => {
204
+ requireArgs(a, 2, "dss macro result <macro_id> <run_id>");
205
+ requireNotBlankId(a[0], "dss macro result <macro_id> <run_id>");
206
+ requireNotBlankId(a[1], "dss macro result <macro_id> <run_id>");
207
+ const pk = f["project-key"];
208
+ const maxBytes = num(f["max-bytes"], "--max-bytes");
209
+ if (maxBytes !== undefined && (maxBytes < 1 || !Number.isInteger(maxBytes))) {
210
+ throw new UsageError("--max-bytes must be a positive integer.", "invalid_flag_value", undefined, { flag: "--max-bytes", });
211
+ }
212
+ return c.macros.result(a[0], a[1], {
213
+ projectKey: pk,
214
+ maxBytes: macroResultMaxBytes(maxBytes),
215
+ });
216
+ },
217
+ usage: "dss macro result <macro_id> <run_id> [--max-bytes N (default 8388608)] [--project-key KEY]",
218
+ description: "Download a macro run's result. Text/HTML bodies print as a JSON string (stdout stays one JSON document, embedded newlines escaped); JSON bodies print as the parsed object.",
219
+ examples: ["dss macro result compute_orders run_42", "dss macro result m r --max-bytes 1024",],
220
+ },
221
+ };
@@ -1,4 +1,5 @@
1
1
  import { jsonInput, requiredJsonInput, } from "../coerce.js";
2
+ import { executionMode, } from "../flags.js";
2
3
  import { isNotFoundError, planResult, skipResult, } from "../output.js";
3
4
  import { requireArgs, } from "../usage.js";
4
5
  const MEANING_PLAN_FAILURE_CODES = { usage: 1, error: 2, transient: 3, };
@@ -40,7 +41,7 @@ export const meaningCommands = {
40
41
  requireArgs(a, 3, "dss meaning create <id> <label> <type> [--data JSON|--data-file PATH|--stdin] [--dry-run]");
41
42
  const body = jsonInput(f) ?? {};
42
43
  const payload = meaningCreatePayload(a[0], a[1], a[2], body);
43
- if (f["dry-run"] === true) {
44
+ if (executionMode(f).dryRun) {
44
45
  return planResult("meaning", "create", {
45
46
  asyncKind: "none",
46
47
  method: "POST",
@@ -62,7 +63,7 @@ export const meaningCommands = {
62
63
  handler: async (c, a, f) => {
63
64
  requireArgs(a, 1, "dss meaning update <meaningId> (--data JSON|--data-file PATH|--stdin) [--dry-run]");
64
65
  const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (meaning definition).");
65
- if (f["dry-run"] === true) {
66
+ if (executionMode(f).dryRun) {
66
67
  return planResult("meaning", "update", {
67
68
  asyncKind: "none",
68
69
  method: "PUT",
@@ -83,7 +84,7 @@ export const meaningCommands = {
83
84
  delete: {
84
85
  handler: async (c, a, f) => {
85
86
  requireArgs(a, 1, "dss meaning delete <meaningId>");
86
- if (f["dry-run"] === true || f["if-exists"] === true) {
87
+ if (executionMode(f).dryRun || f["if-exists"] === true) {
87
88
  const current = await c.meanings.get(a[0]).catch((error) => {
88
89
  if (isNotFoundError(error)
89
90
  || (error instanceof Error && /unknown meaning/i.test(error.message))) {
@@ -93,7 +94,7 @@ export const meaningCommands = {
93
94
  });
94
95
  if (!current)
95
96
  return skipResult("meaning", a[0], "missing");
96
- if (f["dry-run"] === true) {
97
+ if (executionMode(f).dryRun) {
97
98
  return planResult("meaning", "delete", {
98
99
  asyncKind: "none",
99
100
  method: "DELETE",
@@ -1,4 +1,5 @@
1
- import { requiredJsonInput, requiredStringFlag, } from "../coerce.js";
1
+ import { num, requiredJsonInput, requiredStringFlag, } from "../coerce.js";
2
+ import { executionMode, } from "../flags.js";
2
3
  import { requireArgs, UsageError, } from "../usage.js";
3
4
  function optionalStringFlag(flags, name) {
4
5
  const value = flags[name];
@@ -77,21 +78,33 @@ export const mlTaskCommands = {
77
78
  ],
78
79
  },
79
80
  train: {
80
- handler: (c, a, f) => {
81
- requireArgs(a, 2, "dss ml-task train <analysisId> <mlTaskId> [--session-name NAME] [--wait] [--project-key KEY]");
81
+ handler: async (c, a, f) => {
82
+ const usage = "dss ml-task train <analysisId> <mlTaskId> [--session-name NAME] [--wait] [--timeout MS] [--poll-interval MS] [--dry-run] [--project-key KEY]";
83
+ requireArgs(a, 2, usage);
82
84
  const options = {
83
85
  analysisId: a[0],
84
86
  mlTaskId: a[1],
85
87
  sessionName: optionalStringFlag(f, "session-name"),
86
88
  wait: f["wait"] === true,
89
+ timeoutMs: num(f["timeout"], "--timeout"),
90
+ pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
87
91
  projectKey: f["project-key"],
88
92
  };
93
+ if (executionMode(f).dryRun) {
94
+ return {
95
+ dryRun: true,
96
+ action: "train",
97
+ resource: "ml-task",
98
+ ...options,
99
+ };
100
+ }
89
101
  return c.mlTasks.train(options);
90
102
  },
91
- usage: "dss ml-task train <analysisId> <mlTaskId> [--session-name NAME] [--wait] [--project-key KEY]",
92
- description: "Start ML task training, optionally waiting for trained model IDs.",
103
+ usage: "dss ml-task train <analysisId> <mlTaskId> [--session-name NAME] [--wait] [--timeout MS] [--poll-interval MS] [--dry-run] [--project-key KEY]",
104
+ description: "Start ML task training, optionally waiting for trained model IDs. --timeout bounds only the wait phase after DSS accepts training; an invalid timeout fails before any request.",
93
105
  examples: [
94
- "dss ml-task train ANALYSIS_ID TASK_ID --session-name baseline --wait --project-key PROJECT",
106
+ "dss ml-task train ANALYSIS_ID TASK_ID --session-name baseline --wait --timeout 60000 --project-key PROJECT",
107
+ "dss ml-task train ANALYSIS_ID TASK_ID --wait --timeout 0 --poll-interval 1000 --project-key PROJECT",
95
108
  ],
96
109
  },
97
110
  "list-models": {
@@ -127,7 +140,7 @@ export const mlTaskCommands = {
127
140
  testDatasetRef: optionalStringFlag(f, "test-dataset"),
128
141
  projectKey: f["project-key"],
129
142
  };
130
- if (f["dry-run"] === true) {
143
+ if (executionMode(f).dryRun) {
131
144
  return {
132
145
  dryRun: true,
133
146
  action: "deploy",
@@ -148,7 +161,7 @@ export const mlTaskCommands = {
148
161
  handler: async (c, a, f) => {
149
162
  requireArgs(a, 2, "dss ml-task delete <analysisId> <mlTaskId> [--dry-run] [--project-key KEY]");
150
163
  const projectKey = f["project-key"];
151
- if (f["dry-run"] === true) {
164
+ if (executionMode(f).dryRun) {
152
165
  return {
153
166
  dryRun: true,
154
167
  action: "delete",
@@ -1,4 +1,5 @@
1
1
  import { requiredStringFlag, } from "../coerce.js";
2
+ import { executionMode, } from "../flags.js";
2
3
  import { readIfExists, skipResult, } from "../output.js";
3
4
  import { requireArgs, } from "../usage.js";
4
5
  export const modelEvaluationStoreCommands = {
@@ -23,7 +24,7 @@ export const modelEvaluationStoreCommands = {
23
24
  const name = requiredStringFlag(f, "name", usage);
24
25
  const projectKey = f["project-key"];
25
26
  const options = { name, projectKey, };
26
- if (f["dry-run"] === true) {
27
+ if (executionMode(f).dryRun) {
27
28
  return {
28
29
  dryRun: true,
29
30
  action: "create",
@@ -56,11 +57,11 @@ export const modelEvaluationStoreCommands = {
56
57
  handler: async (c, a, f) => {
57
58
  requireArgs(a, 1, "dss model-evaluation-store delete <storeId> [--if-exists] [--dry-run] [--project-key KEY]");
58
59
  const projectKey = f["project-key"];
59
- if (f["dry-run"] === true || f["if-exists"] === true) {
60
+ if (executionMode(f).dryRun || f["if-exists"] === true) {
60
61
  const current = await readIfExists(() => c.modelEvaluationStores.get(a[0], projectKey));
61
62
  if (!current)
62
63
  return skipResult("model-evaluation-store", a[0], "missing");
63
- if (f["dry-run"] === true) {
64
+ if (executionMode(f).dryRun) {
64
65
  return {
65
66
  dryRun: true,
66
67
  action: "delete",
@@ -1,4 +1,5 @@
1
1
  import { jsonInput, num, parseBooleanOption, } from "../coerce.js";
2
+ import { executionMode, } from "../flags.js";
2
3
  import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
3
4
  import { requireArgs, requireNoArgs, UsageError, } from "../usage.js";
4
5
  export const notebookCommands = {
@@ -26,11 +27,11 @@ export const notebookCommands = {
26
27
  handler: async (c, a, f) => {
27
28
  requireArgs(a, 1, "dss notebook delete-jupyter <name>");
28
29
  const pk = f["project-key"];
29
- if (f["dry-run"] === true || f["if-exists"] === true) {
30
+ if (executionMode(f).dryRun || f["if-exists"] === true) {
30
31
  const current = await readIfExists(() => c.notebooks.getJupyter(a[0], pk));
31
32
  if (!current)
32
33
  return skipResult("jupyter-notebook", a[0], "missing");
33
- if (f["dry-run"] === true) {
34
+ if (executionMode(f).dryRun) {
34
35
  return { dryRun: true, action: "delete", resource: "jupyter-notebook", name: a[0], current, };
35
36
  }
36
37
  }
@@ -45,7 +46,7 @@ export const notebookCommands = {
45
46
  handler: async (c, a, f) => {
46
47
  requireArgs(a, 1, "dss notebook clear-jupyter-outputs <name>");
47
48
  const pk = f["project-key"];
48
- if (f["dry-run"] === true) {
49
+ if (executionMode(f).dryRun) {
49
50
  // The real mutation is a single server-side DELETE of the
50
51
  // outputs endpoint, so the dry run can only report the current
51
52
  // content (read-only) and the exact request that would run; the
@@ -82,7 +83,7 @@ export const notebookCommands = {
82
83
  const pk = f["project-key"];
83
84
  if (f["all"] === true) {
84
85
  requireNoArgs(a, "dss notebook unload-jupyter --all [--dry-run] [--project-key KEY]");
85
- if (f["dry-run"] === true) {
86
+ if (executionMode(f).dryRun) {
86
87
  const planned = [];
87
88
  for (const notebook of await c.notebooks.listJupyter(pk, { active: true, })) {
88
89
  for (const session of await c.notebooks.listJupyterSessions(notebook.name, pk)) {
@@ -106,7 +107,7 @@ export const notebookCommands = {
106
107
  return { unloaded, resource: "jupyter-notebook", all: true, };
107
108
  }
108
109
  requireArgs(a, 2, "dss notebook unload-jupyter <name> <sessionId>");
109
- if (f["dry-run"] === true) {
110
+ if (executionMode(f).dryRun) {
110
111
  const sessions = await c.notebooks.listJupyterSessions(a[0], pk);
111
112
  const current = sessions.find((session) => session.sessionId === a[1]);
112
113
  return {
@@ -149,11 +150,11 @@ export const notebookCommands = {
149
150
  handler: async (c, a, f) => {
150
151
  requireArgs(a, 1, "dss notebook delete-sql <id>");
151
152
  const pk = f["project-key"];
152
- if (f["dry-run"] === true || f["if-exists"] === true) {
153
+ if (executionMode(f).dryRun || f["if-exists"] === true) {
153
154
  const current = await readIfExists(() => c.notebooks.getSql(a[0], pk));
154
155
  if (!current)
155
156
  return skipResult("sql-notebook", a[0], "missing");
156
- if (f["dry-run"] === true) {
157
+ if (executionMode(f).dryRun) {
157
158
  return { dryRun: true, action: "delete", resource: "sql-notebook", id: a[0], current, };
158
159
  }
159
160
  }
@@ -181,7 +182,7 @@ export const notebookCommands = {
181
182
  throw new UsageError("--data, --data-file, or --stdin is required (notebook JSON content).");
182
183
  }
183
184
  const pk = f["project-key"];
184
- if (f["dry-run"] === true) {
185
+ if (executionMode(f).dryRun) {
185
186
  const current = await readIfExists(() => c.notebooks.getJupyter(a[0], pk));
186
187
  return {
187
188
  dryRun: true,
@@ -217,7 +218,7 @@ export const notebookCommands = {
217
218
  throw new UsageError("--data, --data-file, or --stdin is required (SQL notebook content JSON).");
218
219
  }
219
220
  const pk = f["project-key"];
220
- if (f["dry-run"] === true) {
221
+ if (executionMode(f).dryRun) {
221
222
  const current = await readIfExists(() => c.notebooks.getSql(a[0], pk));
222
223
  return {
223
224
  dryRun: true,
@@ -232,14 +233,18 @@ export const notebookCommands = {
232
233
  expectHash: f["expect-hash"],
233
234
  });
234
235
  return {
235
- saved: a[0],
236
+ // `saved` is the persisted notebook id: on create DSS allocates it
237
+ // server-side, so every later command must use this id. `requested`
238
+ // echoes the handle, which becomes the notebook's display name.
239
+ saved: result.id,
240
+ requested: a[0],
236
241
  resource: "sql-notebook",
237
242
  created: result.created,
238
243
  hash: result.hash,
239
244
  };
240
245
  },
241
246
  usage: "dss notebook save-sql <id> (--data '{...}' | --data-file PATH | --stdin) [--expect-hash SHA256] [--dry-run] [--project-key KEY]",
242
- description: "Save content to a SQL notebook, creating it if missing. Reports created versus updated and the persisted content hash; --expect-hash rejects a stale read before writing.",
247
+ description: "Save content to a SQL notebook, creating it if missing. On create DSS allocates the notebook id: `saved` is the persisted id to use for every later read/update/delete, and `requested` echoes the handle, which becomes the display name. Reports created versus updated and the persisted content hash; --expect-hash rejects a stale read before writing and refuses a missing notebook.",
243
248
  examples: ["dss notebook save-sql my_sql_notebook --data-file content.json --dry-run",],
244
249
  },
245
250
  "clear-sql-history": {
@@ -251,7 +256,7 @@ export const notebookCommands = {
251
256
  numRunsToRetain: num(f["retain"], "--retain"),
252
257
  projectKey: pk,
253
258
  };
254
- if (f["dry-run"] === true) {
259
+ if (executionMode(f).dryRun) {
255
260
  const current = await c.notebooks.getSqlHistory(a[0], pk);
256
261
  return {
257
262
  dryRun: true,
@@ -0,0 +1,2 @@
1
+ import type { CommandMeta } from "../types.js";
2
+ export declare const pluginCommands: Record<string, CommandMeta>;