dataiku-sdk 3.2.0 → 3.4.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 +151 -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/code.js +1 -1
- 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 +162 -33
- 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/job.js +4 -2
- 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 +15 -55
- 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 +139 -2
- 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 +1098 -297
- 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-schemas.d.ts +24 -0
- package/dist/src/cli/output-schemas.js +233 -0
- 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 +92 -5
- package/dist/src/client.js +202 -31
- package/dist/src/errors.d.ts +3 -0
- package/dist/src/errors.js +8 -4
- package/dist/src/generated/action-output-schemas.json +1735 -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 +136 -5
- package/dist/src/resources/flow-zones.d.ts +6 -2
- package/dist/src/resources/flow-zones.js +6 -3
- package/dist/src/resources/futures.d.ts +6 -1
- package/dist/src/resources/futures.js +68 -22
- 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 +71 -34
- 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 +109 -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 +263 -0
- package/dist/src/resources/plugins.js +455 -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 +12 -12
- package/dist/src/resources/project-git.js +84 -82
- 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 +23 -3
- package/dist/src/resources/projects.js +60 -34
- 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/git-reference.d.ts +12 -0
- package/dist/src/utils/git-reference.js +38 -0
- 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 +9 -8
- 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 +11 -7
- package/skills/dataiku-dss/references/app-releases.md +8 -8
- package/skills/dataiku-dss/references/authentication.md +6 -6
- package/skills/dataiku-dss/references/discovery.md +4 -4
- package/skills/dataiku-dss/references/mutations.md +1 -1
- package/skills/dataiku-dss/references/troubleshooting.md +2 -2
|
@@ -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
|
}
|
|
@@ -1,20 +1,60 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { basename, } from "node:path";
|
|
2
|
+
import { ClientValidationError, } from "../errors.js";
|
|
3
|
+
import { BaseResource, requireNonEmpty, } from "./base.js";
|
|
4
|
+
function requireObject(value, name) {
|
|
5
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
6
|
+
throw new ClientValidationError(`${name} must be a JSON object.`, "validation_failed");
|
|
6
7
|
}
|
|
7
8
|
return value;
|
|
8
9
|
}
|
|
10
|
+
function requireNonEmptyArray(value, name) {
|
|
11
|
+
if (!Array.isArray(value) || value.length === 0) {
|
|
12
|
+
throw new ClientValidationError(`${name} must be a non-empty array.`, "validation_failed");
|
|
13
|
+
}
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function boolQuery(value) {
|
|
17
|
+
return value === undefined ? "true" : String(value);
|
|
18
|
+
}
|
|
19
|
+
function numberQuery(value, fallback) {
|
|
20
|
+
return String(value ?? fallback);
|
|
21
|
+
}
|
|
9
22
|
export class SavedModelsResource extends BaseResource {
|
|
10
23
|
/** List saved models in a project. */
|
|
11
24
|
async list(projectKey) {
|
|
12
25
|
return this.client.get(`/public/api/projects/${this.enc(projectKey)}/savedmodels/`);
|
|
13
26
|
}
|
|
14
|
-
/**
|
|
27
|
+
/**
|
|
28
|
+
* Create a saved model for storing and managing MLflow or external
|
|
29
|
+
* (proxy) models. POST /projects/{pkey}/savedmodels/ (the official Python
|
|
30
|
+
* client's collection-root creation endpoint; `/create-external` 405s).
|
|
31
|
+
*/
|
|
32
|
+
async createExternal(request, projectKey) {
|
|
33
|
+
const body = requireObject(request, "request");
|
|
34
|
+
if (typeof body.name !== "string" || body.name.trim().length === 0) {
|
|
35
|
+
throw new ClientValidationError("request.name must be a non-empty string.", "validation_failed");
|
|
36
|
+
}
|
|
37
|
+
if (body.savedModelType !== "MLFLOW_PYFUNC" && body.savedModelType !== "PROXY_MODEL") {
|
|
38
|
+
throw new ClientValidationError('request.savedModelType must be "MLFLOW_PYFUNC" or "PROXY_MODEL".', "validation_failed");
|
|
39
|
+
}
|
|
40
|
+
return this.client.post(`/public/api/projects/${this.enc(projectKey)}/savedmodels/`, body);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Get saved-model settings and metadata.
|
|
44
|
+
* GET /projects/{pkey}/savedmodels/{savedModelId}
|
|
45
|
+
*/
|
|
15
46
|
async get(savedModelId, projectKey) {
|
|
16
47
|
return this.client.get(this.savedModelPath(savedModelId, projectKey));
|
|
17
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Save the full settings document of a saved model. The body must be the
|
|
51
|
+
* complete settings document as returned by {@link get} (GET-then-PUT
|
|
52
|
+
* workflow), per the official Python client's DSSSavedModelSettings.save().
|
|
53
|
+
*/
|
|
54
|
+
async updateSettings(savedModelId, settings, projectKey) {
|
|
55
|
+
requireObject(settings, "settings");
|
|
56
|
+
await this.client.putVoid(this.savedModelPath(savedModelId, projectKey), settings);
|
|
57
|
+
}
|
|
18
58
|
/** List all versions of a saved model. */
|
|
19
59
|
async listVersions(savedModelId, projectKey) {
|
|
20
60
|
return this.client.get(`${this.savedModelPath(savedModelId, projectKey)}/versions`);
|
|
@@ -24,15 +64,183 @@ export class SavedModelsResource extends BaseResource {
|
|
|
24
64
|
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
25
65
|
return this.client.get(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/details`);
|
|
26
66
|
}
|
|
67
|
+
/** Get the short snippet (summary) for one saved-model version. */
|
|
68
|
+
async versionSnippet(savedModelId, versionId, projectKey) {
|
|
69
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
70
|
+
return this.client.get(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/snippet`);
|
|
71
|
+
}
|
|
27
72
|
/** Make one saved-model version active. */
|
|
28
73
|
async setActiveVersion(savedModelId, versionId, projectKey) {
|
|
29
74
|
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
30
75
|
return this.client.post(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/actions/setActive`, {});
|
|
31
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Delete one or more versions of a saved model.
|
|
79
|
+
*
|
|
80
|
+
* Transport note: the DSS 15 REST reference documents this action as GET
|
|
81
|
+
* `/projects/{pkey}/savedmodels/{savedModelId}/delete-versions{?versions}{?removeIntermediate}`,
|
|
82
|
+
* but the official Python client (dataikuapi/dss/savedmodel.py,
|
|
83
|
+
* DSSSavedModel.delete_versions, verified against dataiku-api-client-python
|
|
84
|
+
* master) performs `POST .../actions/delete-versions` with a JSON body
|
|
85
|
+
* `{versions, removeIntermediate}`. The REST doc is erroneous; this SDK
|
|
86
|
+
* follows the official client. The request is destructive and must never be
|
|
87
|
+
* retried automatically: retryMaxAttempts is pinned to 1 regardless of the
|
|
88
|
+
* client-level retry configuration.
|
|
89
|
+
*/
|
|
90
|
+
async deleteVersions(versions, options, savedModelId, projectKey) {
|
|
91
|
+
const id = requireNonEmpty(savedModelId ?? "", "savedModelId");
|
|
92
|
+
const versionList = requireNonEmptyArray(versions, "versions");
|
|
93
|
+
const body = {
|
|
94
|
+
versions: versionList,
|
|
95
|
+
removeIntermediate: options?.removeIntermediate ?? true,
|
|
96
|
+
};
|
|
97
|
+
await this.client.post(`${this.savedModelPath(id, projectKey)}/actions/delete-versions`, body,
|
|
98
|
+
// Mutating action: a retried attempt could double-delete after a lost
|
|
99
|
+
// response. One attempt only, explicitly overriding any future default.
|
|
100
|
+
{ retryMaxAttempts: 1, });
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Import a new MLflow version from a local MLflow model archive
|
|
104
|
+
* (zip) uploaded as multipart/form-data.
|
|
105
|
+
* POST /projects/{pkey}/savedmodels/{savedModelId}/versions/{versionId}
|
|
106
|
+
* with query codeEnvName, containerExecConfigName, setActive,
|
|
107
|
+
* binaryClassificationThreshold.
|
|
108
|
+
*/
|
|
109
|
+
async importMlflowVersion(archivePath, versionId, options, savedModelId, projectKey) {
|
|
110
|
+
const id = requireNonEmpty(savedModelId ?? "", "savedModelId");
|
|
111
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
112
|
+
const archive = requireNonEmpty(archivePath, "archivePath");
|
|
113
|
+
const exists = await Bun.file(archive).exists();
|
|
114
|
+
if (!exists) {
|
|
115
|
+
throw new ClientValidationError(`MLflow archive file not found: ${archive}.`, "validation_failed");
|
|
116
|
+
}
|
|
117
|
+
const query = this.mlflowImportQuery(options);
|
|
118
|
+
const parts = [
|
|
119
|
+
{ name: "file", blob: Bun.file(archive), fileName: basename(archive), },
|
|
120
|
+
];
|
|
121
|
+
return this.client.uploadForm(`${this.savedModelPath(id, projectKey)}/versions/${version}`, parts, query);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Import a new MLflow version from a path inside a managed folder. The
|
|
125
|
+
* server-side backend mandates a multipart request, so the part set is the
|
|
126
|
+
* same as the archive upload with a zero-byte "file" part, and the model
|
|
127
|
+
* location is carried by the folderRef (PROJECT_KEY.FOLDER_ID) and path
|
|
128
|
+
* query parameters — matching the official Python client, which sends
|
|
129
|
+
* `files={"file": (None, None)}`.
|
|
130
|
+
*/
|
|
131
|
+
async importMlflowVersionFromFolder(folderRef, folderPath, versionId, options, savedModelId, projectKey) {
|
|
132
|
+
const id = requireNonEmpty(savedModelId ?? "", "savedModelId");
|
|
133
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
134
|
+
const ref = requireNonEmpty(folderRef, "folderRef");
|
|
135
|
+
const path = requireNonEmpty(folderPath, "folderPath");
|
|
136
|
+
const query = this.mlflowImportQuery(options);
|
|
137
|
+
query.set("folderRef", ref);
|
|
138
|
+
query.set("path", path);
|
|
139
|
+
// Match the official client exactly: files={"file": (None, None)} — a
|
|
140
|
+
// filename-less, zero-length field part (a Blob part would carry a
|
|
141
|
+
// `filename=` parameter, which the endpoint rejects).
|
|
142
|
+
const parts = [{ name: "file", },];
|
|
143
|
+
return this.client.uploadForm(`${this.savedModelPath(id, projectKey)}/versions/${version}`, parts, query);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get the external-ml metadata of a saved-model version (MLflow or proxy
|
|
147
|
+
* model). Opaque server document; no strict schema is enforced.
|
|
148
|
+
*/
|
|
149
|
+
async externalMetadataGet(savedModelId, versionId, projectKey) {
|
|
150
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
151
|
+
return this.client.get(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/external-ml/metadata`);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* PUT the external-ml metadata of a saved-model version. The body must be
|
|
155
|
+
* the full metadata document as returned by {@link externalMetadataGet}
|
|
156
|
+
* (GET-then-PUT). DSS requires the containerExecConfigName query parameter
|
|
157
|
+
* on this endpoint (live: 400 "Required request parameter
|
|
158
|
+
* 'containerExecConfigName' not present" without it); for an external API
|
|
159
|
+
* caller the container exec config resolves as LOCAL-CONFIG -> NONE, so an
|
|
160
|
+
* omitted option sends NONE rather than dropping the parameter.
|
|
161
|
+
*/
|
|
162
|
+
async externalMetadataPut(savedModelId, versionId, metadata, options, projectKey) {
|
|
163
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
164
|
+
requireObject(metadata, "metadata");
|
|
165
|
+
const containerExecConfigName = options?.containerExecConfigName ?? "NONE";
|
|
166
|
+
const suffix = `?containerExecConfigName=${encodeURIComponent(containerExecConfigName)}`;
|
|
167
|
+
await this.client.putVoid(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/external-ml/metadata${suffix}`, metadata);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Evaluate the performance of an external/MLflow model version on a
|
|
171
|
+
* dataset. POST .../external-ml/actions/evaluate with
|
|
172
|
+
* useOptimalThreshold/skipExpensiveReports as query parameters and the
|
|
173
|
+
* dataset/container/sampling payload in the JSON body.
|
|
174
|
+
*/
|
|
175
|
+
async evaluateVersion(request, options, savedModelId, versionId, projectKey) {
|
|
176
|
+
const id = requireNonEmpty(savedModelId ?? "", "savedModelId");
|
|
177
|
+
const version = encodeURIComponent(requireNonEmpty(versionId ?? "", "versionId"));
|
|
178
|
+
const requestBody = requireObject(request, "request");
|
|
179
|
+
if (typeof requestBody.datasetRef !== "string" || requestBody.datasetRef.trim().length === 0) {
|
|
180
|
+
throw new ClientValidationError("request.datasetRef must be a non-empty string.", "validation_failed");
|
|
181
|
+
}
|
|
182
|
+
// DSS 15 official external-caller semantics: the container exec config
|
|
183
|
+
// resolves as LOCAL-CONFIG -> NONE, so an omitted value sends NONE
|
|
184
|
+
// rather than being left out; an explicit value (including INHERIT)
|
|
185
|
+
// passes through unchanged. The caller's request object is never
|
|
186
|
+
// mutated — the default is applied to a copy.
|
|
187
|
+
const body = {
|
|
188
|
+
...requestBody,
|
|
189
|
+
containerExecConfigName: requestBody.containerExecConfigName ?? "NONE",
|
|
190
|
+
};
|
|
191
|
+
const useOptimal = boolQuery(options?.useOptimalThreshold);
|
|
192
|
+
const skipExpensive = boolQuery(options?.skipExpensiveReports);
|
|
193
|
+
await this.client.post(`${this.savedModelPath(id, projectKey)}/versions/${version}/external-ml/actions/evaluate`
|
|
194
|
+
+ `?useOptimalThreshold=${useOptimal}&skipExpensiveReports=${skipExpensive}`, body);
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* GET the scoring JAR of a version as a binary stream. Caller is
|
|
198
|
+
* responsible for consuming the response body (e.g. writeResponseToFile);
|
|
199
|
+
* the stream is read under the client body deadline.
|
|
200
|
+
*/
|
|
201
|
+
async downloadScoringJar(options, savedModelId, versionId, projectKey) {
|
|
202
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
203
|
+
const query = new URLSearchParams();
|
|
204
|
+
if (options?.fullClassName !== undefined) {
|
|
205
|
+
query.set("fullClassName", options.fullClassName);
|
|
206
|
+
}
|
|
207
|
+
if (options?.includeLibs !== undefined) {
|
|
208
|
+
query.set("includeLibs", String(options.includeLibs));
|
|
209
|
+
}
|
|
210
|
+
const suffix = [...query.keys(),].length > 0 ? `?${query.toString()}` : "";
|
|
211
|
+
return this.client.stream(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/scoring-jar${suffix}`);
|
|
212
|
+
}
|
|
213
|
+
/** GET the scoring PMML of a version as a binary/XML stream. */
|
|
214
|
+
async downloadScoringPmml(savedModelId, versionId, projectKey) {
|
|
215
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
216
|
+
return this.client.stream(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/scoring-pmml`);
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Update the user metadata of a model version. The body must only be the
|
|
220
|
+
* "userMeta" field of a previously-retrieved version-details object.
|
|
221
|
+
*/
|
|
222
|
+
async setUserMeta(savedModelId, versionId, userMeta, projectKey) {
|
|
223
|
+
const version = encodeURIComponent(requireNonEmpty(versionId, "versionId"));
|
|
224
|
+
requireObject(userMeta, "userMeta");
|
|
225
|
+
await this.client.putVoid(`${this.savedModelPath(savedModelId, projectKey)}/versions/${version}/user-meta`, userMeta);
|
|
226
|
+
}
|
|
32
227
|
/** Delete a saved model and all of its versions. */
|
|
33
228
|
async delete(savedModelId, projectKey) {
|
|
34
229
|
await this.client.del(this.savedModelPath(savedModelId, projectKey));
|
|
35
230
|
}
|
|
231
|
+
mlflowImportQuery(options) {
|
|
232
|
+
// DSS 15 official semantics: both import endpoints resolve the
|
|
233
|
+
// container exec config as LOCAL-CONFIG, i.e. NONE for an external
|
|
234
|
+
// caller, and DSS validates the parameter's presence (400 when
|
|
235
|
+
// omitted) — so an omitted option sends NONE. An explicit option
|
|
236
|
+
// (including INHERIT) passes through unchanged.
|
|
237
|
+
const query = new URLSearchParams();
|
|
238
|
+
query.set("codeEnvName", options?.codeEnvName ?? "INHERIT");
|
|
239
|
+
query.set("containerExecConfigName", options?.containerExecConfigName ?? "NONE");
|
|
240
|
+
query.set("setActive", boolQuery(options?.setActive));
|
|
241
|
+
query.set("binaryClassificationThreshold", numberQuery(options?.binaryClassificationThreshold, 0.5));
|
|
242
|
+
return query;
|
|
243
|
+
}
|
|
36
244
|
savedModelPath(savedModelId, projectKey) {
|
|
37
245
|
const id = encodeURIComponent(requireNonEmpty(savedModelId, "savedModelId"));
|
|
38
246
|
return `/public/api/projects/${this.enc(projectKey)}/savedmodels/${id}`;
|
|
@@ -1,6 +1,55 @@
|
|
|
1
1
|
import type { ScenarioDetails, ScenarioStatus, ScenarioSummary, ScenarioWaitResult } from "../schemas.js";
|
|
2
2
|
import { BaseResource } from "./base.js";
|
|
3
3
|
export declare const SCENARIO_CANONICAL_EDITABLE_FIELDS: readonly ["params.steps", "params.triggers", "params.reporters", "params.customScript", "active", "name"];
|
|
4
|
+
/** Default byte cap applied when fetching a scenario run log. */
|
|
5
|
+
export declare const DEFAULT_SCENARIO_MAX_LOG_BYTES = 1048576;
|
|
6
|
+
/** One entry of GET /scenarios/{id}/get-last-runs — a finished (or running) scenario run summary. */
|
|
7
|
+
export interface ScenarioRunSummary {
|
|
8
|
+
runId: string;
|
|
9
|
+
start?: number;
|
|
10
|
+
end?: number;
|
|
11
|
+
scenario?: Record<string, unknown>;
|
|
12
|
+
variables?: Record<string, unknown>;
|
|
13
|
+
result?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
/** Status payload returned by the scenario light endpoints: identity plus running/active flags. */
|
|
16
|
+
export interface ScenarioLightStatus {
|
|
17
|
+
id?: string;
|
|
18
|
+
running?: boolean;
|
|
19
|
+
active?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/** Result of a light active toggle: the light status observed after the PUT. */
|
|
22
|
+
export interface ScenarioActiveUpdateResult {
|
|
23
|
+
scenarioId: string;
|
|
24
|
+
active: boolean;
|
|
25
|
+
before?: boolean;
|
|
26
|
+
status: ScenarioLightStatus;
|
|
27
|
+
}
|
|
28
|
+
/** Step-level entry of a scenario run report, sanitized to documented fields. */
|
|
29
|
+
export interface ScenarioRunStepReport {
|
|
30
|
+
id?: string;
|
|
31
|
+
name?: string;
|
|
32
|
+
type?: string;
|
|
33
|
+
runId?: string;
|
|
34
|
+
start?: number;
|
|
35
|
+
end?: number;
|
|
36
|
+
outcome?: string;
|
|
37
|
+
warningCount?: number;
|
|
38
|
+
}
|
|
39
|
+
/** Response of GET /scenarios/{id}/get-run-for-trigger and GET /scenarios/{id}/{runId}. */
|
|
40
|
+
export interface ScenarioRunDetails {
|
|
41
|
+
scenarioRun?: {
|
|
42
|
+
runId?: string;
|
|
43
|
+
result?: Record<string, unknown>;
|
|
44
|
+
};
|
|
45
|
+
stepRuns?: ScenarioRunStepReport[];
|
|
46
|
+
}
|
|
47
|
+
/** Bounded log retrieval result: text plus whether the byte cap cut it. */
|
|
48
|
+
export interface ScenarioRunLog {
|
|
49
|
+
text: string;
|
|
50
|
+
truncated: boolean;
|
|
51
|
+
maxLogBytes: number;
|
|
52
|
+
}
|
|
4
53
|
export interface ScenarioUpdateNormalization {
|
|
5
54
|
from: string;
|
|
6
55
|
to: string;
|
|
@@ -118,6 +167,62 @@ export declare class ScenariosResource extends BaseResource {
|
|
|
118
167
|
keepScenario?: boolean;
|
|
119
168
|
maxLogBytes?: number;
|
|
120
169
|
}): Promise<ScenarioScriptRunResult>;
|
|
170
|
+
/**
|
|
171
|
+
* Abort a running scenario (POST /scenarios/{id}/abort). The call returns as
|
|
172
|
+
* soon as DSS accepts the abort request; the scenario may take some time to
|
|
173
|
+
* actually stop, so this does not wait for termination.
|
|
174
|
+
*/
|
|
175
|
+
abort(scenarioId: string, projectKey?: string): Promise<void>;
|
|
176
|
+
/** Get the raw last-runs list (GET /scenarios/{id}/get-last-runs/?limit=N). */
|
|
177
|
+
getLastRuns(scenarioId: string, opts?: {
|
|
178
|
+
limit?: number;
|
|
179
|
+
projectKey?: string;
|
|
180
|
+
}): Promise<ScenarioRunSummary[]>;
|
|
181
|
+
/** Get the details of a specific run (GET /scenarios/{id}/{runId}). */
|
|
182
|
+
getRunDetails(scenarioId: string, runId: string, opts?: {
|
|
183
|
+
projectKey?: string;
|
|
184
|
+
}): Promise<ScenarioRunDetails>;
|
|
185
|
+
/**
|
|
186
|
+
* Get the log of a scenario run (GET /scenarios/{id}/{runId}/log), optionally
|
|
187
|
+
* scoped to a single step via `stepId`. The text is byte-bounded: at most
|
|
188
|
+
* `maxLogBytes` (default 1 MiB) of the beginning of the log is retained and
|
|
189
|
+
* `truncated` reports whether the cap cut the body.
|
|
190
|
+
*/
|
|
191
|
+
getRunLog(scenarioId: string, runId: string, opts?: {
|
|
192
|
+
stepId?: string;
|
|
193
|
+
maxLogBytes?: number;
|
|
194
|
+
projectKey?: string;
|
|
195
|
+
}): Promise<ScenarioRunLog>;
|
|
196
|
+
/** Get the payload of a (custom) scenario (GET /scenarios/{id}/payload). */
|
|
197
|
+
getPayload(scenarioId: string, opts?: {
|
|
198
|
+
projectKey?: string;
|
|
199
|
+
}): Promise<Record<string, unknown>>;
|
|
200
|
+
/** Update the payload of a (custom) scenario (PUT /scenarios/{id}/payload). */
|
|
201
|
+
setPayload(scenarioId: string, payload: Record<string, unknown>, opts?: {
|
|
202
|
+
projectKey?: string;
|
|
203
|
+
}): Promise<void>;
|
|
204
|
+
/**
|
|
205
|
+
* Toggle the active flag through the light endpoints (GET then PUT
|
|
206
|
+
* /scenarios/{id}/light) without a full-definition round-trip. Returns the
|
|
207
|
+
* light status observed after the PUT.
|
|
208
|
+
*/
|
|
209
|
+
setActive(scenarioId: string, active: boolean, opts?: {
|
|
210
|
+
projectKey?: string;
|
|
211
|
+
}): Promise<ScenarioActiveUpdateResult>;
|
|
212
|
+
/**
|
|
213
|
+
* Poll get-run-for-trigger until the triggered run reports an outcome or the
|
|
214
|
+
* deadline elapses. Shared by runAndWait and runScript: POST /run/ returns a
|
|
215
|
+
* TRIGGER run id, which differs from the actual scenario run id, so the real
|
|
216
|
+
* run is resolved via get-run-for-trigger (the trigger id never matches
|
|
217
|
+
* lastRun and would misreport a completed scenario as a timeout).
|
|
218
|
+
*/
|
|
219
|
+
private trackTriggerRun;
|
|
220
|
+
/**
|
|
221
|
+
* Best-effort step outcome summaries from the run report
|
|
222
|
+
* (GET /scenarios/{id}/{runId}). Never fails the wait: an unavailable
|
|
223
|
+
* run report returns undefined.
|
|
224
|
+
*/
|
|
225
|
+
private runStepSummaries;
|
|
121
226
|
/**
|
|
122
227
|
* Delete the throwaway scenario at the end of a code run, or report the
|
|
123
228
|
* explicit keep outcome. Never throws: delete failures are surfaced in the
|