dataiku-sdk 3.4.0 → 3.6.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 +4 -4
- package/bin/dss.js +28 -2
- package/dist/build-metadata.json +1 -1
- package/dist/src/cli/coerce.d.ts +0 -1
- package/dist/src/cli/coerce.js +0 -5
- package/dist/src/cli/command-syntax.json +14524 -0
- package/dist/src/cli/commands/analysis.js +6 -9
- package/dist/src/cli/commands/api-deployer.js +15 -33
- package/dist/src/cli/commands/api-service.js +17 -27
- package/dist/src/cli/commands/app.js +25 -41
- package/dist/src/cli/commands/bundle.js +15 -24
- package/dist/src/cli/commands/business-app.js +10 -17
- package/dist/src/cli/commands/code-env.js +23 -36
- package/dist/src/cli/commands/code.js +4 -4
- package/dist/src/cli/commands/connection.js +12 -22
- package/dist/src/cli/commands/continuous-activity.js +6 -9
- package/dist/src/cli/commands/dashboard.js +8 -13
- package/dist/src/cli/commands/data-collection.js +9 -16
- package/dist/src/cli/commands/data-quality.js +14 -26
- package/dist/src/cli/commands/dataset.js +29 -54
- package/dist/src/cli/commands/discussion.js +7 -10
- package/dist/src/cli/commands/doctor.js +3 -3
- package/dist/src/cli/commands/flow-zone.js +8 -17
- package/dist/src/cli/commands/folder.js +12 -20
- package/dist/src/cli/commands/future.js +7 -10
- package/dist/src/cli/commands/group.js +7 -11
- package/dist/src/cli/commands/insight.js +7 -11
- package/dist/src/cli/commands/job.js +17 -26
- package/dist/src/cli/commands/knowledge-bank.js +5 -6
- package/dist/src/cli/commands/llm.js +5 -8
- package/dist/src/cli/commands/macro.js +9 -16
- package/dist/src/cli/commands/meaning.js +7 -11
- package/dist/src/cli/commands/metrics.js +7 -10
- package/dist/src/cli/commands/ml-task.js +12 -20
- package/dist/src/cli/commands/model-evaluation-store.js +7 -11
- package/dist/src/cli/commands/notebook.js +15 -27
- package/dist/src/cli/commands/plugin.js +35 -68
- package/dist/src/cli/commands/project-deployer.js +10 -22
- package/dist/src/cli/commands/project-folder.js +10 -17
- package/dist/src/cli/commands/project-git.js +38 -70
- package/dist/src/cli/commands/project-library.js +15 -23
- package/dist/src/cli/commands/project.js +9 -26
- package/dist/src/cli/commands/recipe.d.ts +16 -0
- package/dist/src/cli/commands/recipe.js +83 -94
- package/dist/src/cli/commands/saved-model.js +23 -39
- package/dist/src/cli/commands/scenario.js +20 -34
- package/dist/src/cli/commands/sql.js +4 -4
- package/dist/src/cli/commands/statistics.js +11 -18
- package/dist/src/cli/commands/streaming-endpoint.js +7 -11
- package/dist/src/cli/commands/user.js +11 -22
- package/dist/src/cli/commands/variable.js +3 -4
- package/dist/src/cli/commands/webapp.js +10 -16
- package/dist/src/cli/commands/wiki.js +9 -13
- package/dist/src/cli/commands/workspace.js +8 -14
- package/dist/src/cli/contract.d.ts +5 -15
- package/dist/src/cli/contract.js +157 -254
- package/dist/src/cli/doctor.js +1 -0
- package/dist/src/cli/env.d.ts +2 -0
- package/dist/src/cli/env.js +16 -1
- package/dist/src/cli/flags.d.ts +1 -0
- package/dist/src/cli/flags.js +4 -9
- package/dist/src/cli/helpers/app-permissions.js +7 -5
- package/dist/src/cli/helpers/flow-zone.js +8 -6
- package/dist/src/cli/helpers/recipe.js +2 -1
- package/dist/src/cli/syntax.d.ts +83 -0
- package/dist/src/cli/syntax.js +217 -0
- package/dist/src/cli/types.d.ts +3 -0
- package/dist/src/cli/usage.d.ts +1 -1
- package/dist/src/cli/usage.js +4 -2
- package/dist/src/cli/version.d.ts +0 -2
- package/dist/src/cli/version.js +6 -7
- package/dist/src/cli.js +132 -274
- package/dist/src/client.d.ts +2 -1
- package/dist/src/client.js +32 -17
- package/dist/src/errors.d.ts +12 -1
- package/dist/src/errors.js +28 -3
- package/dist/src/index.d.ts +1 -3
- package/dist/src/index.js +2 -2
- package/dist/src/resources/api-services.js +2 -3
- package/dist/src/resources/applications.js +2 -4
- package/dist/src/resources/base.d.ts +2 -0
- package/dist/src/resources/base.js +14 -2
- package/dist/src/resources/code-envs.js +3 -5
- package/dist/src/resources/data-quality.js +14 -13
- package/dist/src/resources/datasets.d.ts +13 -0
- package/dist/src/resources/datasets.js +5 -4
- package/dist/src/resources/flow-zones.js +4 -2
- package/dist/src/resources/folders.js +4 -2
- package/dist/src/resources/futures.js +1 -3
- package/dist/src/resources/insights.js +3 -2
- package/dist/src/resources/jobs.js +4 -6
- package/dist/src/resources/macros.d.ts +1 -1
- package/dist/src/resources/macros.js +3 -7
- package/dist/src/resources/notebooks.js +2 -3
- package/dist/src/resources/project-git.js +9 -11
- package/dist/src/resources/project-library.d.ts +0 -2
- package/dist/src/resources/project-library.js +2 -7
- package/dist/src/resources/projects.js +4 -3
- package/dist/src/resources/recipes.d.ts +28 -0
- package/dist/src/resources/recipes.js +117 -89
- package/dist/src/resources/saved-models.js +1 -13
- package/dist/src/resources/scenarios.js +1 -3
- package/dist/src/resources/sql.js +9 -8
- package/dist/src/resources/statistics.js +3 -4
- package/dist/src/resources/variables.js +2 -1
- package/dist/src/resources/webapps.js +2 -3
- package/dist/src/schemas.d.ts +1 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.js +6 -7
- package/dist/src/utils/cleanup-ledger.js +9 -8
- package/dist/src/utils/deep-merge.js +2 -4
- package/dist/src/utils/flow-map.js +1 -6
- package/dist/src/utils/polling.d.ts +3 -0
- package/dist/src/utils/polling.js +3 -0
- package/dist/src/utils/project-archive.js +10 -14
- package/dist/src/utils/project-incarnation.js +3 -7
- package/dist/src/utils/records.d.ts +4 -0
- package/dist/src/utils/records.js +8 -0
- package/dist/src/utils/stable-hash.d.ts +3 -1
- package/dist/src/utils/stable-hash.js +2 -0
- package/package.json +10 -14
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +3 -4
- package/skills/dataiku-dss/references/authentication.md +3 -3
- package/skills/dataiku-dss/references/coding.md +1 -1
- package/skills/dataiku-dss/references/discovery.md +1 -1
- package/skills/dataiku-dss/references/mutations.md +0 -1
- package/dist/src/utils/pagination.d.ts +0 -8
- package/dist/src/utils/pagination.js +0 -23
- package/packages/types/dist/index.d.ts +0 -1062
- package/packages/types/dist/index.js +0 -871
package/dist/src/cli.js
CHANGED
|
@@ -4,11 +4,12 @@ import { homedir, } from "node:os";
|
|
|
4
4
|
import { resolve, } from "node:path";
|
|
5
5
|
import { num, unknownJsonInput, } from "./cli/coerce.js";
|
|
6
6
|
import { commands, } from "./cli/commands/index.js";
|
|
7
|
-
import {
|
|
7
|
+
import { ambientProjectKey, loadEnvFile, } from "./cli/env.js";
|
|
8
8
|
import { executionMode, FLAG_ALIASES, isNegativeNumberToken, parseArgs, SHORT_FLAGS, VALUE_FLAGS, } from "./cli/flags.js";
|
|
9
9
|
import { cleanupLedgerEntry, } from "./cli/helpers/cleanup.js";
|
|
10
10
|
import { commandFailureExitCode, CommandResultFailure, flushCliWarnings, isFailedWaitResult, planResult, projectResultFields, setOutputFieldProjection, writeCommandResult, } from "./cli/output.js";
|
|
11
11
|
import { currentCommandContext, resolveCredentials, resolveLoginCredentials, } from "./cli/runtime.js";
|
|
12
|
+
import { commandUsage, } from "./cli/syntax.js";
|
|
12
13
|
import { COMMANDS_RUN_HINT, inferRequiresProject, missingActionError, noCommandError, requireArgs, RESOURCE_NAMES, unknownActionError, unknownResourceError, UsageError, } from "./cli/usage.js";
|
|
13
14
|
import { cliVersionResult, } from "./cli/version.js";
|
|
14
15
|
import { getCredentialsPath, } from "./config.js";
|
|
@@ -171,17 +172,6 @@ async function runCleanup(flags) {
|
|
|
171
172
|
|| !commands[resource]?.[action]) {
|
|
172
173
|
throw new UsageError(`Invalid cleanup argv: ${entry.cleanup.argv.join(" ")}`);
|
|
173
174
|
}
|
|
174
|
-
if (resource === "project"
|
|
175
|
-
&& action === "delete"
|
|
176
|
-
&& typeof parsed.flags["expect-project-incarnation"] !== "string") {
|
|
177
|
-
throw new UsageError("Project cleanup entry is not bound to a project incarnation. Refusing deletion after possible project-key reuse.", "validation_failed", "Capture a new cleanup entry from the current CLI. Legacy entries cannot safely delete projects.");
|
|
178
|
-
}
|
|
179
|
-
if (resource === "app"
|
|
180
|
-
&& action === "delete-instance"
|
|
181
|
-
&& parsed.flags["unconfirmed-creation"] !== true
|
|
182
|
-
&& typeof parsed.flags["expect-project-incarnation"] !== "string") {
|
|
183
|
-
throw new UsageError("App cleanup entry is not bound to a project incarnation. Refusing deletion after possible project-key reuse.", "validation_failed", "Capture a new cleanup entry from the current CLI. Legacy entries cannot safely delete app projects.");
|
|
184
|
-
}
|
|
185
175
|
const result = await commands[resource][action].handler(client, args, parsed.flags);
|
|
186
176
|
if (isFailedWaitResult(result)) {
|
|
187
177
|
const failure = {
|
|
@@ -334,32 +324,11 @@ function validateSupportedCommandFlags(resource, action, flags) {
|
|
|
334
324
|
? "Remove --dry-run; use --plan to preview the mutation instead."
|
|
335
325
|
: `Remove --dry-run; ${resource} ${action} has no dry-run mode.`);
|
|
336
326
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
for (const char of usage) {
|
|
342
|
-
if (char === "[") {
|
|
343
|
-
optionalDepth++;
|
|
344
|
-
if (optionalDepth === 1)
|
|
345
|
-
stripped += " ";
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
if (char === "]" && optionalDepth > 0) {
|
|
349
|
-
optionalDepth--;
|
|
350
|
-
if (optionalDepth === 0)
|
|
351
|
-
stripped += " ";
|
|
352
|
-
continue;
|
|
353
|
-
}
|
|
354
|
-
if (optionalDepth === 0)
|
|
355
|
-
stripped += char;
|
|
327
|
+
// Registry commands reject --plan in buildMutationPlan; meta commands never reach it.
|
|
328
|
+
if (META_COMMAND_RESOURCES[resource] === true && executionMode(flags).plan
|
|
329
|
+
&& !entry.flags.some((flag) => flag.name === "plan")) {
|
|
330
|
+
throw new UsageError(`--plan is only supported for mutating commands; ${resource} ${action} has no plan mode.`, "usage_error", `Remove --plan; ${resource} ${action} has no plan mode.`);
|
|
356
331
|
}
|
|
357
|
-
return stripped;
|
|
358
|
-
}
|
|
359
|
-
function requiredPositionalCount(usage) {
|
|
360
|
-
const requiredUsage = stripOptionalUsageGroupsForValidation(usage);
|
|
361
|
-
const positionalTokens = [...requiredUsage.matchAll(/<[^>]+>/g),];
|
|
362
|
-
return positionalTokens.length;
|
|
363
332
|
}
|
|
364
333
|
function flagIsProvided(flags, name, allowEmpty = false) {
|
|
365
334
|
const value = flags[name];
|
|
@@ -370,7 +339,7 @@ function flagIsProvided(flags, name, allowEmpty = false) {
|
|
|
370
339
|
return allowEmpty || value.length > 0;
|
|
371
340
|
}
|
|
372
341
|
function validateRequiredCommandInputs(resource, action, args, flags, entry) {
|
|
373
|
-
const argCount =
|
|
342
|
+
const argCount = entry.positionalArguments.filter((positional) => positional.required).length;
|
|
374
343
|
const allowEmptyFlags = {};
|
|
375
344
|
for (const flag of entry.flags) {
|
|
376
345
|
if (flag.allowEmptyValue === true)
|
|
@@ -439,81 +408,60 @@ async function validateDryRunHandlerPreconditions(handler, args, flags) {
|
|
|
439
408
|
throw error;
|
|
440
409
|
}
|
|
441
410
|
}
|
|
411
|
+
/**
|
|
412
|
+
* The one validator for meta commands, shared by direct runs and batch
|
|
413
|
+
* --dry-run: action, supported flags (incl. --plan/--dry-run), flag conflicts,
|
|
414
|
+
* and required inputs. Returns the canonical action, or undefined for a
|
|
415
|
+
* non-meta resource.
|
|
416
|
+
*/
|
|
442
417
|
async function validateMetaCommandInputs(resource, action, flags) {
|
|
443
|
-
if (resource
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
return "run";
|
|
448
|
-
}
|
|
418
|
+
if (META_COMMAND_RESOURCES[resource] !== true)
|
|
419
|
+
return undefined;
|
|
420
|
+
await loadCommandRuntime();
|
|
421
|
+
let resolved;
|
|
449
422
|
if (resource === "auth") {
|
|
450
423
|
const validActions = Object.keys(contract.AUTH_ACTIONS);
|
|
451
|
-
if (!action)
|
|
452
|
-
throw missingActionError("auth", validActions, "
|
|
453
|
-
}
|
|
424
|
+
if (!action)
|
|
425
|
+
throw missingActionError("auth", validActions, commandUsage("auth", "login"));
|
|
454
426
|
if (!contract.AUTH_ACTIONS[action]) {
|
|
455
427
|
throw unknownActionError("auth", action, validActions, "auth only supports 'login'. To check credentials/connectivity, run 'dss doctor'.");
|
|
456
428
|
}
|
|
457
|
-
|
|
429
|
+
resolved = action;
|
|
458
430
|
}
|
|
459
|
-
if (resource === "
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
}
|
|
463
|
-
const { AGENTS, } = await import("./skill.js");
|
|
464
|
-
const agentFilter = typeof flags["agent"] === "string" ? flags["agent"] : undefined;
|
|
465
|
-
if (agentFilter && !AGENTS[agentFilter]) {
|
|
466
|
-
throw new UsageError(`Unknown agent: ${agentFilter}.`, "usage_error", COMMANDS_RUN_HINT, { agent: agentFilter, validAgents: Object.keys(AGENTS), });
|
|
467
|
-
}
|
|
468
|
-
return "run";
|
|
469
|
-
}
|
|
470
|
-
if (resource === "agent") {
|
|
431
|
+
else if (resource === "agent" || resource === "commands") {
|
|
432
|
+
const only = resource === "agent" ? "contract" : "run";
|
|
433
|
+
const usage = resource === "agent" ? contract.AGENT_CONTRACT_USAGE : contract.COMMANDS_USAGE;
|
|
471
434
|
if (!action)
|
|
472
|
-
throw missingActionError(
|
|
473
|
-
if (action !==
|
|
474
|
-
throw unknownActionError(
|
|
475
|
-
|
|
435
|
+
throw missingActionError(resource, [only,], usage);
|
|
436
|
+
if (action !== only)
|
|
437
|
+
throw unknownActionError(resource, action, [only,]);
|
|
438
|
+
resolved = action;
|
|
476
439
|
}
|
|
477
|
-
|
|
478
|
-
if (!action)
|
|
479
|
-
throw missingActionError("commands", ["run",], contract.COMMANDS_USAGE);
|
|
480
|
-
if (action !== "run")
|
|
481
|
-
throw unknownActionError("commands", action, ["run",]);
|
|
482
|
-
validateSupportedCommandFlags("commands", "run", flags);
|
|
483
|
-
commandRegistrySelectors(flags);
|
|
484
|
-
return action;
|
|
485
|
-
}
|
|
486
|
-
if (resource === "version") {
|
|
440
|
+
else {
|
|
487
441
|
if (action !== undefined && action !== "run") {
|
|
488
|
-
throw unknownActionError(
|
|
442
|
+
throw unknownActionError(resource, action, ["run",]);
|
|
489
443
|
}
|
|
490
|
-
|
|
444
|
+
resolved = "run";
|
|
491
445
|
}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
const entry = cachedCommandRegistry(
|
|
446
|
+
validateSupportedCommandFlags(resource, resolved, flags);
|
|
447
|
+
if (resource === "commands")
|
|
448
|
+
commandRegistrySelectors(flags);
|
|
449
|
+
if (resource === "cleanup" || resource === "batch") {
|
|
450
|
+
const entry = cachedCommandRegistry(resource)?.run;
|
|
497
451
|
if (entry)
|
|
498
|
-
validateRequiredCommandInputs(
|
|
499
|
-
return "run";
|
|
452
|
+
validateRequiredCommandInputs(resource, "run", [], flags, entry);
|
|
500
453
|
}
|
|
501
|
-
if (resource === "
|
|
502
|
-
|
|
503
|
-
throw unknownActionError("fixtures", action, ["run",]);
|
|
504
|
-
}
|
|
505
|
-
return "run";
|
|
454
|
+
if (resource === "cleanup" && flags["apply"] === true && executionMode(flags).dryRun) {
|
|
455
|
+
throw new UsageError("--dry-run and --apply are mutually exclusive.", "usage_error");
|
|
506
456
|
}
|
|
507
|
-
if (resource === "
|
|
508
|
-
|
|
509
|
-
|
|
457
|
+
if (resource === "install-skill") {
|
|
458
|
+
const { AGENTS, } = await import("./skill.js");
|
|
459
|
+
const agentFilter = typeof flags["agent"] === "string" ? flags["agent"] : undefined;
|
|
460
|
+
if (agentFilter && !AGENTS[agentFilter]) {
|
|
461
|
+
throw new UsageError(`Unknown agent: ${agentFilter}.`, "usage_error", COMMANDS_RUN_HINT, { agent: agentFilter, validAgents: Object.keys(AGENTS), });
|
|
510
462
|
}
|
|
511
|
-
const entry = cachedCommandRegistry("batch")?.run;
|
|
512
|
-
if (entry)
|
|
513
|
-
validateRequiredCommandInputs("batch", "run", [], flags, entry);
|
|
514
|
-
return "run";
|
|
515
463
|
}
|
|
516
|
-
return
|
|
464
|
+
return resolved;
|
|
517
465
|
}
|
|
518
466
|
async function validateBatchStep(argv) {
|
|
519
467
|
const { positional, flags, } = parseArgs(argv);
|
|
@@ -553,29 +501,8 @@ function batchStepNeedsClient(argv) {
|
|
|
553
501
|
}
|
|
554
502
|
}
|
|
555
503
|
function batchStepCommandContext(argv) {
|
|
556
|
-
const
|
|
557
|
-
|
|
558
|
-
const arg = argv[index];
|
|
559
|
-
if (arg === "--") {
|
|
560
|
-
positionals.push(...argv.slice(index + 1));
|
|
561
|
-
break;
|
|
562
|
-
}
|
|
563
|
-
if (arg.startsWith("--")) {
|
|
564
|
-
const name = arg.slice(2).split("=")[0] ?? "";
|
|
565
|
-
const canonical = FLAG_ALIASES[name] ?? name;
|
|
566
|
-
if (!arg.includes("=") && VALUE_FLAGS.has(canonical))
|
|
567
|
-
index++;
|
|
568
|
-
continue;
|
|
569
|
-
}
|
|
570
|
-
if (arg.length === 2 && arg[0] === "-" && arg[1] !== "-") {
|
|
571
|
-
const long = SHORT_FLAGS[arg[1]];
|
|
572
|
-
if (long && VALUE_FLAGS.has(long))
|
|
573
|
-
index++;
|
|
574
|
-
continue;
|
|
575
|
-
}
|
|
576
|
-
positionals.push(arg);
|
|
577
|
-
}
|
|
578
|
-
return { resource: positionals[0], action: positionals[1], };
|
|
504
|
+
const [resource, action,] = rawPositionals(argv);
|
|
505
|
+
return { resource, action, };
|
|
579
506
|
}
|
|
580
507
|
const SENSITIVE_ARGV_VALUE_FLAGS = {
|
|
581
508
|
"api-key": true,
|
|
@@ -769,133 +696,78 @@ function batchPlan(flags) {
|
|
|
769
696
|
plannedAndDryRun: executionMode(flags).dryRun,
|
|
770
697
|
});
|
|
771
698
|
}
|
|
772
|
-
async function runMetaCommand(resource,
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
if (resource === "auth") {
|
|
784
|
-
await loadCommandRuntime();
|
|
785
|
-
const validActions = Object.keys(contract.AUTH_ACTIONS);
|
|
786
|
-
if (!action) {
|
|
787
|
-
throw missingActionError("auth", validActions, "dss auth login --url URL --api-key KEY");
|
|
788
|
-
}
|
|
789
|
-
currentCommandContext.action = action;
|
|
790
|
-
const authMeta = contract.AUTH_ACTIONS[action];
|
|
791
|
-
if (!authMeta) {
|
|
792
|
-
throw unknownActionError("auth", action, validActions, "auth only supports 'login'. To check credentials/connectivity, run 'dss doctor'.");
|
|
793
|
-
}
|
|
794
|
-
if (executionMode(flags).plan) {
|
|
795
|
-
return { action, result: authLoginPlan(flags), exitCode: 0, };
|
|
796
|
-
}
|
|
797
|
-
return { action, result: await authMeta.handler(flags), exitCode: 0, };
|
|
798
|
-
}
|
|
799
|
-
if (resource === "install-skill") {
|
|
800
|
-
await loadCommandRuntime();
|
|
801
|
-
if (action !== undefined && action !== "run") {
|
|
802
|
-
throw unknownActionError("install-skill", action, ["run",]);
|
|
803
|
-
}
|
|
804
|
-
currentCommandContext.action = action ?? "run";
|
|
805
|
-
return { action: "run", result: await runInstallSkill(flags), exitCode: 0, };
|
|
806
|
-
}
|
|
807
|
-
if (resource === "agent") {
|
|
808
|
-
await loadCommandRuntime();
|
|
809
|
-
if (!action)
|
|
810
|
-
throw missingActionError("agent", ["contract",], contract.AGENT_CONTRACT_USAGE);
|
|
811
|
-
currentCommandContext.action = action;
|
|
812
|
-
if (action !== "contract")
|
|
813
|
-
throw unknownActionError("agent", action, ["contract",]);
|
|
814
|
-
return { action, result: contract.buildAgentContract(), exitCode: 0, };
|
|
815
|
-
}
|
|
816
|
-
if (resource === "commands") {
|
|
817
|
-
await loadCommandRuntime();
|
|
818
|
-
if (!action)
|
|
819
|
-
throw missingActionError("commands", ["run",], contract.COMMANDS_USAGE);
|
|
820
|
-
currentCommandContext.action = action;
|
|
821
|
-
if (action !== "run")
|
|
822
|
-
throw unknownActionError("commands", action, ["run",]);
|
|
823
|
-
validateSupportedCommandFlags("commands", "run", flags);
|
|
824
|
-
const selectors = commandRegistrySelectors(flags);
|
|
825
|
-
const outputPath = flags["output"];
|
|
826
|
-
if (selectors.length === 0 && typeof outputPath !== "string") {
|
|
827
|
-
return { action, result: contract.commandActionSummary(), exitCode: 0, };
|
|
699
|
+
async function runMetaCommand(resource, rawAction, flags) {
|
|
700
|
+
const action = await validateMetaCommandInputs(resource, rawAction, flags);
|
|
701
|
+
if (action === undefined)
|
|
702
|
+
return undefined;
|
|
703
|
+
currentCommandContext.action = action;
|
|
704
|
+
const plan = executionMode(flags).plan;
|
|
705
|
+
switch (resource) {
|
|
706
|
+
case "doctor": {
|
|
707
|
+
const { runDoctor, } = await import("./cli/doctor.js");
|
|
708
|
+
const { result, exitCode, } = await runDoctor(flags);
|
|
709
|
+
return { action, result, exitCode, };
|
|
828
710
|
}
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
}
|
|
711
|
+
case "auth":
|
|
712
|
+
if (plan)
|
|
713
|
+
return { action, result: authLoginPlan(flags), exitCode: 0, };
|
|
714
|
+
return { action, result: await contract.AUTH_ACTIONS[action].handler(flags), exitCode: 0, };
|
|
715
|
+
case "install-skill":
|
|
716
|
+
return { action, result: await runInstallSkill(flags), exitCode: 0, };
|
|
717
|
+
case "agent":
|
|
718
|
+
return { action, result: contract.buildAgentContract(), exitCode: 0, };
|
|
719
|
+
case "version":
|
|
720
|
+
return { action, result: cliVersionResult(), exitCode: 0, };
|
|
721
|
+
case "fixtures": {
|
|
722
|
+
const { runFixtures, } = await import("./cli/doctor.js");
|
|
723
|
+
return { action, result: await runFixtures(flags), exitCode: 0, };
|
|
843
724
|
}
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
await fs.writeFile(outputPath, `${JSON.stringify(exported)}\n`, "utf-8");
|
|
850
|
-
return { action, result: { path: outputPath, }, exitCode: 0, };
|
|
725
|
+
case "cleanup": {
|
|
726
|
+
if (plan)
|
|
727
|
+
return { action, result: cleanupPlan(flags), exitCode: 0, };
|
|
728
|
+
const { result, exitCode, } = await runCleanup(flags);
|
|
729
|
+
return { action, result, exitCode, };
|
|
851
730
|
}
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
exitCode
|
|
856
|
-
|
|
857
|
-
}
|
|
858
|
-
if (resource === "version") {
|
|
859
|
-
if (action !== undefined && action !== "run") {
|
|
860
|
-
throw unknownActionError("version", action, ["run",]);
|
|
731
|
+
case "batch": {
|
|
732
|
+
if (plan)
|
|
733
|
+
return { action, result: batchPlan(flags), exitCode: 0, };
|
|
734
|
+
const { result, exitCode, } = await runBatch(flags);
|
|
735
|
+
return { action, result, exitCode, };
|
|
861
736
|
}
|
|
862
|
-
|
|
863
|
-
|
|
737
|
+
default:
|
|
738
|
+
return { action, result: await commandsRunResult(flags), exitCode: 0, };
|
|
864
739
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
740
|
+
}
|
|
741
|
+
async function commandsRunResult(flags) {
|
|
742
|
+
const selectors = commandRegistrySelectors(flags);
|
|
743
|
+
const outputPath = flags["output"];
|
|
744
|
+
if (selectors.length === 0 && typeof outputPath !== "string") {
|
|
745
|
+
return contract.commandActionSummary();
|
|
746
|
+
}
|
|
747
|
+
const registry = selectors.length === 0 ? contract.buildCommandRegistry() : {};
|
|
748
|
+
for (const selector of selectors) {
|
|
749
|
+
const selectorParts = selector.split(".");
|
|
750
|
+
if (selectorParts.some((part) => part.length === 0)) {
|
|
751
|
+
throw new UsageError(`Invalid --fields selector: ${selector}. Expected RESOURCE or RESOURCE.ACTION[.FIELD...].`, "usage_error", contract.COMMANDS_USAGE, { selector, });
|
|
873
752
|
}
|
|
874
|
-
const
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
if (
|
|
880
|
-
throw unknownActionError(
|
|
753
|
+
const [selectedResource, selectedAction,] = selectorParts;
|
|
754
|
+
const resourceActions = cachedCommandRegistry(selectedResource);
|
|
755
|
+
if (!resourceActions)
|
|
756
|
+
throw unknownResourceError(selectedResource);
|
|
757
|
+
registry[selectedResource] = resourceActions;
|
|
758
|
+
if (selectedAction && !resourceActions[selectedAction]) {
|
|
759
|
+
throw unknownActionError(selectedResource, selectedAction, Object.keys(resourceActions));
|
|
881
760
|
}
|
|
882
|
-
currentCommandContext.action = action ?? "run";
|
|
883
|
-
const { runFixtures, } = await import("./cli/doctor.js");
|
|
884
|
-
return { action: "run", result: await runFixtures(flags), exitCode: 0, };
|
|
885
761
|
}
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
return { action: "run", result: batchPlan(flags), exitCode: 0, };
|
|
894
|
-
}
|
|
895
|
-
const { result, exitCode, } = await runBatch(flags);
|
|
896
|
-
return { action: "run", result, exitCode, };
|
|
762
|
+
const selectedRegistry = selectors.length === 0
|
|
763
|
+
? registry
|
|
764
|
+
: projectResultFields(registry, selectors, () => Object.keys(contract.commandActionSummary()).sort());
|
|
765
|
+
if (typeof outputPath === "string") {
|
|
766
|
+
const exported = selectedRegistry;
|
|
767
|
+
await fs.writeFile(outputPath, `${JSON.stringify(exported)}\n`, "utf-8");
|
|
768
|
+
return { path: outputPath, };
|
|
897
769
|
}
|
|
898
|
-
return
|
|
770
|
+
return selectedRegistry;
|
|
899
771
|
}
|
|
900
772
|
/**
|
|
901
773
|
* Cleanup-ledger support is checked before a handler runs so an unsupported
|
|
@@ -993,9 +865,7 @@ async function runBatch(flags) {
|
|
|
993
865
|
if (executionMode(flags).dryRun) {
|
|
994
866
|
const batchProjectKey = typeof flags["project-key"] === "string"
|
|
995
867
|
? flags["project-key"]
|
|
996
|
-
:
|
|
997
|
-
? process.env.DATAIKU_PROJECT_KEY
|
|
998
|
-
: undefined;
|
|
868
|
+
: ambientProjectKey();
|
|
999
869
|
const planned = await Promise.all(steps.map(async (argv, index) => {
|
|
1000
870
|
const context = batchStepCommandContext(argv);
|
|
1001
871
|
Object.assign(currentCommandContext, { ...context, projectKey: batchProjectKey, });
|
|
@@ -1018,7 +888,8 @@ async function runBatch(flags) {
|
|
|
1018
888
|
};
|
|
1019
889
|
}
|
|
1020
890
|
catch (error) {
|
|
1021
|
-
|
|
891
|
+
// Steps validate concurrently; the shared context may belong to a sibling.
|
|
892
|
+
const envelope = buildErrorReport(error, { ...context, projectKey: batchProjectKey, });
|
|
1022
893
|
return {
|
|
1023
894
|
index,
|
|
1024
895
|
args: redactArgv(argv),
|
|
@@ -1037,9 +908,7 @@ async function runBatch(flags) {
|
|
|
1037
908
|
validateBatchStepModes(steps);
|
|
1038
909
|
let projectKey = typeof flags["project-key"] === "string"
|
|
1039
910
|
? flags["project-key"]
|
|
1040
|
-
:
|
|
1041
|
-
? process.env.DATAIKU_PROJECT_KEY
|
|
1042
|
-
: undefined;
|
|
911
|
+
: ambientProjectKey();
|
|
1043
912
|
let client;
|
|
1044
913
|
const needsClient = steps.some((argv) => batchStepNeedsClient(argv));
|
|
1045
914
|
if (needsClient) {
|
|
@@ -1247,8 +1116,7 @@ function rawFlagValue(argv, flagName) {
|
|
|
1247
1116
|
function commandIsProjectScoped(resource, action) {
|
|
1248
1117
|
if (!resource)
|
|
1249
1118
|
return false;
|
|
1250
|
-
|
|
1251
|
-
return inferRequiresProject(resource, action ?? "", usage);
|
|
1119
|
+
return inferRequiresProject(resource, action ?? "");
|
|
1252
1120
|
}
|
|
1253
1121
|
function rawCommandContext() {
|
|
1254
1122
|
const argv = process.argv.slice(2);
|
|
@@ -1256,15 +1124,13 @@ function rawCommandContext() {
|
|
|
1256
1124
|
const resource = currentCommandContext.resource ?? positionals[0];
|
|
1257
1125
|
const action = currentCommandContext.action ?? positionals[1];
|
|
1258
1126
|
const explicitProjectKey = rawFlagValue(argv, "project-key") ?? rawFlagValue(argv, "project");
|
|
1259
|
-
const
|
|
1260
|
-
? process.env.DATAIKU_PROJECT_KEY
|
|
1261
|
-
: undefined;
|
|
1127
|
+
const environmentProjectKey = ambientProjectKey();
|
|
1262
1128
|
return {
|
|
1263
1129
|
resource,
|
|
1264
1130
|
action,
|
|
1265
1131
|
projectKey: explicitProjectKey
|
|
1266
1132
|
?? (commandIsProjectScoped(resource, action)
|
|
1267
|
-
? currentCommandContext.projectKey ??
|
|
1133
|
+
? currentCommandContext.projectKey ?? environmentProjectKey
|
|
1268
1134
|
: undefined),
|
|
1269
1135
|
};
|
|
1270
1136
|
}
|
|
@@ -1364,7 +1230,6 @@ function dssDiagnosticDetails(err) {
|
|
|
1364
1230
|
return {};
|
|
1365
1231
|
}
|
|
1366
1232
|
}
|
|
1367
|
-
const MISSING_PROJECT_KEY_ERROR_PREFIX = "projectKey is required";
|
|
1368
1233
|
function isAmbiguousMutationFailure(err, context) {
|
|
1369
1234
|
if (!(err instanceof DataikuError))
|
|
1370
1235
|
return false;
|
|
@@ -1399,9 +1264,15 @@ function boundedFailureResult(result) {
|
|
|
1399
1264
|
function errorExitCode(err) {
|
|
1400
1265
|
if (err instanceof CommandResultFailure)
|
|
1401
1266
|
return err.exitCode;
|
|
1402
|
-
if (err instanceof ClientValidationError
|
|
1267
|
+
if (err instanceof ClientValidationError
|
|
1268
|
+
&& (err.code === "assertion_failed" || err.code === "long_running_failure"))
|
|
1403
1269
|
return 4;
|
|
1404
|
-
if (err instanceof ClientValidationError
|
|
1270
|
+
if (err instanceof ClientValidationError
|
|
1271
|
+
&& (err.code === "ambiguous_outcome" || err.code === "internal_error"))
|
|
1272
|
+
return 2;
|
|
1273
|
+
// A permission/environment refusal is not a usage error (exit 1 is usage only).
|
|
1274
|
+
if ((err instanceof UsageError || err instanceof ClientValidationError)
|
|
1275
|
+
&& err.code === "target_absence_unverifiable")
|
|
1405
1276
|
return 2;
|
|
1406
1277
|
if (err instanceof UsageError || err instanceof ClientValidationError)
|
|
1407
1278
|
return 1;
|
|
@@ -1409,15 +1280,14 @@ function errorExitCode(err) {
|
|
|
1409
1280
|
return 2;
|
|
1410
1281
|
if (err instanceof DataikuError)
|
|
1411
1282
|
return err.category === "transient" ? 3 : 2;
|
|
1412
|
-
if (err instanceof Error && err.message.startsWith(MISSING_PROJECT_KEY_ERROR_PREFIX))
|
|
1413
|
-
return 1;
|
|
1414
1283
|
return 2;
|
|
1415
1284
|
}
|
|
1416
|
-
function buildErrorReport(err) {
|
|
1417
|
-
const context = rawCommandContext();
|
|
1285
|
+
function buildErrorReport(err, contextOverride) {
|
|
1286
|
+
const context = contextOverride ?? rawCommandContext();
|
|
1418
1287
|
const exitCode = errorExitCode(err);
|
|
1419
1288
|
if (err instanceof ClientValidationError
|
|
1420
|
-
&& (err.code === "ambiguous_outcome" || err.code === "assertion_failed"
|
|
1289
|
+
&& (err.code === "ambiguous_outcome" || err.code === "assertion_failed"
|
|
1290
|
+
|| err.code === "long_running_failure")) {
|
|
1421
1291
|
return {
|
|
1422
1292
|
type: "error",
|
|
1423
1293
|
ok: false,
|
|
@@ -1439,7 +1309,9 @@ function buildErrorReport(err) {
|
|
|
1439
1309
|
code: err.code,
|
|
1440
1310
|
category: err.code === "target_absence_unverifiable"
|
|
1441
1311
|
? "permission_or_environment"
|
|
1442
|
-
: "
|
|
1312
|
+
: err.code === "internal_error"
|
|
1313
|
+
? "internal"
|
|
1314
|
+
: "usage",
|
|
1443
1315
|
exitCode,
|
|
1444
1316
|
...(err.code === "target_absence_unverifiable" ? { retryable: false, } : {}),
|
|
1445
1317
|
...(err.hint ? { hint: err.hint, } : {}),
|
|
@@ -1517,18 +1389,6 @@ function buildErrorReport(err) {
|
|
|
1517
1389
|
...context,
|
|
1518
1390
|
};
|
|
1519
1391
|
}
|
|
1520
|
-
if (err instanceof Error && err.message.startsWith(MISSING_PROJECT_KEY_ERROR_PREFIX)) {
|
|
1521
|
-
return {
|
|
1522
|
-
type: "error",
|
|
1523
|
-
ok: false,
|
|
1524
|
-
error: err.message,
|
|
1525
|
-
code: "missing_required_flag",
|
|
1526
|
-
category: "usage",
|
|
1527
|
-
exitCode,
|
|
1528
|
-
hint: "Pass --project-key or set DATAIKU_PROJECT_KEY.",
|
|
1529
|
-
...context,
|
|
1530
|
-
};
|
|
1531
|
-
}
|
|
1532
1392
|
const message = err instanceof Error ? err.message : String(err);
|
|
1533
1393
|
return {
|
|
1534
1394
|
type: "error",
|
|
@@ -1579,9 +1439,7 @@ async function main() {
|
|
|
1579
1439
|
action: positional[1],
|
|
1580
1440
|
projectKey: typeof flags["project-key"] === "string"
|
|
1581
1441
|
? flags["project-key"]
|
|
1582
|
-
:
|
|
1583
|
-
? process.env.DATAIKU_PROJECT_KEY
|
|
1584
|
-
: undefined,
|
|
1442
|
+
: ambientProjectKey(),
|
|
1585
1443
|
});
|
|
1586
1444
|
const metaCommand = await runMetaCommand(resource, positional[1], flags);
|
|
1587
1445
|
if (metaCommand) {
|
package/dist/src/client.d.ts
CHANGED
|
@@ -118,7 +118,7 @@ export interface DataikuClientConfig {
|
|
|
118
118
|
projectKey?: string;
|
|
119
119
|
/** Request/header timeout and buffered-body budget; idle timeout per raw stream read (default 30 000 ms). */
|
|
120
120
|
requestTimeoutMs?: number;
|
|
121
|
-
/**
|
|
121
|
+
/** Maximum total attempts, initial request included, for idempotent requests (default 4, capped at 10; 1 = no retry) */
|
|
122
122
|
retryMaxAttempts?: number;
|
|
123
123
|
/**
|
|
124
124
|
* Maximum bytes retained from a single response body by text/JSON consumers
|
|
@@ -336,6 +336,7 @@ export declare class DataikuClient {
|
|
|
336
336
|
stream(path: string): Promise<Response>;
|
|
337
337
|
/** Bound each pending read, not total transfer time; preserve large downloads and backpressure. */
|
|
338
338
|
private withBodyDeadline;
|
|
339
|
+
/** JSON request headers; Content-Type only when a body is sent. */
|
|
339
340
|
private getHeaders;
|
|
340
341
|
private getAnyHeaders;
|
|
341
342
|
private responseMeta;
|