dataiku-sdk 3.2.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.
- package/README.md +149 -46
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +102 -0
- package/dist/packages/types/src/index.js +76 -0
- package/dist/src/cli/commands/app.js +57 -15
- package/dist/src/cli/commands/bundle.js +1 -1
- package/dist/src/cli/commands/code-env.js +13 -7
- package/dist/src/cli/commands/connection.d.ts +9 -0
- package/dist/src/cli/commands/connection.js +267 -1
- package/dist/src/cli/commands/data-collection.d.ts +2 -0
- package/dist/src/cli/commands/data-collection.js +164 -0
- package/dist/src/cli/commands/dataset.js +161 -32
- package/dist/src/cli/commands/future.js +2 -2
- package/dist/src/cli/commands/group.d.ts +2 -0
- package/dist/src/cli/commands/group.js +109 -0
- package/dist/src/cli/commands/index.js +151 -78
- package/dist/src/cli/commands/knowledge-bank.d.ts +2 -0
- package/dist/src/cli/commands/knowledge-bank.js +80 -0
- package/dist/src/cli/commands/llm.d.ts +2 -0
- package/dist/src/cli/commands/llm.js +93 -0
- package/dist/src/cli/commands/macro.d.ts +2 -0
- package/dist/src/cli/commands/macro.js +221 -0
- package/dist/src/cli/commands/ml-task.js +18 -6
- package/dist/src/cli/commands/notebook.js +6 -2
- package/dist/src/cli/commands/plugin.d.ts +2 -0
- package/dist/src/cli/commands/plugin.js +799 -0
- package/dist/src/cli/commands/project-folder.d.ts +2 -0
- package/dist/src/cli/commands/project-folder.js +197 -0
- package/dist/src/cli/commands/project-git.js +14 -54
- package/dist/src/cli/commands/project.js +52 -6
- package/dist/src/cli/commands/recipe.js +36 -1
- package/dist/src/cli/commands/saved-model.d.ts +5 -0
- package/dist/src/cli/commands/saved-model.js +388 -1
- package/dist/src/cli/commands/scenario.js +138 -1
- package/dist/src/cli/commands/user.d.ts +8 -0
- package/dist/src/cli/commands/user.js +296 -0
- package/dist/src/cli/contract.d.ts +1 -2
- package/dist/src/cli/contract.js +1089 -103
- package/dist/src/cli/flags.js +30 -1
- package/dist/src/cli/helpers/app-successor.d.ts +19 -4
- package/dist/src/cli/helpers/app-successor.js +90 -30
- package/dist/src/cli/helpers/cleanup.js +3 -1
- package/dist/src/cli/helpers/flow-zone.js +1 -2
- package/dist/src/cli/output.d.ts +1 -1
- package/dist/src/cli/output.js +23 -10
- package/dist/src/cli/usage.d.ts +1 -0
- package/dist/src/cli/usage.js +47 -1
- package/dist/src/cli.js +147 -41
- package/dist/src/client.d.ts +83 -5
- package/dist/src/client.js +185 -29
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.js +2 -0
- package/dist/src/index.d.ts +16 -7
- package/dist/src/index.js +11 -2
- package/dist/src/resources/analyses.js +1 -8
- package/dist/src/resources/applications.d.ts +8 -6
- package/dist/src/resources/applications.js +21 -21
- package/dist/src/resources/base.d.ts +4 -0
- package/dist/src/resources/base.js +15 -0
- package/dist/src/resources/bundles.d.ts +9 -4
- package/dist/src/resources/bundles.js +10 -5
- package/dist/src/resources/connections.d.ts +78 -1
- package/dist/src/resources/connections.js +132 -1
- package/dist/src/resources/data-collections.d.ts +118 -0
- package/dist/src/resources/data-collections.js +49 -0
- package/dist/src/resources/datasets.d.ts +69 -0
- package/dist/src/resources/datasets.js +99 -1
- package/dist/src/resources/futures.d.ts +4 -1
- package/dist/src/resources/futures.js +38 -6
- package/dist/src/resources/groups.d.ts +47 -0
- package/dist/src/resources/groups.js +56 -0
- package/dist/src/resources/jobs.d.ts +8 -13
- package/dist/src/resources/jobs.js +41 -16
- package/dist/src/resources/knowledge-banks.d.ts +58 -0
- package/dist/src/resources/knowledge-banks.js +61 -0
- package/dist/src/resources/llms.d.ts +92 -0
- package/dist/src/resources/llms.js +62 -0
- package/dist/src/resources/macros.d.ts +121 -0
- package/dist/src/resources/macros.js +231 -0
- package/dist/src/resources/ml-tasks.d.ts +37 -2
- package/dist/src/resources/ml-tasks.js +100 -20
- package/dist/src/resources/model-evaluation-stores.js +1 -8
- package/dist/src/resources/notebooks.d.ts +43 -7
- package/dist/src/resources/notebooks.js +53 -13
- package/dist/src/resources/plugins.d.ts +265 -0
- package/dist/src/resources/plugins.js +458 -0
- package/dist/src/resources/project-folders.d.ts +71 -0
- package/dist/src/resources/project-folders.js +57 -0
- package/dist/src/resources/project-git.d.ts +6 -0
- package/dist/src/resources/project-git.js +69 -42
- package/dist/src/resources/project-library.d.ts +0 -1
- package/dist/src/resources/project-library.js +1 -17
- package/dist/src/resources/projects.d.ts +19 -1
- package/dist/src/resources/projects.js +27 -1
- package/dist/src/resources/recipes.d.ts +15 -1
- package/dist/src/resources/recipes.js +73 -6
- package/dist/src/resources/saved-models.d.ts +134 -1
- package/dist/src/resources/saved-models.js +214 -6
- package/dist/src/resources/scenarios.d.ts +105 -0
- package/dist/src/resources/scenarios.js +232 -106
- package/dist/src/resources/sql.js +5 -1
- package/dist/src/resources/users.d.ts +129 -0
- package/dist/src/resources/users.js +128 -0
- package/dist/src/resources/webapps.d.ts +15 -2
- package/dist/src/resources/webapps.js +18 -4
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/utils/deep-merge.d.ts +1 -1
- package/dist/src/utils/polling.d.ts +20 -0
- package/dist/src/utils/polling.js +27 -0
- package/dist/src/utils/response-file.js +1 -1
- package/dist/src/utils/secret-sanitize.d.ts +54 -0
- package/dist/src/utils/secret-sanitize.js +101 -0
- package/package.json +6 -5
- package/packages/types/dist/index.d.ts +102 -0
- package/packages/types/dist/index.js +76 -0
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +7 -5
- package/skills/dataiku-dss/references/app-releases.md +8 -7
- package/skills/dataiku-dss/references/discovery.md +4 -4
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { ClientValidationError,
|
|
1
|
+
import { ClientValidationError, } from "../errors.js";
|
|
2
2
|
import { ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagsSchema, } from "../schemas.js";
|
|
3
|
+
import { computeNextPollDelayMs, isRequestDeadlineError, } from "../utils/polling.js";
|
|
4
|
+
import { sanitizeErrorSecrets, } from "../utils/secret-sanitize.js";
|
|
3
5
|
import { BaseResource, } from "./base.js";
|
|
4
6
|
/**
|
|
5
7
|
* The per-project Git routes exist only under the dataikuapi base, not under
|
|
@@ -89,28 +91,10 @@ function validatedRepository(repository, field) {
|
|
|
89
91
|
return candidate;
|
|
90
92
|
}
|
|
91
93
|
/** Replace every exact occurrence of a secret so echoed errors cannot leak it. */
|
|
92
|
-
function redactSecrets(text, secrets) {
|
|
93
|
-
let result = text;
|
|
94
|
-
for (const secret of secrets) {
|
|
95
|
-
if (secret !== undefined && secret !== "") {
|
|
96
|
-
result = result.split(secret).join("[redacted]");
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
return result;
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* Strip a password that a server misconfiguration may have echoed from an
|
|
103
|
-
* error response. `DataikuError.message` was built at construction, so the
|
|
104
|
-
* raw body, the message, and the stack all need scrubbing.
|
|
105
|
-
*/
|
|
106
94
|
function scrubErrorSecrets(error, secrets) {
|
|
107
|
-
if (
|
|
95
|
+
if (secrets.length === 0)
|
|
108
96
|
return;
|
|
109
|
-
error
|
|
110
|
-
error.message = redactSecrets(error.message, secrets);
|
|
111
|
-
if (typeof error.stack === "string") {
|
|
112
|
-
error.stack = redactSecrets(error.stack, secrets);
|
|
113
|
-
}
|
|
97
|
+
sanitizeErrorSecrets(error, { sensitiveKeys: {}, secrets, });
|
|
114
98
|
}
|
|
115
99
|
function describeFutureFailure(error) {
|
|
116
100
|
if (error === undefined || error === null)
|
|
@@ -129,6 +113,31 @@ function describeFutureFailure(error) {
|
|
|
129
113
|
return String(error);
|
|
130
114
|
}
|
|
131
115
|
/* ------------------------------------------------------------------ */
|
|
116
|
+
/**
|
|
117
|
+
* DSS answers the lib-git-refs listing as an object map of attached external
|
|
118
|
+
* libraries keyed by target path alongside code-library metadata (observed
|
|
119
|
+
* raw on DSS 15: `{gitReferences, pythonPath, rsrcPath,
|
|
120
|
+
* importLibrariesFromProjects}`), while the official Python client and this
|
|
121
|
+
* resource's typed contract expose a plain array. Normalize the map into
|
|
122
|
+
* entries, preserving each key as the library's `localTargetPath`; a bare
|
|
123
|
+
* array passes through untouched.
|
|
124
|
+
*/
|
|
125
|
+
function normalizeLibraryList(raw) {
|
|
126
|
+
if (Array.isArray(raw) || raw === undefined || raw === null)
|
|
127
|
+
return raw ?? [];
|
|
128
|
+
if (typeof raw !== "object")
|
|
129
|
+
return raw;
|
|
130
|
+
const record = raw;
|
|
131
|
+
const refs = record["gitReferences"];
|
|
132
|
+
if (refs === undefined || refs === null || typeof refs !== "object" || Array.isArray(refs)) {
|
|
133
|
+
return raw;
|
|
134
|
+
}
|
|
135
|
+
return Object.entries(refs).map(([localTargetPath, spec,]) => ({
|
|
136
|
+
localTargetPath,
|
|
137
|
+
...(typeof spec === "object" && spec !== null ? spec : {}),
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
/* ------------------------------------------------------------------ */
|
|
132
141
|
/* Resource */
|
|
133
142
|
/* ------------------------------------------------------------------ */
|
|
134
143
|
export class ProjectGitResource extends BaseResource {
|
|
@@ -287,7 +296,7 @@ export class ProjectGitResource extends BaseResource {
|
|
|
287
296
|
/* ---- external libraries (async futures) ---- */
|
|
288
297
|
async listLibraries(projectKey) {
|
|
289
298
|
const raw = await this.request("GET", `${this.libraryPath(projectKey)}/`);
|
|
290
|
-
return this.client.safeParse(ProjectGitLibrariesSchema, raw
|
|
299
|
+
return this.client.safeParse(ProjectGitLibrariesSchema, normalizeLibraryList(raw), "projectGit.listLibraries");
|
|
291
300
|
}
|
|
292
301
|
/** Attach an external Git library. Runs as a DSS future. */
|
|
293
302
|
async addLibrary(projectKey, options) {
|
|
@@ -355,7 +364,7 @@ export class ProjectGitResource extends BaseResource {
|
|
|
355
364
|
* what polling loops want; the default consumes it like the Python client.
|
|
356
365
|
*/
|
|
357
366
|
async getFutureState(jobId, options = {}) {
|
|
358
|
-
const raw = await this.request("GET", `/futures/${encodeURIComponent(jobId)}${this.query({ peek: options.peek === true, })}
|
|
367
|
+
const raw = await this.request("GET", `/futures/${encodeURIComponent(jobId)}${this.query({ peek: options.peek === true, })}`, undefined, [], { timeoutMs: options.timeoutMs, });
|
|
359
368
|
return this.client.safeParse(ProjectGitFutureStateSchema, raw ?? {}, "projectGit.getFutureState");
|
|
360
369
|
}
|
|
361
370
|
/** Abort a running future. */
|
|
@@ -376,10 +385,36 @@ export class ProjectGitResource extends BaseResource {
|
|
|
376
385
|
if (!Number.isFinite(timeoutMs) || timeoutMs < 0) {
|
|
377
386
|
throw new ClientValidationError("timeoutMs must be a finite non-negative number.");
|
|
378
387
|
}
|
|
388
|
+
// Adaptive backoff applies only when the caller did not pin an exact
|
|
389
|
+
// interval; an explicit pollIntervalMs is an exact contract.
|
|
390
|
+
const adaptiveEnabled = options.pollIntervalMs === undefined;
|
|
391
|
+
let pollCount = 0;
|
|
379
392
|
const startedAt = Date.now();
|
|
380
393
|
while (true) {
|
|
381
394
|
// Unlike peek state, the ordinary state includes the completed result.
|
|
382
|
-
|
|
395
|
+
// One state observation always happens, even when the budget is
|
|
396
|
+
// already spent (the poll precedes the deadline check); only the
|
|
397
|
+
// requests issued while budget remains are bounded by the remaining
|
|
398
|
+
// time, so a stalled endpoint can never defeat the caller's deadline.
|
|
399
|
+
const remainingMs = timeoutMs - (Date.now() - startedAt);
|
|
400
|
+
pollCount += 1;
|
|
401
|
+
let state;
|
|
402
|
+
try {
|
|
403
|
+
state = await this.getFutureState(jobId, remainingMs > 0
|
|
404
|
+
? {
|
|
405
|
+
peek: false,
|
|
406
|
+
timeoutMs: remainingMs,
|
|
407
|
+
}
|
|
408
|
+
: { peek: false, });
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
// The poll budget ran out mid-request: report the documented
|
|
412
|
+
// timeout failure instead of letting the transport deadline
|
|
413
|
+
// error escape.
|
|
414
|
+
if (!isRequestDeadlineError(error, startedAt + timeoutMs))
|
|
415
|
+
throw error;
|
|
416
|
+
throw new Error(`Timed out after ${String(Date.now() - startedAt)}ms waiting for Dataiku future ${jobId}`, { cause: error, });
|
|
417
|
+
}
|
|
383
418
|
const failure = describeFutureFailure(state.error);
|
|
384
419
|
if (failure !== undefined) {
|
|
385
420
|
throw new Error(`Dataiku future ${jobId} failed: ${failure}`);
|
|
@@ -395,13 +430,18 @@ export class ProjectGitResource extends BaseResource {
|
|
|
395
430
|
if (state.alive === false) {
|
|
396
431
|
throw new Error(`Dataiku future ${jobId} ended without producing a result`);
|
|
397
432
|
}
|
|
398
|
-
// Only the remaining budget is slept, so a caller's deadline is never
|
|
399
|
-
// overshot by a whole poll interval.
|
|
400
433
|
const elapsedMs = Date.now() - startedAt;
|
|
401
434
|
if (elapsedMs >= timeoutMs) {
|
|
402
435
|
throw new Error(`Timed out after ${String(elapsedMs)}ms waiting for Dataiku future ${jobId}`);
|
|
403
436
|
}
|
|
404
|
-
|
|
437
|
+
const nextDelayMs = computeNextPollDelayMs({
|
|
438
|
+
pollCount,
|
|
439
|
+
baseIntervalMs: pollIntervalMs,
|
|
440
|
+
adaptiveEnabled,
|
|
441
|
+
});
|
|
442
|
+
// Only the remaining budget is slept, so a caller's deadline is never
|
|
443
|
+
// overshot by a whole interval.
|
|
444
|
+
await sleep(Math.min(nextDelayMs, timeoutMs - elapsedMs));
|
|
405
445
|
}
|
|
406
446
|
}
|
|
407
447
|
/* ---- private ---- */
|
|
@@ -424,22 +464,9 @@ export class ProjectGitResource extends BaseResource {
|
|
|
424
464
|
const queryString = search.toString();
|
|
425
465
|
return queryString === "" ? "" : `?${queryString}`;
|
|
426
466
|
}
|
|
427
|
-
async request(method, path, body, secrets = []) {
|
|
428
|
-
const transport = this.client;
|
|
429
|
-
const init = {
|
|
430
|
-
method,
|
|
431
|
-
headers: {
|
|
432
|
-
// The Git routes are only reachable with dataikuapi-style Basic auth:
|
|
433
|
-
// API key as the username, empty password.
|
|
434
|
-
Authorization: `Basic ${Buffer.from(`${transport.apiKey}:`, "utf8").toString("base64")}`,
|
|
435
|
-
Accept: "application/json",
|
|
436
|
-
"Content-Type": "application/json",
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
if (body !== undefined)
|
|
440
|
-
init.body = JSON.stringify(body);
|
|
467
|
+
async request(method, path, body, secrets = [], opts = {}) {
|
|
441
468
|
try {
|
|
442
|
-
const res = await
|
|
469
|
+
const res = await this.client.requestGit(method, `${GIT_API_BASE}${path}`, body, opts.timeoutMs === undefined ? undefined : Date.now() + opts.timeoutMs);
|
|
443
470
|
const text = await res.text();
|
|
444
471
|
if (text.trim() === "")
|
|
445
472
|
return undefined;
|
|
@@ -147,7 +147,6 @@ export declare class ProjectLibraryResource extends BaseResource {
|
|
|
147
147
|
/** Move a project code-library file or folder into another library folder. */
|
|
148
148
|
move(path: string, destinationFolderPath: string, projectKey?: string): Promise<void>;
|
|
149
149
|
private contentsPath;
|
|
150
|
-
private postRawBody;
|
|
151
150
|
private alreadyExistsError;
|
|
152
151
|
private assertLibraryFileAbsent;
|
|
153
152
|
}
|
|
@@ -403,7 +403,7 @@ export class ProjectLibraryResource extends BaseResource {
|
|
|
403
403
|
}
|
|
404
404
|
const bytes = typeof content === "string" ? Buffer.from(content, "utf8") : content;
|
|
405
405
|
const sha256 = sha256Hex(bytes);
|
|
406
|
-
await this.postRawBody(this.contentsPath(valid, projectKey), content);
|
|
406
|
+
await this.client.postRawBody(this.contentsPath(valid, projectKey), content);
|
|
407
407
|
return {
|
|
408
408
|
path: valid,
|
|
409
409
|
bytes: bytes.length,
|
|
@@ -518,22 +518,6 @@ export class ProjectLibraryResource extends BaseResource {
|
|
|
518
518
|
const projectKeyPart = this.enc(projectKey);
|
|
519
519
|
return `/public/api/projects/${projectKeyPart}/libraries/contents/${encodeLibraryPath(path)}`;
|
|
520
520
|
}
|
|
521
|
-
async postRawBody(path, body) {
|
|
522
|
-
// DSS library writes use dataikuapi's raw_body; route through the client's
|
|
523
|
-
// transport so auth, retries, TLS options, and DSS error handling stay aligned.
|
|
524
|
-
// BodyInit rejects plain Uint8Array views, so non-Buffer bytes are copied
|
|
525
|
-
// into a Buffer (an ArrayBufferView BodyInit accepts).
|
|
526
|
-
const payload = body instanceof Uint8Array && !(body instanceof Buffer)
|
|
527
|
-
? Buffer.from(body.buffer, body.byteOffset, body.byteLength)
|
|
528
|
-
: body;
|
|
529
|
-
const rawClient = this.client;
|
|
530
|
-
const res = await rawClient.fetchWithRetry(`${rawClient.baseUrl}${path}`, {
|
|
531
|
-
method: "POST",
|
|
532
|
-
headers: rawClient.getAnyHeaders(),
|
|
533
|
-
body: payload,
|
|
534
|
-
});
|
|
535
|
-
await res.text();
|
|
536
|
-
}
|
|
537
521
|
alreadyExistsError(path) {
|
|
538
522
|
return new ClientValidationError(`Project library item "${path}" already exists.`, "validation_failed", "Refuse to overwrite an existing item; delete it first, or use the create-or-replace update to replace an existing file.", { path, });
|
|
539
523
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { FlowMapOptions, ProjectDetails, ProjectMetadata, ProjectSummary } from "../schemas.js";
|
|
1
|
+
import type { FlowMapOptions, ProjectDetails, ProjectMetadata, ProjectSummary, ProjectTags } from "../schemas.js";
|
|
2
2
|
import type { AnalyzedFlowMap, FlowMapRendering } from "../utils/flow-analysis.js";
|
|
3
3
|
import { BaseResource } from "./base.js";
|
|
4
4
|
interface FlowMapTruncationSummary {
|
|
@@ -124,6 +124,24 @@ export declare class ProjectsResource extends BaseResource {
|
|
|
124
124
|
get(projectKey?: string): Promise<ProjectDetails>;
|
|
125
125
|
/** Get metadata (tags, custom fields, checklists) for a project. */
|
|
126
126
|
metadata(projectKey?: string): Promise<ProjectMetadata>;
|
|
127
|
+
/**
|
|
128
|
+
* Replace project metadata with the supplied full object.
|
|
129
|
+
*
|
|
130
|
+
* DSS PUT semantics replace the whole metadata object: pass a metadata
|
|
131
|
+
* object obtained from {@link metadata}, edit it, and send it back — fields
|
|
132
|
+
* absent from the payload are removed from the project.
|
|
133
|
+
*/
|
|
134
|
+
setMetadata(projectKey: string | undefined, metadata: ProjectMetadata): Promise<void>;
|
|
135
|
+
/** Get project-level tags (tag name → {color?}). */
|
|
136
|
+
tags(projectKey?: string): Promise<ProjectTags>;
|
|
137
|
+
/**
|
|
138
|
+
* Replace project-level tags with the supplied full object.
|
|
139
|
+
*
|
|
140
|
+
* DSS PUT semantics replace the whole tags dictionary: pass a tags object
|
|
141
|
+
* obtained from {@link tags}, edit it, and send it back — tags absent from
|
|
142
|
+
* the payload are removed from the project.
|
|
143
|
+
*/
|
|
144
|
+
setTags(projectKey: string | undefined, tags: ProjectTags): Promise<void>;
|
|
127
145
|
/** Get the raw flow graph for a project. */
|
|
128
146
|
flow(projectKey?: string): Promise<unknown>;
|
|
129
147
|
/** Compute a stable fingerprint of flow nodes and edges, excluding visual metadata. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ClientValidationError, DataikuError, } from "../errors.js";
|
|
2
2
|
import { writeResponseToFile, } from "../utils/response-file.js";
|
|
3
|
-
import { ProjectDetailsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, } from "../schemas.js";
|
|
3
|
+
import { ProjectDetailsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectTagsSchema, } from "../schemas.js";
|
|
4
4
|
import { analyzeFlowMap, flowTopologyFingerprint, renderFlowMap, } from "../utils/flow-analysis.js";
|
|
5
5
|
import { normalizeFlowGraph, } from "../utils/flow-map.js";
|
|
6
6
|
import { assertImportableProjectArchive, } from "../utils/project-archive.js";
|
|
@@ -302,6 +302,32 @@ export class ProjectsResource extends BaseResource {
|
|
|
302
302
|
const raw = await this.client.get(`/public/api/projects/${enc}/metadata`);
|
|
303
303
|
return this.client.safeParse(ProjectMetadataSchema, raw, "projects.metadata");
|
|
304
304
|
}
|
|
305
|
+
/**
|
|
306
|
+
* Replace project metadata with the supplied full object.
|
|
307
|
+
*
|
|
308
|
+
* DSS PUT semantics replace the whole metadata object: pass a metadata
|
|
309
|
+
* object obtained from {@link metadata}, edit it, and send it back — fields
|
|
310
|
+
* absent from the payload are removed from the project.
|
|
311
|
+
*/
|
|
312
|
+
async setMetadata(projectKey, metadata) {
|
|
313
|
+
await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/metadata`, metadata);
|
|
314
|
+
}
|
|
315
|
+
/** Get project-level tags (tag name → {color?}). */
|
|
316
|
+
async tags(projectKey) {
|
|
317
|
+
const enc = this.enc(projectKey);
|
|
318
|
+
const raw = await this.client.get(`/public/api/projects/${enc}/tags`);
|
|
319
|
+
return this.client.safeParse(ProjectTagsSchema, raw, "projects.tags");
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Replace project-level tags with the supplied full object.
|
|
323
|
+
*
|
|
324
|
+
* DSS PUT semantics replace the whole tags dictionary: pass a tags object
|
|
325
|
+
* obtained from {@link tags}, edit it, and send it back — tags absent from
|
|
326
|
+
* the payload are removed from the project.
|
|
327
|
+
*/
|
|
328
|
+
async setTags(projectKey, tags) {
|
|
329
|
+
await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/tags`, tags);
|
|
330
|
+
}
|
|
305
331
|
/** Get the raw flow graph for a project. */
|
|
306
332
|
async flow(projectKey) {
|
|
307
333
|
const enc = this.enc(projectKey);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BuildMode, JobWaitResult, RecipeCreateOptions, RecipeCreateResult, RecipeSummary } from "../schemas.js";
|
|
1
|
+
import type { BuildMode, JobWaitResult, ProjectMetadata, RecipeCreateOptions, RecipeCreateResult, RecipeSummary } from "../schemas.js";
|
|
2
2
|
import { BaseResource } from "./base.js";
|
|
3
3
|
import type { JobBuildTarget, JobBuildTargetType, JobLogFilter, JobLogSummary } from "./jobs.js";
|
|
4
4
|
export interface RecipeRunOutput extends JobBuildTarget {
|
|
@@ -68,6 +68,20 @@ export interface RecipeCloneResult {
|
|
|
68
68
|
export declare class RecipesResource extends BaseResource {
|
|
69
69
|
/** List all recipes in a project. */
|
|
70
70
|
list(projectKey?: string): Promise<RecipeSummary[]>;
|
|
71
|
+
/** Get recipe metadata (label, tags, description, custom fields). */
|
|
72
|
+
metadata(recipeName: string, opts?: {
|
|
73
|
+
projectKey?: string;
|
|
74
|
+
}): Promise<ProjectMetadata>;
|
|
75
|
+
/**
|
|
76
|
+
* Replace recipe metadata with the supplied full object.
|
|
77
|
+
*
|
|
78
|
+
* DSS PUT semantics replace the whole metadata object: pass a metadata
|
|
79
|
+
* object obtained from {@link metadata}, edit it, and send it back — fields
|
|
80
|
+
* absent from the payload are removed from the recipe.
|
|
81
|
+
*/
|
|
82
|
+
setMetadata(recipeName: string, metadata: ProjectMetadata, opts?: {
|
|
83
|
+
projectKey?: string;
|
|
84
|
+
}): Promise<void>;
|
|
71
85
|
/**
|
|
72
86
|
* Get a recipe definition (and optionally its payload).
|
|
73
87
|
* Returns the raw API response shape: `{ recipe, payload }`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { writeFile, } from "node:fs/promises";
|
|
2
2
|
import { resolve, } from "node:path";
|
|
3
3
|
import { DataikuError, } from "../errors.js";
|
|
4
|
-
import { RecipeSummaryArraySchema, } from "../schemas.js";
|
|
4
|
+
import { ProjectMetadataSchema, RecipeSummaryArraySchema, } from "../schemas.js";
|
|
5
5
|
import { deepMerge, } from "../utils/deep-merge.js";
|
|
6
6
|
import { sanitizeFileName, } from "../utils/sanitize.js";
|
|
7
7
|
import { BaseResource, } from "./base.js";
|
|
@@ -95,6 +95,8 @@ function normalizeRecipeOutputType(value) {
|
|
|
95
95
|
return "DATASET";
|
|
96
96
|
if (normalized === "MANAGED_FOLDER" || normalized === "FOLDER")
|
|
97
97
|
return "MANAGED_FOLDER";
|
|
98
|
+
if (normalized === "MODEL_EVALUATION_STORE")
|
|
99
|
+
return "MODEL_EVALUATION_STORE";
|
|
98
100
|
return undefined;
|
|
99
101
|
}
|
|
100
102
|
function recipeOutputItems(recipe) {
|
|
@@ -116,7 +118,12 @@ function recipeOutputItems(recipe) {
|
|
|
116
118
|
if (seen.has(seenKey))
|
|
117
119
|
continue;
|
|
118
120
|
seen.add(seenKey);
|
|
119
|
-
|
|
121
|
+
// The evaluation recipe's "evaluationStore" role targets a model
|
|
122
|
+
// evaluation store even when the item carries no explicit type
|
|
123
|
+
// (recipe.py EvaluationRecipeCreator.with_output_evaluation_store);
|
|
124
|
+
// the store is a valid job target (run object_type_map).
|
|
125
|
+
const type = normalizeRecipeOutputType(item?.type ?? item?.targetType ?? item?.objectType)
|
|
126
|
+
?? (role === "evaluationStore" ? "MODEL_EVALUATION_STORE" : undefined);
|
|
120
127
|
result.push({
|
|
121
128
|
ref,
|
|
122
129
|
role,
|
|
@@ -292,6 +299,25 @@ export class RecipesResource extends BaseResource {
|
|
|
292
299
|
const raw = await this.client.get(`/public/api/projects/${enc}/recipes/`);
|
|
293
300
|
return this.client.safeParse(RecipeSummaryArraySchema, raw, "recipes.list");
|
|
294
301
|
}
|
|
302
|
+
/** Get recipe metadata (label, tags, description, custom fields). */
|
|
303
|
+
async metadata(recipeName, opts) {
|
|
304
|
+
const enc = this.enc(opts?.projectKey);
|
|
305
|
+
const rnEnc = encodeURIComponent(recipeName);
|
|
306
|
+
const raw = await this.client.get(`/public/api/projects/${enc}/recipes/${rnEnc}/metadata`);
|
|
307
|
+
return this.client.safeParse(ProjectMetadataSchema, raw, "recipes.metadata");
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Replace recipe metadata with the supplied full object.
|
|
311
|
+
*
|
|
312
|
+
* DSS PUT semantics replace the whole metadata object: pass a metadata
|
|
313
|
+
* object obtained from {@link metadata}, edit it, and send it back — fields
|
|
314
|
+
* absent from the payload are removed from the recipe.
|
|
315
|
+
*/
|
|
316
|
+
async setMetadata(recipeName, metadata, opts) {
|
|
317
|
+
const enc = this.enc(opts?.projectKey);
|
|
318
|
+
const rnEnc = encodeURIComponent(recipeName);
|
|
319
|
+
await this.client.putVoid(`/public/api/projects/${enc}/recipes/${rnEnc}/metadata`, metadata);
|
|
320
|
+
}
|
|
295
321
|
/**
|
|
296
322
|
* Get a recipe definition (and optionally its payload).
|
|
297
323
|
* Returns the raw API response shape: `{ recipe, payload }`.
|
|
@@ -320,11 +346,13 @@ export class RecipesResource extends BaseResource {
|
|
|
320
346
|
const { recipe, } = await this.get(recipeName, { projectKey: pk, });
|
|
321
347
|
const inputItems = recipeInputItems(recipe);
|
|
322
348
|
const outputItems = recipeOutputItems(recipe);
|
|
323
|
-
const [datasets, folders,] = await Promise.all([
|
|
349
|
+
const [datasets, folders, stores,] = await Promise.all([
|
|
324
350
|
this.client.datasets.list(pk),
|
|
325
351
|
this.client.folders.list(pk),
|
|
352
|
+
this.client.modelEvaluationStores.list(pk),
|
|
326
353
|
]);
|
|
327
354
|
const datasetNames = new Set(datasets.map((dataset) => dataset.name));
|
|
355
|
+
const storeIds = new Set(stores.map((store) => store.id));
|
|
328
356
|
const folderIdByRef = new Map();
|
|
329
357
|
for (const folder of folders) {
|
|
330
358
|
folderIdByRef.set(folder.id, folder.id);
|
|
@@ -337,6 +365,15 @@ export class RecipesResource extends BaseResource {
|
|
|
337
365
|
if (item.type === "DATASET") {
|
|
338
366
|
return { ref: item.ref, role: item.role, type: "DATASET", exists: isDataset, id: item.ref, };
|
|
339
367
|
}
|
|
368
|
+
if (item.type === "MODEL_EVALUATION_STORE") {
|
|
369
|
+
return {
|
|
370
|
+
ref: item.ref,
|
|
371
|
+
role: item.role,
|
|
372
|
+
type: "MODEL_EVALUATION_STORE",
|
|
373
|
+
exists: storeIds.has(item.ref),
|
|
374
|
+
id: item.ref,
|
|
375
|
+
};
|
|
376
|
+
}
|
|
340
377
|
if (item.type === "MANAGED_FOLDER") {
|
|
341
378
|
return {
|
|
342
379
|
ref: item.ref,
|
|
@@ -420,6 +457,19 @@ export class RecipesResource extends BaseResource {
|
|
|
420
457
|
partition: opts?.partition,
|
|
421
458
|
};
|
|
422
459
|
}
|
|
460
|
+
if (item.type === "MODEL_EVALUATION_STORE") {
|
|
461
|
+
// The store id is the target id; evaluation builds into the store
|
|
462
|
+
// exactly like the official client (recipe.run maps
|
|
463
|
+
// COMPUTABLE_MODEL_EVALUATION_STORE -> MODEL_EVALUATION_STORE).
|
|
464
|
+
return {
|
|
465
|
+
ref: item.ref,
|
|
466
|
+
role: item.role,
|
|
467
|
+
id: item.ref,
|
|
468
|
+
type: "MODEL_EVALUATION_STORE",
|
|
469
|
+
projectKey: pk,
|
|
470
|
+
partition: opts?.partition,
|
|
471
|
+
};
|
|
472
|
+
}
|
|
423
473
|
const folderId = folderIdByRef.get(item.ref);
|
|
424
474
|
if (item.type === "MANAGED_FOLDER") {
|
|
425
475
|
return {
|
|
@@ -632,10 +682,22 @@ export class RecipesResource extends BaseResource {
|
|
|
632
682
|
}
|
|
633
683
|
}
|
|
634
684
|
};
|
|
685
|
+
let finalRecipeName;
|
|
686
|
+
// DSS renames some recipe types server-side (e.g. prediction_scoring
|
|
687
|
+
// becomes "score_<inputDataset>") and documents the creation response as
|
|
688
|
+
// the final unique name: Body {"name": "recipe1"} ("Returns the final
|
|
689
|
+
// unique name of the recipe"). The response name is the contract —
|
|
690
|
+
// falling back to the requested name would mask a missing/invalid
|
|
691
|
+
// receipt, so a body without it is an error.
|
|
635
692
|
try {
|
|
636
693
|
if (rawConnection)
|
|
637
694
|
await provisionOutputDatasets();
|
|
638
|
-
await createRecipe();
|
|
695
|
+
const created = await createRecipe();
|
|
696
|
+
const receivedName = asString(created?.["name"]);
|
|
697
|
+
if (!receivedName) {
|
|
698
|
+
throw new Error('DSS create-recipe response did not include the final recipe name (documented body: {"name": ...}).');
|
|
699
|
+
}
|
|
700
|
+
finalRecipeName = receivedName;
|
|
639
701
|
}
|
|
640
702
|
catch (error) {
|
|
641
703
|
if (!shouldRetryRecipeCreateWithOutputProvisioning(error)) {
|
|
@@ -643,7 +705,12 @@ export class RecipesResource extends BaseResource {
|
|
|
643
705
|
}
|
|
644
706
|
usedOutputProvisioningFallback = true;
|
|
645
707
|
await provisionOutputDatasets();
|
|
646
|
-
await createRecipe();
|
|
708
|
+
const retryCreated = await createRecipe();
|
|
709
|
+
const retryName = asString(retryCreated?.["name"]);
|
|
710
|
+
if (!retryName) {
|
|
711
|
+
throw new Error('DSS create-recipe response did not include the final recipe name (documented body: {"name": ...}).', { cause: error, });
|
|
712
|
+
}
|
|
713
|
+
finalRecipeName = retryName;
|
|
647
714
|
}
|
|
648
715
|
// For sync recipes (a 1:1 copy) DSS does not propagate schema on build, so a
|
|
649
716
|
// schemaless dataset output silently builds to an empty dataset. Copy the
|
|
@@ -781,7 +848,7 @@ export class RecipesResource extends BaseResource {
|
|
|
781
848
|
}
|
|
782
849
|
}
|
|
783
850
|
return {
|
|
784
|
-
recipeName:
|
|
851
|
+
recipeName: finalRecipeName,
|
|
785
852
|
type,
|
|
786
853
|
createdDatasets,
|
|
787
854
|
joinConfigured,
|
|
@@ -24,18 +24,151 @@ export interface SavedModelVersionDetails extends Record<string, unknown> {
|
|
|
24
24
|
export interface SavedModelActionResult extends Record<string, unknown> {
|
|
25
25
|
message?: string;
|
|
26
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Body of POST /projects/{pkey}/savedmodels/ (official Python client
|
|
29
|
+
* `create_mlflow_model` / `create_external_model`; the REST reference's
|
|
30
|
+
* `/savedmodels/create-external` path returns 405 on DSS 15.0.1).
|
|
31
|
+
* `savedModelType` is only "MLFLOW_PYFUNC" or "PROXY_MODEL"; `proxyModelConfiguration`
|
|
32
|
+
* carries the protocol settings for PROXY_MODEL creation (sagemaker, azure-ml,
|
|
33
|
+
* vertex-ai, databricks — per the official Python client `create_external_model`).
|
|
34
|
+
*/
|
|
35
|
+
export interface SavedModelCreateRequest extends Record<string, unknown> {
|
|
36
|
+
savedModelType: "MLFLOW_PYFUNC" | "PROXY_MODEL";
|
|
37
|
+
name: string;
|
|
38
|
+
predictionType?: "BINARY_CLASSIFICATION" | "MULTICLASS" | "REGRESSION" | null;
|
|
39
|
+
/** PROXY_MODEL only: e.g. { protocol: "sagemaker", region: "eu-west-1" }. */
|
|
40
|
+
proxyModelConfiguration?: Record<string, unknown>;
|
|
41
|
+
}
|
|
42
|
+
/** Full saved-model settings document as returned by GET, sent back by PUT. */
|
|
43
|
+
export type SavedModelSettings = Record<string, unknown>;
|
|
44
|
+
/** Body of POST .../actions/delete-versions (official Python client, see docs note below). */
|
|
45
|
+
export interface SavedModelDeleteVersionsRequest extends Record<string, unknown> {
|
|
46
|
+
versions: string[];
|
|
47
|
+
removeIntermediate: boolean;
|
|
48
|
+
}
|
|
49
|
+
/** Query options for MLflow version import (POST .../versions/{versionId}). */
|
|
50
|
+
export interface SavedModelVersionImportOptions extends Record<string, unknown> {
|
|
51
|
+
codeEnvName?: string;
|
|
52
|
+
containerExecConfigName?: string;
|
|
53
|
+
setActive?: boolean;
|
|
54
|
+
binaryClassificationThreshold?: number;
|
|
55
|
+
}
|
|
56
|
+
/** Body of POST .../external-ml/actions/evaluate. */
|
|
57
|
+
export interface ExternalModelVersionEvaluateRequest extends Record<string, unknown> {
|
|
58
|
+
datasetRef: string;
|
|
59
|
+
containerExecConfigName?: string;
|
|
60
|
+
samplingParam?: Record<string, unknown> | null;
|
|
61
|
+
}
|
|
62
|
+
/** Query flags for .../external-ml/actions/evaluate. */
|
|
63
|
+
export interface ExternalModelVersionEvaluateOptions extends Record<string, unknown> {
|
|
64
|
+
useOptimalThreshold?: boolean;
|
|
65
|
+
skipExpensiveReports?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/** Query options for the scoring JAR export (GET .../scoring-jar). */
|
|
68
|
+
export interface SavedModelScoringJarOptions extends Record<string, unknown> {
|
|
69
|
+
fullClassName?: string;
|
|
70
|
+
includeLibs?: boolean;
|
|
71
|
+
}
|
|
27
72
|
export declare class SavedModelsResource extends BaseResource {
|
|
28
73
|
/** List saved models in a project. */
|
|
29
74
|
list(projectKey?: string): Promise<SavedModelListItem[]>;
|
|
30
|
-
/**
|
|
75
|
+
/**
|
|
76
|
+
* Create a saved model for storing and managing MLflow or external
|
|
77
|
+
* (proxy) models. POST /projects/{pkey}/savedmodels/ (the official Python
|
|
78
|
+
* client's collection-root creation endpoint; `/create-external` 405s).
|
|
79
|
+
*/
|
|
80
|
+
createExternal(request: SavedModelCreateRequest, projectKey?: string): Promise<SavedModel>;
|
|
81
|
+
/**
|
|
82
|
+
* Get saved-model settings and metadata.
|
|
83
|
+
* GET /projects/{pkey}/savedmodels/{savedModelId}
|
|
84
|
+
*/
|
|
31
85
|
get(savedModelId: string, projectKey?: string): Promise<SavedModel>;
|
|
86
|
+
/**
|
|
87
|
+
* Save the full settings document of a saved model. The body must be the
|
|
88
|
+
* complete settings document as returned by {@link get} (GET-then-PUT
|
|
89
|
+
* workflow), per the official Python client's DSSSavedModelSettings.save().
|
|
90
|
+
*/
|
|
91
|
+
updateSettings(savedModelId: string, settings: SavedModelSettings, projectKey?: string): Promise<void>;
|
|
32
92
|
/** List all versions of a saved model. */
|
|
33
93
|
listVersions(savedModelId: string, projectKey?: string): Promise<SavedModelVersionListItem[]>;
|
|
34
94
|
/** Get full details for one saved-model version. */
|
|
35
95
|
versionDetails(savedModelId: string, versionId: string, projectKey?: string): Promise<SavedModelVersionDetails>;
|
|
96
|
+
/** Get the short snippet (summary) for one saved-model version. */
|
|
97
|
+
versionSnippet(savedModelId: string, versionId: string, projectKey?: string): Promise<Record<string, unknown>>;
|
|
36
98
|
/** Make one saved-model version active. */
|
|
37
99
|
setActiveVersion(savedModelId: string, versionId: string, projectKey?: string): Promise<SavedModelActionResult | undefined>;
|
|
100
|
+
/**
|
|
101
|
+
* Delete one or more versions of a saved model.
|
|
102
|
+
*
|
|
103
|
+
* Transport note: the DSS 15 REST reference documents this action as GET
|
|
104
|
+
* `/projects/{pkey}/savedmodels/{savedModelId}/delete-versions{?versions}{?removeIntermediate}`,
|
|
105
|
+
* but the official Python client (dataikuapi/dss/savedmodel.py,
|
|
106
|
+
* DSSSavedModel.delete_versions, verified against dataiku-api-client-python
|
|
107
|
+
* master) performs `POST .../actions/delete-versions` with a JSON body
|
|
108
|
+
* `{versions, removeIntermediate}`. The REST doc is erroneous; this SDK
|
|
109
|
+
* follows the official client. The request is destructive and must never be
|
|
110
|
+
* retried automatically: retryMaxAttempts is pinned to 1 regardless of the
|
|
111
|
+
* client-level retry configuration.
|
|
112
|
+
*/
|
|
113
|
+
deleteVersions(versions: string[], options?: {
|
|
114
|
+
removeIntermediate?: boolean;
|
|
115
|
+
}, savedModelId?: string, projectKey?: string): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Import a new MLflow version from a local MLflow model archive
|
|
118
|
+
* (zip) uploaded as multipart/form-data.
|
|
119
|
+
* POST /projects/{pkey}/savedmodels/{savedModelId}/versions/{versionId}
|
|
120
|
+
* with query codeEnvName, containerExecConfigName, setActive,
|
|
121
|
+
* binaryClassificationThreshold.
|
|
122
|
+
*/
|
|
123
|
+
importMlflowVersion(archivePath: string, versionId: string, options?: SavedModelVersionImportOptions, savedModelId?: string, projectKey?: string): Promise<Record<string, unknown> | undefined>;
|
|
124
|
+
/**
|
|
125
|
+
* Import a new MLflow version from a path inside a managed folder. The
|
|
126
|
+
* server-side backend mandates a multipart request, so the part set is the
|
|
127
|
+
* same as the archive upload with a zero-byte "file" part, and the model
|
|
128
|
+
* location is carried by the folderRef (PROJECT_KEY.FOLDER_ID) and path
|
|
129
|
+
* query parameters — matching the official Python client, which sends
|
|
130
|
+
* `files={"file": (None, None)}`.
|
|
131
|
+
*/
|
|
132
|
+
importMlflowVersionFromFolder(folderRef: string, folderPath: string, versionId: string, options?: SavedModelVersionImportOptions, savedModelId?: string, projectKey?: string): Promise<Record<string, unknown> | undefined>;
|
|
133
|
+
/**
|
|
134
|
+
* Get the external-ml metadata of a saved-model version (MLflow or proxy
|
|
135
|
+
* model). Opaque server document; no strict schema is enforced.
|
|
136
|
+
*/
|
|
137
|
+
externalMetadataGet(savedModelId: string, versionId: string, projectKey?: string): Promise<Record<string, unknown>>;
|
|
138
|
+
/**
|
|
139
|
+
* PUT the external-ml metadata of a saved-model version. The body must be
|
|
140
|
+
* the full metadata document as returned by {@link externalMetadataGet}
|
|
141
|
+
* (GET-then-PUT). DSS requires the containerExecConfigName query parameter
|
|
142
|
+
* on this endpoint (live: 400 "Required request parameter
|
|
143
|
+
* 'containerExecConfigName' not present" without it); for an external API
|
|
144
|
+
* caller the container exec config resolves as LOCAL-CONFIG -> NONE, so an
|
|
145
|
+
* omitted option sends NONE rather than dropping the parameter.
|
|
146
|
+
*/
|
|
147
|
+
externalMetadataPut(savedModelId: string, versionId: string, metadata: Record<string, unknown>, options?: {
|
|
148
|
+
containerExecConfigName?: string;
|
|
149
|
+
}, projectKey?: string): Promise<void>;
|
|
150
|
+
/**
|
|
151
|
+
* Evaluate the performance of an external/MLflow model version on a
|
|
152
|
+
* dataset. POST .../external-ml/actions/evaluate with
|
|
153
|
+
* useOptimalThreshold/skipExpensiveReports as query parameters and the
|
|
154
|
+
* dataset/container/sampling payload in the JSON body.
|
|
155
|
+
*/
|
|
156
|
+
evaluateVersion(request: ExternalModelVersionEvaluateRequest, options?: ExternalModelVersionEvaluateOptions, savedModelId?: string, versionId?: string, projectKey?: string): Promise<void>;
|
|
157
|
+
/**
|
|
158
|
+
* GET the scoring JAR of a version as a binary stream. Caller is
|
|
159
|
+
* responsible for consuming the response body (e.g. writeResponseToFile);
|
|
160
|
+
* the stream is read under the client body deadline.
|
|
161
|
+
*/
|
|
162
|
+
downloadScoringJar(options: SavedModelScoringJarOptions | undefined, savedModelId: string, versionId: string, projectKey?: string): Promise<Response>;
|
|
163
|
+
/** GET the scoring PMML of a version as a binary/XML stream. */
|
|
164
|
+
downloadScoringPmml(savedModelId: string, versionId: string, projectKey?: string): Promise<Response>;
|
|
165
|
+
/**
|
|
166
|
+
* Update the user metadata of a model version. The body must only be the
|
|
167
|
+
* "userMeta" field of a previously-retrieved version-details object.
|
|
168
|
+
*/
|
|
169
|
+
setUserMeta(savedModelId: string, versionId: string, userMeta: Record<string, unknown>, projectKey?: string): Promise<void>;
|
|
38
170
|
/** Delete a saved model and all of its versions. */
|
|
39
171
|
delete(savedModelId: string, projectKey?: string): Promise<void>;
|
|
172
|
+
private mlflowImportQuery;
|
|
40
173
|
private savedModelPath;
|
|
41
174
|
}
|