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
package/dist/src/cli/flags.js
CHANGED
|
@@ -61,6 +61,10 @@ export const BOOLEAN_FLAGS = new Set([
|
|
|
61
61
|
"peek",
|
|
62
62
|
"raw-data",
|
|
63
63
|
"all",
|
|
64
|
+
"connected",
|
|
65
|
+
"conda",
|
|
66
|
+
"force",
|
|
67
|
+
"partitioning-folder",
|
|
64
68
|
]);
|
|
65
69
|
export const SHORT_FLAGS = {
|
|
66
70
|
v: "verbose",
|
|
@@ -82,9 +86,12 @@ export const VALUE_FLAGS = new Set([
|
|
|
82
86
|
"owner",
|
|
83
87
|
"topic",
|
|
84
88
|
"reply",
|
|
85
|
-
"
|
|
89
|
+
"configuration",
|
|
86
90
|
"partitions",
|
|
87
91
|
"since",
|
|
92
|
+
"keys",
|
|
93
|
+
"candidates",
|
|
94
|
+
"text",
|
|
88
95
|
"activity",
|
|
89
96
|
"agent",
|
|
90
97
|
"api-key",
|
|
@@ -225,6 +232,28 @@ export const VALUE_FLAGS = new Set([
|
|
|
225
232
|
"to",
|
|
226
233
|
"zone",
|
|
227
234
|
"zone-id",
|
|
235
|
+
"purpose",
|
|
236
|
+
"step-id",
|
|
237
|
+
"max-bytes",
|
|
238
|
+
"type-option-id",
|
|
239
|
+
"format-option-id",
|
|
240
|
+
"copy-partitioning-from",
|
|
241
|
+
"creation-mode",
|
|
242
|
+
"max-dataset-count",
|
|
243
|
+
"logins",
|
|
244
|
+
"max-log-bytes",
|
|
245
|
+
"llm-id",
|
|
246
|
+
"remove-intermediate",
|
|
247
|
+
"code-env",
|
|
248
|
+
"container-exec-config",
|
|
249
|
+
"set-active",
|
|
250
|
+
"binary-classification-threshold",
|
|
251
|
+
"sampling",
|
|
252
|
+
"use-optimal-threshold",
|
|
253
|
+
"skip-expensive-reports",
|
|
254
|
+
"full-class-name",
|
|
255
|
+
"include-libs",
|
|
256
|
+
"archive",
|
|
228
257
|
]);
|
|
229
258
|
export const REPEATABLE_VALUE_FLAGS = new Set([
|
|
230
259
|
"dataset",
|
|
@@ -13,6 +13,14 @@ export declare const VISUAL_UI_GATE: {
|
|
|
13
13
|
readonly requiredAuthentication: "pre-authenticated-sso-or-dedicated-ui-test-identity";
|
|
14
14
|
readonly evidenceRequired: "Open the instance in the Dataiku Apps UI and exercise the affected tiles, forms, and actions to confirm the release behaves as intended.";
|
|
15
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* The one generated instance-key shape shared by `app create-instance` and
|
|
18
|
+
* `app create-successor-instance` when no caller-chosen target is supplied:
|
|
19
|
+
* `APP_` plus 122 random bits of UUIDv4 hex, matching the official client's
|
|
20
|
+
* random-key mode. Collisions are negligible, so a generated key is never
|
|
21
|
+
* probed for absence and is never retried under an alternate key.
|
|
22
|
+
*/
|
|
23
|
+
export declare function generatedInstanceKey(): string;
|
|
16
24
|
export type AppInstanceCheckName = "project-type" | "app-registration" | "manifest-version" | "manifest-references";
|
|
17
25
|
export interface AppInstanceCheck {
|
|
18
26
|
check: AppInstanceCheckName;
|
|
@@ -46,7 +54,11 @@ export interface AppInstanceVerification {
|
|
|
46
54
|
export interface SuccessorInstanceRequest {
|
|
47
55
|
appId: string;
|
|
48
56
|
from: string;
|
|
49
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Caller-chosen successor key. Omitted for generated-key mode: the key is
|
|
59
|
+
* generated once during apply and DSS's own creation future names it.
|
|
60
|
+
*/
|
|
61
|
+
to?: string;
|
|
50
62
|
name?: string;
|
|
51
63
|
copyPermissions: boolean;
|
|
52
64
|
dryRun: boolean;
|
|
@@ -92,9 +104,12 @@ interface TargetAbsenceContext {
|
|
|
92
104
|
visibleAppInstanceKeys?: readonly (string | undefined)[];
|
|
93
105
|
}
|
|
94
106
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
107
|
+
* Caller-chosen-key guard: when the caller supplies the target key, creation
|
|
108
|
+
* cleanup is safe only when that target was proven absent before POST. A
|
|
109
|
+
* hidden 403 is not absence: project listing can prove a collision, but it
|
|
110
|
+
* cannot prove that an inaccessible project does not exist. Generated keys
|
|
111
|
+
* (app create-instance with targetProjectKey omitted) skip this guard: a
|
|
112
|
+
* freshly generated random key does not need an absence probe.
|
|
98
113
|
*/
|
|
99
114
|
export declare function requireAbsentProjectTarget(client: DataikuClient, targetProjectKey: string, targetFlag: "--to" | "targetProjectKey", context: TargetAbsenceContext): Promise<void>;
|
|
100
115
|
/**
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID, } from "node:crypto";
|
|
1
2
|
import { DataikuError, } from "../../errors.js";
|
|
2
3
|
import { projectIncarnationHash, } from "../../utils/project-incarnation.js";
|
|
3
4
|
import { stableHash, stringField, } from "../coerce.js";
|
|
@@ -17,6 +18,16 @@ export const VISUAL_UI_GATE = {
|
|
|
17
18
|
requiredAuthentication: "pre-authenticated-sso-or-dedicated-ui-test-identity",
|
|
18
19
|
evidenceRequired: "Open the instance in the Dataiku Apps UI and exercise the affected tiles, forms, and actions to confirm the release behaves as intended.",
|
|
19
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* The one generated instance-key shape shared by `app create-instance` and
|
|
23
|
+
* `app create-successor-instance` when no caller-chosen target is supplied:
|
|
24
|
+
* `APP_` plus 122 random bits of UUIDv4 hex, matching the official client's
|
|
25
|
+
* random-key mode. Collisions are negligible, so a generated key is never
|
|
26
|
+
* probed for absence and is never retried under an alternate key.
|
|
27
|
+
*/
|
|
28
|
+
export function generatedInstanceKey() {
|
|
29
|
+
return `APP_${randomUUID().replace(/-/g, "").toUpperCase()}`;
|
|
30
|
+
}
|
|
20
31
|
/**
|
|
21
32
|
* DSS answers the app-manifest probe with 400 ("neither an app template nor an
|
|
22
33
|
* app instance") for ordinary projects and 404 for missing ones. Both mean "not
|
|
@@ -183,9 +194,12 @@ export function futureTargetIdentity(result) {
|
|
|
183
194
|
return null;
|
|
184
195
|
}
|
|
185
196
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
197
|
+
* Caller-chosen-key guard: when the caller supplies the target key, creation
|
|
198
|
+
* cleanup is safe only when that target was proven absent before POST. A
|
|
199
|
+
* hidden 403 is not absence: project listing can prove a collision, but it
|
|
200
|
+
* cannot prove that an inaccessible project does not exist. Generated keys
|
|
201
|
+
* (app create-instance with targetProjectKey omitted) skip this guard: a
|
|
202
|
+
* freshly generated random key does not need an absence probe.
|
|
189
203
|
*/
|
|
190
204
|
export async function requireAbsentProjectTarget(client, targetProjectKey, targetFlag, context) {
|
|
191
205
|
if (context.visibleAppInstanceKeys?.includes(targetProjectKey) === true) {
|
|
@@ -251,11 +265,14 @@ export async function requireAbsentProjectTarget(client, targetProjectKey, targe
|
|
|
251
265
|
creationPostAttempted: false,
|
|
252
266
|
};
|
|
253
267
|
if (targetVisibleInProjectList !== true && targetVisibleInAppInstances !== true) {
|
|
254
|
-
throw new UsageError(`Could not confirm target project ${targetProjectKey} is absent.`, "target_absence_unverifiable", "
|
|
268
|
+
throw new UsageError(`Could not confirm target project ${targetProjectKey} is absent.`, "target_absence_unverifiable", "Creation was not attempted. For a fresh instance with a different key, omit targetProjectKey from `dss app create-instance`. To keep this exact key, retry with an identity that has global project visibility. DSS exposes no permission-independent key-availability endpoint or published atomic duplicate-key guarantee.", {
|
|
255
269
|
...probeDetails,
|
|
256
270
|
targetProbe: "forbidden-and-not-listable",
|
|
257
271
|
deploymentMasksUnknownProjects: "possible-but-unproven",
|
|
258
|
-
supportedRecoveryModes: [
|
|
272
|
+
supportedRecoveryModes: [
|
|
273
|
+
"create-instance-with-generated-key",
|
|
274
|
+
"grant-global-project-visibility",
|
|
275
|
+
],
|
|
259
276
|
unavailableRecoveryModes: [
|
|
260
277
|
"use-supported-key-availability-endpoint",
|
|
261
278
|
"server-atomic-create",
|
|
@@ -272,7 +289,7 @@ export async function requireAbsentProjectTarget(client, targetProjectKey, targe
|
|
|
272
289
|
*/
|
|
273
290
|
async function preflightSuccessor(client, request, usage) {
|
|
274
291
|
const { appId, from, to, } = request;
|
|
275
|
-
if (from === to) {
|
|
292
|
+
if (to !== undefined && from === to) {
|
|
276
293
|
throw new UsageError("--from and --to must be different project keys: a successor instance is created alongside its predecessor.", "validation_failed", `Usage: ${usage}`, { sourceProjectKey: from, targetProjectKey: to, });
|
|
277
294
|
}
|
|
278
295
|
const instances = await client.applications.listInstances(appId);
|
|
@@ -290,10 +307,16 @@ async function preflightSuccessor(client, request, usage) {
|
|
|
290
307
|
if (source.projectAppType !== "APP_INSTANCE") {
|
|
291
308
|
throw new UsageError(`Project ${from} is a ${source.projectAppType ?? "non-app"} project, not a classic Dataiku App instance.`, "validation_failed", "--from must name an APP_INSTANCE project; app templates are versioned with `dss app set-manifest-version`.", { sourceProjectKey: from, projectAppType: source.projectAppType ?? null, });
|
|
292
309
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
310
|
+
if (to !== undefined) {
|
|
311
|
+
// Caller-chosen keys must be proven absent before the single POST.
|
|
312
|
+
// Generated keys skip the probe entirely: the key does not exist yet,
|
|
313
|
+
// so an absence probe would prove nothing and probe a project the
|
|
314
|
+
// caller never named.
|
|
315
|
+
await requireAbsentProjectTarget(client, to, "--to", {
|
|
316
|
+
appId,
|
|
317
|
+
visibleAppInstanceKeys: instances.map((instance) => instance.projectKey),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
297
320
|
const templateManifest = await client.applications.getAppManifest(appId);
|
|
298
321
|
const templateVersion = rawVersion(templateManifest);
|
|
299
322
|
if (templateVersion === null) {
|
|
@@ -317,8 +340,10 @@ async function preflightSuccessor(client, request, usage) {
|
|
|
317
340
|
sourceProjectAppType: source.projectAppType,
|
|
318
341
|
sourceVersion: source.version,
|
|
319
342
|
sourceManifestHash: source.manifestHash,
|
|
320
|
-
|
|
321
|
-
|
|
343
|
+
generatedTarget: to === undefined,
|
|
344
|
+
...(request.name !== undefined || to !== undefined
|
|
345
|
+
? { targetProjectName: request.name ?? to, }
|
|
346
|
+
: {}),
|
|
322
347
|
templateManifestHash: stableHash(templateManifest),
|
|
323
348
|
templateVersion,
|
|
324
349
|
templateReferenceValidation,
|
|
@@ -343,6 +368,7 @@ export async function preflightSuccessorInstance(client, request, usage) {
|
|
|
343
368
|
preflightExecuted: true,
|
|
344
369
|
creationPostAttempted: false,
|
|
345
370
|
versionMutationAttempted: false,
|
|
371
|
+
...(preflight.generatedTarget ? { targetProjectKeyGeneratedDuringApply: true, } : {}),
|
|
346
372
|
appId: request.appId,
|
|
347
373
|
source: {
|
|
348
374
|
projectKey: request.from,
|
|
@@ -353,12 +379,28 @@ export async function preflightSuccessorInstance(client, request, usage) {
|
|
|
353
379
|
? { permissionsHash: preflight.sourcePermissionsHash, }
|
|
354
380
|
: {}),
|
|
355
381
|
},
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
382
|
+
...(preflight.generatedTarget
|
|
383
|
+
? {
|
|
384
|
+
// Generated mode: the target key does not exist yet, so no
|
|
385
|
+
// absence probe ran and none can be claimed. The plan/receipt
|
|
386
|
+
// names no key at all: it is generated once during apply and
|
|
387
|
+
// named by DSS's own terminal creation future.
|
|
388
|
+
target: {
|
|
389
|
+
targetProjectKeyGeneratedDuringApply: true,
|
|
390
|
+
...(preflight.targetProjectName !== undefined
|
|
391
|
+
? { name: preflight.targetProjectName, }
|
|
392
|
+
: { targetProjectNameGeneratedDuringApply: true, }),
|
|
393
|
+
},
|
|
394
|
+
targetPreflight: "not-applicable-generated-key",
|
|
395
|
+
}
|
|
396
|
+
: {
|
|
397
|
+
target: {
|
|
398
|
+
projectKey: request.to,
|
|
399
|
+
name: preflight.targetProjectName,
|
|
400
|
+
exists: false,
|
|
401
|
+
},
|
|
402
|
+
targetPreflight: "confirmed-absent",
|
|
403
|
+
}),
|
|
362
404
|
template: {
|
|
363
405
|
projectKey: request.appId,
|
|
364
406
|
version: preflight.templateVersion,
|
|
@@ -372,7 +414,7 @@ export async function preflightSuccessorInstance(client, request, usage) {
|
|
|
372
414
|
copyPermissions: request.copyPermissions,
|
|
373
415
|
next: {
|
|
374
416
|
setVersion: `dss app set-manifest-version --manifest-version <VERSION> --expect-hash ${preflight.templateManifestHash} --project-key ${request.appId}`,
|
|
375
|
-
createSuccessor: `dss app create-successor-instance ${request.appId} --from ${request.from} --to ${request.to}${request.name !== undefined ? ` --name ${JSON.stringify(request.name)}` : ""}${request.copyPermissions ? " --copy-permissions" : ""}`,
|
|
417
|
+
createSuccessor: `dss app create-successor-instance ${request.appId} --from ${request.from}${request.to !== undefined ? ` --to ${request.to}` : ""}${request.name !== undefined ? ` --name ${JSON.stringify(request.name)}` : ""}${request.copyPermissions ? " --copy-permissions" : ""}`,
|
|
376
418
|
},
|
|
377
419
|
};
|
|
378
420
|
}
|
|
@@ -388,7 +430,8 @@ export async function preflightSuccessorInstance(client, request, usage) {
|
|
|
388
430
|
* indeterminate and produces no cleanup entry.
|
|
389
431
|
*/
|
|
390
432
|
export async function createSuccessorInstance(client, request, usage) {
|
|
391
|
-
const { appId, from,
|
|
433
|
+
const { appId, from, } = request;
|
|
434
|
+
const generatedTarget = request.to === undefined;
|
|
392
435
|
const preflight = await preflightSuccessor(client, request, usage);
|
|
393
436
|
const source = {
|
|
394
437
|
projectKey: from,
|
|
@@ -408,27 +451,44 @@ export async function createSuccessorInstance(client, request, usage) {
|
|
|
408
451
|
sourcePreserved: true,
|
|
409
452
|
uiPublicationVerified: false,
|
|
410
453
|
requiredExternalGates: [VISUAL_UI_GATE,],
|
|
411
|
-
|
|
454
|
+
// Generated mode never probes a target, so it must not claim the
|
|
455
|
+
// probe-backed absence verdict: no target existed to verify.
|
|
456
|
+
targetPreflight: generatedTarget ? "not-applicable-generated-key" : "confirmed-absent",
|
|
412
457
|
};
|
|
413
458
|
if (request.dryRun) {
|
|
414
459
|
return {
|
|
415
460
|
dryRun: true,
|
|
416
461
|
action: "create-successor-instance",
|
|
417
462
|
...shared,
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
463
|
+
...(generatedTarget
|
|
464
|
+
? { targetProjectKeyGeneratedDuringApply: true, }
|
|
465
|
+
: {}),
|
|
466
|
+
target: generatedTarget
|
|
467
|
+
? {
|
|
468
|
+
targetProjectKeyGeneratedDuringApply: true,
|
|
469
|
+
...(preflight.targetProjectName !== undefined
|
|
470
|
+
? { name: preflight.targetProjectName, }
|
|
471
|
+
: { targetProjectNameGeneratedDuringApply: true, }),
|
|
472
|
+
}
|
|
473
|
+
: {
|
|
474
|
+
projectKey: request.to,
|
|
475
|
+
name: preflight.targetProjectName,
|
|
476
|
+
exists: false,
|
|
477
|
+
},
|
|
423
478
|
copyPermissions: request.copyPermissions,
|
|
424
479
|
preflight: "passed",
|
|
425
480
|
};
|
|
426
481
|
}
|
|
482
|
+
// Generated exactly once, here, immediately before the single POST: plan,
|
|
483
|
+
// preflight and dry-run never allocate. A definitive rejection does not
|
|
484
|
+
// retry and does not fall back to an alternate key.
|
|
485
|
+
const to = request.to ?? generatedInstanceKey();
|
|
486
|
+
const targetProjectName = preflight.targetProjectName ?? to;
|
|
427
487
|
let created;
|
|
428
488
|
try {
|
|
429
489
|
created = await client.applications.createInstance(appId, {
|
|
430
490
|
targetProjectKey: to,
|
|
431
|
-
targetProjectName
|
|
491
|
+
targetProjectName,
|
|
432
492
|
});
|
|
433
493
|
}
|
|
434
494
|
catch (error) {
|
|
@@ -436,7 +496,7 @@ export async function createSuccessorInstance(client, request, usage) {
|
|
|
436
496
|
return {
|
|
437
497
|
...shared,
|
|
438
498
|
projectKey: to,
|
|
439
|
-
target: { projectKey: to, name:
|
|
499
|
+
target: { projectKey: to, name: targetProjectName, },
|
|
440
500
|
success: false,
|
|
441
501
|
state: rejected ? "CREATE_FAILED" : "INDETERMINATE",
|
|
442
502
|
elapsedMs: 0,
|
|
@@ -465,7 +525,7 @@ export async function createSuccessorInstance(client, request, usage) {
|
|
|
465
525
|
return {
|
|
466
526
|
...shared,
|
|
467
527
|
projectKey: to,
|
|
468
|
-
target: { projectKey: to, name:
|
|
528
|
+
target: { projectKey: to, name: targetProjectName, },
|
|
469
529
|
success: false,
|
|
470
530
|
state: "VERIFICATION_FAILED",
|
|
471
531
|
elapsedMs: 0,
|
|
@@ -485,7 +545,7 @@ export async function createSuccessorInstance(client, request, usage) {
|
|
|
485
545
|
const base = {
|
|
486
546
|
...shared,
|
|
487
547
|
projectKey: to,
|
|
488
|
-
target: { projectKey: to, name:
|
|
548
|
+
target: { projectKey: to, name: targetProjectName, },
|
|
489
549
|
...(instance ? { instance, } : {}),
|
|
490
550
|
};
|
|
491
551
|
let waited;
|
|
@@ -280,7 +280,9 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
|
|
|
280
280
|
};
|
|
281
281
|
}
|
|
282
282
|
case "notebook.save-sql": {
|
|
283
|
-
|
|
283
|
+
// On create the persisted id is the server receipt (`saved`), not the
|
|
284
|
+
// requested handle, which only becomes the display name.
|
|
285
|
+
const id = stringField(record, ["saved", "id",]) ?? args[0];
|
|
284
286
|
if (!id)
|
|
285
287
|
return undefined;
|
|
286
288
|
return {
|
|
@@ -116,8 +116,7 @@ export function flowZonePlanPosition(value, source) {
|
|
|
116
116
|
};
|
|
117
117
|
}
|
|
118
118
|
export function flowZoneCurrentPosition(zone) {
|
|
119
|
-
const
|
|
120
|
-
const position = plainRecord(record.position);
|
|
119
|
+
const position = plainRecord(zone.position);
|
|
121
120
|
if (!position)
|
|
122
121
|
return undefined;
|
|
123
122
|
const x = position.x;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical discovery output schemas, keyed by `resource.action`.
|
|
3
|
+
*
|
|
4
|
+
* TypeBox definitions from `packages/types` plus the inline literal schemas
|
|
5
|
+
* that exist only on the CLI side (code-env log envelope, code.run outcome,
|
|
6
|
+
* project-library payloads, notebook saves, sql.query handoff envelope).
|
|
7
|
+
* `scripts/generate-action-output-schemas.mjs` serializes this map into
|
|
8
|
+
* `src/generated/action-output-schemas.json`; discovery (src/cli/contract.ts)
|
|
9
|
+
* reads that generated JSON as plain data, so the TypeBox schema graph never
|
|
10
|
+
* loads on the discovery path. SDK validation keeps using the TypeBox schema
|
|
11
|
+
* objects from `packages/types` directly.
|
|
12
|
+
*
|
|
13
|
+
* Imported by the generator and the discovery parity test only.
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* Canonical TypeBox-derived output schemas, keyed by `resource.action`. This is
|
|
17
|
+
* the single source of truth for `src/generated/action-output-schemas.json`,
|
|
18
|
+
* which discovery reads as plain data so no TypeBox schema graph loads on the
|
|
19
|
+
* discovery path. Regenerate with
|
|
20
|
+
* `bun scripts/generate-action-output-schemas.mjs`; `bun run check` fails when
|
|
21
|
+
* the generated file is stale. SDK validation keeps using the TypeBox schema
|
|
22
|
+
* objects from `packages/types` directly and never depends on the generated file.
|
|
23
|
+
*/
|
|
24
|
+
export declare function typeBoxCommandOutputSchemas(): Record<string, Record<string, unknown>>;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Canonical discovery output schemas, keyed by `resource.action`.
|
|
3
|
+
*
|
|
4
|
+
* TypeBox definitions from `packages/types` plus the inline literal schemas
|
|
5
|
+
* that exist only on the CLI side (code-env log envelope, code.run outcome,
|
|
6
|
+
* project-library payloads, notebook saves, sql.query handoff envelope).
|
|
7
|
+
* `scripts/generate-action-output-schemas.mjs` serializes this map into
|
|
8
|
+
* `src/generated/action-output-schemas.json`; discovery (src/cli/contract.ts)
|
|
9
|
+
* reads that generated JSON as plain data, so the TypeBox schema graph never
|
|
10
|
+
* loads on the discovery path. SDK validation keeps using the TypeBox schema
|
|
11
|
+
* objects from `packages/types` directly.
|
|
12
|
+
*
|
|
13
|
+
* Imported by the generator and the discovery parity test only.
|
|
14
|
+
*/
|
|
15
|
+
const PROJECT_LIBRARY_ITEM_OUTPUT_SCHEMA = {
|
|
16
|
+
type: "object",
|
|
17
|
+
additionalProperties: false,
|
|
18
|
+
required: ["name",],
|
|
19
|
+
properties: {
|
|
20
|
+
name: { type: "string", },
|
|
21
|
+
path: { type: "string", },
|
|
22
|
+
size: { type: "integer", minimum: 0, },
|
|
23
|
+
mimeType: { type: "string", },
|
|
24
|
+
hasData: { type: "boolean", },
|
|
25
|
+
lastModified: { type: "number", },
|
|
26
|
+
children: { type: "array", items: { type: "object", additionalProperties: true, }, },
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
const NOTEBOOK_SAVE_OUTPUT_SCHEMA = {
|
|
30
|
+
type: "object",
|
|
31
|
+
additionalProperties: false,
|
|
32
|
+
required: ["saved", "resource", "created", "hash",],
|
|
33
|
+
properties: {
|
|
34
|
+
saved: { type: "string", },
|
|
35
|
+
resource: { enum: ["jupyter-notebook", "sql-notebook",], },
|
|
36
|
+
created: { type: "boolean", },
|
|
37
|
+
hash: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* `notebook.save-sql` adds `requested`: on create DSS allocates the persisted
|
|
42
|
+
* id (`saved`), while the requested handle only becomes the display name.
|
|
43
|
+
*/
|
|
44
|
+
const NOTEBOOK_SAVE_SQL_OUTPUT_SCHEMA = {
|
|
45
|
+
...NOTEBOOK_SAVE_OUTPUT_SCHEMA,
|
|
46
|
+
required: ["saved", "requested", "resource", "created", "hash",],
|
|
47
|
+
properties: {
|
|
48
|
+
...NOTEBOOK_SAVE_OUTPUT_SCHEMA["properties"],
|
|
49
|
+
requested: { type: "string", },
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
let commandOutputSchemas;
|
|
53
|
+
/**
|
|
54
|
+
* Canonical TypeBox-derived output schemas, keyed by `resource.action`. This is
|
|
55
|
+
* the single source of truth for `src/generated/action-output-schemas.json`,
|
|
56
|
+
* which discovery reads as plain data so no TypeBox schema graph loads on the
|
|
57
|
+
* discovery path. Regenerate with
|
|
58
|
+
* `bun scripts/generate-action-output-schemas.mjs`; `bun run check` fails when
|
|
59
|
+
* the generated file is stale. SDK validation keeps using the TypeBox schema
|
|
60
|
+
* objects from `packages/types` directly and never depends on the generated file.
|
|
61
|
+
*/
|
|
62
|
+
export function typeBoxCommandOutputSchemas() {
|
|
63
|
+
if (commandOutputSchemas)
|
|
64
|
+
return commandOutputSchemas;
|
|
65
|
+
const { CodeEnvDetailsSchema, CodeEnvLogSummaryArraySchema, CodeEnvSummaryArraySchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, FlowZoneArraySchema, FlowZoneSchema, JobSummaryArraySchema, JobWaitResultSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, NotebookSessionArraySchema, ProjectDetailsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, RecipeSummaryArraySchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioSummaryArraySchema, SqlNotebookContentSchema, SqlNotebookHistorySchema, SqlNotebookSummaryArraySchema, SqlQueryResponseSchema, } = require("../schemas.js");
|
|
66
|
+
return commandOutputSchemas = {
|
|
67
|
+
"code-env.list": CodeEnvSummaryArraySchema,
|
|
68
|
+
"code-env.get": CodeEnvDetailsSchema,
|
|
69
|
+
"code-env.list-logs": CodeEnvLogSummaryArraySchema,
|
|
70
|
+
"code-env.get-log": {
|
|
71
|
+
oneOf: [
|
|
72
|
+
{
|
|
73
|
+
type: "object",
|
|
74
|
+
required: ["log", "bytes", "truncated", "tailed", "envLang", "envName", "logName",],
|
|
75
|
+
properties: {
|
|
76
|
+
log: { type: "string", },
|
|
77
|
+
bytes: { type: "integer", minimum: 0, },
|
|
78
|
+
truncated: { type: "boolean", },
|
|
79
|
+
tailed: { type: "boolean", },
|
|
80
|
+
envLang: { enum: ["PYTHON", "R",], },
|
|
81
|
+
envName: { type: "string", },
|
|
82
|
+
logName: { type: "string", },
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: "object",
|
|
87
|
+
required: ["path", "bytes", "truncated", "tailed", "envLang", "envName", "logName",],
|
|
88
|
+
properties: {
|
|
89
|
+
path: { type: "string", },
|
|
90
|
+
bytes: { type: "integer", minimum: 0, },
|
|
91
|
+
truncated: { type: "boolean", },
|
|
92
|
+
tailed: { type: "boolean", },
|
|
93
|
+
envLang: { enum: ["PYTHON", "R",], },
|
|
94
|
+
envName: { type: "string", },
|
|
95
|
+
logName: { type: "string", },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
"code-env.version": CodeEnvVersionForProjectSchema,
|
|
101
|
+
"code-env.usages": CodeEnvUsageArraySchema,
|
|
102
|
+
"code.run": {
|
|
103
|
+
type: "object",
|
|
104
|
+
additionalProperties: false,
|
|
105
|
+
required: [
|
|
106
|
+
"outcome",
|
|
107
|
+
"success",
|
|
108
|
+
"runId",
|
|
109
|
+
"elapsedMs",
|
|
110
|
+
"pollCount",
|
|
111
|
+
"output",
|
|
112
|
+
"logTruncated",
|
|
113
|
+
"maxLogBytes",
|
|
114
|
+
"cleanup",
|
|
115
|
+
],
|
|
116
|
+
properties: {
|
|
117
|
+
outcome: { type: "string", },
|
|
118
|
+
success: { type: "boolean", },
|
|
119
|
+
runId: { type: "string", },
|
|
120
|
+
elapsedMs: { type: "number", minimum: 0, },
|
|
121
|
+
pollCount: { type: "integer", minimum: 0, },
|
|
122
|
+
output: { type: "string", },
|
|
123
|
+
log: { type: "string", },
|
|
124
|
+
logTruncated: { type: "boolean", },
|
|
125
|
+
maxLogBytes: { type: "integer", minimum: 0, },
|
|
126
|
+
timedOut: { const: true, },
|
|
127
|
+
timeoutMs: { type: "integer", minimum: 0, },
|
|
128
|
+
cleanup: {
|
|
129
|
+
type: "object",
|
|
130
|
+
additionalProperties: false,
|
|
131
|
+
required: ["status",],
|
|
132
|
+
properties: {
|
|
133
|
+
status: { enum: ["deleted", "kept", "failed",], },
|
|
134
|
+
error: { type: "string", },
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
"notebook.list-jupyter": JupyterNotebookSummaryArraySchema,
|
|
140
|
+
"notebook.get-jupyter": JupyterNotebookContentSchema,
|
|
141
|
+
"notebook.sessions-jupyter": NotebookSessionArraySchema,
|
|
142
|
+
"notebook.list-sql": SqlNotebookSummaryArraySchema,
|
|
143
|
+
"notebook.get-sql": SqlNotebookContentSchema,
|
|
144
|
+
"notebook.history-sql": SqlNotebookHistorySchema,
|
|
145
|
+
"notebook.save-jupyter": NOTEBOOK_SAVE_OUTPUT_SCHEMA,
|
|
146
|
+
"notebook.save-sql": NOTEBOOK_SAVE_SQL_OUTPUT_SCHEMA,
|
|
147
|
+
"project-library.list": { type: "array", items: PROJECT_LIBRARY_ITEM_OUTPUT_SCHEMA, },
|
|
148
|
+
"project-library.get-bytes": {
|
|
149
|
+
type: "object",
|
|
150
|
+
additionalProperties: false,
|
|
151
|
+
required: ["path", "bytes", "sha256",],
|
|
152
|
+
properties: {
|
|
153
|
+
path: { type: "string", },
|
|
154
|
+
bytes: { type: "integer", minimum: 0, },
|
|
155
|
+
sha256: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
"project-library.put": {
|
|
159
|
+
type: "object",
|
|
160
|
+
additionalProperties: false,
|
|
161
|
+
required: ["updated", "bytes", "sha256",],
|
|
162
|
+
properties: {
|
|
163
|
+
updated: { type: "string", },
|
|
164
|
+
bytes: { type: "integer", minimum: 0, },
|
|
165
|
+
sha256: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
166
|
+
beforeSha256: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
"project-library.diff": {
|
|
170
|
+
type: "object",
|
|
171
|
+
additionalProperties: false,
|
|
172
|
+
required: [
|
|
173
|
+
"path",
|
|
174
|
+
"unchanged",
|
|
175
|
+
"added",
|
|
176
|
+
"removed",
|
|
177
|
+
"diff",
|
|
178
|
+
"diffTruncated",
|
|
179
|
+
"localSha256",
|
|
180
|
+
"localBytes",
|
|
181
|
+
"maxLines",
|
|
182
|
+
],
|
|
183
|
+
properties: {
|
|
184
|
+
path: { type: "string", },
|
|
185
|
+
unchanged: { type: "boolean", },
|
|
186
|
+
added: { type: "integer", minimum: 0, },
|
|
187
|
+
removed: { type: "integer", minimum: 0, },
|
|
188
|
+
diff: { type: "string", },
|
|
189
|
+
diffTruncated: { type: "boolean", },
|
|
190
|
+
binary: { type: "boolean", },
|
|
191
|
+
remoteAbsent: { type: "boolean", },
|
|
192
|
+
remoteSha256: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
193
|
+
remoteBytes: { type: "integer", minimum: 0, },
|
|
194
|
+
localSha256: { type: "string", pattern: "^[a-f0-9]{64}$", },
|
|
195
|
+
localBytes: { type: "integer", minimum: 0, },
|
|
196
|
+
maxLines: { type: "integer", minimum: 0, },
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
"project.list": ProjectSummaryArraySchema,
|
|
200
|
+
"project.get": ProjectDetailsSchema,
|
|
201
|
+
"project.metadata": ProjectMetadataSchema,
|
|
202
|
+
"dataset.list": DatasetSummaryArraySchema,
|
|
203
|
+
"dataset.get": DatasetDetailsSchema,
|
|
204
|
+
"dataset.schema": DatasetSchemaSchema,
|
|
205
|
+
"recipe.list": RecipeSummaryArraySchema,
|
|
206
|
+
"job.list": JobSummaryArraySchema,
|
|
207
|
+
"job.wait": JobWaitResultSchema,
|
|
208
|
+
"job.monitor": JobWaitResultSchema,
|
|
209
|
+
"scenario.list": ScenarioSummaryArraySchema,
|
|
210
|
+
"scenario.get": ScenarioDetailsSchema,
|
|
211
|
+
"scenario.status": ScenarioStatusSchema,
|
|
212
|
+
"flow-zone.list": FlowZoneArraySchema,
|
|
213
|
+
"flow-zone.get": FlowZoneSchema,
|
|
214
|
+
"sql.query": {
|
|
215
|
+
anyOf: [
|
|
216
|
+
SqlQueryResponseSchema,
|
|
217
|
+
{
|
|
218
|
+
type: "object",
|
|
219
|
+
required: ["queryId", "rowCount", "preview",],
|
|
220
|
+
additionalProperties: true,
|
|
221
|
+
properties: {
|
|
222
|
+
queryId: { type: "string", },
|
|
223
|
+
rowCount: { type: "number", },
|
|
224
|
+
preview: { type: "array", items: true, },
|
|
225
|
+
truncated: { type: "boolean", },
|
|
226
|
+
outputPath: { type: "string", },
|
|
227
|
+
written: { type: "string", },
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
],
|
|
231
|
+
},
|
|
232
|
+
};
|
|
233
|
+
}
|
package/dist/src/cli/output.d.ts
CHANGED
|
@@ -10,7 +10,7 @@ export declare function pickResultFields(item: unknown, fields: string[]): unkno
|
|
|
10
10
|
* element-wise; scalars and string results pass through untouched. Requested keys
|
|
11
11
|
* that are absent become null so every row keeps a stable, predictable shape.
|
|
12
12
|
*/
|
|
13
|
-
export declare function projectResultFields(result: unknown, fields: string[]): unknown;
|
|
13
|
+
export declare function projectResultFields(result: unknown, fields: string[], availableFieldNames?: () => string[]): unknown;
|
|
14
14
|
export declare function writeCommandResult(result: unknown): void;
|
|
15
15
|
export declare function transientBodyWithTargetContext(body: string, target: string, elapsedMs: number): string;
|
|
16
16
|
export declare function addTransientTargetContext(error: unknown, target: string, elapsedMs: number): never;
|