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/contract.js
CHANGED
|
@@ -6,19 +6,24 @@ import { DataikuError, } from "../errors.js";
|
|
|
6
6
|
import actionOutputSchemasMetadata from "../generated/action-output-schemas.json" with { type: "json"
|
|
7
7
|
};
|
|
8
8
|
import { APP_MANIFEST_CONCURRENCY_CONTROL, } from "../resources/applications.js";
|
|
9
|
+
import { buildDatasetCreateBody, } from "../resources/datasets.js";
|
|
10
|
+
import { validatePluginDestinationPath, validatePluginPath, } from "../resources/plugins.js";
|
|
9
11
|
import { encodeLibraryPath, PROJECT_LIBRARY_CONCURRENCY_CONTROL, validateLibraryDestinationPath, validateLibraryName, validateLibraryPath, } from "../resources/project-library.js";
|
|
12
|
+
import { buildRecipeCreateRequest, } from "../resources/recipes.js";
|
|
10
13
|
import { encodeGitReferencePath, validateGitReferencePath, } from "../utils/git-reference.js";
|
|
11
|
-
import { jobBuildTargetTypeFromFlags, json, jsonInput, num, parseBooleanOption, parseJsonObject,
|
|
14
|
+
import { jobBuildTargetTypeFromFlags, json, jsonInput, num, parseBooleanOption, parseJsonObject, requiredJsonInput, rewritePairsFromFlags, schemaColumnsInput, sha256Hex, stableHash, stringField, textInput, } from "./coerce.js";
|
|
12
15
|
import { parseCodeRunIntegerFlag, resolveCodeInputWithSource, } from "./commands/code.js";
|
|
13
16
|
import { commands, } from "./commands/index.js";
|
|
14
17
|
import { projectLibraryPutPayload, } from "./commands/project-library.js";
|
|
18
|
+
import { recipeCreateOptionsFromFlags, } from "./commands/recipe.js";
|
|
15
19
|
import { resolveSqlQueryInvocation, } from "./commands/sql.js";
|
|
16
|
-
import {
|
|
17
|
-
import { BOOLEAN_FLAGS, executionMode, FLAG_ALIASES,
|
|
20
|
+
import { ambientProjectKey, } from "./env.js";
|
|
21
|
+
import { BOOLEAN_FLAGS, executionMode, FLAG_ALIASES, SHORT_FLAGS, } from "./flags.js";
|
|
18
22
|
import { flowZoneColor, flowZoneMoveItems, flowZoneName, } from "./helpers/flow-zone.js";
|
|
19
23
|
import { recipeBackupPath, recipeRunShouldWait, } from "./helpers/recipe.js";
|
|
20
24
|
import { encodedProjectEndpointForPlan, planResult, } from "./output.js";
|
|
21
25
|
import { resolveLoginCredentials, } from "./runtime.js";
|
|
26
|
+
import { commandSyntax, commandSyntaxTree, commandUsage, renderNodes, syntaxCommandWords, syntaxHasFlag, } from "./syntax.js";
|
|
22
27
|
import { inferRequiresProject, requireArgs, UsageError, } from "./usage.js";
|
|
23
28
|
import { AGENT_CONTRACT_SCHEMA_ID, AGENT_CONTRACT_VERSION, cliVersionResult, JSON_SCHEMA_DRAFT, } from "./version.js";
|
|
24
29
|
function codeEnvWait(flags) {
|
|
@@ -81,7 +86,6 @@ export const AUTH_ACTIONS = {
|
|
|
81
86
|
saveCredentials({ url, apiKey, projectKey, ...tlsSettings, });
|
|
82
87
|
return { saved: true, path: credentialsPath, };
|
|
83
88
|
},
|
|
84
|
-
usage: "dss auth login --url URL --api-key KEY [--project-key KEY] [--insecure] [--ca-cert PATH]",
|
|
85
89
|
description: "Validate and save DSS credentials from flags or environment variables.",
|
|
86
90
|
examples: [
|
|
87
91
|
"dss auth login --url https://dss.example.com --api-key YOUR_KEY",
|
|
@@ -238,7 +242,7 @@ const AUTHENTICATED_AGENT_FLAGS = [
|
|
|
238
242
|
"insecure",
|
|
239
243
|
"ca-cert",
|
|
240
244
|
];
|
|
241
|
-
export const COMMANDS_USAGE = "
|
|
245
|
+
export const COMMANDS_USAGE = commandUsage("commands", "run");
|
|
242
246
|
const COMMANDS_DESCRIPTION = "Print a compact resource/action summary by default; use --fields for scoped command metadata or --output PATH to export the full registry without sending it through stdout.";
|
|
243
247
|
const COMMANDS_EXAMPLES = [
|
|
244
248
|
"dss commands run",
|
|
@@ -248,28 +252,28 @@ const COMMANDS_EXAMPLES = [
|
|
|
248
252
|
"dss commands run --output commands.json",
|
|
249
253
|
];
|
|
250
254
|
export const AGENT_CONTRACT_COMMAND = "dss agent contract";
|
|
251
|
-
export const AGENT_CONTRACT_USAGE = "
|
|
255
|
+
export const AGENT_CONTRACT_USAGE = commandUsage("agent", "contract");
|
|
252
256
|
const AGENT_CONTRACT_DESCRIPTION = "Print the versioned JSON agent contract; scope bootstrap fields, use commands.actions to enumerate the surface, and read schemas only when needed.";
|
|
253
257
|
const AGENT_CONTRACT_EXAMPLES = [
|
|
254
258
|
"dss agent contract --fields protocol,agentContractVersion,cli,stdio,planning,compatibility",
|
|
255
259
|
"dss agent contract --fields commands.actions",
|
|
256
260
|
];
|
|
257
|
-
const VERSION_USAGE = "
|
|
261
|
+
const VERSION_USAGE = commandUsage("version", "run");
|
|
258
262
|
const VERSION_DESCRIPTION = "Print the CLI version, checkout/build revisions, load source, runtime, and stale-build status as JSON.";
|
|
259
263
|
const VERSION_EXAMPLES = ["dss version", "dss --version",];
|
|
260
|
-
const INSTALL_SKILL_USAGE = "
|
|
264
|
+
const INSTALL_SKILL_USAGE = commandUsage("install-skill", "run");
|
|
261
265
|
const INSTALL_SKILL_DESCRIPTION = "Report missing/stale/current skill status and atomically install changed dataiku-dss agent skills.";
|
|
262
266
|
const INSTALL_SKILL_EXAMPLES = [
|
|
263
267
|
"dss install-skill --list-agents",
|
|
264
268
|
"dss install-skill --agent omp --dry-run",
|
|
265
269
|
];
|
|
266
|
-
export const CLEANUP_USAGE = "
|
|
270
|
+
export const CLEANUP_USAGE = commandUsage("cleanup", "run");
|
|
267
271
|
const CLEANUP_DESCRIPTION = "Replay cleanup entries in reverse order; failures include structured code/category/exitCode/retryability summaries.";
|
|
268
272
|
const CLEANUP_EXAMPLES = [
|
|
269
273
|
"dss cleanup --file cleanup.jsonl",
|
|
270
274
|
"dss cleanup --file cleanup.jsonl --apply",
|
|
271
275
|
];
|
|
272
|
-
const FIXTURES_USAGE = "
|
|
276
|
+
const FIXTURES_USAGE = commandUsage("fixtures", "run");
|
|
273
277
|
const FIXTURES_DESCRIPTION = "Discover safe live-test fixtures for agent workflows.";
|
|
274
278
|
const FIXTURES_EXAMPLES = [
|
|
275
279
|
"dss fixtures",
|
|
@@ -500,10 +504,9 @@ function shortFlagPattern(flags) {
|
|
|
500
504
|
* use an actionless prefix, while real command paths that spell `run` in their
|
|
501
505
|
* usage (e.g. `dss commands run`) keep the action token.
|
|
502
506
|
*/
|
|
503
|
-
function argvPrefix(resource, action
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
return head[0] === resource && head[1] === action ? [resource, action,] : [resource,];
|
|
507
|
+
function argvPrefix(resource, action) {
|
|
508
|
+
const words = syntaxCommandWords(commandSyntaxTree(resource, action) ?? []);
|
|
509
|
+
return words[0] === resource && words[1] === action ? [resource, action,] : [resource,];
|
|
507
510
|
}
|
|
508
511
|
/**
|
|
509
512
|
* Describe one invocation as a canonical argv token array. Agents emit the
|
|
@@ -520,7 +523,7 @@ function argvPrefix(resource, action, usage) {
|
|
|
520
523
|
* negative-number and `--` separator rules.
|
|
521
524
|
*/
|
|
522
525
|
function argvJsonSchema(resource, action, flags, usage, requiredFlags, requiredOneOf) {
|
|
523
|
-
const prefix = argvPrefix(resource, action
|
|
526
|
+
const prefix = argvPrefix(resource, action);
|
|
524
527
|
const aliases = {};
|
|
525
528
|
for (const flag of flags) {
|
|
526
529
|
aliases[flag.name] = flag.aliases ?? [];
|
|
@@ -528,7 +531,8 @@ function argvJsonSchema(resource, action, flags, usage, requiredFlags, requiredO
|
|
|
528
531
|
const booleanNames = flags.filter((flag) => flag.kind === "boolean")
|
|
529
532
|
.flatMap((flag) => [flag.name, ...(flag.aliases ?? []),]);
|
|
530
533
|
const valueFlags = flags.filter((flag) => flag.kind === "value");
|
|
531
|
-
const requiredPositionals =
|
|
534
|
+
const requiredPositionals = commandSyntax(resource, action).positionalArguments
|
|
535
|
+
.filter((positional) => positional.required).map((positional) => positional.name);
|
|
532
536
|
const itemSchemas = [
|
|
533
537
|
{ not: { pattern: "^-", }, },
|
|
534
538
|
{ const: "-", },
|
|
@@ -659,45 +663,6 @@ const EXPLICIT_REGISTRY_OVERRIDES = {
|
|
|
659
663
|
examplePayload: { article: { name: "Updated article", }, },
|
|
660
664
|
},
|
|
661
665
|
};
|
|
662
|
-
function extractUsageFlags(usage) {
|
|
663
|
-
const flags = [];
|
|
664
|
-
for (const match of usage.matchAll(/--([a-z0-9-]+)/g)) {
|
|
665
|
-
flags.push(FLAG_ALIASES[match[1]] ?? match[1]);
|
|
666
|
-
}
|
|
667
|
-
return uniqueStrings(flags).filter((flag) => KNOWN_LONG_FLAGS.has(flag));
|
|
668
|
-
}
|
|
669
|
-
function extractPositionalArguments(usage) {
|
|
670
|
-
const positionals = [];
|
|
671
|
-
const add = (name, required) => {
|
|
672
|
-
const existing = positionals.find((positional) => positional.name === name);
|
|
673
|
-
if (existing)
|
|
674
|
-
existing.required ||= required;
|
|
675
|
-
else
|
|
676
|
-
positionals.push({ name, required, });
|
|
677
|
-
};
|
|
678
|
-
for (const match of usage.matchAll(/<([^>]+)>/g)) {
|
|
679
|
-
const before = usage.slice(0, match.index);
|
|
680
|
-
const openParen = before.lastIndexOf("(");
|
|
681
|
-
const insideParen = openParen > before.lastIndexOf(")");
|
|
682
|
-
const closeParen = insideParen ? usage.indexOf(")", match.index) : -1;
|
|
683
|
-
const group = closeParen >= 0 ? usage.slice(openParen + 1, closeParen) : "";
|
|
684
|
-
const hasFlagAlternative = group.split("|").some((alternative) => alternative.includes("--"));
|
|
685
|
-
const required = before.lastIndexOf("[") <= before.lastIndexOf("]")
|
|
686
|
-
&& !hasFlagAlternative;
|
|
687
|
-
add(match[1], required);
|
|
688
|
-
}
|
|
689
|
-
for (const suffix of usage.split("[").slice(1)) {
|
|
690
|
-
const candidate = suffix.split("]", 1)[0];
|
|
691
|
-
if (candidate && /^[A-Za-z][A-Za-z0-9_-]*$/.test(candidate))
|
|
692
|
-
add(candidate, false);
|
|
693
|
-
}
|
|
694
|
-
for (const group of topLevelParenGroups(usage)) {
|
|
695
|
-
const candidate = group.split("|", 1)[0]?.trim();
|
|
696
|
-
if (candidate && /^[A-Z][A-Z0-9_-]*$/.test(candidate))
|
|
697
|
-
add(candidate, false);
|
|
698
|
-
}
|
|
699
|
-
return positionals;
|
|
700
|
-
}
|
|
701
666
|
const COMMAND_REQUIRED_INPUT_GROUPS = {
|
|
702
667
|
"notebook.unload-jupyter": [
|
|
703
668
|
{
|
|
@@ -769,7 +734,7 @@ function inferSideEffect(resource, action) {
|
|
|
769
734
|
// LLM Mesh completions/embeddings invoke the LLM provider (cost-bearing,
|
|
770
735
|
// arbitrary-prompt execution); the verb shapes match no mutating pattern
|
|
771
736
|
// and would fall through to read, wrongly rejecting --plan. Knowledge-bank
|
|
772
|
-
// search stays
|
|
737
|
+
// search stays read: it only queries an existing index.
|
|
773
738
|
if (resource === "llm" && (action === "completions" || action === "embeddings")) {
|
|
774
739
|
return "write";
|
|
775
740
|
}
|
|
@@ -856,102 +821,6 @@ function inferOutputShape(resource, action) {
|
|
|
856
821
|
return "string";
|
|
857
822
|
return "object";
|
|
858
823
|
}
|
|
859
|
-
export function inferInputContract(usage) {
|
|
860
|
-
return {
|
|
861
|
-
...(usage.includes("--stdin") ? { stdin: true, } : {}),
|
|
862
|
-
...(usage.includes("--data ") || usage.includes("--data JSON") ? { dataFlag: true, } : {}),
|
|
863
|
-
...(usage.includes("--data-file") ? { dataFileFlag: true, } : {}),
|
|
864
|
-
};
|
|
865
|
-
}
|
|
866
|
-
function stripOptionalUsageGroups(usage) {
|
|
867
|
-
return usage.replace(/\[[^\]]*\]/g, " ");
|
|
868
|
-
}
|
|
869
|
-
function stripAllUsageGroups(usage) {
|
|
870
|
-
return usage.replace(/\[[^\]]*\]/g, " ").replace(/\([^)]*\)/g, " ");
|
|
871
|
-
}
|
|
872
|
-
function topLevelParenGroups(usage) {
|
|
873
|
-
const groups = [];
|
|
874
|
-
let depth = 0;
|
|
875
|
-
let current = "";
|
|
876
|
-
for (const char of usage) {
|
|
877
|
-
if (char === "(") {
|
|
878
|
-
if (depth > 0)
|
|
879
|
-
current += char;
|
|
880
|
-
else
|
|
881
|
-
current = "";
|
|
882
|
-
depth++;
|
|
883
|
-
}
|
|
884
|
-
else if (char === ")") {
|
|
885
|
-
depth--;
|
|
886
|
-
if (depth === 0)
|
|
887
|
-
groups.push(current);
|
|
888
|
-
else
|
|
889
|
-
current += char;
|
|
890
|
-
}
|
|
891
|
-
else if (depth > 0) {
|
|
892
|
-
current += char;
|
|
893
|
-
}
|
|
894
|
-
}
|
|
895
|
-
return groups;
|
|
896
|
-
}
|
|
897
|
-
function splitTopLevelChoices(group) {
|
|
898
|
-
const parts = [];
|
|
899
|
-
let depth = 0;
|
|
900
|
-
let current = "";
|
|
901
|
-
for (let index = 0; index < group.length; index++) {
|
|
902
|
-
const char = group[index];
|
|
903
|
-
if (char === "[" || char === "(")
|
|
904
|
-
depth++;
|
|
905
|
-
else if (char === "]" || char === ")")
|
|
906
|
-
depth--;
|
|
907
|
-
const nextAlternative = group.slice(index + 1).trimStart();
|
|
908
|
-
if (char === "|" && depth === 0 && nextAlternative.startsWith("--")) {
|
|
909
|
-
parts.push(current);
|
|
910
|
-
current = "";
|
|
911
|
-
}
|
|
912
|
-
else {
|
|
913
|
-
current += char;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
parts.push(current);
|
|
917
|
-
return parts;
|
|
918
|
-
}
|
|
919
|
-
function flagsInUsageFragment(fragment) {
|
|
920
|
-
return extractUsageFlags(fragment.replace(/\[[^\]]*\]/g, " "));
|
|
921
|
-
}
|
|
922
|
-
/**
|
|
923
|
-
* Split required usage flags into unconditional flags and required choice
|
|
924
|
-
* groups. A required `(--a X | --b Y)` group becomes a requiredOneOf entry
|
|
925
|
-
* (at least one alternative; an alternative listing several flags must be
|
|
926
|
-
* supplied together) instead of marking every flag as unconditionally required.
|
|
927
|
-
*/
|
|
928
|
-
function deriveRequiredUsage(usage) {
|
|
929
|
-
const requiredFlags = extractUsageFlags(stripAllUsageGroups(usage));
|
|
930
|
-
const requiredOneOf = [];
|
|
931
|
-
for (const group of topLevelParenGroups(usage)) {
|
|
932
|
-
const alternatives = splitTopLevelChoices(group);
|
|
933
|
-
if (alternatives.length <= 1) {
|
|
934
|
-
requiredFlags.push(...flagsInUsageFragment(group));
|
|
935
|
-
continue;
|
|
936
|
-
}
|
|
937
|
-
const oneOf = alternatives
|
|
938
|
-
.map((alternative) => flagsInUsageFragment(alternative))
|
|
939
|
-
.filter((alternativeFlags) => alternativeFlags.length > 0);
|
|
940
|
-
// A group mixing a positional alternative with flags (e.g. sql query's
|
|
941
|
-
// `(SQL | --sql QUERY | --sql-file PATH | --sql - | --stdin)`) cannot be
|
|
942
|
-
// expressed as a flag-only choice: filtering out the flagless alternative
|
|
943
|
-
// would falsely require one of the flags. Omit the group from the flag
|
|
944
|
-
// contract entirely; the handler stays the runtime authority.
|
|
945
|
-
if (alternatives.some((alternative) => flagsInUsageFragment(alternative).length === 0)) {
|
|
946
|
-
continue;
|
|
947
|
-
}
|
|
948
|
-
if (oneOf.length > 1)
|
|
949
|
-
requiredOneOf.push({ oneOf, });
|
|
950
|
-
else if (oneOf.length === 1)
|
|
951
|
-
requiredFlags.push(...oneOf[0]);
|
|
952
|
-
}
|
|
953
|
-
return { requiredFlags: uniqueStrings(requiredFlags), requiredOneOf, };
|
|
954
|
-
}
|
|
955
824
|
const GLOBAL_FLAG_VALUE_HINTS = {
|
|
956
825
|
url: { valueType: "URL", },
|
|
957
826
|
fields: { valueType: "CSV", },
|
|
@@ -967,22 +836,6 @@ const GLOBAL_FLAG_VALUE_HINTS = {
|
|
|
967
836
|
standard: { valueType: "JSON", },
|
|
968
837
|
until: { valueType: "STATE", },
|
|
969
838
|
};
|
|
970
|
-
/** Derive a value placeholder (and enum members) for each value flag from its usage token. */
|
|
971
|
-
function extractFlagValueHints(usage) {
|
|
972
|
-
const hints = new Map();
|
|
973
|
-
for (const match of usage.matchAll(/--([a-z0-9-]+)\s+([A-Za-z][A-Za-z0-9_-]*(?:\|[A-Za-z][A-Za-z0-9_-]*)+)(?![A-Za-z0-9_=-])/g)) {
|
|
974
|
-
const flag = FLAG_ALIASES[match[1]] ?? match[1];
|
|
975
|
-
if (!hints.has(flag)) {
|
|
976
|
-
hints.set(flag, { valueType: "enum", enumValues: match[2].split("|"), });
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
for (const match of usage.matchAll(/--([a-z0-9-]+)\s+(<[^>]+>|[A-Z][A-Za-z0-9_]*)/g)) {
|
|
980
|
-
const flag = FLAG_ALIASES[match[1]] ?? match[1];
|
|
981
|
-
if (!hints.has(flag))
|
|
982
|
-
hints.set(flag, { valueType: match[2], });
|
|
983
|
-
}
|
|
984
|
-
return hints;
|
|
985
|
-
}
|
|
986
839
|
function inferPayloadSchema(inputContract) {
|
|
987
840
|
if (!inputContract.stdin && !inputContract.dataFlag && !inputContract.dataFileFlag) {
|
|
988
841
|
return undefined;
|
|
@@ -1036,11 +889,11 @@ function cleanupCommandFromDeleteUsage(resource, action) {
|
|
|
1036
889
|
: action === "create-instance" || action === "create-successor-instance"
|
|
1037
890
|
? "delete-instance"
|
|
1038
891
|
: "delete";
|
|
1039
|
-
const
|
|
1040
|
-
if (!
|
|
892
|
+
const deleteSyntax = commandSyntaxTree(resource, deleteAction);
|
|
893
|
+
if (!deleteSyntax)
|
|
1041
894
|
return undefined;
|
|
1042
|
-
const base =
|
|
1043
|
-
if (
|
|
895
|
+
const base = renderNodes(deleteSyntax, true);
|
|
896
|
+
if (syntaxHasFlag(deleteSyntax, "if-exists"))
|
|
1044
897
|
return `${base} --if-exists`;
|
|
1045
898
|
return base;
|
|
1046
899
|
}
|
|
@@ -1123,14 +976,15 @@ function inferAsyncKind(resource, action) {
|
|
|
1123
976
|
}
|
|
1124
977
|
return "none";
|
|
1125
978
|
}
|
|
1126
|
-
function inferIdempotency(resource, sideEffect, action,
|
|
979
|
+
function inferIdempotency(resource, sideEffect, action, syntax) {
|
|
1127
980
|
if (sideEffect === "read")
|
|
1128
981
|
return "safe";
|
|
1129
982
|
if (`${resource}.${action}` === "install-skill.run")
|
|
1130
983
|
return "convergent";
|
|
1131
|
-
if (action.startsWith("create") &&
|
|
984
|
+
if (action.startsWith("create") && syntaxHasFlag(syntax, "if-not-exists")) {
|
|
1132
985
|
return "if-not-exists";
|
|
1133
|
-
|
|
986
|
+
}
|
|
987
|
+
if (action.startsWith("delete") && syntaxHasFlag(syntax, "if-exists"))
|
|
1134
988
|
return "if-exists";
|
|
1135
989
|
if (`${resource}.${action}` === "app.set-manifest-version")
|
|
1136
990
|
return "none";
|
|
@@ -1182,10 +1036,10 @@ export function inferCleanupHint(resource, action) {
|
|
|
1182
1036
|
: action === "create-instance" || action === "create-successor-instance"
|
|
1183
1037
|
? "delete-instance"
|
|
1184
1038
|
: "delete";
|
|
1185
|
-
const
|
|
1186
|
-
if (!
|
|
1039
|
+
const deleteSyntax = commandSyntaxTree(resource, deleteAction);
|
|
1040
|
+
if (!deleteSyntax)
|
|
1187
1041
|
return undefined;
|
|
1188
|
-
const ifExists =
|
|
1042
|
+
const ifExists = syntaxHasFlag(deleteSyntax, "if-exists") ? " --if-exists" : "";
|
|
1189
1043
|
if (resource === "code-env") {
|
|
1190
1044
|
return `Delete with \`dss code-env delete <lang> <name>${ifExists}\`.`;
|
|
1191
1045
|
}
|
|
@@ -1196,14 +1050,16 @@ export function inferCleanupHint(resource, action) {
|
|
|
1196
1050
|
}
|
|
1197
1051
|
function buildRegistryEntry(resource, action, meta) {
|
|
1198
1052
|
const requiresAuth = meta.localHandler === undefined && inferRequiresAuth(resource);
|
|
1199
|
-
const requiresProject = inferRequiresProject(resource, action
|
|
1053
|
+
const requiresProject = inferRequiresProject(resource, action);
|
|
1200
1054
|
const sideEffect = inferSideEffect(resource, action);
|
|
1201
1055
|
const destructive = inferDestructiveLevel(resource, sideEffect, action);
|
|
1202
1056
|
const asyncKind = inferAsyncKind(resource, action);
|
|
1203
1057
|
const mutatesDss = sideEffect === "write" && resource !== "auth" && resource !== "install-skill";
|
|
1204
|
-
|
|
1058
|
+
// auth login writes local credentials only; its --plan previews that write.
|
|
1059
|
+
const supportsPlan = sideEffect === "write" || resource === "auth";
|
|
1205
1060
|
const supportsCleanup = supportsCleanupLedger(resource, action);
|
|
1206
|
-
const
|
|
1061
|
+
const syntax = commandSyntax(resource, action);
|
|
1062
|
+
const usageFlags = syntax.flags;
|
|
1207
1063
|
const flags = uniqueStrings([
|
|
1208
1064
|
...usageFlags,
|
|
1209
1065
|
...(supportsPlan ? ["plan",] : []),
|
|
@@ -1212,7 +1068,7 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1212
1068
|
...(requiresAuth ? AUTHENTICATED_AGENT_FLAGS : []),
|
|
1213
1069
|
...(requiresProject ? ["project-key",] : []),
|
|
1214
1070
|
]);
|
|
1215
|
-
const derivedRequired =
|
|
1071
|
+
const derivedRequired = syntax;
|
|
1216
1072
|
const requiredFlags = meta.requiredFlags
|
|
1217
1073
|
?? EXPLICIT_REGISTRY_OVERRIDES[registryKey(resource, action)]?.requiredFlags
|
|
1218
1074
|
?? derivedRequired.requiredFlags;
|
|
@@ -1223,8 +1079,8 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1223
1079
|
const optionalFlags = meta.optionalFlags
|
|
1224
1080
|
?? EXPLICIT_REGISTRY_OVERRIDES[registryKey(resource, action)]?.optionalFlags
|
|
1225
1081
|
?? flags.filter((flag) => !requiredFlags.includes(flag) && !oneOfFlags.has(flag));
|
|
1226
|
-
const valueHints =
|
|
1227
|
-
const inputContract =
|
|
1082
|
+
const valueHints = syntax.valueHints;
|
|
1083
|
+
const inputContract = syntax.inputContract;
|
|
1228
1084
|
const cleanupHint = inferCleanupHint(resource, action);
|
|
1229
1085
|
const payloadSchema = meta.payloadSchema
|
|
1230
1086
|
?? EXPLICIT_REGISTRY_OVERRIDES[registryKey(resource, action)]?.payloadSchema
|
|
@@ -1238,15 +1094,13 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1238
1094
|
? undefined
|
|
1239
1095
|
: inferredCleanupCommand;
|
|
1240
1096
|
const flagMetadata = flags.map((name) => {
|
|
1241
|
-
const aliases =
|
|
1242
|
-
.filter(([raw, canonical,]) => canonical === name && new RegExp(`--${raw}(?![a-z0-9-])`).test(meta.usage))
|
|
1243
|
-
.map(([raw,]) => raw);
|
|
1097
|
+
const aliases = syntax.aliases[name] ?? [];
|
|
1244
1098
|
const aliasPart = aliases.length > 0 ? { aliases, } : {};
|
|
1245
1099
|
const kind = flagKind(name);
|
|
1246
1100
|
if (kind === "boolean")
|
|
1247
1101
|
return { name, kind, ...aliasPart, };
|
|
1248
1102
|
const allowEmptyPart = ALLOW_EMPTY_VALUE_FLAGS[name] === true ? { allowEmptyValue: true, } : {};
|
|
1249
|
-
const hint = valueHints
|
|
1103
|
+
const hint = valueHints[name] ?? GLOBAL_FLAG_VALUE_HINTS[name];
|
|
1250
1104
|
if (!hint)
|
|
1251
1105
|
return { name, kind, ...aliasPart, ...allowEmptyPart, };
|
|
1252
1106
|
return {
|
|
@@ -1258,12 +1112,11 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1258
1112
|
...allowEmptyPart,
|
|
1259
1113
|
};
|
|
1260
1114
|
});
|
|
1261
|
-
const positionalArguments =
|
|
1115
|
+
const positionalArguments = syntax.positionalArguments;
|
|
1262
1116
|
const positionals = positionalArguments.map((positional) => positional.name);
|
|
1263
1117
|
const inputGroups = requiredInputGroups(resource, action);
|
|
1264
1118
|
const outputShape = inferOutputShape(resource, action);
|
|
1265
|
-
const producesLocalFile =
|
|
1266
|
-
|| meta.usage.includes("--output-file PATH");
|
|
1119
|
+
const producesLocalFile = syntax.producesLocalFile;
|
|
1267
1120
|
const uniqueRequiredFlags = uniqueStrings(requiredFlags);
|
|
1268
1121
|
const uniqueOptionalFlags = uniqueStrings(optionalFlags);
|
|
1269
1122
|
const unsafe = unsafeOutputs(resource, action, producesLocalFile);
|
|
@@ -1287,8 +1140,8 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1287
1140
|
producesLocalFile,
|
|
1288
1141
|
mutatesDss,
|
|
1289
1142
|
async: asyncKind,
|
|
1290
|
-
idempotency: inferIdempotency(resource, sideEffect, action,
|
|
1291
|
-
dryRun:
|
|
1143
|
+
idempotency: inferIdempotency(resource, sideEffect, action, commandSyntaxTree(resource, action) ?? []),
|
|
1144
|
+
dryRun: syntax.dryRun,
|
|
1292
1145
|
requiredFlags: uniqueRequiredFlags,
|
|
1293
1146
|
optionalFlags: uniqueOptionalFlags,
|
|
1294
1147
|
...(requiredOneOf.length > 0 ? { requiredOneOf, } : {}),
|
|
@@ -1389,7 +1242,7 @@ function commandDefinitions(resourceFilter) {
|
|
|
1389
1242
|
for (const [action, meta,] of Object.entries(AUTH_ACTIONS)) {
|
|
1390
1243
|
registry.auth[action] = {
|
|
1391
1244
|
handler: async () => undefined,
|
|
1392
|
-
usage:
|
|
1245
|
+
usage: commandUsage("auth", action),
|
|
1393
1246
|
description: meta.description,
|
|
1394
1247
|
examples: meta.examples,
|
|
1395
1248
|
requiredFlags: meta.requiredFlags,
|
|
@@ -1656,9 +1509,7 @@ function planProjectKeyFromArgs(flags) {
|
|
|
1656
1509
|
const fromFlag = flags["project-key"];
|
|
1657
1510
|
if (typeof fromFlag === "string" && fromFlag.trim().length > 0)
|
|
1658
1511
|
return fromFlag.trim();
|
|
1659
|
-
|
|
1660
|
-
return undefined;
|
|
1661
|
-
const fromEnv = process.env.DATAIKU_PROJECT_KEY;
|
|
1512
|
+
const fromEnv = ambientProjectKey();
|
|
1662
1513
|
return fromEnv !== undefined && fromEnv.trim().length > 0 ? fromEnv.trim() : undefined;
|
|
1663
1514
|
}
|
|
1664
1515
|
/**
|
|
@@ -1710,11 +1561,6 @@ function optionalJsonFlag(flags, name) {
|
|
|
1710
1561
|
function requiredPlanJsonInput(flags, usage) {
|
|
1711
1562
|
return requiredJsonInput(flags, `--data, --data-file, or --stdin is required. Usage: ${usage}`);
|
|
1712
1563
|
}
|
|
1713
|
-
function requiredPlanPositionals(usage) {
|
|
1714
|
-
return extractPositionalArguments(usage)
|
|
1715
|
-
.filter((positional) => positional.required)
|
|
1716
|
-
.map((positional) => positional.name);
|
|
1717
|
-
}
|
|
1718
1564
|
function dataQualityEndpoint(projectKey, datasetName, suffix) {
|
|
1719
1565
|
return encodedProjectEndpointForPlan(projectKey, `/datasets/${encodeURIComponent(datasetName)}/data-quality${suffix}`);
|
|
1720
1566
|
}
|
|
@@ -1797,15 +1643,12 @@ function encodePluginSegmentsForPlan(contentPath) {
|
|
|
1797
1643
|
*/
|
|
1798
1644
|
function pluginGitPlanPayload(flags) {
|
|
1799
1645
|
const repository = requiredPlanFlag(flags, "repository", "dss plugin install-from-git --repository URL");
|
|
1800
|
-
|
|
1646
|
+
// Mirrors PluginsResource install/update bodies: absent options are sent as null.
|
|
1647
|
+
return {
|
|
1801
1648
|
gitRepositoryUrl: validatedPlanRepositoryUrl(repository, "repository", "--repository URL"),
|
|
1649
|
+
gitCheckout: typeof flags["checkout"] === "string" ? flags["checkout"] : null,
|
|
1650
|
+
gitSubpath: typeof flags["path-in-repository"] === "string" ? flags["path-in-repository"] : null,
|
|
1802
1651
|
};
|
|
1803
|
-
if (typeof flags["checkout"] === "string")
|
|
1804
|
-
payload.gitCheckout = flags["checkout"];
|
|
1805
|
-
if (typeof flags["path-in-repository"] === "string") {
|
|
1806
|
-
payload.gitSubpath = flags["path-in-repository"];
|
|
1807
|
-
}
|
|
1808
|
-
return payload;
|
|
1809
1652
|
}
|
|
1810
1653
|
function optionalPlanProjectScope(flags) {
|
|
1811
1654
|
const projectKey = flags["project-key"];
|
|
@@ -1938,16 +1781,28 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
1938
1781
|
};
|
|
1939
1782
|
case "wiki.create": {
|
|
1940
1783
|
const name = requiredPlanFlag(flags, "name", entry.usage);
|
|
1941
|
-
|
|
1784
|
+
const content = textInput(flags);
|
|
1785
|
+
const create = {
|
|
1942
1786
|
method: "POST",
|
|
1943
1787
|
endpoint: projectEndpoint("/wiki/"),
|
|
1788
|
+
payload: { projectKey, name, parent: flags["parent"] ?? null, },
|
|
1789
|
+
};
|
|
1790
|
+
return {
|
|
1791
|
+
...create,
|
|
1944
1792
|
identifiers: { name, },
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1793
|
+
// Content is not accepted by the create endpoint; it lands in a follow-up update.
|
|
1794
|
+
...(content === undefined ? {} : {
|
|
1795
|
+
requests: [
|
|
1796
|
+
{ sequence: 1, ...create, },
|
|
1797
|
+
{ sequence: 2, method: "GET", endpoint: projectEndpoint("/wiki/{createdArticleId}"), },
|
|
1798
|
+
{
|
|
1799
|
+
sequence: 3,
|
|
1800
|
+
method: "PUT",
|
|
1801
|
+
endpoint: projectEndpoint("/wiki/{createdArticleId}"),
|
|
1802
|
+
payload: { payload: content, },
|
|
1803
|
+
},
|
|
1804
|
+
],
|
|
1805
|
+
}),
|
|
1951
1806
|
};
|
|
1952
1807
|
}
|
|
1953
1808
|
case "wiki.update":
|
|
@@ -1973,7 +1828,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
1973
1828
|
const dataName = data?.["name"];
|
|
1974
1829
|
const name = flagName ?? (typeof dataName === "string" ? dataName : undefined);
|
|
1975
1830
|
if (!name) {
|
|
1976
|
-
throw new UsageError(
|
|
1831
|
+
throw new UsageError(`--name or dashboard settings containing a string name are required. Usage: ${commandUsage("dashboard", "create")}`);
|
|
1977
1832
|
}
|
|
1978
1833
|
const listed = parseBooleanOption(flags["listed"], "--listed");
|
|
1979
1834
|
const payload = { ...(data ?? { pages: [], }), name, };
|
|
@@ -2011,7 +1866,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2011
1866
|
const name = flags["name"];
|
|
2012
1867
|
const type = flags["type"];
|
|
2013
1868
|
if (!data && (!name || !type)) {
|
|
2014
|
-
throw new UsageError(
|
|
1869
|
+
throw new UsageError(`--data or both --name and --type are required. Usage: ${commandUsage("insight", "create")}`);
|
|
2015
1870
|
}
|
|
2016
1871
|
const prototype = { ...data, };
|
|
2017
1872
|
if (name !== undefined)
|
|
@@ -2095,7 +1950,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2095
1950
|
};
|
|
2096
1951
|
case "flow-zone.create": {
|
|
2097
1952
|
const name = flowZoneName(flags["name"]);
|
|
2098
|
-
const payload = { name, color: flowZoneColor(flags["color"])
|
|
1953
|
+
const payload = { name, color: flowZoneColor(flags["color"]) ?? "#2ab1ac", };
|
|
2099
1954
|
return {
|
|
2100
1955
|
method: "POST",
|
|
2101
1956
|
endpoint: projectEndpoint("/flow/zones"),
|
|
@@ -2134,17 +1989,25 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2134
1989
|
if (!connection && dsType.toLowerCase() !== "uploadedfiles") {
|
|
2135
1990
|
throw new UsageError("--connection is required unless --type is UploadedFiles.");
|
|
2136
1991
|
}
|
|
1992
|
+
const endpoint = projectEndpoint("/datasets/"); // throws without a project key
|
|
2137
1993
|
return {
|
|
2138
1994
|
method: "POST",
|
|
2139
|
-
endpoint
|
|
1995
|
+
endpoint,
|
|
2140
1996
|
identifiers: { name, },
|
|
2141
|
-
payload: {
|
|
1997
|
+
payload: buildDatasetCreateBody({
|
|
1998
|
+
projectKey: projectKey,
|
|
1999
|
+
datasetName: name,
|
|
2000
|
+
connection,
|
|
2001
|
+
dsType,
|
|
2002
|
+
}),
|
|
2142
2003
|
};
|
|
2143
2004
|
}
|
|
2144
2005
|
case "dataset.clone": {
|
|
2145
2006
|
const source = args[0];
|
|
2146
2007
|
const target = args[1];
|
|
2147
2008
|
return {
|
|
2009
|
+
exact: false,
|
|
2010
|
+
reason: "Apply GETs the source dataset and copies its current connection, format, and schema into the new dataset body.",
|
|
2148
2011
|
method: "POST",
|
|
2149
2012
|
endpoint: projectEndpoint("/datasets/"),
|
|
2150
2013
|
identifiers: { source, target, },
|
|
@@ -2306,7 +2169,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2306
2169
|
identifiers: { name: id, },
|
|
2307
2170
|
};
|
|
2308
2171
|
case "recipe.create": {
|
|
2309
|
-
|
|
2172
|
+
requiredPlanFlag(flags, "type", entry.usage);
|
|
2310
2173
|
const outputDataset = flags["output"];
|
|
2311
2174
|
const outputFolder = flags["output-folder"];
|
|
2312
2175
|
if (outputDataset && outputFolder) {
|
|
@@ -2318,19 +2181,14 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2318
2181
|
if (outputFolder && !flags["output-connection"]) {
|
|
2319
2182
|
throw new UsageError("--output-connection is required when using --output-folder.");
|
|
2320
2183
|
}
|
|
2184
|
+
const endpoint = projectEndpoint("/recipes/"); // throws without a project key
|
|
2185
|
+
// Same flag mapping and body construction as the handler and RecipesResource.create.
|
|
2186
|
+
const { recipePrototype, creationSettings, } = buildRecipeCreateRequest(recipeCreateOptionsFromFlags(flags), projectKey);
|
|
2321
2187
|
return {
|
|
2322
2188
|
method: "POST",
|
|
2323
|
-
endpoint
|
|
2324
|
-
identifiers: { name:
|
|
2325
|
-
payload: {
|
|
2326
|
-
type,
|
|
2327
|
-
name: flags["name"],
|
|
2328
|
-
inputDatasets: recipeInputDatasetsFromFlags(flags),
|
|
2329
|
-
outputDataset,
|
|
2330
|
-
outputFolder,
|
|
2331
|
-
outputConnection: flags["output-connection"],
|
|
2332
|
-
projectKey,
|
|
2333
|
-
},
|
|
2189
|
+
endpoint,
|
|
2190
|
+
identifiers: { name: recipePrototype.name, },
|
|
2191
|
+
payload: { recipePrototype, creationSettings, },
|
|
2334
2192
|
};
|
|
2335
2193
|
}
|
|
2336
2194
|
case "recipe.run":
|
|
@@ -2456,22 +2314,54 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2456
2314
|
if (activeRaw !== "true" && activeRaw !== "false") {
|
|
2457
2315
|
throw new UsageError(`Usage: ${entry.usage}`);
|
|
2458
2316
|
}
|
|
2317
|
+
const lightEndpoint = projectEndpoint(`/scenarios/${encodeURIComponent(id)}/light`);
|
|
2318
|
+
const active = activeRaw === "true";
|
|
2319
|
+
// DSS parses the light PUT as a full Scenario, so the command echoes the
|
|
2320
|
+
// current light status with `active` overridden (see ScenariosResource.setActive).
|
|
2459
2321
|
return {
|
|
2460
2322
|
method: "PUT",
|
|
2461
|
-
endpoint:
|
|
2323
|
+
endpoint: lightEndpoint,
|
|
2462
2324
|
identifiers: { id, },
|
|
2463
|
-
payload: {
|
|
2325
|
+
payload: { active, },
|
|
2326
|
+
requests: [
|
|
2327
|
+
{ sequence: 1, method: "GET", endpoint: lightEndpoint, },
|
|
2328
|
+
{
|
|
2329
|
+
sequence: 2,
|
|
2330
|
+
method: "PUT",
|
|
2331
|
+
endpoint: lightEndpoint,
|
|
2332
|
+
payload: { "...current": true, active, },
|
|
2333
|
+
},
|
|
2334
|
+
{ sequence: 3, method: "GET", endpoint: lightEndpoint, },
|
|
2335
|
+
],
|
|
2464
2336
|
};
|
|
2465
2337
|
}
|
|
2466
2338
|
case "folder.create": {
|
|
2467
2339
|
const name = requiredPlanFlag(flags, "name", entry.usage);
|
|
2468
2340
|
const type = flags["type"];
|
|
2469
2341
|
const connection = flags["connection"];
|
|
2342
|
+
const pathFlag = flags["path"];
|
|
2343
|
+
const body = {
|
|
2344
|
+
name,
|
|
2345
|
+
projectKey,
|
|
2346
|
+
type: type ?? null,
|
|
2347
|
+
params: { connection, path: pathFlag?.trim() || "/${projectKey}/${odbId}", },
|
|
2348
|
+
};
|
|
2349
|
+
// Mirrors FoldersResource.create.
|
|
2350
|
+
if (connection === undefined) {
|
|
2351
|
+
return {
|
|
2352
|
+
exact: false,
|
|
2353
|
+
reason: "Without --connection, apply reads DSS admin settings to pick the managed-folder connection (falling back to filesystem_folders); params.connection is set then.",
|
|
2354
|
+
method: "POST",
|
|
2355
|
+
endpoint: projectEndpoint("/managedfolders/"),
|
|
2356
|
+
identifiers: { name, },
|
|
2357
|
+
payload: body,
|
|
2358
|
+
};
|
|
2359
|
+
}
|
|
2470
2360
|
return {
|
|
2471
2361
|
method: "POST",
|
|
2472
2362
|
endpoint: projectEndpoint("/managedfolders/"),
|
|
2473
2363
|
identifiers: { name, },
|
|
2474
|
-
payload:
|
|
2364
|
+
payload: body,
|
|
2475
2365
|
};
|
|
2476
2366
|
}
|
|
2477
2367
|
case "job.abort":
|
|
@@ -2495,18 +2385,22 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2495
2385
|
endpoint: projectEndpoint(`/scenarios/${encodeURIComponent(id)}/`),
|
|
2496
2386
|
identifiers: { id, },
|
|
2497
2387
|
};
|
|
2498
|
-
case "scenario.create":
|
|
2388
|
+
case "scenario.create": {
|
|
2389
|
+
const type = flags["type"] ?? "step_based";
|
|
2499
2390
|
return {
|
|
2500
2391
|
method: "POST",
|
|
2501
2392
|
endpoint: projectEndpoint("/scenarios/"),
|
|
2502
2393
|
identifiers: { id: args[0], name: args[1], },
|
|
2394
|
+
// Mirrors ScenariosResource.create's default params for step-based scenarios.
|
|
2503
2395
|
payload: {
|
|
2504
2396
|
id: args[0],
|
|
2505
2397
|
name: args[1],
|
|
2506
2398
|
projectKey,
|
|
2507
|
-
type
|
|
2399
|
+
type,
|
|
2400
|
+
params: type === "step_based" ? { steps: [], triggers: [], reporters: [], } : {},
|
|
2508
2401
|
},
|
|
2509
2402
|
};
|
|
2403
|
+
}
|
|
2510
2404
|
case "scenario.update":
|
|
2511
2405
|
return {
|
|
2512
2406
|
method: "PUT",
|
|
@@ -2541,6 +2435,8 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2541
2435
|
};
|
|
2542
2436
|
case "variable.set":
|
|
2543
2437
|
return {
|
|
2438
|
+
exact: false,
|
|
2439
|
+
reason: "The payload lists the requested changes; apply PUTs the full {standard, local} object (merged with the current variables unless --replace).",
|
|
2544
2440
|
method: "PUT",
|
|
2545
2441
|
endpoint: projectEndpoint("/variables/"),
|
|
2546
2442
|
payload: {
|
|
@@ -2968,6 +2864,8 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
2968
2864
|
};
|
|
2969
2865
|
case "saved-model.import-mlflow-version-from-folder":
|
|
2970
2866
|
return {
|
|
2867
|
+
exact: false,
|
|
2868
|
+
reason: "Apply sends these values as query parameters (with codeEnvName and binaryClassificationThreshold defaults) on an empty multipart body; the payload shows them structured.",
|
|
2971
2869
|
method: "POST",
|
|
2972
2870
|
endpoint: projectEndpoint(`/savedmodels/${encodeURIComponent(id)}/versions/${encodeURIComponent(args[1] ?? "")}`),
|
|
2973
2871
|
identifiers: { savedModelId: id, versionId: args[1], },
|
|
@@ -3018,7 +2916,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3018
2916
|
}
|
|
3019
2917
|
return {
|
|
3020
2918
|
method: "POST",
|
|
3021
|
-
endpoint: projectEndpoint(`/savedmodels/${encodeURIComponent(id)}/versions/${encodeURIComponent(args[1] ?? "")}/external-ml/actions/evaluate`),
|
|
2919
|
+
endpoint: `${projectEndpoint(`/savedmodels/${encodeURIComponent(id)}/versions/${encodeURIComponent(args[1] ?? "")}/external-ml/actions/evaluate`)}?useOptimalThreshold=${parseBooleanOption(flags["use-optimal-threshold"], "--use-optimal-threshold") ?? true}&skipExpensiveReports=${parseBooleanOption(flags["skip-expensive-reports"], "--skip-expensive-reports") ?? true}`,
|
|
3022
2920
|
identifiers: { savedModelId: id, versionId: args[1], },
|
|
3023
2921
|
payload,
|
|
3024
2922
|
};
|
|
@@ -3217,17 +3115,19 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3217
3115
|
};
|
|
3218
3116
|
case "plugin.create-dev": {
|
|
3219
3117
|
const creationMode = requiredPlanFlag(flags, "creation-mode", entry.usage);
|
|
3118
|
+
const needsGit = creationMode !== "EMPTY";
|
|
3119
|
+
// Mirrors PluginsResource.createDev: git fields are always present, null when unused.
|
|
3220
3120
|
const payload = {
|
|
3221
3121
|
pluginId: id,
|
|
3222
3122
|
creationMode,
|
|
3123
|
+
gitRepository: needsGit && typeof flags["repository"] === "string"
|
|
3124
|
+
? validatedPlanRepositoryUrl(flags["repository"], "repository", "--repository URL")
|
|
3125
|
+
: null,
|
|
3126
|
+
gitCheckout: needsGit && typeof flags["checkout"] === "string" ? flags["checkout"] : null,
|
|
3127
|
+
gitSubpath: creationMode === "GIT_EXPORT" && typeof flags["path-in-repository"] === "string"
|
|
3128
|
+
? flags["path-in-repository"]
|
|
3129
|
+
: null,
|
|
3223
3130
|
};
|
|
3224
|
-
if (typeof flags["repository"] === "string")
|
|
3225
|
-
payload.gitRepository = flags["repository"];
|
|
3226
|
-
if (typeof flags["checkout"] === "string")
|
|
3227
|
-
payload.gitCheckout = flags["checkout"];
|
|
3228
|
-
if (typeof flags["path-in-repository"] === "string") {
|
|
3229
|
-
payload.gitSubpath = flags["path-in-repository"];
|
|
3230
|
-
}
|
|
3231
3131
|
return {
|
|
3232
3132
|
method: "POST",
|
|
3233
3133
|
endpoint: "/public/api/plugins/actions/createDev",
|
|
@@ -3288,14 +3188,13 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3288
3188
|
identifiers: { pluginId: id, path: args[1], },
|
|
3289
3189
|
};
|
|
3290
3190
|
case "plugin.rename": {
|
|
3291
|
-
|
|
3292
|
-
if (!newName)
|
|
3191
|
+
if (!args[2])
|
|
3293
3192
|
throw new UsageError(`Usage: ${entry.usage}`);
|
|
3294
3193
|
return {
|
|
3295
3194
|
method: "POST",
|
|
3296
3195
|
endpoint: `${pluginRootEndpoint(id, "/contents-actions/rename")}`,
|
|
3297
3196
|
identifiers: { pluginId: id, path: args[1], },
|
|
3298
|
-
payload: { oldPath: args[1]
|
|
3197
|
+
payload: { oldPath: `/${validatePluginPath(args[1] ?? "")}`, newName: args[2], },
|
|
3299
3198
|
};
|
|
3300
3199
|
}
|
|
3301
3200
|
case "plugin.move": {
|
|
@@ -3306,7 +3205,10 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3306
3205
|
method: "POST",
|
|
3307
3206
|
endpoint: `${pluginRootEndpoint(id, "/contents-actions/move")}`,
|
|
3308
3207
|
identifiers: { pluginId: id, path: args[1], },
|
|
3309
|
-
payload: {
|
|
3208
|
+
payload: {
|
|
3209
|
+
oldPath: `/${validatePluginPath(args[1] ?? "")}`,
|
|
3210
|
+
newPath: validatePluginDestinationPath(destination),
|
|
3211
|
+
},
|
|
3310
3212
|
};
|
|
3311
3213
|
}
|
|
3312
3214
|
case "business-app.save-settings":
|
|
@@ -3356,6 +3258,8 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3356
3258
|
// plan carries no preflight requests and no fake concrete GET
|
|
3357
3259
|
// path: `{targetProjectKey}` resolves at apply time.
|
|
3358
3260
|
return {
|
|
3261
|
+
exact: false,
|
|
3262
|
+
reason: "targetProjectKey (and targetProjectName when omitted) are generated during apply; the sent body adds them.",
|
|
3359
3263
|
method: "POST",
|
|
3360
3264
|
endpoint: `/public/api/apps/${encodeURIComponent(id)}/instances`,
|
|
3361
3265
|
identifiers: {
|
|
@@ -4037,7 +3941,6 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
4037
3941
|
evaluateProjectStandardsChecks,
|
|
4038
3942
|
}),
|
|
4039
3943
|
identifiers: { bundleId: id, },
|
|
4040
|
-
payload: {},
|
|
4041
3944
|
};
|
|
4042
3945
|
}
|
|
4043
3946
|
case "bundle.publish":
|
|
@@ -4255,7 +4158,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
4255
4158
|
case "code-env.set-jupyter": {
|
|
4256
4159
|
const active = parseBooleanOption(flags["active"], "--active");
|
|
4257
4160
|
if (active === undefined) {
|
|
4258
|
-
throw new UsageError(
|
|
4161
|
+
throw new UsageError(`--active is required. Usage: ${commandUsage("code-env", "set-jupyter")}`);
|
|
4259
4162
|
}
|
|
4260
4163
|
const wait = codeEnvWait(flags);
|
|
4261
4164
|
return {
|
|
@@ -4890,7 +4793,7 @@ export function buildMutationPlan(resource, action, meta, args, flags) {
|
|
|
4890
4793
|
if (!entry.mutatesDss && entry.sideEffect !== "write") {
|
|
4891
4794
|
throw new UsageError(`--plan is only supported for mutating commands. Usage: ${meta.usage}`);
|
|
4892
4795
|
}
|
|
4893
|
-
const requiredPositionals =
|
|
4796
|
+
const requiredPositionals = entry.positionalArguments.filter((positional) => positional.required);
|
|
4894
4797
|
requireArgs(args, requiredPositionals.length, meta.usage);
|
|
4895
4798
|
const projectKey = projectKeyForPlan(entry, flags);
|
|
4896
4799
|
const shape = commandPlanShape(resource, action, args, flags, entry, projectKey);
|
|
@@ -4914,7 +4817,7 @@ export const BATCH_PLAN_EXIT_CODES = {
|
|
|
4914
4817
|
longRunningFailure: 4,
|
|
4915
4818
|
assertionFailure: 4,
|
|
4916
4819
|
};
|
|
4917
|
-
export const BATCH_USAGE = "
|
|
4820
|
+
export const BATCH_USAGE = commandUsage("batch", "run");
|
|
4918
4821
|
const BATCH_DESCRIPTION = "Run dss argv arrays fail-fast by default. The result aggregates failed/retryable/failureCodes; process exit remains the first failed step's exit code.";
|
|
4919
4822
|
export const BATCH_HINT = 'Pass a JSON array of argv arrays, e.g. [["dataset","list"],["recipe","update","r","--data-file","p.json"]].';
|
|
4920
4823
|
export const BATCH_EXAMPLE_PAYLOAD = [
|