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.
Files changed (132) hide show
  1. package/README.md +151 -46
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +102 -0
  4. package/dist/packages/types/src/index.js +76 -0
  5. package/dist/src/cli/commands/app.js +57 -15
  6. package/dist/src/cli/commands/bundle.js +1 -1
  7. package/dist/src/cli/commands/code-env.js +13 -7
  8. package/dist/src/cli/commands/code.js +1 -1
  9. package/dist/src/cli/commands/connection.d.ts +9 -0
  10. package/dist/src/cli/commands/connection.js +267 -1
  11. package/dist/src/cli/commands/data-collection.d.ts +2 -0
  12. package/dist/src/cli/commands/data-collection.js +164 -0
  13. package/dist/src/cli/commands/dataset.js +162 -33
  14. package/dist/src/cli/commands/future.js +2 -2
  15. package/dist/src/cli/commands/group.d.ts +2 -0
  16. package/dist/src/cli/commands/group.js +109 -0
  17. package/dist/src/cli/commands/index.js +151 -78
  18. package/dist/src/cli/commands/job.js +4 -2
  19. package/dist/src/cli/commands/knowledge-bank.d.ts +2 -0
  20. package/dist/src/cli/commands/knowledge-bank.js +80 -0
  21. package/dist/src/cli/commands/llm.d.ts +2 -0
  22. package/dist/src/cli/commands/llm.js +93 -0
  23. package/dist/src/cli/commands/macro.d.ts +2 -0
  24. package/dist/src/cli/commands/macro.js +221 -0
  25. package/dist/src/cli/commands/ml-task.js +18 -6
  26. package/dist/src/cli/commands/notebook.js +6 -2
  27. package/dist/src/cli/commands/plugin.d.ts +2 -0
  28. package/dist/src/cli/commands/plugin.js +799 -0
  29. package/dist/src/cli/commands/project-folder.d.ts +2 -0
  30. package/dist/src/cli/commands/project-folder.js +197 -0
  31. package/dist/src/cli/commands/project-git.js +15 -55
  32. package/dist/src/cli/commands/project.js +52 -6
  33. package/dist/src/cli/commands/recipe.js +36 -1
  34. package/dist/src/cli/commands/saved-model.d.ts +5 -0
  35. package/dist/src/cli/commands/saved-model.js +388 -1
  36. package/dist/src/cli/commands/scenario.js +139 -2
  37. package/dist/src/cli/commands/user.d.ts +8 -0
  38. package/dist/src/cli/commands/user.js +296 -0
  39. package/dist/src/cli/contract.d.ts +1 -2
  40. package/dist/src/cli/contract.js +1098 -297
  41. package/dist/src/cli/flags.js +30 -1
  42. package/dist/src/cli/helpers/app-successor.d.ts +19 -4
  43. package/dist/src/cli/helpers/app-successor.js +90 -30
  44. package/dist/src/cli/helpers/cleanup.js +3 -1
  45. package/dist/src/cli/helpers/flow-zone.js +1 -2
  46. package/dist/src/cli/output-schemas.d.ts +24 -0
  47. package/dist/src/cli/output-schemas.js +233 -0
  48. package/dist/src/cli/output.d.ts +1 -1
  49. package/dist/src/cli/output.js +23 -10
  50. package/dist/src/cli/usage.d.ts +1 -0
  51. package/dist/src/cli/usage.js +47 -1
  52. package/dist/src/cli.js +147 -41
  53. package/dist/src/client.d.ts +92 -5
  54. package/dist/src/client.js +202 -31
  55. package/dist/src/errors.d.ts +3 -0
  56. package/dist/src/errors.js +8 -4
  57. package/dist/src/generated/action-output-schemas.json +1735 -0
  58. package/dist/src/index.d.ts +16 -7
  59. package/dist/src/index.js +11 -2
  60. package/dist/src/resources/analyses.js +1 -8
  61. package/dist/src/resources/applications.d.ts +8 -6
  62. package/dist/src/resources/applications.js +21 -21
  63. package/dist/src/resources/base.d.ts +4 -0
  64. package/dist/src/resources/base.js +15 -0
  65. package/dist/src/resources/bundles.d.ts +9 -4
  66. package/dist/src/resources/bundles.js +10 -5
  67. package/dist/src/resources/connections.d.ts +78 -1
  68. package/dist/src/resources/connections.js +132 -1
  69. package/dist/src/resources/data-collections.d.ts +118 -0
  70. package/dist/src/resources/data-collections.js +49 -0
  71. package/dist/src/resources/datasets.d.ts +69 -0
  72. package/dist/src/resources/datasets.js +136 -5
  73. package/dist/src/resources/flow-zones.d.ts +6 -2
  74. package/dist/src/resources/flow-zones.js +6 -3
  75. package/dist/src/resources/futures.d.ts +6 -1
  76. package/dist/src/resources/futures.js +68 -22
  77. package/dist/src/resources/groups.d.ts +47 -0
  78. package/dist/src/resources/groups.js +56 -0
  79. package/dist/src/resources/jobs.d.ts +8 -13
  80. package/dist/src/resources/jobs.js +71 -34
  81. package/dist/src/resources/knowledge-banks.d.ts +58 -0
  82. package/dist/src/resources/knowledge-banks.js +61 -0
  83. package/dist/src/resources/llms.d.ts +92 -0
  84. package/dist/src/resources/llms.js +62 -0
  85. package/dist/src/resources/macros.d.ts +121 -0
  86. package/dist/src/resources/macros.js +231 -0
  87. package/dist/src/resources/ml-tasks.d.ts +37 -2
  88. package/dist/src/resources/ml-tasks.js +109 -20
  89. package/dist/src/resources/model-evaluation-stores.js +1 -8
  90. package/dist/src/resources/notebooks.d.ts +43 -7
  91. package/dist/src/resources/notebooks.js +53 -13
  92. package/dist/src/resources/plugins.d.ts +263 -0
  93. package/dist/src/resources/plugins.js +455 -0
  94. package/dist/src/resources/project-folders.d.ts +71 -0
  95. package/dist/src/resources/project-folders.js +57 -0
  96. package/dist/src/resources/project-git.d.ts +12 -12
  97. package/dist/src/resources/project-git.js +84 -82
  98. package/dist/src/resources/project-library.d.ts +0 -1
  99. package/dist/src/resources/project-library.js +1 -17
  100. package/dist/src/resources/projects.d.ts +23 -3
  101. package/dist/src/resources/projects.js +60 -34
  102. package/dist/src/resources/recipes.d.ts +15 -1
  103. package/dist/src/resources/recipes.js +73 -6
  104. package/dist/src/resources/saved-models.d.ts +134 -1
  105. package/dist/src/resources/saved-models.js +214 -6
  106. package/dist/src/resources/scenarios.d.ts +105 -0
  107. package/dist/src/resources/scenarios.js +232 -106
  108. package/dist/src/resources/sql.js +5 -1
  109. package/dist/src/resources/users.d.ts +129 -0
  110. package/dist/src/resources/users.js +128 -0
  111. package/dist/src/resources/webapps.d.ts +15 -2
  112. package/dist/src/resources/webapps.js +18 -4
  113. package/dist/src/schemas.d.ts +2 -2
  114. package/dist/src/schemas.js +1 -1
  115. package/dist/src/utils/deep-merge.d.ts +1 -1
  116. package/dist/src/utils/git-reference.d.ts +12 -0
  117. package/dist/src/utils/git-reference.js +38 -0
  118. package/dist/src/utils/polling.d.ts +20 -0
  119. package/dist/src/utils/polling.js +27 -0
  120. package/dist/src/utils/response-file.js +1 -1
  121. package/dist/src/utils/secret-sanitize.d.ts +54 -0
  122. package/dist/src/utils/secret-sanitize.js +101 -0
  123. package/package.json +9 -8
  124. package/packages/types/dist/index.d.ts +102 -0
  125. package/packages/types/dist/index.js +76 -0
  126. package/plugin.json +1 -1
  127. package/skills/dataiku-dss/SKILL.md +11 -7
  128. package/skills/dataiku-dss/references/app-releases.md +8 -8
  129. package/skills/dataiku-dss/references/authentication.md +6 -6
  130. package/skills/dataiku-dss/references/discovery.md +4 -4
  131. package/skills/dataiku-dss/references/mutations.md +1 -1
  132. 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
- /** Get saved-model settings and metadata. */
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 { UsageError, } from "../cli/usage.js";
2
- import { BaseResource, } from "./base.js";
3
- function requireNonEmpty(value, name) {
4
- if (typeof value !== "string" || value.trim().length === 0) {
5
- throw new UsageError(`${name} must be a non-empty string.`, "validation_failed");
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
- /** Get saved-model settings and metadata. */
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