dataiku-sdk 3.6.1 → 3.7.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 +14 -6
- package/bin/bun-version.js +14 -0
- package/bin/dss.js +11 -15
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +74 -1
- package/dist/packages/types/src/index.js +53 -1
- package/dist/src/cli/coerce.d.ts +1 -0
- package/dist/src/cli/coerce.js +19 -15
- package/dist/src/cli/command-syntax.json +3521 -416
- package/dist/src/cli/commands/analysis.js +19 -1
- package/dist/src/cli/commands/bundle.js +22 -0
- package/dist/src/cli/commands/connection.js +26 -2
- package/dist/src/cli/commands/data-quality.js +33 -1
- package/dist/src/cli/commands/dataset.js +35 -4
- package/dist/src/cli/commands/discussion.js +15 -0
- package/dist/src/cli/commands/doctor.js +1 -1
- package/dist/src/cli/commands/flow.d.ts +5 -0
- package/dist/src/cli/commands/flow.js +57 -0
- package/dist/src/cli/commands/future.js +8 -0
- package/dist/src/cli/commands/index.js +6 -0
- package/dist/src/cli/commands/job.js +29 -6
- package/dist/src/cli/commands/metrics.js +21 -1
- package/dist/src/cli/commands/ml-task.d.ts +5 -0
- package/dist/src/cli/commands/ml-task.js +86 -16
- package/dist/src/cli/commands/mlflow.d.ts +11 -0
- package/dist/src/cli/commands/mlflow.js +121 -0
- package/dist/src/cli/commands/plugin.js +5 -11
- package/dist/src/cli/commands/project-deployer.js +70 -0
- package/dist/src/cli/commands/project-library.js +2 -5
- package/dist/src/cli/commands/project.js +8 -0
- package/dist/src/cli/commands/recipe.d.ts +9 -0
- package/dist/src/cli/commands/recipe.js +93 -7
- package/dist/src/cli/commands/saved-model.d.ts +1 -1
- package/dist/src/cli/commands/saved-model.js +9 -76
- package/dist/src/cli/commands/streaming-endpoint.js +30 -1
- package/dist/src/cli/commands/webapp.js +8 -0
- package/dist/src/cli/commands/wiki.js +22 -0
- package/dist/src/cli/commands/workspace.js +8 -0
- package/dist/src/cli/contract.d.ts +16 -15
- package/dist/src/cli/contract.js +139 -3404
- package/dist/src/cli/doctor.d.ts +13 -0
- package/dist/src/cli/doctor.js +41 -1
- package/dist/src/cli/flags.d.ts +7 -1
- package/dist/src/cli/flags.js +78 -6
- package/dist/src/cli/helpers/app-successor.js +1 -2
- package/dist/src/cli/helpers/documentation.d.ts +21 -0
- package/dist/src/cli/helpers/documentation.js +53 -0
- package/dist/src/cli/helpers/trained-model.d.ts +26 -0
- package/dist/src/cli/helpers/trained-model.js +144 -0
- package/dist/src/cli/list-output.d.ts +7 -0
- package/dist/src/cli/list-output.js +77 -0
- package/dist/src/cli/list-shapes.d.ts +21 -0
- package/dist/src/cli/list-shapes.js +111 -0
- package/dist/src/cli/output-schemas.d.ts +0 -14
- package/dist/src/cli/output-schemas.js +4 -7
- package/dist/src/cli/output.d.ts +0 -1
- package/dist/src/cli/output.js +27 -19
- package/dist/src/cli/plans.d.ts +14 -0
- package/dist/src/cli/plans.js +3684 -0
- package/dist/src/cli/usage.d.ts +7 -0
- package/dist/src/cli/usage.js +20 -1
- package/dist/src/cli/version.d.ts +2 -2
- package/dist/src/cli/version.js +2 -2
- package/dist/src/cli.js +127 -113
- package/dist/src/client.d.ts +52 -43
- package/dist/src/client.js +267 -96
- package/dist/src/errors.d.ts +11 -1
- package/dist/src/errors.js +31 -47
- package/dist/src/generated/action-output-schemas.json +345 -89
- package/dist/src/index.d.ts +5 -1
- package/dist/src/index.js +3 -0
- package/dist/src/resources/analyses.d.ts +8 -0
- package/dist/src/resources/analyses.js +13 -1
- package/dist/src/resources/bundles.d.ts +34 -0
- package/dist/src/resources/bundles.js +67 -0
- package/dist/src/resources/connections.d.ts +9 -0
- package/dist/src/resources/connections.js +15 -0
- package/dist/src/resources/data-quality.d.ts +20 -0
- package/dist/src/resources/data-quality.js +30 -0
- package/dist/src/resources/dataset-create.d.ts +19 -0
- package/dist/src/resources/dataset-create.js +66 -0
- package/dist/src/resources/datasets.d.ts +25 -15
- package/dist/src/resources/datasets.js +59 -111
- package/dist/src/resources/discussions.d.ts +5 -0
- package/dist/src/resources/discussions.js +7 -0
- package/dist/src/resources/documentation.d.ts +25 -0
- package/dist/src/resources/documentation.js +16 -0
- package/dist/src/resources/flow.d.ts +48 -0
- package/dist/src/resources/flow.js +65 -0
- package/dist/src/resources/futures.d.ts +23 -0
- package/dist/src/resources/futures.js +32 -0
- package/dist/src/resources/jobs.js +102 -2
- package/dist/src/resources/metrics.d.ts +10 -0
- package/dist/src/resources/metrics.js +10 -0
- package/dist/src/resources/ml-tasks.d.ts +65 -2
- package/dist/src/resources/ml-tasks.js +102 -28
- package/dist/src/resources/mlflow-extension.d.ts +73 -0
- package/dist/src/resources/mlflow-extension.js +105 -0
- package/dist/src/resources/projects.d.ts +6 -0
- package/dist/src/resources/projects.js +8 -0
- package/dist/src/resources/recipe-create.d.ts +65 -0
- package/dist/src/resources/recipe-create.js +338 -0
- package/dist/src/resources/recipes.d.ts +28 -29
- package/dist/src/resources/recipes.js +126 -245
- package/dist/src/resources/saved-models.d.ts +10 -6
- package/dist/src/resources/saved-models.js +16 -14
- package/dist/src/resources/scenarios.js +8 -14
- package/dist/src/resources/streaming-endpoints.d.ts +12 -0
- package/dist/src/resources/streaming-endpoints.js +15 -0
- package/dist/src/resources/trained-model.d.ts +60 -0
- package/dist/src/resources/trained-model.js +98 -0
- package/dist/src/resources/webapps.d.ts +8 -0
- package/dist/src/resources/webapps.js +10 -0
- package/dist/src/resources/wiki.d.ts +5 -0
- package/dist/src/resources/wiki.js +7 -0
- package/dist/src/resources/workspaces.d.ts +2 -0
- package/dist/src/resources/workspaces.js +4 -0
- package/dist/src/utils/response-file.js +20 -9
- package/dist/src/utils/secret-sanitize.d.ts +7 -0
- package/dist/src/utils/secret-sanitize.js +46 -0
- package/package.json +25 -26
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +1 -1
- package/skills/dataiku-dss/references/authentication.md +3 -1
- package/skills/dataiku-dss/references/coding.md +1 -0
- package/skills/dataiku-dss/references/discovery.md +4 -6
- package/skills/dataiku-dss/references/troubleshooting.md +3 -2
package/dist/src/cli/usage.d.ts
CHANGED
|
@@ -12,6 +12,13 @@ export declare function unsupportedHelpFlag(): UsageError;
|
|
|
12
12
|
export declare function noCommandError(): UsageError;
|
|
13
13
|
export declare function missingActionError(resource: string, validActions: string[], usage?: string): UsageError;
|
|
14
14
|
export declare function unknownResourceError(resource: string): UsageError;
|
|
15
|
+
/**
|
|
16
|
+
* Agents rarely mistype; they reuse plausible flags from other commands or
|
|
17
|
+
* CLIs. When the command is known, the hint is its usage line, which lists
|
|
18
|
+
* every flag it takes, so one error carries the fix without a discovery round
|
|
19
|
+
* trip. `--json` gets its own hint: stdout is always JSON.
|
|
20
|
+
*/
|
|
21
|
+
export declare function unknownFlagError(flagLabel: string, resource?: string, action?: string): UsageError;
|
|
15
22
|
export declare function unknownActionError(resource: string, action: string | undefined, validActions: string[], hint?: string): UsageError;
|
|
16
23
|
export declare function requireArgs(args: string[], count: number, usage: string): void;
|
|
17
24
|
export declare function requireNoArgs(args: string[], usage: string): void;
|
package/dist/src/cli/usage.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { commandSyntaxTree, syntaxHasFlag, } from "./syntax.js";
|
|
1
|
+
import { commandSyntaxTree, renderNodes, syntaxHasFlag, } from "./syntax.js";
|
|
2
2
|
export const RESOURCE_NAMES = [
|
|
3
3
|
"agent",
|
|
4
4
|
"app",
|
|
@@ -35,8 +35,10 @@ export const RESOURCE_NAMES = [
|
|
|
35
35
|
"analysis",
|
|
36
36
|
"ml-task",
|
|
37
37
|
"saved-model",
|
|
38
|
+
"mlflow",
|
|
38
39
|
"model-evaluation-store",
|
|
39
40
|
"future",
|
|
41
|
+
"flow",
|
|
40
42
|
"flow-zone",
|
|
41
43
|
"dataset",
|
|
42
44
|
"recipe",
|
|
@@ -64,6 +66,7 @@ const PROJECT_SCOPED_RESOURCES = new Set([
|
|
|
64
66
|
"knowledge-bank",
|
|
65
67
|
"dataset",
|
|
66
68
|
"llm",
|
|
69
|
+
"flow",
|
|
67
70
|
"flow-zone",
|
|
68
71
|
"insight",
|
|
69
72
|
"folder",
|
|
@@ -72,6 +75,7 @@ const PROJECT_SCOPED_RESOURCES = new Set([
|
|
|
72
75
|
"notebook",
|
|
73
76
|
"macro",
|
|
74
77
|
"ml-task",
|
|
78
|
+
"mlflow",
|
|
75
79
|
"model-evaluation-store",
|
|
76
80
|
"recipe",
|
|
77
81
|
"scenario",
|
|
@@ -121,6 +125,21 @@ export function missingActionError(resource, validActions, usage) {
|
|
|
121
125
|
export function unknownResourceError(resource) {
|
|
122
126
|
return new UsageError(`Unknown resource: ${resource}.`, "usage_error", COMMANDS_RUN_HINT, { resource, validResources: RESOURCE_NAMES, });
|
|
123
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Agents rarely mistype; they reuse plausible flags from other commands or
|
|
130
|
+
* CLIs. When the command is known, the hint is its usage line, which lists
|
|
131
|
+
* every flag it takes, so one error carries the fix without a discovery round
|
|
132
|
+
* trip. `--json` gets its own hint: stdout is always JSON.
|
|
133
|
+
*/
|
|
134
|
+
export function unknownFlagError(flagLabel, resource, action) {
|
|
135
|
+
const command = resource && action ? commandSyntaxTree(resource, action) : undefined;
|
|
136
|
+
// The envelope already names resource and action; the message stays the flag.
|
|
137
|
+
const message = `Unknown flag: ${flagLabel}`;
|
|
138
|
+
if (flagLabel === "--json") {
|
|
139
|
+
return new UsageError(message, "unknown_flag", "Drop --json: stdout is always one JSON value.");
|
|
140
|
+
}
|
|
141
|
+
return new UsageError(message, "unknown_flag", command ? `Usage: ${renderNodes(command)}` : undefined);
|
|
142
|
+
}
|
|
124
143
|
export function unknownActionError(resource, action, validActions, hint) {
|
|
125
144
|
return new UsageError(`Unknown action: ${resource} ${action ?? ""}`.trim(), "usage_error", hint ?? COMMANDS_RUN_HINT, { resource, action, validActions, });
|
|
126
145
|
}
|
|
@@ -49,7 +49,7 @@ export declare function buildVersionPayload(input: {
|
|
|
49
49
|
export declare const PACKAGE_ROOT: string | undefined;
|
|
50
50
|
export declare const CLI_VERSION: string;
|
|
51
51
|
export declare const CLI_GIT_REVISION: string | undefined;
|
|
52
|
-
export declare const AGENT_CONTRACT_VERSION =
|
|
52
|
+
export declare const AGENT_CONTRACT_VERSION = 3;
|
|
53
53
|
export declare const JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema";
|
|
54
|
-
export declare const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-
|
|
54
|
+
export declare const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-v3.json";
|
|
55
55
|
export declare function cliVersionResult(): CliVersionPayload;
|
package/dist/src/cli/version.js
CHANGED
|
@@ -204,9 +204,9 @@ export function buildVersionPayload(input) {
|
|
|
204
204
|
export const PACKAGE_ROOT = findPackageRoot();
|
|
205
205
|
export const CLI_VERSION = packageVersion(PACKAGE_ROOT);
|
|
206
206
|
export const CLI_GIT_REVISION = gitRevision(PACKAGE_ROOT);
|
|
207
|
-
export const AGENT_CONTRACT_VERSION =
|
|
207
|
+
export const AGENT_CONTRACT_VERSION = 3;
|
|
208
208
|
export const JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema";
|
|
209
|
-
export const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-
|
|
209
|
+
export const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-v3.json";
|
|
210
210
|
export function cliVersionResult() {
|
|
211
211
|
// Only code actually loaded from dist/ may report dist provenance; an
|
|
212
212
|
// inherited DSS_LOAD_SOURCE on a source run is ignored.
|
package/dist/src/cli.js
CHANGED
|
@@ -2,18 +2,19 @@
|
|
|
2
2
|
import * as fs from "node:fs/promises";
|
|
3
3
|
import { homedir, } from "node:os";
|
|
4
4
|
import { resolve, } from "node:path";
|
|
5
|
-
import { num, unknownJsonInput, } from "./cli/coerce.js";
|
|
5
|
+
import { num, seenJsonInputCredentials, unknownJsonInput, } from "./cli/coerce.js";
|
|
6
6
|
import { commands, } from "./cli/commands/index.js";
|
|
7
7
|
import { ambientProjectKey, loadEnvFile, } from "./cli/env.js";
|
|
8
|
-
import { executionMode, FLAG_ALIASES, isNegativeNumberToken, parseArgs,
|
|
8
|
+
import { executionMode, FLAG_ALIASES, isNegativeNumberToken, parseArgs, rawPositionals, } from "./cli/flags.js";
|
|
9
9
|
import { cleanupLedgerEntry, } from "./cli/helpers/cleanup.js";
|
|
10
|
-
import {
|
|
10
|
+
import { shapeListResult, } from "./cli/list-output.js";
|
|
11
|
+
import { commandFailureExitCode, CommandResultFailure, enqueueCliWarning, flushCliWarnings, isFailedWaitResult, planResult, projectResultFields, setOutputFieldProjection, writeCommandResult, } from "./cli/output.js";
|
|
11
12
|
import { currentCommandContext, resolveCredentials, resolveLoginCredentials, } from "./cli/runtime.js";
|
|
12
|
-
import { commandUsage, } from "./cli/syntax.js";
|
|
13
|
-
import { COMMANDS_RUN_HINT, inferRequiresProject, missingActionError, noCommandError, requireArgs, RESOURCE_NAMES, unknownActionError, unknownResourceError, UsageError, } from "./cli/usage.js";
|
|
13
|
+
import { commandSyntaxTree, commandUsage, } from "./cli/syntax.js";
|
|
14
|
+
import { COMMANDS_RUN_HINT, inferRequiresProject, missingActionError, noCommandError, requireArgs, RESOURCE_NAMES, unknownActionError, unknownFlagError, unknownResourceError, UsageError, } from "./cli/usage.js";
|
|
14
15
|
import { cliVersionResult, } from "./cli/version.js";
|
|
15
16
|
import { getCredentialsPath, } from "./config.js";
|
|
16
|
-
import {
|
|
17
|
+
import { ClientValidationError, DataikuError, dataikuErrorCode, FORBIDDEN_HINT, NOT_FOUND_HINT, } from "./errors.js";
|
|
17
18
|
import { appendCleanupLedgerEntry, findCleanupLedgerBindingViolation, preflightCleanupLedgerPath, readCleanupLedger, reserveCleanupLedgerDssUrl, } from "./utils/cleanup-ledger.js";
|
|
18
19
|
import { canonicalDssUrl, } from "./utils/dss-url.js";
|
|
19
20
|
import { sanitizeSecrets, } from "./utils/secret-sanitize.js";
|
|
@@ -26,6 +27,12 @@ function loadCommandRuntime() {
|
|
|
26
27
|
contract = module;
|
|
27
28
|
});
|
|
28
29
|
}
|
|
30
|
+
// Plan builders (and the command helpers they share with live handlers) load
|
|
31
|
+
// only for --plan; flag validation needs just the registry.
|
|
32
|
+
let planBuildersLoad;
|
|
33
|
+
function loadPlanBuilders() {
|
|
34
|
+
return planBuildersLoad ??= import("./cli/plans.js");
|
|
35
|
+
}
|
|
29
36
|
// ---------------------------------------------------------------------------
|
|
30
37
|
// Arg parsing
|
|
31
38
|
// ---------------------------------------------------------------------------
|
|
@@ -290,9 +297,6 @@ function supportedCommandFlags(entry) {
|
|
|
290
297
|
}
|
|
291
298
|
return supported;
|
|
292
299
|
}
|
|
293
|
-
function scopedCommandDiscoveryHint(resource, action) {
|
|
294
|
-
return `Use \`dss commands run --fields ${resource}.${action}\` to list the flags this command supports.`;
|
|
295
|
-
}
|
|
296
300
|
/**
|
|
297
301
|
* Resolve the registry field selectors for `commands run --fields`. Omitting the flag
|
|
298
302
|
* selects the action summary; `--output` exports the full registry, but an explicitly supplied value carrying no selector is a
|
|
@@ -315,9 +319,8 @@ function validateSupportedCommandFlags(resource, action, flags) {
|
|
|
315
319
|
return;
|
|
316
320
|
const supported = supportedCommandFlags(entry);
|
|
317
321
|
for (const flagName of Object.keys(flags)) {
|
|
318
|
-
if (supported[flagName] !== true)
|
|
319
|
-
throw
|
|
320
|
-
}
|
|
322
|
+
if (supported[flagName] !== true)
|
|
323
|
+
throw unknownFlagError(`--${flagName}`, resource, action);
|
|
321
324
|
}
|
|
322
325
|
if (executionMode(flags).dryRun && !entry.dryRun) {
|
|
323
326
|
throw new UsageError(`--dry-run is not supported for ${resource} ${action}.`, "unknown_flag", entry.flags.some((flag) => flag.name === "plan")
|
|
@@ -339,14 +342,12 @@ function flagIsProvided(flags, name, allowEmpty = false) {
|
|
|
339
342
|
return allowEmpty || value.length > 0;
|
|
340
343
|
}
|
|
341
344
|
function validateRequiredCommandInputs(resource, action, args, flags, entry) {
|
|
342
|
-
const argCount = entry.positionalArguments.filter((positional) => positional.required).length;
|
|
343
345
|
const allowEmptyFlags = {};
|
|
344
346
|
for (const flag of entry.flags) {
|
|
345
347
|
if (flag.allowEmptyValue === true)
|
|
346
348
|
allowEmptyFlags[flag.name] = true;
|
|
347
349
|
}
|
|
348
|
-
|
|
349
|
-
requireArgs(args, argCount, entry.usage);
|
|
350
|
+
requireEntryPositionals(entry, args);
|
|
350
351
|
for (const flagName of entry.requiredFlags) {
|
|
351
352
|
if (!flagIsProvided(flags, flagName, allowEmptyFlags[flagName] === true)) {
|
|
352
353
|
throw new UsageError(`--${flagName} is required. Usage: ${entry.usage}`, "missing_required_flag");
|
|
@@ -367,6 +368,11 @@ function validateRegistryCommandInputs(resource, action, args, flags) {
|
|
|
367
368
|
validateSupportedCommandFlags(resource, action, flags);
|
|
368
369
|
validateRequiredCommandInputs(resource, action, args, flags, entry);
|
|
369
370
|
}
|
|
371
|
+
function requireEntryPositionals(entry, args) {
|
|
372
|
+
const argCount = entry.positionalArguments.filter((positional) => positional.required).length;
|
|
373
|
+
if (args.length < argCount)
|
|
374
|
+
requireArgs(args, argCount, entry.usage);
|
|
375
|
+
}
|
|
370
376
|
class BatchDryRunValidationComplete extends Error {
|
|
371
377
|
constructor() {
|
|
372
378
|
super("Batch dry-run validation reached client execution.");
|
|
@@ -738,7 +744,24 @@ async function runMetaCommand(resource, rawAction, flags) {
|
|
|
738
744
|
return { action, result: await commandsRunResult(flags), exitCode: 0, };
|
|
739
745
|
}
|
|
740
746
|
}
|
|
747
|
+
const COMMAND_SEARCH_LIMIT = 5;
|
|
741
748
|
async function commandsRunResult(flags) {
|
|
749
|
+
const query = flags["contains"];
|
|
750
|
+
if (typeof query === "string") {
|
|
751
|
+
if (flags["fields"] !== undefined || flags["output"] !== undefined) {
|
|
752
|
+
throw new UsageError("--contains cannot be combined with --fields or --output.", "usage_error", contract.COMMANDS_USAGE);
|
|
753
|
+
}
|
|
754
|
+
const matches = contract.searchCommands(query);
|
|
755
|
+
if (matches.length > COMMAND_SEARCH_LIMIT) {
|
|
756
|
+
enqueueCliWarning({
|
|
757
|
+
code: "results_truncated",
|
|
758
|
+
shown: COMMAND_SEARCH_LIMIT,
|
|
759
|
+
total: matches.length,
|
|
760
|
+
hint: "Add words to --contains to narrow the search.",
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
return matches.slice(0, COMMAND_SEARCH_LIMIT);
|
|
764
|
+
}
|
|
742
765
|
const selectors = commandRegistrySelectors(flags);
|
|
743
766
|
const outputPath = flags["output"];
|
|
744
767
|
if (selectors.length === 0 && typeof outputPath !== "string") {
|
|
@@ -990,7 +1013,7 @@ async function runBatch(flags) {
|
|
|
990
1013
|
throw unknownActionError(resource, action, Object.keys(resourceActions));
|
|
991
1014
|
validateSupportedCommandFlags(resource, action, stepFlags);
|
|
992
1015
|
if (executionMode(stepFlags).plan) {
|
|
993
|
-
result =
|
|
1016
|
+
result = (await loadPlanBuilders()).buildMutationPlan(resource, action, meta, positional.slice(2), stepFlags);
|
|
994
1017
|
}
|
|
995
1018
|
else {
|
|
996
1019
|
if (!client) {
|
|
@@ -1000,6 +1023,8 @@ async function runBatch(flags) {
|
|
|
1000
1023
|
await preflightCleanupLedgerForFlags(client, stepFlags);
|
|
1001
1024
|
const stepArgs = positional.slice(2);
|
|
1002
1025
|
result = await meta.handler(client, stepArgs, stepFlags);
|
|
1026
|
+
if (action === "list")
|
|
1027
|
+
result = shapeListResult(resource, result, stepFlags);
|
|
1003
1028
|
await recordCleanupLedgerEntry(client, resource, action, stepArgs, stepFlags, result, projectKey);
|
|
1004
1029
|
}
|
|
1005
1030
|
const failureExitCode = commandFailureExitCode(result);
|
|
@@ -1070,36 +1095,6 @@ function summarizeCleanupFailures(failures) {
|
|
|
1070
1095
|
: [];
|
|
1071
1096
|
}));
|
|
1072
1097
|
}
|
|
1073
|
-
/**
|
|
1074
|
-
* Positional arguments scanned with the same flag grammar as `parseArgs`, so
|
|
1075
|
-
* error reporting can recover the invoked resource/action without depending
|
|
1076
|
-
* on the command registry being loaded.
|
|
1077
|
-
*/
|
|
1078
|
-
function rawPositionals(argv) {
|
|
1079
|
-
const positionals = [];
|
|
1080
|
-
for (let index = 0; index < argv.length; index++) {
|
|
1081
|
-
const arg = argv[index];
|
|
1082
|
-
if (arg === "--") {
|
|
1083
|
-
positionals.push(...argv.slice(index + 1));
|
|
1084
|
-
break;
|
|
1085
|
-
}
|
|
1086
|
-
if (arg.startsWith("--")) {
|
|
1087
|
-
const name = arg.slice(2).split("=")[0] ?? "";
|
|
1088
|
-
const canonical = FLAG_ALIASES[name] ?? name;
|
|
1089
|
-
if (!arg.includes("=") && VALUE_FLAGS.has(canonical))
|
|
1090
|
-
index++;
|
|
1091
|
-
continue;
|
|
1092
|
-
}
|
|
1093
|
-
if (arg.length === 2 && arg[0] === "-" && arg[1] !== "-") {
|
|
1094
|
-
const long = SHORT_FLAGS[arg[1]];
|
|
1095
|
-
if (long && VALUE_FLAGS.has(long))
|
|
1096
|
-
index++;
|
|
1097
|
-
continue;
|
|
1098
|
-
}
|
|
1099
|
-
positionals.push(arg);
|
|
1100
|
-
}
|
|
1101
|
-
return positionals;
|
|
1102
|
-
}
|
|
1103
1098
|
function rawFlagValue(argv, flagName) {
|
|
1104
1099
|
const longFlag = `--${flagName}`;
|
|
1105
1100
|
for (let index = 0; index < argv.length; index++) {
|
|
@@ -1173,62 +1168,81 @@ function requestIdFromBody(body) {
|
|
|
1173
1168
|
const DSS_DIAGNOSTIC_MESSAGE_FIELDS = ["detailedMessage", "message", "errorMessage",];
|
|
1174
1169
|
const MAX_DSS_DIAGNOSTIC_LENGTH = 300;
|
|
1175
1170
|
/**
|
|
1176
|
-
* Credential material for redacting a server echo in
|
|
1177
|
-
* through the same resolver every command uses (flag → env →
|
|
1178
|
-
*
|
|
1171
|
+
* Credential material for redacting a server echo in an error report: the API
|
|
1172
|
+
* key, resolved through the same resolver every command uses (flag → env →
|
|
1173
|
+
* saved), and credential values from the command's JSON input, which DSS
|
|
1174
|
+
* error text can echo back.
|
|
1179
1175
|
*/
|
|
1180
1176
|
function cliSecretValues() {
|
|
1177
|
+
const inputCredentials = [...seenJsonInputCredentials(),];
|
|
1181
1178
|
try {
|
|
1182
1179
|
const { apiKey, } = resolveCredentials(parseArgs(process.argv.slice(2)).flags);
|
|
1183
|
-
return apiKey ? [apiKey,] :
|
|
1180
|
+
return apiKey ? [apiKey, ...inputCredentials,] : inputCredentials;
|
|
1184
1181
|
}
|
|
1185
1182
|
catch {
|
|
1186
|
-
return
|
|
1183
|
+
return inputCredentials;
|
|
1187
1184
|
}
|
|
1188
1185
|
}
|
|
1189
1186
|
/**
|
|
1190
|
-
*
|
|
1191
|
-
*
|
|
1192
|
-
*
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1187
|
+
* Envelope details a DSS failure carries beyond the top-level fields: safe
|
|
1188
|
+
* response metadata (target, elapsed time), a truncated-body marker, and the
|
|
1189
|
+
* retry record only when a retry or timeout actually happened.
|
|
1190
|
+
*/
|
|
1191
|
+
function dssErrorDetails(err) {
|
|
1192
|
+
const { requestId: _requestId, request_id: _requestIdAlt, errorId: _errorId, ...metadata } = safeResponseMetadata(err.body);
|
|
1193
|
+
return {
|
|
1194
|
+
...metadata,
|
|
1195
|
+
...(err.trustedTarget ? { target: err.trustedTarget, } : {}),
|
|
1196
|
+
...(err.trustedElapsedMs !== undefined ? { elapsedMs: err.trustedElapsedMs, } : {}),
|
|
1197
|
+
...(err.bodyTruncated ? { bodyTruncated: true, } : {}),
|
|
1198
|
+
...(err.retry && (err.retry.retries > 0 || err.retry.timedOut) ? { retry: err.retry, } : {}),
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Bounded, sanitized server diagnostic: the DSS error text (`dssMessage`) and
|
|
1203
|
+
* Java error type (`dssErrorType`) the response body carried. Whitespace
|
|
1204
|
+
* collapses to one line, credential material is redacted, long text
|
|
1205
|
+
* truncates, and the raw body/stack never pass through.
|
|
1196
1206
|
*/
|
|
1197
1207
|
function dssDiagnosticDetails(err) {
|
|
1208
|
+
let secrets;
|
|
1209
|
+
const diagnostic = (value) => {
|
|
1210
|
+
if (typeof value !== "string" || value.trim() === "")
|
|
1211
|
+
return undefined;
|
|
1212
|
+
secrets ??= cliSecretValues();
|
|
1213
|
+
const sanitized = sanitizeSecrets(value.replace(/\s+/g, " ").trim(), {
|
|
1214
|
+
sensitiveKeys: {},
|
|
1215
|
+
secrets,
|
|
1216
|
+
redactUrlUserinfo: true,
|
|
1217
|
+
});
|
|
1218
|
+
return sanitized.length > MAX_DSS_DIAGNOSTIC_LENGTH
|
|
1219
|
+
? `${sanitized.slice(0, MAX_DSS_DIAGNOSTIC_LENGTH)}…`
|
|
1220
|
+
: sanitized;
|
|
1221
|
+
};
|
|
1222
|
+
let parsed;
|
|
1198
1223
|
try {
|
|
1199
|
-
|
|
1200
|
-
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1201
|
-
return {};
|
|
1202
|
-
const record = parsed;
|
|
1203
|
-
let secrets;
|
|
1204
|
-
const diagnostic = (value) => {
|
|
1205
|
-
if (typeof value !== "string" || value.trim() === "")
|
|
1206
|
-
return undefined;
|
|
1207
|
-
secrets ??= cliSecretValues();
|
|
1208
|
-
const sanitized = sanitizeSecrets(value.replace(/\s+/g, " ").trim(), {
|
|
1209
|
-
sensitiveKeys: {},
|
|
1210
|
-
secrets,
|
|
1211
|
-
redactUrlUserinfo: true,
|
|
1212
|
-
});
|
|
1213
|
-
return sanitized.length > MAX_DSS_DIAGNOSTIC_LENGTH
|
|
1214
|
-
? `${sanitized.slice(0, MAX_DSS_DIAGNOSTIC_LENGTH)}…`
|
|
1215
|
-
: sanitized;
|
|
1216
|
-
};
|
|
1217
|
-
let message;
|
|
1218
|
-
for (const field of DSS_DIAGNOSTIC_MESSAGE_FIELDS) {
|
|
1219
|
-
message = diagnostic(record[field]);
|
|
1220
|
-
if (message !== undefined)
|
|
1221
|
-
break;
|
|
1222
|
-
}
|
|
1223
|
-
const errorType = diagnostic(record["errorType"]);
|
|
1224
|
-
return {
|
|
1225
|
-
...(message !== undefined ? { dssMessage: message, } : {}),
|
|
1226
|
-
...(errorType !== undefined ? { dssErrorType: errorType, } : {}),
|
|
1227
|
-
};
|
|
1224
|
+
parsed = JSON.parse(err.body);
|
|
1228
1225
|
}
|
|
1229
1226
|
catch {
|
|
1227
|
+
// Plain-text or HTML bodies, and the client's own transport detail for
|
|
1228
|
+
// status 0, surface through the bounded summary.
|
|
1229
|
+
const dssMessage = err.body.trim() === "" ? undefined : diagnostic(err.summary);
|
|
1230
|
+
return dssMessage === undefined ? {} : { dssMessage, };
|
|
1231
|
+
}
|
|
1232
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
1230
1233
|
return {};
|
|
1234
|
+
const record = parsed;
|
|
1235
|
+
let message;
|
|
1236
|
+
for (const field of DSS_DIAGNOSTIC_MESSAGE_FIELDS) {
|
|
1237
|
+
message = diagnostic(record[field]);
|
|
1238
|
+
if (message !== undefined)
|
|
1239
|
+
break;
|
|
1231
1240
|
}
|
|
1241
|
+
const errorType = diagnostic(record["errorType"]);
|
|
1242
|
+
return {
|
|
1243
|
+
...(message !== undefined ? { dssMessage: message, } : {}),
|
|
1244
|
+
...(errorType !== undefined ? { dssErrorType: errorType, } : {}),
|
|
1245
|
+
};
|
|
1232
1246
|
}
|
|
1233
1247
|
function isAmbiguousMutationFailure(err, context) {
|
|
1234
1248
|
if (!(err instanceof DataikuError))
|
|
@@ -1344,48 +1358,41 @@ function buildErrorReport(err, contextOverride) {
|
|
|
1344
1358
|
status: err.status,
|
|
1345
1359
|
retryable: false,
|
|
1346
1360
|
requestId: err.requestId ?? requestIdFromBody(err.body),
|
|
1361
|
+
// The retry record proves how many times the mutation was dispatched.
|
|
1347
1362
|
details: {
|
|
1348
|
-
dssCategory: err.category,
|
|
1349
|
-
...(err.bodyTruncated ? { bodyTruncated: true, } : {}),
|
|
1350
|
-
...dssDiagnosticDetails(err),
|
|
1351
|
-
statusText: canonicalStatusText(err.status),
|
|
1352
1363
|
idempotency: "none",
|
|
1364
|
+
...dssErrorDetails(err),
|
|
1365
|
+
...dssDiagnosticDetails(err),
|
|
1353
1366
|
...(err.retry ? { retry: err.retry, } : {}),
|
|
1354
1367
|
},
|
|
1355
1368
|
...context,
|
|
1356
1369
|
};
|
|
1357
1370
|
}
|
|
1358
1371
|
if (err instanceof DataikuError) {
|
|
1359
|
-
const
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
const
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1372
|
+
const { dssMessage, dssErrorType, } = dssDiagnosticDetails(err);
|
|
1373
|
+
const details = { ...dssErrorDetails(err), ...(dssErrorType ? { dssErrorType, } : {}), };
|
|
1374
|
+
// Generic hints name what the command targeted. DSS answers 403 (not
|
|
1375
|
+
// 404) for a project that does not exist: "Failed to read project
|
|
1376
|
+
// permissions". A 403 about something else keeps the generic hint.
|
|
1377
|
+
const inProject = context.projectKey ? ` in project ${context.projectKey}` : "";
|
|
1378
|
+
const projectLevel = dssMessage === undefined || /\bproject\b/i.test(dssMessage);
|
|
1379
|
+
const hint = err.retryHint === FORBIDDEN_HINT && context.projectKey && projectLevel
|
|
1380
|
+
? `Check that project ${context.projectKey} exists (\`dss project list\`) and that this API key may access it.`
|
|
1381
|
+
: err.retryHint === NOT_FOUND_HINT && context.resource
|
|
1382
|
+
? `Check the ${context.resource} identifier${inProject}${commandSyntaxTree(context.resource, "list") ? ` (\`dss ${context.resource} list\`)` : ""}.`
|
|
1383
|
+
: err.retryHint;
|
|
1371
1384
|
return {
|
|
1372
1385
|
type: "error",
|
|
1373
1386
|
ok: false,
|
|
1374
|
-
error:
|
|
1387
|
+
error: dssMessage ? `${err.safeMessage}: ${dssMessage}` : err.safeMessage,
|
|
1375
1388
|
code: dataikuErrorCode(err.category),
|
|
1376
1389
|
category: "dss",
|
|
1377
1390
|
exitCode,
|
|
1378
|
-
hint
|
|
1391
|
+
hint,
|
|
1379
1392
|
status: err.status,
|
|
1380
1393
|
retryable: err.retryable,
|
|
1381
1394
|
requestId: err.requestId ?? requestIdFromBody(err.body),
|
|
1382
|
-
details: {
|
|
1383
|
-
dssCategory: err.category,
|
|
1384
|
-
...(err.bodyTruncated ? { bodyTruncated: true, } : {}),
|
|
1385
|
-
statusText: canonicalStatusText(err.status),
|
|
1386
|
-
body: safeBody,
|
|
1387
|
-
...(err.retry ? { retry: err.retry, } : {}),
|
|
1388
|
-
},
|
|
1395
|
+
...(Object.keys(details).length > 0 ? { details, } : {}),
|
|
1389
1396
|
...context,
|
|
1390
1397
|
};
|
|
1391
1398
|
}
|
|
@@ -1463,11 +1470,17 @@ async function main() {
|
|
|
1463
1470
|
await loadCommandRuntime();
|
|
1464
1471
|
validateSupportedCommandFlags(resource, action, flags);
|
|
1465
1472
|
const args = positional.slice(2);
|
|
1473
|
+
// A missing required positional is a usage error with the usage line, never
|
|
1474
|
+
// a handler crash. Required flags stay with the handlers' own validation,
|
|
1475
|
+
// which names the specific alternatives.
|
|
1476
|
+
const registryEntry = cachedCommandRegistry(resource)?.[action];
|
|
1477
|
+
if (registryEntry)
|
|
1478
|
+
requireEntryPositionals(registryEntry, args);
|
|
1466
1479
|
// Command-local validation runs for live, --plan, and --dry-run alike, so a
|
|
1467
1480
|
// bad identifier is a usage error before any plan is built or request made.
|
|
1468
1481
|
actionMeta.validate?.(args, flags);
|
|
1469
1482
|
if (executionMode(flags).plan) {
|
|
1470
|
-
const plan =
|
|
1483
|
+
const plan = (await loadPlanBuilders()).buildMutationPlan(resource, action, actionMeta, args, flags);
|
|
1471
1484
|
writeCommandResult(plan);
|
|
1472
1485
|
return;
|
|
1473
1486
|
}
|
|
@@ -1502,7 +1515,8 @@ async function main() {
|
|
|
1502
1515
|
});
|
|
1503
1516
|
assertCleanupLedgerSupported(resource, action, flags);
|
|
1504
1517
|
await preflightCleanupLedgerForFlags(client, flags);
|
|
1505
|
-
const
|
|
1518
|
+
const handled = await actionMeta.handler(client, args, flags);
|
|
1519
|
+
const result = action === "list" ? shapeListResult(resource, handled, flags) : handled;
|
|
1506
1520
|
await recordCleanupLedgerEntry(client, resource, action, args, flags, result, projectKey);
|
|
1507
1521
|
const failureExitCode = commandFailureExitCode(result);
|
|
1508
1522
|
if (failureExitCode !== undefined)
|
package/dist/src/client.d.ts
CHANGED
|
@@ -1,47 +1,49 @@
|
|
|
1
1
|
import { type Static, type TSchema } from "@sinclair/typebox";
|
|
2
|
-
import { AnalysesResource } from "./resources/analyses.js";
|
|
3
|
-
import { ApiDeployerResource } from "./resources/api-deployer.js";
|
|
4
|
-
import { ApiServicesResource } from "./resources/api-services.js";
|
|
5
|
-
import { ApplicationsResource } from "./resources/applications.js";
|
|
6
|
-
import { BundlesResource, ProjectDeployerResource } from "./resources/bundles.js";
|
|
7
|
-
import { CodeEnvsResource } from "./resources/code-envs.js";
|
|
8
|
-
import { ConnectionsResource } from "./resources/connections.js";
|
|
9
|
-
import { ContinuousActivitiesResource } from "./resources/continuous-activities.js";
|
|
10
|
-
import { DashboardsResource } from "./resources/dashboards.js";
|
|
11
|
-
import { DataCollectionsResource } from "./resources/data-collections.js";
|
|
12
|
-
import { DataQualityResource } from "./resources/data-quality.js";
|
|
13
|
-
import { DatasetsResource } from "./resources/datasets.js";
|
|
14
|
-
import { DiscussionsResource } from "./resources/discussions.js";
|
|
15
|
-
import { FlowZonesResource } from "./resources/flow-zones.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
import {
|
|
38
|
-
import {
|
|
39
|
-
import {
|
|
40
|
-
import {
|
|
41
|
-
import {
|
|
42
|
-
import {
|
|
43
|
-
import {
|
|
44
|
-
import {
|
|
2
|
+
import type { AnalysesResource } from "./resources/analyses.js";
|
|
3
|
+
import type { ApiDeployerResource } from "./resources/api-deployer.js";
|
|
4
|
+
import type { ApiServicesResource } from "./resources/api-services.js";
|
|
5
|
+
import type { ApplicationsResource } from "./resources/applications.js";
|
|
6
|
+
import type { BundlesResource, ProjectDeployerResource } from "./resources/bundles.js";
|
|
7
|
+
import type { CodeEnvsResource } from "./resources/code-envs.js";
|
|
8
|
+
import type { ConnectionsResource } from "./resources/connections.js";
|
|
9
|
+
import type { ContinuousActivitiesResource } from "./resources/continuous-activities.js";
|
|
10
|
+
import type { DashboardsResource } from "./resources/dashboards.js";
|
|
11
|
+
import type { DataCollectionsResource } from "./resources/data-collections.js";
|
|
12
|
+
import type { DataQualityResource } from "./resources/data-quality.js";
|
|
13
|
+
import type { DatasetsResource } from "./resources/datasets.js";
|
|
14
|
+
import type { DiscussionsResource } from "./resources/discussions.js";
|
|
15
|
+
import type { FlowZonesResource } from "./resources/flow-zones.js";
|
|
16
|
+
import type { FlowResource } from "./resources/flow.js";
|
|
17
|
+
import type { FoldersResource } from "./resources/folders.js";
|
|
18
|
+
import type { FuturesResource } from "./resources/futures.js";
|
|
19
|
+
import type { GroupsResource } from "./resources/groups.js";
|
|
20
|
+
import type { InsightsResource } from "./resources/insights.js";
|
|
21
|
+
import type { JobsResource } from "./resources/jobs.js";
|
|
22
|
+
import type { KnowledgeBanksResource } from "./resources/knowledge-banks.js";
|
|
23
|
+
import type { LlmsResource } from "./resources/llms.js";
|
|
24
|
+
import type { MacrosResource } from "./resources/macros.js";
|
|
25
|
+
import type { MeaningsResource } from "./resources/meanings.js";
|
|
26
|
+
import type { MetricsResource } from "./resources/metrics.js";
|
|
27
|
+
import type { MlTasksResource } from "./resources/ml-tasks.js";
|
|
28
|
+
import type { MlflowExtensionResource } from "./resources/mlflow-extension.js";
|
|
29
|
+
import type { ModelEvaluationStoresResource } from "./resources/model-evaluation-stores.js";
|
|
30
|
+
import type { NotebooksResource } from "./resources/notebooks.js";
|
|
31
|
+
import type { PluginsResource } from "./resources/plugins.js";
|
|
32
|
+
import type { ProjectFoldersResource } from "./resources/project-folders.js";
|
|
33
|
+
import type { ProjectGitResource } from "./resources/project-git.js";
|
|
34
|
+
import type { ProjectLibraryResource } from "./resources/project-library.js";
|
|
35
|
+
import type { ProjectsResource } from "./resources/projects.js";
|
|
36
|
+
import type { RecipesResource } from "./resources/recipes.js";
|
|
37
|
+
import type { SavedModelsResource } from "./resources/saved-models.js";
|
|
38
|
+
import type { ScenariosResource } from "./resources/scenarios.js";
|
|
39
|
+
import type { SqlResource } from "./resources/sql.js";
|
|
40
|
+
import type { StatisticsResource } from "./resources/statistics.js";
|
|
41
|
+
import type { StreamingEndpointsResource } from "./resources/streaming-endpoints.js";
|
|
42
|
+
import type { UsersResource } from "./resources/users.js";
|
|
43
|
+
import type { VariablesResource } from "./resources/variables.js";
|
|
44
|
+
import type { WebappsResource } from "./resources/webapps.js";
|
|
45
|
+
import type { WikiResource } from "./resources/wiki.js";
|
|
46
|
+
import type { WorkspacesResource } from "./resources/workspaces.js";
|
|
45
47
|
/** One part of a {@link DataikuClient.uploadForm} multipart/form-data body. */
|
|
46
48
|
export interface UploadFormPart {
|
|
47
49
|
/** Form field name. */
|
|
@@ -82,6 +84,8 @@ export interface DataikuGetOptions {
|
|
|
82
84
|
* server once instead of failing before any transport attempt.
|
|
83
85
|
*/
|
|
84
86
|
noRetry?: boolean;
|
|
87
|
+
/** Extra request headers, e.g. `x-dku-mlflow-project-key` for the MLflow API. */
|
|
88
|
+
headers?: Record<string, string>;
|
|
85
89
|
}
|
|
86
90
|
export interface DataikuClientTraceEvent {
|
|
87
91
|
type: "trace";
|
|
@@ -162,6 +166,8 @@ export declare class DataikuClient {
|
|
|
162
166
|
private scenariosResource?;
|
|
163
167
|
private foldersResource?;
|
|
164
168
|
private flowZonesResource?;
|
|
169
|
+
private flowResource?;
|
|
170
|
+
private mlflowExtensionResource?;
|
|
165
171
|
private variablesResource?;
|
|
166
172
|
private connectionsResource?;
|
|
167
173
|
private codeEnvsResource?;
|
|
@@ -206,6 +212,8 @@ export declare class DataikuClient {
|
|
|
206
212
|
get scenarios(): ScenariosResource;
|
|
207
213
|
get folders(): FoldersResource;
|
|
208
214
|
get flowZones(): FlowZonesResource;
|
|
215
|
+
get flow(): FlowResource;
|
|
216
|
+
get mlflowExtension(): MlflowExtensionResource;
|
|
209
217
|
get variables(): VariablesResource;
|
|
210
218
|
get connections(): ConnectionsResource;
|
|
211
219
|
get codeEnvs(): CodeEnvsResource;
|
|
@@ -298,6 +306,7 @@ export declare class DataikuClient {
|
|
|
298
306
|
*/
|
|
299
307
|
post<T = unknown>(path: string, body?: unknown, options?: {
|
|
300
308
|
retryMaxAttempts?: number;
|
|
309
|
+
headers?: Record<string, string>;
|
|
301
310
|
}): Promise<T>;
|
|
302
311
|
/**
|
|
303
312
|
* POST returning the text body, under the same bounded buffering rules as
|