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
@@ -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
- "text",
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
- to: string;
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
- * Creation cleanup is safe only when the target was proven absent before POST.
96
- * A hidden 403 is not absence: project listing can prove a collision, but it
97
- * cannot prove that an inaccessible project does not exist.
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
- * Creation cleanup is safe only when the target was proven absent before POST.
187
- * A hidden 403 is not absence: project listing can prove a collision, but it
188
- * cannot prove that an inaccessible project does not exist.
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", "DSS exposes no permission-independent project-key availability endpoint, and app-instance creation has no published atomic duplicate-key guarantee. Retry with an identity that has global project visibility; creation was not attempted.", {
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: ["grant-global-project-visibility",],
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
- await requireAbsentProjectTarget(client, to, "--to", {
294
- appId,
295
- visibleAppInstanceKeys: instances.map((instance) => instance.projectKey),
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
- targetProjectName: request.name ?? to,
321
- targetExists: false,
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
- target: {
357
- projectKey: request.to,
358
- name: preflight.targetProjectName,
359
- exists: false,
360
- },
361
- targetPreflight: "confirmed-absent",
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, to, } = request;
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
- targetPreflight: "confirmed-absent",
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
- target: {
419
- projectKey: to,
420
- name: preflight.targetProjectName,
421
- exists: false,
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: preflight.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: preflight.targetProjectName, },
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: preflight.targetProjectName, },
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: preflight.targetProjectName, },
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
- const id = args[0];
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 record = zone;
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
+ }
@@ -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;