dataiku-sdk 3.6.0 → 3.7.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 +14 -6
- package/bin/bun-version.js +14 -0
- package/bin/dss.js +23 -12
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +74 -1
- package/dist/packages/types/src/index.js +53 -1
- package/dist/src/cli/coerce.d.ts +1 -0
- package/dist/src/cli/coerce.js +19 -15
- package/dist/src/cli/command-syntax.json +3521 -416
- package/dist/src/cli/commands/analysis.js +19 -1
- package/dist/src/cli/commands/bundle.js +22 -0
- package/dist/src/cli/commands/connection.js +26 -2
- package/dist/src/cli/commands/data-quality.js +33 -1
- package/dist/src/cli/commands/dataset.js +35 -4
- package/dist/src/cli/commands/discussion.js +15 -0
- package/dist/src/cli/commands/doctor.js +1 -1
- package/dist/src/cli/commands/flow.d.ts +5 -0
- package/dist/src/cli/commands/flow.js +57 -0
- package/dist/src/cli/commands/future.js +8 -0
- package/dist/src/cli/commands/index.js +6 -0
- package/dist/src/cli/commands/job.js +29 -6
- package/dist/src/cli/commands/metrics.js +21 -1
- package/dist/src/cli/commands/ml-task.d.ts +5 -0
- package/dist/src/cli/commands/ml-task.js +86 -16
- package/dist/src/cli/commands/mlflow.d.ts +11 -0
- package/dist/src/cli/commands/mlflow.js +121 -0
- package/dist/src/cli/commands/plugin.js +5 -11
- package/dist/src/cli/commands/project-deployer.js +70 -0
- package/dist/src/cli/commands/project-library.js +2 -5
- package/dist/src/cli/commands/project.js +8 -0
- package/dist/src/cli/commands/recipe.d.ts +9 -0
- package/dist/src/cli/commands/recipe.js +93 -7
- package/dist/src/cli/commands/saved-model.d.ts +1 -1
- package/dist/src/cli/commands/saved-model.js +9 -76
- package/dist/src/cli/commands/streaming-endpoint.js +30 -1
- package/dist/src/cli/commands/webapp.js +8 -0
- package/dist/src/cli/commands/wiki.js +22 -0
- package/dist/src/cli/commands/workspace.js +8 -0
- package/dist/src/cli/contract.d.ts +16 -15
- package/dist/src/cli/contract.js +139 -3404
- package/dist/src/cli/doctor.d.ts +13 -0
- package/dist/src/cli/doctor.js +41 -1
- package/dist/src/cli/flags.d.ts +7 -1
- package/dist/src/cli/flags.js +78 -6
- package/dist/src/cli/helpers/app-successor.js +1 -2
- package/dist/src/cli/helpers/documentation.d.ts +21 -0
- package/dist/src/cli/helpers/documentation.js +53 -0
- package/dist/src/cli/helpers/trained-model.d.ts +26 -0
- package/dist/src/cli/helpers/trained-model.js +144 -0
- package/dist/src/cli/list-output.d.ts +7 -0
- package/dist/src/cli/list-output.js +77 -0
- package/dist/src/cli/list-shapes.d.ts +21 -0
- package/dist/src/cli/list-shapes.js +111 -0
- package/dist/src/cli/output-schemas.d.ts +0 -14
- package/dist/src/cli/output-schemas.js +4 -7
- package/dist/src/cli/output.d.ts +0 -1
- package/dist/src/cli/output.js +27 -19
- package/dist/src/cli/plans.d.ts +14 -0
- package/dist/src/cli/plans.js +3684 -0
- package/dist/src/cli/usage.d.ts +7 -0
- package/dist/src/cli/usage.js +20 -1
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +2 -2
- package/dist/src/cli.js +127 -113
- package/dist/src/client.d.ts +52 -43
- package/dist/src/client.js +267 -96
- package/dist/src/errors.d.ts +11 -1
- package/dist/src/errors.js +31 -47
- package/dist/src/generated/action-output-schemas.json +345 -89
- package/dist/src/index.d.ts +5 -1
- package/dist/src/index.js +3 -0
- package/dist/src/resources/analyses.d.ts +8 -0
- package/dist/src/resources/analyses.js +13 -1
- package/dist/src/resources/bundles.d.ts +34 -0
- package/dist/src/resources/bundles.js +67 -0
- package/dist/src/resources/connections.d.ts +9 -0
- package/dist/src/resources/connections.js +15 -0
- package/dist/src/resources/data-quality.d.ts +20 -0
- package/dist/src/resources/data-quality.js +30 -0
- package/dist/src/resources/dataset-create.d.ts +19 -0
- package/dist/src/resources/dataset-create.js +66 -0
- package/dist/src/resources/datasets.d.ts +25 -15
- package/dist/src/resources/datasets.js +59 -111
- package/dist/src/resources/discussions.d.ts +5 -0
- package/dist/src/resources/discussions.js +7 -0
- package/dist/src/resources/documentation.d.ts +25 -0
- package/dist/src/resources/documentation.js +16 -0
- package/dist/src/resources/flow.d.ts +48 -0
- package/dist/src/resources/flow.js +65 -0
- package/dist/src/resources/futures.d.ts +23 -0
- package/dist/src/resources/futures.js +32 -0
- package/dist/src/resources/jobs.js +102 -2
- package/dist/src/resources/metrics.d.ts +10 -0
- package/dist/src/resources/metrics.js +10 -0
- package/dist/src/resources/ml-tasks.d.ts +65 -2
- package/dist/src/resources/ml-tasks.js +102 -28
- package/dist/src/resources/mlflow-extension.d.ts +73 -0
- package/dist/src/resources/mlflow-extension.js +105 -0
- package/dist/src/resources/projects.d.ts +6 -0
- package/dist/src/resources/projects.js +8 -0
- package/dist/src/resources/recipe-create.d.ts +65 -0
- package/dist/src/resources/recipe-create.js +338 -0
- package/dist/src/resources/recipes.d.ts +28 -29
- package/dist/src/resources/recipes.js +126 -245
- package/dist/src/resources/saved-models.d.ts +10 -6
- package/dist/src/resources/saved-models.js +16 -14
- package/dist/src/resources/scenarios.js +8 -14
- package/dist/src/resources/streaming-endpoints.d.ts +12 -0
- package/dist/src/resources/streaming-endpoints.js +15 -0
- package/dist/src/resources/trained-model.d.ts +60 -0
- package/dist/src/resources/trained-model.js +98 -0
- package/dist/src/resources/webapps.d.ts +8 -0
- package/dist/src/resources/webapps.js +10 -0
- package/dist/src/resources/wiki.d.ts +5 -0
- package/dist/src/resources/wiki.js +7 -0
- package/dist/src/resources/workspaces.d.ts +2 -0
- package/dist/src/resources/workspaces.js +4 -0
- package/dist/src/utils/response-file.js +20 -9
- package/dist/src/utils/secret-sanitize.d.ts +7 -0
- package/dist/src/utils/secret-sanitize.js +46 -0
- package/package.json +25 -26
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +1 -1
- package/skills/dataiku-dss/references/authentication.md +3 -1
- package/skills/dataiku-dss/references/coding.md +1 -0
- package/skills/dataiku-dss/references/discovery.md +4 -6
- package/skills/dataiku-dss/references/troubleshooting.md +3 -2
package/dist/src/cli/doctor.d.ts
CHANGED
|
@@ -68,11 +68,24 @@ export interface DoctorResult {
|
|
|
68
68
|
tlsVerify: "strict" | "disabled";
|
|
69
69
|
caCert: "default" | "custom";
|
|
70
70
|
};
|
|
71
|
+
identity?: DoctorIdentity;
|
|
71
72
|
permissions?: DoctorPermissions;
|
|
72
73
|
permissionDetails?: Partial<Record<DoctorPermissionKey, Record<string, unknown>>>;
|
|
73
74
|
fixtures?: DoctorFixtures;
|
|
74
75
|
environment?: DoctorEnvironment;
|
|
75
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* The identity a DSS API key acts as, from `GET /public/api/auth/info`
|
|
79
|
+
* (no admin privilege required). Explains unexplained 403s: a personal key
|
|
80
|
+
* acts as its owner, a global key shows up as an `api:<id>` identity.
|
|
81
|
+
* Carries no secret material.
|
|
82
|
+
*/
|
|
83
|
+
export interface DoctorIdentity {
|
|
84
|
+
authSource?: string;
|
|
85
|
+
authIdentifier?: string;
|
|
86
|
+
groups?: string[];
|
|
87
|
+
userProfile?: string;
|
|
88
|
+
}
|
|
76
89
|
export declare function errorDetails(error: unknown): Record<string, unknown>;
|
|
77
90
|
export declare function firstStringField(items: unknown[] | undefined, fields: string[]): string | null;
|
|
78
91
|
export declare function integrationFlag(name: string): boolean;
|
package/dist/src/cli/doctor.js
CHANGED
|
@@ -49,6 +49,34 @@ export function doctorEnvironment(projectKey, versionInfo) {
|
|
|
49
49
|
},
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* Identity fields this doctor version reports, read from the documented
|
|
54
|
+
* `GET /public/api/auth/info` payload. Everything is optional: the field set
|
|
55
|
+
* varies across DSS versions and absent fields stay absent.
|
|
56
|
+
*/
|
|
57
|
+
function doctorIdentityFromAuthInfo(raw) {
|
|
58
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
59
|
+
return undefined;
|
|
60
|
+
const record = raw;
|
|
61
|
+
const groups = Array.isArray(record["groups"])
|
|
62
|
+
? record["groups"].filter((g) => typeof g === "string")
|
|
63
|
+
: undefined;
|
|
64
|
+
const authSource = typeof record["authSource"] === "string" ? record["authSource"] : undefined;
|
|
65
|
+
const authIdentifier = typeof record["authIdentifier"] === "string"
|
|
66
|
+
? record["authIdentifier"]
|
|
67
|
+
: undefined;
|
|
68
|
+
const userProfile = typeof record["userProfile"] === "string" ? record["userProfile"] : undefined;
|
|
69
|
+
if (authSource === undefined && authIdentifier === undefined && userProfile === undefined
|
|
70
|
+
&& (groups === undefined || groups.length === 0)) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
...(authSource !== undefined ? { authSource, } : {}),
|
|
75
|
+
...(authIdentifier !== undefined ? { authIdentifier, } : {}),
|
|
76
|
+
...(groups !== undefined && groups.length > 0 ? { groups, } : {}),
|
|
77
|
+
...(userProfile !== undefined ? { userProfile, } : {}),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
52
80
|
export function permissionStatusForError(error) {
|
|
53
81
|
if (error instanceof DataikuError) {
|
|
54
82
|
if (error.status === 401 || error.status === 403 || error.status === 404)
|
|
@@ -261,6 +289,7 @@ export async function runDoctor(flags) {
|
|
|
261
289
|
});
|
|
262
290
|
let accessibleProjects;
|
|
263
291
|
let environmentVersion;
|
|
292
|
+
let identity;
|
|
264
293
|
if (credentialsOk) {
|
|
265
294
|
const requestTimeoutMs = num(flags["request-timeout"], "--request-timeout");
|
|
266
295
|
const retryMaxAttempts = num(flags["retries"], "--retries");
|
|
@@ -318,6 +347,12 @@ export async function runDoctor(flags) {
|
|
|
318
347
|
details: errorDetails(error),
|
|
319
348
|
});
|
|
320
349
|
}
|
|
350
|
+
// Which principal the key acts as (personal vs global key, groups) explains
|
|
351
|
+
// 403s on objects the user's UI profile can use. Diagnostic only: an
|
|
352
|
+
// unanswered /auth/info (older DSS) never fails doctor.
|
|
353
|
+
if (accessibleProjects) {
|
|
354
|
+
identity = await client.get("/public/api/auth/info").then(doctorIdentityFromAuthInfo, () => undefined);
|
|
355
|
+
}
|
|
321
356
|
if (projectKey) {
|
|
322
357
|
try {
|
|
323
358
|
const project = await client.projects.get(projectKey);
|
|
@@ -341,7 +376,12 @@ export async function runDoctor(flags) {
|
|
|
341
376
|
}
|
|
342
377
|
}
|
|
343
378
|
}
|
|
344
|
-
const result = {
|
|
379
|
+
const result = {
|
|
380
|
+
ok: checks.every((check) => check.ok),
|
|
381
|
+
checks,
|
|
382
|
+
context,
|
|
383
|
+
...(identity ? { identity, } : {}),
|
|
384
|
+
};
|
|
345
385
|
if (flags["capabilities"] === true && credentialsOk) {
|
|
346
386
|
const requestTimeoutMs = num(flags["request-timeout"], "--request-timeout");
|
|
347
387
|
const retryMaxAttempts = num(flags["retries"], "--retries") ?? 1;
|
package/dist/src/cli/flags.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Positional arguments scanned with the same flag grammar as `parseArgs`, so
|
|
3
|
+
* error reporting can recover the invoked resource/action without depending
|
|
4
|
+
* on the command registry being loaded.
|
|
5
|
+
*/
|
|
6
|
+
export declare function rawPositionals(argv: string[]): string[];
|
|
1
7
|
/** Planning wins dispatch; dryRun remains set for combined plan metadata. */
|
|
2
8
|
export declare function executionMode(flags: Record<string, string | boolean>): {
|
|
3
9
|
readonly plan: boolean;
|
|
@@ -10,7 +16,7 @@ export declare const FLAG_ALIASES: Record<string, string>;
|
|
|
10
16
|
export declare const VALUE_FLAGS: Set<string>;
|
|
11
17
|
export declare const REPEATABLE_VALUE_FLAGS: Set<string>;
|
|
12
18
|
export declare const KNOWN_LONG_FLAGS: Set<string>;
|
|
13
|
-
export declare function normalizeLongFlag(rawFlagName: string): string;
|
|
19
|
+
export declare function normalizeLongFlag(rawFlagName: string, argv: string[]): string;
|
|
14
20
|
export declare function isNegativeNumberToken(value: string): boolean;
|
|
15
21
|
export declare function requireFlagValue(flagLabel: string, next: string | undefined): string;
|
|
16
22
|
export declare function setParsedFlagValue(flags: Record<string, string | boolean>, flagName: string, value: string): void;
|
package/dist/src/cli/flags.js
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
import { parseBooleanOption, } from "./coerce.js";
|
|
2
|
-
import { unsupportedHelpFlag, UsageError, } from "./usage.js";
|
|
2
|
+
import { unknownFlagError, unsupportedHelpFlag, UsageError, } from "./usage.js";
|
|
3
|
+
/**
|
|
4
|
+
* Positional arguments scanned with the same flag grammar as `parseArgs`, so
|
|
5
|
+
* error reporting can recover the invoked resource/action without depending
|
|
6
|
+
* on the command registry being loaded.
|
|
7
|
+
*/
|
|
8
|
+
export function rawPositionals(argv) {
|
|
9
|
+
const positionals = [];
|
|
10
|
+
for (let index = 0; index < argv.length; index++) {
|
|
11
|
+
const arg = argv[index];
|
|
12
|
+
if (arg === "--") {
|
|
13
|
+
positionals.push(...argv.slice(index + 1));
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
if (arg.startsWith("--")) {
|
|
17
|
+
const name = arg.slice(2).split("=")[0] ?? "";
|
|
18
|
+
const canonical = FLAG_ALIASES[name] ?? name;
|
|
19
|
+
if (!arg.includes("=") && VALUE_FLAGS.has(canonical))
|
|
20
|
+
index++;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (arg.length === 2 && arg[0] === "-" && arg[1] !== "-") {
|
|
24
|
+
const long = SHORT_FLAGS[arg[1]];
|
|
25
|
+
if (long && VALUE_FLAGS.has(long))
|
|
26
|
+
index++;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
positionals.push(arg);
|
|
30
|
+
}
|
|
31
|
+
return positionals;
|
|
32
|
+
}
|
|
33
|
+
/** Unknown flags name the invoked command, so the error carries its usage line. */
|
|
34
|
+
function commandUnknownFlagError(flagLabel, argv) {
|
|
35
|
+
const [resource, action,] = rawPositionals(argv);
|
|
36
|
+
return unknownFlagError(flagLabel, resource, action);
|
|
37
|
+
}
|
|
3
38
|
/** Planning wins dispatch; dryRun remains set for combined plan metadata. */
|
|
4
39
|
export function executionMode(flags) {
|
|
5
40
|
return {
|
|
@@ -31,11 +66,17 @@ export const BOOLEAN_FLAGS = new Set([
|
|
|
31
66
|
"if-exists",
|
|
32
67
|
"no-wait",
|
|
33
68
|
"force-rebuild",
|
|
69
|
+
"auto-update-schema",
|
|
34
70
|
"latest",
|
|
71
|
+
"full",
|
|
35
72
|
"copy-output-settings",
|
|
36
73
|
"copy-permissions",
|
|
37
74
|
"continue-on-error",
|
|
38
75
|
"no-backup",
|
|
76
|
+
"no-auto-rebuild",
|
|
77
|
+
"all-users",
|
|
78
|
+
"with-scenarios",
|
|
79
|
+
"for-everybody",
|
|
39
80
|
"payload-only",
|
|
40
81
|
"allow-same-path",
|
|
41
82
|
"sync",
|
|
@@ -249,6 +290,37 @@ export const VALUE_FLAGS = new Set([
|
|
|
249
290
|
"full-class-name",
|
|
250
291
|
"include-libs",
|
|
251
292
|
"archive",
|
|
293
|
+
"stop-at",
|
|
294
|
+
"mark-ok",
|
|
295
|
+
"template-file",
|
|
296
|
+
"group-by",
|
|
297
|
+
"aggregate",
|
|
298
|
+
"order-by",
|
|
299
|
+
"rename",
|
|
300
|
+
"fill-empty",
|
|
301
|
+
"formula",
|
|
302
|
+
"filter",
|
|
303
|
+
"drop-columns",
|
|
304
|
+
"keep-columns",
|
|
305
|
+
"columns",
|
|
306
|
+
"format-option",
|
|
307
|
+
"bundle-id",
|
|
308
|
+
"archive-path",
|
|
309
|
+
"project-folder",
|
|
310
|
+
"classes",
|
|
311
|
+
"version-id",
|
|
312
|
+
"evaluation-dataset",
|
|
313
|
+
"experiments",
|
|
314
|
+
"view-type",
|
|
315
|
+
"format",
|
|
316
|
+
"kind",
|
|
317
|
+
"features",
|
|
318
|
+
"sample-size",
|
|
319
|
+
"random-state",
|
|
320
|
+
"n-jobs",
|
|
321
|
+
"time-variable",
|
|
322
|
+
"timeseries-ids",
|
|
323
|
+
"full-reguess",
|
|
252
324
|
]);
|
|
253
325
|
export const REPEATABLE_VALUE_FLAGS = new Set([
|
|
254
326
|
"dataset",
|
|
@@ -269,12 +341,12 @@ export const KNOWN_LONG_FLAGS = new Set([
|
|
|
269
341
|
...Object.keys(FLAG_ALIASES),
|
|
270
342
|
...Object.values(FLAG_ALIASES),
|
|
271
343
|
]);
|
|
272
|
-
export function normalizeLongFlag(rawFlagName) {
|
|
344
|
+
export function normalizeLongFlag(rawFlagName, argv) {
|
|
273
345
|
if (rawFlagName === "help")
|
|
274
346
|
throw unsupportedHelpFlag();
|
|
275
347
|
const flagName = FLAG_ALIASES[rawFlagName] ?? rawFlagName;
|
|
276
348
|
if (!KNOWN_LONG_FLAGS.has(rawFlagName) && !KNOWN_LONG_FLAGS.has(flagName)) {
|
|
277
|
-
throw
|
|
349
|
+
throw commandUnknownFlagError(`--${rawFlagName}`, argv);
|
|
278
350
|
}
|
|
279
351
|
return flagName;
|
|
280
352
|
}
|
|
@@ -309,7 +381,7 @@ export function parseArgs(argv) {
|
|
|
309
381
|
const eqIdx = arg.indexOf("=");
|
|
310
382
|
if (eqIdx !== -1) {
|
|
311
383
|
const raw = arg.slice(2, eqIdx);
|
|
312
|
-
const flagName = normalizeLongFlag(raw);
|
|
384
|
+
const flagName = normalizeLongFlag(raw, argv);
|
|
313
385
|
const value = arg.slice(eqIdx + 1);
|
|
314
386
|
if (BOOLEAN_FLAGS.has(flagName)) {
|
|
315
387
|
flags[flagName] = parseBooleanOption(value, `--${flagName}`);
|
|
@@ -320,7 +392,7 @@ export function parseArgs(argv) {
|
|
|
320
392
|
}
|
|
321
393
|
else {
|
|
322
394
|
const rawFlagName = arg.slice(2);
|
|
323
|
-
const flagName = normalizeLongFlag(rawFlagName);
|
|
395
|
+
const flagName = normalizeLongFlag(rawFlagName, argv);
|
|
324
396
|
if (BOOLEAN_FLAGS.has(flagName)) {
|
|
325
397
|
flags[flagName] = true;
|
|
326
398
|
}
|
|
@@ -346,7 +418,7 @@ export function parseArgs(argv) {
|
|
|
346
418
|
else {
|
|
347
419
|
if (arg[1] === "h")
|
|
348
420
|
throw unsupportedHelpFlag();
|
|
349
|
-
throw
|
|
421
|
+
throw commandUnknownFlagError(`-${arg[1]}`, argv);
|
|
350
422
|
}
|
|
351
423
|
}
|
|
352
424
|
else {
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { randomUUID, } from "node:crypto";
|
|
2
1
|
import { DataikuError, } from "../../errors.js";
|
|
3
2
|
import { projectIncarnationHash, } from "../../utils/project-incarnation.js";
|
|
4
3
|
import { stableHash, stringField, } from "../coerce.js";
|
|
@@ -26,7 +25,7 @@ export const VISUAL_UI_GATE = {
|
|
|
26
25
|
* probed for absence and is never retried under an alternate key.
|
|
27
26
|
*/
|
|
28
27
|
export function generatedInstanceKey() {
|
|
29
|
-
return `APP_${randomUUID().replace(/-/g, "").toUpperCase()}`;
|
|
28
|
+
return `APP_${crypto.randomUUID().replace(/-/g, "").toUpperCase()}`;
|
|
30
29
|
}
|
|
31
30
|
/**
|
|
32
31
|
* DSS answers the app-manifest probe with 400 ("neither an app template nor an
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { DataikuClient } from "../../client.js";
|
|
2
|
+
import type { DocumentationTemplate } from "../../resources/documentation.js";
|
|
3
|
+
import type { DssTask, FutureWaitOptions } from "../../resources/futures.js";
|
|
4
|
+
import type { FutureWaitResult } from "../../schemas.js";
|
|
5
|
+
type Flags = Record<string, string | boolean>;
|
|
6
|
+
/** Documentation template from flags: --template-file, or --folder with --path, or the DSS default. */
|
|
7
|
+
export declare function documentationTemplateFromFlags(flags: Flags): DocumentationTemplate;
|
|
8
|
+
/** `--poll-interval` / `--timeout` for commands that wait on a DSS task. */
|
|
9
|
+
export declare function taskWaitOptions(flags: Flags): FutureWaitOptions;
|
|
10
|
+
/**
|
|
11
|
+
* Shared `generate-documentation` flow: return the started task; with
|
|
12
|
+
* --wait, its final state; with --output PATH, wait and download the docx
|
|
13
|
+
* named by the result's `exportId`. A failed or timed-out generation carries
|
|
14
|
+
* no exportId, so its state is returned instead.
|
|
15
|
+
*/
|
|
16
|
+
export declare function runDocumentationCommand(client: DataikuClient, flags: Flags, task: DssTask, download: (exportId: string) => Promise<Response>): Promise<DssTask | FutureWaitResult | {
|
|
17
|
+
path: string;
|
|
18
|
+
bytes: number;
|
|
19
|
+
exportId: string;
|
|
20
|
+
}>;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { writeResponseToFile, } from "../../utils/response-file.js";
|
|
2
|
+
import { num, } from "../coerce.js";
|
|
3
|
+
import { UsageError, } from "../usage.js";
|
|
4
|
+
/** Documentation template from flags: --template-file, or --folder with --path, or the DSS default. */
|
|
5
|
+
export function documentationTemplateFromFlags(flags) {
|
|
6
|
+
const file = flags["template-file"];
|
|
7
|
+
const folder = flags["folder"];
|
|
8
|
+
const path = flags["path"];
|
|
9
|
+
if (typeof file === "string" && (folder !== undefined || path !== undefined)) {
|
|
10
|
+
throw new UsageError("Use either --template-file or --folder with --path, not both.", "conflicting_input_sources");
|
|
11
|
+
}
|
|
12
|
+
if (typeof file === "string")
|
|
13
|
+
return { kind: "file", filePath: file, };
|
|
14
|
+
if (typeof folder === "string" || typeof path === "string") {
|
|
15
|
+
if (typeof folder !== "string" || typeof path !== "string") {
|
|
16
|
+
throw new UsageError("A template in a managed folder needs both --folder FOLDER_ID and --path PATH.", "missing_required_flag");
|
|
17
|
+
}
|
|
18
|
+
return { kind: "folder", folderId: folder, path, };
|
|
19
|
+
}
|
|
20
|
+
return { kind: "default", };
|
|
21
|
+
}
|
|
22
|
+
/** `--poll-interval` / `--timeout` for commands that wait on a DSS task. */
|
|
23
|
+
export function taskWaitOptions(flags) {
|
|
24
|
+
return {
|
|
25
|
+
pollIntervalMs: num(flags["poll-interval"], "--poll-interval"),
|
|
26
|
+
timeoutMs: num(flags["timeout"], "--timeout"),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Shared `generate-documentation` flow: return the started task; with
|
|
31
|
+
* --wait, its final state; with --output PATH, wait and download the docx
|
|
32
|
+
* named by the result's `exportId`. A failed or timed-out generation carries
|
|
33
|
+
* no exportId, so its state is returned instead.
|
|
34
|
+
*/
|
|
35
|
+
export async function runDocumentationCommand(client, flags, task, download) {
|
|
36
|
+
const output = flags["output"];
|
|
37
|
+
if (flags["wait"] !== true && typeof output !== "string")
|
|
38
|
+
return task;
|
|
39
|
+
const waited = await client.futures.waitTask(task, taskWaitOptions(flags));
|
|
40
|
+
if (typeof output !== "string")
|
|
41
|
+
return waited;
|
|
42
|
+
const result = waited.result;
|
|
43
|
+
const exportId = result && typeof result === "object" && "exportId" in result
|
|
44
|
+
? result.exportId
|
|
45
|
+
: undefined;
|
|
46
|
+
if (typeof exportId !== "string")
|
|
47
|
+
return waited;
|
|
48
|
+
return {
|
|
49
|
+
path: output,
|
|
50
|
+
bytes: await writeResponseToFile(output, await download(exportId)),
|
|
51
|
+
exportId,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { DataikuClient } from "../../client.js";
|
|
2
|
+
import { type ComputedModelDiagnostic, type ModelDiagnostic, type ModelDiagnosticsComputation, type TrainedModel } from "../../resources/trained-model.js";
|
|
3
|
+
import type { CommandDefinition } from "../types.js";
|
|
4
|
+
type Flags = Record<string, string | boolean>;
|
|
5
|
+
export declare function diagnosticKindFromFlags(flags: Flags): ModelDiagnostic;
|
|
6
|
+
/** `compute-diagnostics` flags → kind, features, and computation settings (shared with --plan). */
|
|
7
|
+
export declare function diagnosticsComputationFromFlags(flags: Flags): {
|
|
8
|
+
kind: ComputedModelDiagnostic;
|
|
9
|
+
features: string[];
|
|
10
|
+
computation: ModelDiagnosticsComputation;
|
|
11
|
+
};
|
|
12
|
+
export interface TrainedModelCommandSpec {
|
|
13
|
+
resource: "ml-task" | "saved-model";
|
|
14
|
+
/** Positional ids in examples, e.g. `ANALYSIS_ID TASK_ID MODEL_ID`. */
|
|
15
|
+
ids: string;
|
|
16
|
+
/** What one model is called in descriptions: "lab model" or "saved-model version". */
|
|
17
|
+
noun: string;
|
|
18
|
+
model: (client: DataikuClient, args: string[], projectKey: string | undefined) => TrainedModel;
|
|
19
|
+
downloadDocumentation: (client: DataikuClient, exportId: string, projectKey: string | undefined) => Promise<Response>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The actions lab models and saved-model versions share, over one
|
|
23
|
+
* {@link TrainedModel}: user meta, scoring exports, diagnostics, documentation.
|
|
24
|
+
*/
|
|
25
|
+
export declare function trainedModelCommands(spec: TrainedModelCommandSpec): Record<string, CommandDefinition>;
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { unexpectedResponseError, } from "../../errors.js";
|
|
2
|
+
import { COMPUTED_MODEL_DIAGNOSTICS, MODEL_DIAGNOSTICS, } from "../../resources/trained-model.js";
|
|
3
|
+
import { writeResponseToFile, } from "../../utils/response-file.js";
|
|
4
|
+
import { num, parseBooleanOption, requiredJsonInput, splitCsvFlag, } from "../coerce.js";
|
|
5
|
+
import { executionMode, } from "../flags.js";
|
|
6
|
+
import { commandUsage, } from "../syntax.js";
|
|
7
|
+
import { requireArgs, UsageError, } from "../usage.js";
|
|
8
|
+
import { documentationTemplateFromFlags, runDocumentationCommand, taskWaitOptions, } from "./documentation.js";
|
|
9
|
+
export function diagnosticKindFromFlags(flags) {
|
|
10
|
+
const kind = flags["kind"];
|
|
11
|
+
if (typeof kind !== "string" || MODEL_DIAGNOSTICS[kind] !== true) {
|
|
12
|
+
throw new UsageError(`--kind must be one of ${Object.keys(MODEL_DIAGNOSTICS).join(", ")}.`, "invalid_enum");
|
|
13
|
+
}
|
|
14
|
+
return kind;
|
|
15
|
+
}
|
|
16
|
+
/** `compute-diagnostics` flags → kind, features, and computation settings (shared with --plan). */
|
|
17
|
+
export function diagnosticsComputationFromFlags(flags) {
|
|
18
|
+
const kind = flags["kind"];
|
|
19
|
+
if (typeof kind !== "string" || COMPUTED_MODEL_DIAGNOSTICS[kind] !== true) {
|
|
20
|
+
throw new UsageError(`--kind must be one of ${Object.keys(COMPUTED_MODEL_DIAGNOSTICS).join(", ")}.`, "invalid_enum");
|
|
21
|
+
}
|
|
22
|
+
const sampleSize = num(flags["sample-size"], "--sample-size");
|
|
23
|
+
const randomState = num(flags["random-state"], "--random-state");
|
|
24
|
+
const nJobs = num(flags["n-jobs"], "--n-jobs");
|
|
25
|
+
return {
|
|
26
|
+
kind: kind,
|
|
27
|
+
features: splitCsvFlag(flags["features"]),
|
|
28
|
+
computation: {
|
|
29
|
+
...(sampleSize !== undefined ? { sampleSize, } : {}),
|
|
30
|
+
...(randomState !== undefined ? { randomState, } : {}),
|
|
31
|
+
...(nJobs !== undefined ? { nJobs, } : {}),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Write a binary export to `--output`; DSS answering without a body is an unexpected response. */
|
|
36
|
+
async function writeExport(res, out, operation) {
|
|
37
|
+
if (!res.body)
|
|
38
|
+
throw unexpectedResponseError(`${operation} response did not include a body`);
|
|
39
|
+
return { path: out, bytes: await writeResponseToFile(out, res), };
|
|
40
|
+
}
|
|
41
|
+
function requiredOutput(flags) {
|
|
42
|
+
const out = flags["output"];
|
|
43
|
+
if (typeof out !== "string") {
|
|
44
|
+
throw new UsageError("--output PATH is required.", "missing_required_flag");
|
|
45
|
+
}
|
|
46
|
+
return out;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* The actions lab models and saved-model versions share, over one
|
|
50
|
+
* {@link TrainedModel}: user meta, scoring exports, diagnostics, documentation.
|
|
51
|
+
*/
|
|
52
|
+
export function trainedModelCommands(spec) {
|
|
53
|
+
const { resource, ids, noun, } = spec;
|
|
54
|
+
const argCount = ids.split(" ").length;
|
|
55
|
+
const model = (c, a, f, action) => {
|
|
56
|
+
requireArgs(a, argCount, commandUsage(resource, action));
|
|
57
|
+
return spec.model(c, a, f["project-key"]);
|
|
58
|
+
};
|
|
59
|
+
return {
|
|
60
|
+
"set-user-meta": {
|
|
61
|
+
handler: async (c, a, f) => {
|
|
62
|
+
const target = model(c, a, f, "set-user-meta");
|
|
63
|
+
const userMeta = requiredJsonInput(f, "User-meta JSON is required via --data, --data-file, or --stdin.");
|
|
64
|
+
if (executionMode(f).dryRun) {
|
|
65
|
+
return {
|
|
66
|
+
dryRun: true,
|
|
67
|
+
action: "set-user-meta",
|
|
68
|
+
resource,
|
|
69
|
+
ids: a.slice(0, argCount),
|
|
70
|
+
payload: userMeta,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
await target.setUserMeta(userMeta);
|
|
74
|
+
return { updated: a[argCount - 1], resource, };
|
|
75
|
+
},
|
|
76
|
+
description: `Update the user metadata (name, description, labels, ...) of a ${noun}. Send only the "userMeta" field of its details, edited.`,
|
|
77
|
+
examples: [
|
|
78
|
+
`dss ${resource} set-user-meta ${ids} --data '{"name":"Churn model","description":"v2"}'`,
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
"download-scoring-jar": {
|
|
82
|
+
handler: async (c, a, f) => {
|
|
83
|
+
const target = model(c, a, f, "download-scoring-jar");
|
|
84
|
+
const out = requiredOutput(f);
|
|
85
|
+
const fullClassName = f["full-class-name"];
|
|
86
|
+
const res = await target.downloadScoringJar({
|
|
87
|
+
...(typeof fullClassName === "string" ? { fullClassName, } : {}),
|
|
88
|
+
...(f["include-libs"] !== undefined
|
|
89
|
+
? { includeLibs: parseBooleanOption(f["include-libs"], "--include-libs"), }
|
|
90
|
+
: {}),
|
|
91
|
+
});
|
|
92
|
+
return writeExport(res, out, "Scoring JAR download");
|
|
93
|
+
},
|
|
94
|
+
description: `Download the optimized scoring JAR of a ${noun} (license-gated server side). --full-class-name sets the Java class; --include-libs toggles bundling the scoring libraries.`,
|
|
95
|
+
examples: [`dss ${resource} download-scoring-jar ${ids} --output ./scoring.jar`,],
|
|
96
|
+
},
|
|
97
|
+
"download-scoring-pmml": {
|
|
98
|
+
handler: async (c, a, f) => {
|
|
99
|
+
const target = model(c, a, f, "download-scoring-pmml");
|
|
100
|
+
const out = requiredOutput(f);
|
|
101
|
+
return writeExport(await target.downloadScoringPmml(), out, "Scoring PMML download");
|
|
102
|
+
},
|
|
103
|
+
description: `Download the PMML scoring file of a ${noun} (license-gated server side).`,
|
|
104
|
+
examples: [`dss ${resource} download-scoring-pmml ${ids} --output ./model.pmml`,],
|
|
105
|
+
},
|
|
106
|
+
diagnostics: {
|
|
107
|
+
handler: (c, a, f) => model(c, a, f, "diagnostics").get(diagnosticKindFromFlags(f)),
|
|
108
|
+
description: `Read computed diagnostics of a ${noun}: subpopulation-analyses, partial-dependencies, timeseries-residuals, or (forecasting) per-timeseries-metrics / per-timeseries-evaluation-forecasts.`,
|
|
109
|
+
examples: [`dss ${resource} diagnostics ${ids} --kind partial-dependencies`,],
|
|
110
|
+
},
|
|
111
|
+
"compute-diagnostics": {
|
|
112
|
+
handler: async (c, a, f) => {
|
|
113
|
+
const target = model(c, a, f, "compute-diagnostics");
|
|
114
|
+
const { kind, features, computation, } = diagnosticsComputationFromFlags(f);
|
|
115
|
+
const task = await target.compute(kind, features, computation);
|
|
116
|
+
return f["wait"] === true ? c.futures.waitTask(task, taskWaitOptions(f)) : task;
|
|
117
|
+
},
|
|
118
|
+
description: `Compute subpopulation-analyses or partial-dependencies over --features COLS (--sample-size N, default 10000), or timeseries-residuals, for a ${noun}. Returns the DSS future; --wait waits and returns the result.`,
|
|
119
|
+
examples: [
|
|
120
|
+
`dss ${resource} compute-diagnostics ${ids} --kind partial-dependencies --features age,income --wait`,
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
"generate-documentation": {
|
|
124
|
+
handler: async (c, a, f) => {
|
|
125
|
+
const target = model(c, a, f, "generate-documentation");
|
|
126
|
+
const pk = f["project-key"];
|
|
127
|
+
const task = await target.generateDocumentation(documentationTemplateFromFlags(f));
|
|
128
|
+
return runDocumentationCommand(c, f, task, (exportId) => spec.downloadDocumentation(c, exportId, pk));
|
|
129
|
+
},
|
|
130
|
+
description: `Generate the model documentation (Word docx) of a ${noun} from the DSS default template, an uploaded --template-file, or a template in a managed folder (--folder FOLDER_ID --path PATH). Returns the DSS future; --wait waits; --output PATH waits and downloads.`,
|
|
131
|
+
examples: [`dss ${resource} generate-documentation ${ids} --output model.docx`,],
|
|
132
|
+
},
|
|
133
|
+
"download-documentation": {
|
|
134
|
+
handler: async (c, a, f) => {
|
|
135
|
+
requireArgs(a, 1, commandUsage(resource, "download-documentation"));
|
|
136
|
+
const out = requiredOutput(f);
|
|
137
|
+
const res = await spec.downloadDocumentation(c, a[0], f["project-key"]);
|
|
138
|
+
return writeExport(res, out, "Model documentation download");
|
|
139
|
+
},
|
|
140
|
+
description: "Download a generated model documentation by the exportId from a finished generate-documentation future.",
|
|
141
|
+
examples: [`dss ${resource} download-documentation EXPORT_ID --output model.docx`,],
|
|
142
|
+
},
|
|
143
|
+
};
|
|
144
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shape a `*.list` result for agents: `--contains` filters on identifier
|
|
3
|
+
* fields, `--limit` caps the count (a `list_truncated` warning reports the
|
|
4
|
+
* total), and large DSS objects compact to their decision fields unless
|
|
5
|
+
* `--full` or `--fields` asks for the DSS objects.
|
|
6
|
+
*/
|
|
7
|
+
export declare function shapeListResult(resource: string, result: unknown, flags: Record<string, string | boolean>): unknown;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { num, } from "./coerce.js";
|
|
2
|
+
import { COMPACT_LIST_FIELDS, } from "./list-shapes.js";
|
|
3
|
+
import { enqueueCliWarning, } from "./output.js";
|
|
4
|
+
function record(value) {
|
|
5
|
+
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
6
|
+
}
|
|
7
|
+
function compactValue(item, spec) {
|
|
8
|
+
let value = item;
|
|
9
|
+
for (const key of spec.path.split("."))
|
|
10
|
+
value = record(value)[key];
|
|
11
|
+
if (spec.roleRefs !== true)
|
|
12
|
+
return value;
|
|
13
|
+
// Dataset refs across every role of recipe inputs/outputs (`{main:{items:[{ref}]}}`).
|
|
14
|
+
return Object.values(record(value)).flatMap((role) => {
|
|
15
|
+
const items = record(role).items;
|
|
16
|
+
return Array.isArray(items)
|
|
17
|
+
? items.flatMap((entry) => {
|
|
18
|
+
const ref = record(entry).ref;
|
|
19
|
+
return typeof ref === "string" ? [ref,] : [];
|
|
20
|
+
})
|
|
21
|
+
: [];
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
/** Identifier fields `--contains` matches; string items match themselves. */
|
|
25
|
+
const IDENTIFIER_FIELDS = [
|
|
26
|
+
"id",
|
|
27
|
+
"name",
|
|
28
|
+
"projectKey",
|
|
29
|
+
"envName",
|
|
30
|
+
"login",
|
|
31
|
+
"displayName",
|
|
32
|
+
"label",
|
|
33
|
+
"runnableType",
|
|
34
|
+
];
|
|
35
|
+
/** `job list` filters by --contains/--limit itself (job name, state, outputs). */
|
|
36
|
+
const LISTS_WITH_OWN_FILTERS = { job: true, };
|
|
37
|
+
function itemMatches(item, needle) {
|
|
38
|
+
if (typeof item === "string")
|
|
39
|
+
return item.toLowerCase().includes(needle);
|
|
40
|
+
const fields = record(item);
|
|
41
|
+
return IDENTIFIER_FIELDS.some((field) => {
|
|
42
|
+
const value = fields[field];
|
|
43
|
+
return typeof value === "string" && value.toLowerCase().includes(needle);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Shape a `*.list` result for agents: `--contains` filters on identifier
|
|
48
|
+
* fields, `--limit` caps the count (a `list_truncated` warning reports the
|
|
49
|
+
* total), and large DSS objects compact to their decision fields unless
|
|
50
|
+
* `--full` or `--fields` asks for the DSS objects.
|
|
51
|
+
*/
|
|
52
|
+
export function shapeListResult(resource, result, flags) {
|
|
53
|
+
if (!Array.isArray(result))
|
|
54
|
+
return result;
|
|
55
|
+
let items = result;
|
|
56
|
+
if (LISTS_WITH_OWN_FILTERS[resource] !== true) {
|
|
57
|
+
const contains = flags["contains"];
|
|
58
|
+
if (typeof contains === "string" && contains.length > 0) {
|
|
59
|
+
const needle = contains.toLowerCase();
|
|
60
|
+
items = items.filter((item) => itemMatches(item, needle));
|
|
61
|
+
}
|
|
62
|
+
const limit = num(flags["limit"], "--limit");
|
|
63
|
+
if (limit !== undefined && items.length > limit) {
|
|
64
|
+
enqueueCliWarning({
|
|
65
|
+
code: "list_truncated",
|
|
66
|
+
shown: limit,
|
|
67
|
+
total: items.length,
|
|
68
|
+
hint: "Raise --limit or narrow with --contains.",
|
|
69
|
+
});
|
|
70
|
+
items = items.slice(0, Math.max(0, limit));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const fields = COMPACT_LIST_FIELDS[resource];
|
|
74
|
+
if (!fields || flags["full"] === true || typeof flags["fields"] === "string")
|
|
75
|
+
return items;
|
|
76
|
+
return items.map((item) => Object.fromEntries(Object.entries(fields).map(([name, spec,]) => [name, compactValue(record(item), spec),])));
|
|
77
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compact `RESOURCE.list` item shapes, as plain data shared by the runtime
|
|
3
|
+
* mapper (src/cli/list-output.ts) and the discovery output schemas
|
|
4
|
+
* (src/cli/output-schemas.ts), so the advertised schema is the emitted shape.
|
|
5
|
+
*/
|
|
6
|
+
/** Where a compact field comes from in the DSS object, and its JSON Schema. */
|
|
7
|
+
export interface CompactListField {
|
|
8
|
+
/** Dotted path into the DSS list item. */
|
|
9
|
+
path: string;
|
|
10
|
+
/** Flatten recipe roles (`{main:{items:[{ref}]}}`) to the dataset refs. */
|
|
11
|
+
roleRefs?: true;
|
|
12
|
+
schema: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Lists whose DSS objects are large: the identifier the follow-up get/build
|
|
16
|
+
* commands take, the kind, and the one or two attributes that decide what to
|
|
17
|
+
* call next. Lists not named here keep the DSS objects.
|
|
18
|
+
*/
|
|
19
|
+
export declare const COMPACT_LIST_FIELDS: Record<string, Record<string, CompactListField>>;
|
|
20
|
+
/** Discovery output schemas of the compact `RESOURCE.list` defaults. */
|
|
21
|
+
export declare function compactListOutputSchemas(): Record<string, Record<string, unknown>>;
|