dataiku-sdk 3.9.0 → 4.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.
- package/README.md +4 -3
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +6 -0
- package/dist/packages/types/src/index.js +6 -0
- package/dist/src/cli/coerce.d.ts +6 -0
- package/dist/src/cli/coerce.js +9 -0
- package/dist/src/cli/command-syntax.json +216 -0
- package/dist/src/cli/commands/app.js +2 -2
- package/dist/src/cli/commands/code-env.js +10 -9
- package/dist/src/cli/commands/code.js +16 -2
- package/dist/src/cli/commands/dashboard.js +1 -2
- package/dist/src/cli/commands/dataset.js +6 -4
- package/dist/src/cli/commands/flow-zone.js +1 -1
- package/dist/src/cli/commands/job.js +70 -16
- package/dist/src/cli/commands/plugin.js +7 -7
- package/dist/src/cli/commands/project-library.js +2 -2
- package/dist/src/cli/commands/project.js +21 -4
- package/dist/src/cli/commands/recipe.js +34 -21
- package/dist/src/cli/commands/scenario.js +78 -12
- package/dist/src/cli/contract.js +30 -7
- package/dist/src/cli/env.d.ts +6 -0
- package/dist/src/cli/env.js +10 -3
- package/dist/src/cli/helpers/app-permissions.d.ts +1 -1
- package/dist/src/cli/helpers/app-permissions.js +2 -2
- package/dist/src/cli/helpers/cleanup.d.ts +2 -0
- package/dist/src/cli/helpers/cleanup.js +122 -8
- package/dist/src/cli/helpers/flow-zone.d.ts +1 -1
- package/dist/src/cli/helpers/flow-zone.js +3 -4
- package/dist/src/cli/list-output.d.ts +5 -0
- package/dist/src/cli/list-output.js +11 -2
- package/dist/src/cli/list-shapes.d.ts +6 -0
- package/dist/src/cli/list-shapes.js +7 -1
- package/dist/src/cli/output-schemas.d.ts +1 -1
- package/dist/src/cli/output-schemas.js +1 -1
- package/dist/src/cli/output.d.ts +2 -0
- package/dist/src/cli/output.js +31 -4
- package/dist/src/cli/read-shapes.js +90 -0
- package/dist/src/cli/result-shapes.d.ts +19 -1
- package/dist/src/cli/result-shapes.js +227 -4
- package/dist/src/cli/selector-suggestions.d.ts +14 -0
- package/dist/src/cli/selector-suggestions.js +56 -0
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +29 -4
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +4 -5
- package/dist/src/cli.js +128 -30
- package/dist/src/client.d.ts +15 -2
- package/dist/src/client.js +36 -11
- package/dist/src/errors.d.ts +2 -0
- package/dist/src/errors.js +12 -2
- package/dist/src/generated/action-output-schemas.json +232 -0
- package/dist/src/index.d.ts +1 -1
- package/dist/src/resources/datasets.d.ts +11 -1
- package/dist/src/resources/datasets.js +91 -30
- package/dist/src/resources/jobs.d.ts +35 -5
- package/dist/src/resources/jobs.js +68 -41
- package/dist/src/resources/projects.js +2 -2
- package/dist/src/resources/recipe-create.d.ts +4 -1
- package/dist/src/resources/recipe-create.js +11 -2
- package/dist/src/resources/recipes.d.ts +12 -1
- package/dist/src/resources/recipes.js +39 -12
- package/dist/src/resources/scenarios.d.ts +8 -1
- package/dist/src/resources/scenarios.js +51 -12
- package/dist/src/resources/sql.js +3 -3
- package/dist/src/resources/wiki.js +3 -7
- package/dist/src/skill.js +1 -2
- package/dist/src/utils/project-archive.d.ts +25 -0
- package/dist/src/utils/project-archive.js +216 -5
- package/dist/src/utils/response-file.js +15 -8
- package/package.json +12 -12
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +15 -17
- package/skills/dataiku-dss/references/discovery.md +2 -2
- package/skills/dataiku-dss/references/troubleshooting.md +1 -0
package/dist/src/cli/env.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { readFileSync, } from "node:fs";
|
|
2
|
-
import {
|
|
3
|
-
import { fileURLToPath, } from "node:url";
|
|
2
|
+
import { resolve, } from "node:path";
|
|
4
3
|
const projectEnvVars = new Set();
|
|
5
4
|
const installEnvVars = new Set();
|
|
6
5
|
/**
|
|
@@ -24,6 +23,14 @@ export function dataikuEnvironmentEnabled() {
|
|
|
24
23
|
export function ambientProjectKey() {
|
|
25
24
|
return dataikuEnvironmentEnabled() ? process.env.DATAIKU_PROJECT_KEY : undefined;
|
|
26
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* `DSS_PRETTY=1` indents stdout JSON. Agent shells that cut long lines (omp at
|
|
28
|
+
* 768 bytes) truncate a one-line result; indented output keeps each line short.
|
|
29
|
+
* Read from the process environment only, never from a `.env` file.
|
|
30
|
+
*/
|
|
31
|
+
export function prettyOutputEnabled() {
|
|
32
|
+
return process.env.DSS_PRETTY === "1";
|
|
33
|
+
}
|
|
27
34
|
const allowedEnvKeys = new Set(["NODE_EXTRA_CA_CERTS", "NODE_TLS_REJECT_UNAUTHORIZED",]);
|
|
28
35
|
/**
|
|
29
36
|
* `.env` files are untrusted input: only the CLI's own `DATAIKU_*` variables and
|
|
@@ -42,7 +49,7 @@ export function loadEnvFile() {
|
|
|
42
49
|
// CLI. First writer wins below, so cwd must be listed first.
|
|
43
50
|
const dirs = [
|
|
44
51
|
process.cwd(),
|
|
45
|
-
resolve(
|
|
52
|
+
resolve(import.meta.dir, "..", ".."),
|
|
46
53
|
];
|
|
47
54
|
for (const [index, dir,] of dirs.entries()) {
|
|
48
55
|
try {
|
|
@@ -43,7 +43,7 @@ export declare function buildAppPermissionsSnapshot(projectKey: string, dssUrl:
|
|
|
43
43
|
export declare function writeAppPermissionsSnapshot(filePath: string, snapshot: AppPermissionsSnapshot): void;
|
|
44
44
|
/** Validate envelope shape, version, and hash integrity. Never echoes permission payloads. */
|
|
45
45
|
export declare function parseAppPermissionsSnapshot(text: string, source: string): AppPermissionsSnapshot;
|
|
46
|
-
export declare function readAppPermissionsSnapshot(filePath: string): AppPermissionsSnapshot
|
|
46
|
+
export declare function readAppPermissionsSnapshot(filePath: string): Promise<AppPermissionsSnapshot>;
|
|
47
47
|
/**
|
|
48
48
|
* Refuse to use a snapshot outside the exact project *and* DSS server it was captured
|
|
49
49
|
* from. Access-control rules are server-scoped: the same project key, users, and groups
|
|
@@ -153,10 +153,10 @@ export function parseAppPermissionsSnapshot(text, source) {
|
|
|
153
153
|
permissions,
|
|
154
154
|
};
|
|
155
155
|
}
|
|
156
|
-
export function readAppPermissionsSnapshot(filePath) {
|
|
156
|
+
export async function readAppPermissionsSnapshot(filePath) {
|
|
157
157
|
let text;
|
|
158
158
|
try {
|
|
159
|
-
text = fs.
|
|
159
|
+
text = await fs.promises.readFile(filePath, "utf-8");
|
|
160
160
|
}
|
|
161
161
|
catch (error) {
|
|
162
162
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { CleanupLedgerEntry } from "../../utils/cleanup-ledger.js";
|
|
2
2
|
export declare function projectArg(projectKey: string | undefined): string[];
|
|
3
|
+
/** Input field that identifies the created object, when the result does not. */
|
|
4
|
+
export declare function cleanupInputIdentifierField(resource: string, action: string): string | undefined;
|
|
3
5
|
export declare function cleanupLedgerEntry(resource: string, action: string, args: string[], flags: Record<string, string | boolean>, result: unknown, projectKey: string | undefined): CleanupLedgerEntry | undefined;
|
|
@@ -35,6 +35,30 @@ function createInputFromFlags(flags) {
|
|
|
35
35
|
return undefined;
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates whose DSS response carries no identifier: the cleanup ledger pins the
|
|
40
|
+
* created object from this field of the `--data`/`--data-file` input instead.
|
|
41
|
+
* `--stdin` cannot be replayed, so the CLI rejects it with `--record-cleanup`
|
|
42
|
+
* before mutating.
|
|
43
|
+
*/
|
|
44
|
+
const CLEANUP_INPUT_IDENTIFIER_FIELDS = {
|
|
45
|
+
"workspace.create": "workspaceKey",
|
|
46
|
+
"connection.create": "name",
|
|
47
|
+
"user.create": "login",
|
|
48
|
+
"group.create": "name",
|
|
49
|
+
};
|
|
50
|
+
/** Input field that identifies the created object, when the result does not. */
|
|
51
|
+
export function cleanupInputIdentifierField(resource, action) {
|
|
52
|
+
return CLEANUP_INPUT_IDENTIFIER_FIELDS[`${resource}.${action}`];
|
|
53
|
+
}
|
|
54
|
+
function inputIdentifier(resource, action, flags) {
|
|
55
|
+
const field = cleanupInputIdentifierField(resource, action);
|
|
56
|
+
if (!field)
|
|
57
|
+
return undefined;
|
|
58
|
+
const input = resultRecord(createInputFromFlags(flags));
|
|
59
|
+
const identifier = stringField(input, [field,]);
|
|
60
|
+
return identifier ? { identifier, input, } : undefined;
|
|
61
|
+
}
|
|
38
62
|
export function cleanupLedgerEntry(resource, action, args, flags, result, projectKey) {
|
|
39
63
|
const record = resultRecord(result);
|
|
40
64
|
// A notebook save is ledger-eligible only when it created the notebook:
|
|
@@ -77,6 +101,22 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
|
|
|
77
101
|
cleanup: { argv: ["dataset", "delete", name, "--if-exists", ...withProject,], },
|
|
78
102
|
};
|
|
79
103
|
}
|
|
104
|
+
case "dataset.create-managed": {
|
|
105
|
+
// The handler returns `created` as the dataset name and the project
|
|
106
|
+
// DSS created it in, which wins over the requested project key.
|
|
107
|
+
const name = stringField(record, ["created", "name",]) ?? flags["name"];
|
|
108
|
+
if (!name)
|
|
109
|
+
return undefined;
|
|
110
|
+
const landedProject = stringField(record, ["projectKey",]) ?? project;
|
|
111
|
+
return {
|
|
112
|
+
...base,
|
|
113
|
+
...(landedProject ? { projectKey: landedProject, } : {}),
|
|
114
|
+
name,
|
|
115
|
+
cleanup: {
|
|
116
|
+
argv: ["dataset", "delete", name, "--if-exists", ...projectArg(landedProject),],
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
80
120
|
case "recipe.create": {
|
|
81
121
|
const name = stringField(record, ["created", "recipeName", "name",])
|
|
82
122
|
?? flags["name"];
|
|
@@ -199,6 +239,78 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
|
|
|
199
239
|
cleanup: { argv: ["ml-task", "delete", analysisId, taskId, ...withProject,], },
|
|
200
240
|
};
|
|
201
241
|
}
|
|
242
|
+
case "ml-task.create-for-dataset": {
|
|
243
|
+
// This create opens a new visual analysis around the task, so cleanup
|
|
244
|
+
// removes the whole analysis rather than leaving an empty one behind.
|
|
245
|
+
const analysisId = stringField(record, ["analysisId",]);
|
|
246
|
+
if (!analysisId)
|
|
247
|
+
return undefined;
|
|
248
|
+
return {
|
|
249
|
+
...base,
|
|
250
|
+
id: analysisId,
|
|
251
|
+
cleanup: { argv: ["analysis", "delete", analysisId, "--if-exists", ...withProject,], },
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
case "saved-model.create-external": {
|
|
255
|
+
const id = stringField(record, ["id",]);
|
|
256
|
+
if (!id)
|
|
257
|
+
return undefined;
|
|
258
|
+
const landedProject = stringField(record, ["projectKey",]) ?? project;
|
|
259
|
+
return {
|
|
260
|
+
...base,
|
|
261
|
+
...(landedProject ? { projectKey: landedProject, } : {}),
|
|
262
|
+
id,
|
|
263
|
+
name: args[0],
|
|
264
|
+
cleanup: {
|
|
265
|
+
argv: ["saved-model", "delete", id, "--if-exists", ...projectArg(landedProject),],
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
case "project-folder.create-child": {
|
|
270
|
+
// `created` falls back to the requested name when DSS omits the id,
|
|
271
|
+
// and a name cannot address a folder delete: only `id` pins it.
|
|
272
|
+
const id = stringField(record, ["id",]);
|
|
273
|
+
if (!id)
|
|
274
|
+
return undefined;
|
|
275
|
+
return {
|
|
276
|
+
...base,
|
|
277
|
+
id,
|
|
278
|
+
name: flags["name"],
|
|
279
|
+
cleanup: { argv: ["project-folder", "delete", id, "--if-exists",], },
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
case "data-collection.create": {
|
|
283
|
+
const id = stringField(record, ["id",]);
|
|
284
|
+
if (!id)
|
|
285
|
+
return undefined;
|
|
286
|
+
return {
|
|
287
|
+
...base,
|
|
288
|
+
id,
|
|
289
|
+
cleanup: { argv: ["data-collection", "delete", id,], },
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
case "plugin.create-dev": {
|
|
293
|
+
const id = stringField(record, ["created",]) ?? args[0];
|
|
294
|
+
if (!id)
|
|
295
|
+
return undefined;
|
|
296
|
+
return {
|
|
297
|
+
...base,
|
|
298
|
+
id,
|
|
299
|
+
cleanup: { argv: ["plugin", "delete", id,], },
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
case "connection.create":
|
|
303
|
+
case "user.create":
|
|
304
|
+
case "group.create": {
|
|
305
|
+
const pinned = inputIdentifier(resource, action, flags);
|
|
306
|
+
if (!pinned)
|
|
307
|
+
return undefined;
|
|
308
|
+
return {
|
|
309
|
+
...base,
|
|
310
|
+
name: pinned.identifier,
|
|
311
|
+
cleanup: { argv: [resource, "delete", pinned.identifier, "--if-exists",], },
|
|
312
|
+
};
|
|
313
|
+
}
|
|
202
314
|
case "data-quality.create-rule": {
|
|
203
315
|
const ruleId = stringField(record, ["id", "created",]);
|
|
204
316
|
if (!ruleId)
|
|
@@ -222,8 +334,11 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
|
|
|
222
334
|
cleanup: { argv: ["code-env", "delete", lang, name, "--if-exists",], },
|
|
223
335
|
};
|
|
224
336
|
}
|
|
225
|
-
case "streaming-endpoint.create":
|
|
226
|
-
|
|
337
|
+
case "streaming-endpoint.create":
|
|
338
|
+
case "streaming-endpoint.create-managed": {
|
|
339
|
+
const id = stringField(record, ["created",]) ?? args[0];
|
|
340
|
+
if (!id)
|
|
341
|
+
return undefined;
|
|
227
342
|
return {
|
|
228
343
|
...base,
|
|
229
344
|
id,
|
|
@@ -240,15 +355,14 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
|
|
|
240
355
|
};
|
|
241
356
|
}
|
|
242
357
|
case "workspace.create": {
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
if (!workspaceKey)
|
|
358
|
+
const pinned = inputIdentifier(resource, action, flags);
|
|
359
|
+
if (!pinned)
|
|
246
360
|
return undefined;
|
|
247
361
|
return {
|
|
248
362
|
...base,
|
|
249
|
-
id:
|
|
250
|
-
name: stringField(input, ["displayName",]),
|
|
251
|
-
cleanup: { argv: ["workspace", "delete",
|
|
363
|
+
id: pinned.identifier,
|
|
364
|
+
name: stringField(pinned.input, ["displayName",]),
|
|
365
|
+
cleanup: { argv: ["workspace", "delete", pinned.identifier,], },
|
|
252
366
|
};
|
|
253
367
|
}
|
|
254
368
|
case "project-library.create-file":
|
|
@@ -56,7 +56,7 @@ export declare function dedupeFlowZonePlanItems(items: FlowZoneItemInput[]): Flo
|
|
|
56
56
|
export declare function flowZonePlanItemKeys(plan: FlowZoneOrganizePlan): Set<string>;
|
|
57
57
|
export declare function validateUniqueFlowZoneAssignments(plan: FlowZoneOrganizePlan): void;
|
|
58
58
|
export declare function parseFlowZoneOrganizePlan(input: Record<string, unknown>): FlowZoneOrganizePlan;
|
|
59
|
-
export declare function readFlowZoneOrganizePlan(flags: Record<string, string | boolean>, usage: string): FlowZoneOrganizePlan
|
|
59
|
+
export declare function readFlowZoneOrganizePlan(flags: Record<string, string | boolean>, usage: string): Promise<FlowZoneOrganizePlan>;
|
|
60
60
|
export declare function findFlowZoneForPlan(zones: FlowZone[], plan: FlowZoneOrganizeZonePlan): FlowZone | undefined;
|
|
61
61
|
export declare function ensureFlowZonePlanTarget(plan: FlowZoneOrganizeZonePlan, existing: FlowZone | undefined): void;
|
|
62
62
|
export declare function flowZoneExplicitItems(zone: FlowZone): FlowZoneItemInput[];
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { readFileSync, } from "node:fs";
|
|
2
1
|
import { ClientValidationError, } from "../../errors.js";
|
|
3
2
|
import { asRecord, } from "../../utils/records.js";
|
|
4
3
|
import { compareStrings, } from "../../utils/stable-hash.js";
|
|
5
|
-
import { finiteNumberField, jsonInput, optionalStringField, parseJsonObject, requiredStringArray, splitCsvFlag, } from "../coerce.js";
|
|
4
|
+
import { finiteNumberField, jsonInput, optionalStringField, parseJsonObject, readTextFile, requiredStringArray, splitCsvFlag, } from "../coerce.js";
|
|
6
5
|
import { commandUsage, } from "../syntax.js";
|
|
7
6
|
import { UsageError, } from "../usage.js";
|
|
8
7
|
export function flowZoneId(value) {
|
|
@@ -257,9 +256,9 @@ export function parseFlowZoneOrganizePlan(input) {
|
|
|
257
256
|
validateUniqueFlowZoneAssignments(plan);
|
|
258
257
|
return plan;
|
|
259
258
|
}
|
|
260
|
-
export function readFlowZoneOrganizePlan(flags, usage) {
|
|
259
|
+
export async function readFlowZoneOrganizePlan(flags, usage) {
|
|
261
260
|
const data = typeof flags["file"] === "string"
|
|
262
|
-
? parseJsonObject(
|
|
261
|
+
? parseJsonObject(await readTextFile(flags["file"]), flags["file"])
|
|
263
262
|
: jsonInput(flags);
|
|
264
263
|
if (!data) {
|
|
265
264
|
throw new UsageError(`--data, --data-file, --file, or --stdin is required. Usage: ${usage}`, "missing_required_flag");
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
import { type CompactListField } from "./list-shapes.js";
|
|
2
|
+
type Item = Record<string, unknown>;
|
|
3
|
+
/** One compact field of a DSS list item, as `RESOURCE.list` prints it. */
|
|
4
|
+
export declare function compactValue(item: Item, spec: CompactListField): unknown;
|
|
1
5
|
/**
|
|
2
6
|
* Shape a `*.list` result for agents: `--contains` filters on identifier
|
|
3
7
|
* fields, `--limit` caps the count (a `list_truncated` warning reports the
|
|
@@ -5,3 +9,4 @@
|
|
|
5
9
|
* `--full` or `--fields` asks for the DSS objects.
|
|
6
10
|
*/
|
|
7
11
|
export declare function shapeListResult(resource: string, result: unknown, flags: Record<string, string | boolean>): unknown;
|
|
12
|
+
export {};
|
|
@@ -4,10 +4,19 @@ import { enqueueCliWarning, } from "./output.js";
|
|
|
4
4
|
function record(value) {
|
|
5
5
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6
6
|
}
|
|
7
|
-
function
|
|
7
|
+
function valueAt(item, path) {
|
|
8
8
|
let value = item;
|
|
9
|
-
for (const key of
|
|
9
|
+
for (const key of path.split("."))
|
|
10
10
|
value = record(value)[key];
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
/** One compact field of a DSS list item, as `RESOURCE.list` prints it. */
|
|
14
|
+
export function compactValue(item, spec) {
|
|
15
|
+
const value = valueAt(item, spec.path);
|
|
16
|
+
if (value === undefined && spec.fallback
|
|
17
|
+
&& valueAt(item, spec.fallback.when) === spec.fallback.equals) {
|
|
18
|
+
return spec.fallback.value;
|
|
19
|
+
}
|
|
11
20
|
if (spec.roleRefs !== true)
|
|
12
21
|
return value;
|
|
13
22
|
// Dataset refs across every role of recipe inputs/outputs (`{main:{items:[{ref}]}}`).
|
|
@@ -9,6 +9,12 @@ export interface CompactListField {
|
|
|
9
9
|
path: string;
|
|
10
10
|
/** Flatten recipe roles (`{main:{items:[{ref}]}}`) to the dataset refs. */
|
|
11
11
|
roleRefs?: true;
|
|
12
|
+
/** Value when `path` is absent and the item's `when` path equals `equals`. */
|
|
13
|
+
fallback?: {
|
|
14
|
+
when: string;
|
|
15
|
+
equals: unknown;
|
|
16
|
+
value: unknown;
|
|
17
|
+
};
|
|
12
18
|
schema: Record<string, unknown>;
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
@@ -51,7 +51,12 @@ export const COMPACT_LIST_FIELDS = {
|
|
|
51
51
|
id: field("def.id", STRING),
|
|
52
52
|
name: field("def.name", STRING),
|
|
53
53
|
type: field("def.type", STRING),
|
|
54
|
-
|
|
54
|
+
// DSS lists in-progress jobs with `stableState: false` and no `state`
|
|
55
|
+
// (COMPUTING_DEPS or RUNNING); `job get` reports the exact phase.
|
|
56
|
+
state: {
|
|
57
|
+
...field("state", STRING),
|
|
58
|
+
fallback: { when: "stableState", equals: false, value: "RUNNING", },
|
|
59
|
+
},
|
|
55
60
|
startTime: field("startTime", NUMBER),
|
|
56
61
|
endTime: field("endTime", NUMBER),
|
|
57
62
|
},
|
|
@@ -83,6 +88,7 @@ export const COMPACT_LIST_FIELDS = {
|
|
|
83
88
|
id: field("id", STRING),
|
|
84
89
|
version: field("version", STRING),
|
|
85
90
|
label: field("meta.label", STRING),
|
|
91
|
+
isDev: field("isDev", BOOLEAN),
|
|
86
92
|
},
|
|
87
93
|
macro: {
|
|
88
94
|
runnableType: field("runnableType", STRING),
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* the single source of truth for `src/generated/action-output-schemas.json`,
|
|
4
4
|
* which discovery reads as plain data so no TypeBox schema graph loads on the
|
|
5
5
|
* discovery path. Regenerate with
|
|
6
|
-
* `bun scripts/generate-action-output-schemas.mjs`; `bun run
|
|
6
|
+
* `bun scripts/generate-action-output-schemas.mjs`; `bun run verify` fails when
|
|
7
7
|
* the generated file is stale. SDK validation keeps using the TypeBox schema
|
|
8
8
|
* objects from `packages/types` directly and never depends on the generated file.
|
|
9
9
|
*/
|
|
@@ -72,7 +72,7 @@ let commandOutputSchemas;
|
|
|
72
72
|
* the single source of truth for `src/generated/action-output-schemas.json`,
|
|
73
73
|
* which discovery reads as plain data so no TypeBox schema graph loads on the
|
|
74
74
|
* discovery path. Regenerate with
|
|
75
|
-
* `bun scripts/generate-action-output-schemas.mjs`; `bun run
|
|
75
|
+
* `bun scripts/generate-action-output-schemas.mjs`; `bun run verify` fails when
|
|
76
76
|
* the generated file is stale. SDK validation keeps using the TypeBox schema
|
|
77
77
|
* objects from `packages/types` directly and never depends on the generated file.
|
|
78
78
|
*/
|
package/dist/src/cli/output.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export declare function pickResultFields(item: unknown, fields: string[]): unkno
|
|
|
11
11
|
* that are absent become null so every row keeps a stable, predictable shape.
|
|
12
12
|
*/
|
|
13
13
|
export declare function projectResultFields(result: unknown, fields: string[], availableFieldNames?: () => string[]): unknown;
|
|
14
|
+
/** One JSON value plus newline for stdout; indented when `DSS_PRETTY=1`. */
|
|
15
|
+
export declare function stdoutJson(value: unknown): string;
|
|
14
16
|
export declare function writeCommandResult(result: unknown): void;
|
|
15
17
|
export declare function addTransientTargetContext(error: unknown, target: string, elapsedMs: number): never;
|
|
16
18
|
export declare function isFailedWaitResult(result: unknown): boolean;
|
package/dist/src/cli/output.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DataikuError, } from "../errors.js";
|
|
2
|
+
import { prettyOutputEnabled, } from "./env.js";
|
|
2
3
|
let outputFieldProjection;
|
|
3
4
|
export function setOutputFieldProjection(fields) {
|
|
4
5
|
outputFieldProjection = fields;
|
|
@@ -98,12 +99,16 @@ export function projectResultFields(result, fields, availableFieldNames) {
|
|
|
98
99
|
return result.map((item) => pickResultFields(item, fields));
|
|
99
100
|
return pickResultFields(result, fields);
|
|
100
101
|
}
|
|
102
|
+
/** One JSON value plus newline for stdout; indented when `DSS_PRETTY=1`. */
|
|
103
|
+
export function stdoutJson(value) {
|
|
104
|
+
return `${JSON.stringify(value, null, prettyOutputEnabled() ? 2 : undefined)}\n`;
|
|
105
|
+
}
|
|
101
106
|
export function writeCommandResult(result) {
|
|
102
107
|
const projected = outputFieldProjection
|
|
103
108
|
? projectResultFields(result, outputFieldProjection)
|
|
104
109
|
: result;
|
|
105
110
|
flushCliWarnings();
|
|
106
|
-
process.stdout.write(
|
|
111
|
+
process.stdout.write(stdoutJson(projected ?? { ok: true, }));
|
|
107
112
|
}
|
|
108
113
|
export function addTransientTargetContext(error, target, elapsedMs) {
|
|
109
114
|
if (error instanceof DataikuError && error.category === "transient") {
|
|
@@ -193,13 +198,35 @@ export function commandFailureMessage(result) {
|
|
|
193
198
|
if (typeof message === "string" && message.length > 0)
|
|
194
199
|
return message;
|
|
195
200
|
}
|
|
201
|
+
if (record.timedOut === true && typeof record.jobId === "string"
|
|
202
|
+
&& typeof record.progress === "object" && typeof record.state === "string") {
|
|
203
|
+
// A job wait result: the timeout only stopped polling, the DSS job is
|
|
204
|
+
// still running (and was not cancelled).
|
|
205
|
+
const resume = typeof record.resume === "string" ? ` Resume with: ${record.resume}` : "";
|
|
206
|
+
return `Timed out waiting for job ${record.jobId} after ${record.elapsedMs}ms (last known state: ${record.state}); the job is still running in DSS and was not cancelled.${resume}`;
|
|
207
|
+
}
|
|
208
|
+
if (record.timedOut === true) {
|
|
209
|
+
// ML training, scenario runs, futures, code run: the client stopped waiting. Only a
|
|
210
|
+
// result that says `cancelled: false` proves nothing was stopped; `code run` cleans up
|
|
211
|
+
// its throwaway scenario, so its `cleanup` status is what tells.
|
|
212
|
+
const known = typeof record.state === "string"
|
|
213
|
+
? record.state
|
|
214
|
+
: typeof record.outcome === "string"
|
|
215
|
+
? record.outcome
|
|
216
|
+
: undefined;
|
|
217
|
+
const elapsed = typeof record.elapsedMs === "number" ? ` after ${record.elapsedMs}ms` : "";
|
|
218
|
+
const after = record.cancelled === false
|
|
219
|
+
? "the operation was not cancelled and may still be running in DSS."
|
|
220
|
+
: record.cleanup !== undefined
|
|
221
|
+
? "the client stopped waiting; see `cleanup` for what happened to the run."
|
|
222
|
+
: "the client stopped waiting; the operation may still be running in DSS.";
|
|
223
|
+
return `Timed out waiting${elapsed}${known ? ` (last known state: ${known})` : ""}; ${after}`;
|
|
224
|
+
}
|
|
196
225
|
const state = typeof record.state === "string"
|
|
197
226
|
? record.state
|
|
198
227
|
: typeof record.outcome === "string"
|
|
199
228
|
? record.outcome
|
|
200
|
-
:
|
|
201
|
-
? "timed out"
|
|
202
|
-
: undefined;
|
|
229
|
+
: undefined;
|
|
203
230
|
return `Command completed with failed long-running result${state ? `: ${state}` : ""}.`;
|
|
204
231
|
}
|
|
205
232
|
if (isAssertionFailureResult(result)) {
|
|
@@ -32,6 +32,28 @@ export function compactReadOutputSchemas() {
|
|
|
32
32
|
additionalProperties: false,
|
|
33
33
|
properties: { type: STRING, message: STRING, },
|
|
34
34
|
};
|
|
35
|
+
const triggerSchema = {
|
|
36
|
+
type: "object",
|
|
37
|
+
additionalProperties: false,
|
|
38
|
+
properties: { type: STRING, name: STRING, },
|
|
39
|
+
};
|
|
40
|
+
const failureSchema = {
|
|
41
|
+
type: "object",
|
|
42
|
+
additionalProperties: false,
|
|
43
|
+
properties: {
|
|
44
|
+
stepId: STRING,
|
|
45
|
+
jobId: STRING,
|
|
46
|
+
dataset: STRING,
|
|
47
|
+
recipe: STRING,
|
|
48
|
+
inputs: { type: "array", items: { type: "string", }, },
|
|
49
|
+
message: STRING,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
const nextSchema = {
|
|
53
|
+
type: "array",
|
|
54
|
+
description: "Next commands to run, each as an argv array.",
|
|
55
|
+
items: { type: "array", items: STRING, },
|
|
56
|
+
};
|
|
35
57
|
return {
|
|
36
58
|
"job.get": {
|
|
37
59
|
type: "object",
|
|
@@ -110,5 +132,73 @@ export function compactReadOutputSchemas() {
|
|
|
110
132
|
lastModifiedBy: STRING,
|
|
111
133
|
},
|
|
112
134
|
},
|
|
135
|
+
"scenario.get-run": {
|
|
136
|
+
type: "object",
|
|
137
|
+
additionalProperties: false,
|
|
138
|
+
required: ["runId", "steps",],
|
|
139
|
+
properties: {
|
|
140
|
+
runId: STRING,
|
|
141
|
+
scenarioId: STRING,
|
|
142
|
+
projectKey: STRING,
|
|
143
|
+
outcome: STRING,
|
|
144
|
+
start: NUMBER,
|
|
145
|
+
end: NUMBER,
|
|
146
|
+
durationMs: NUMBER,
|
|
147
|
+
trigger: triggerSchema,
|
|
148
|
+
steps: {
|
|
149
|
+
type: "array",
|
|
150
|
+
items: {
|
|
151
|
+
type: "object",
|
|
152
|
+
additionalProperties: false,
|
|
153
|
+
properties: {
|
|
154
|
+
id: STRING,
|
|
155
|
+
name: STRING,
|
|
156
|
+
type: STRING,
|
|
157
|
+
outcome: STRING,
|
|
158
|
+
message: STRING,
|
|
159
|
+
datasets: {
|
|
160
|
+
type: "array",
|
|
161
|
+
items: {
|
|
162
|
+
type: "object",
|
|
163
|
+
additionalProperties: false,
|
|
164
|
+
properties: { dataset: STRING, projectKey: STRING, partition: STRING, outcome: STRING, },
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
jobs: {
|
|
168
|
+
type: "array",
|
|
169
|
+
items: {
|
|
170
|
+
type: "object",
|
|
171
|
+
additionalProperties: false,
|
|
172
|
+
properties: { jobId: STRING, outcome: STRING, message: STRING, },
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
failure: failureSchema,
|
|
179
|
+
next: nextSchema,
|
|
180
|
+
hint: {
|
|
181
|
+
type: "string",
|
|
182
|
+
description: "Edit-and-rerun commands when the failed recipe is known.",
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
"scenario.last-runs": {
|
|
187
|
+
type: "array",
|
|
188
|
+
items: {
|
|
189
|
+
type: "object",
|
|
190
|
+
additionalProperties: false,
|
|
191
|
+
required: ["runId",],
|
|
192
|
+
properties: {
|
|
193
|
+
runId: STRING,
|
|
194
|
+
outcome: STRING,
|
|
195
|
+
start: NUMBER,
|
|
196
|
+
end: NUMBER,
|
|
197
|
+
trigger: triggerSchema,
|
|
198
|
+
failure: { type: "object", additionalProperties: false, properties: { message: STRING, }, },
|
|
199
|
+
next: nextSchema,
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
113
203
|
};
|
|
114
204
|
}
|
|
@@ -1,6 +1,24 @@
|
|
|
1
|
+
type Item = Record<string, unknown>;
|
|
2
|
+
/** The failed activity of a job: the recipe that failed and the datasets it read. */
|
|
3
|
+
export interface FailedActivity {
|
|
4
|
+
recipe: string;
|
|
5
|
+
inputs: string[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Failure diagnosis of a raw `scenario get-run` report: the first failure
|
|
9
|
+
* (`{ stepId, jobId, dataset, message }`) and the next command(s) to run as
|
|
10
|
+
* argv arrays. With the failed recipe known, `hint` names the edit-and-rerun
|
|
11
|
+
* loop, so the agent does not look up the write commands. Empty when the run did not fail.
|
|
12
|
+
*/
|
|
13
|
+
export declare function scenarioRunDiagnosis(details: unknown, activity?: FailedActivity): {
|
|
14
|
+
failure?: Item;
|
|
15
|
+
next?: string[][];
|
|
16
|
+
hint?: string;
|
|
17
|
+
};
|
|
1
18
|
/**
|
|
2
19
|
* Compact a command result for agents: `*.list` items (filter, cap, compact
|
|
3
|
-
* fields) and the
|
|
20
|
+
* fields) and the large read commands. `--full` and `--fields` bypass
|
|
4
21
|
* the read shapers so the DSS object (or a projection of it) is returned.
|
|
5
22
|
*/
|
|
6
23
|
export declare function shapeCommandResult(resource: string, action: string, result: unknown, flags: Record<string, string | boolean>): unknown;
|
|
24
|
+
export {};
|