dataiku-sdk 3.1.0 → 3.2.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 +124 -12
- package/dist/build-metadata.json +1 -1
- package/dist/src/auth.js +1 -1
- package/dist/src/cli/coerce.js +11 -2
- package/dist/src/cli/commands/analysis.js +4 -3
- package/dist/src/cli/commands/api-service.js +5 -3
- package/dist/src/cli/commands/app.js +4 -3
- package/dist/src/cli/commands/bundle.js +2 -1
- package/dist/src/cli/commands/code-env.js +10 -9
- package/dist/src/cli/commands/dashboard.js +7 -6
- package/dist/src/cli/commands/data-quality.js +9 -8
- package/dist/src/cli/commands/dataset.js +9 -8
- package/dist/src/cli/commands/doctor.js +4 -2
- package/dist/src/cli/commands/flow-zone.js +9 -8
- package/dist/src/cli/commands/folder.js +9 -8
- package/dist/src/cli/commands/future.js +2 -1
- package/dist/src/cli/commands/insight.js +8 -7
- package/dist/src/cli/commands/job.js +4 -3
- package/dist/src/cli/commands/meaning.js +5 -4
- package/dist/src/cli/commands/ml-task.js +3 -2
- package/dist/src/cli/commands/model-evaluation-store.js +4 -3
- package/dist/src/cli/commands/notebook.js +11 -10
- package/dist/src/cli/commands/project-library.js +7 -6
- package/dist/src/cli/commands/project.js +3 -2
- package/dist/src/cli/commands/recipe.js +14 -13
- package/dist/src/cli/commands/saved-model.js +4 -3
- package/dist/src/cli/commands/scenario.js +9 -8
- package/dist/src/cli/commands/sql.js +3 -2
- package/dist/src/cli/commands/statistics.js +7 -6
- package/dist/src/cli/commands/variable.js +2 -1
- package/dist/src/cli/commands/webapp.js +2 -1
- package/dist/src/cli/commands/wiki.js +7 -6
- package/dist/src/cli/contract.d.ts +1 -1
- package/dist/src/cli/contract.js +100 -82
- package/dist/src/cli/flags.d.ts +4 -0
- package/dist/src/cli/flags.js +20 -1
- package/dist/src/cli.js +92 -68
- package/dist/src/client.d.ts +3 -1
- package/dist/src/client.js +78 -21
- package/dist/src/errors.js +2 -0
- package/dist/src/resources/folders.js +2 -1
- package/dist/src/resources/projects.d.ts +0 -2
- package/dist/src/resources/projects.js +3 -17
- package/dist/src/resources/sql.js +1 -1
- package/dist/src/skill.d.ts +13 -4
- package/dist/src/skill.js +75 -24
- package/dist/src/utils/response-file.d.ts +2 -0
- package/dist/src/utils/response-file.js +34 -0
- package/package.json +6 -4
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +44 -224
- package/skills/dataiku-dss/references/app-releases.md +27 -0
- package/skills/dataiku-dss/references/authentication.md +39 -0
- package/skills/dataiku-dss/references/coding.md +8 -0
- package/skills/dataiku-dss/references/discovery.md +30 -0
- package/skills/dataiku-dss/references/flow-maps.md +12 -0
- package/skills/dataiku-dss/references/mutations.md +33 -0
- package/skills/dataiku-dss/references/troubleshooting.md +29 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { scenarioUpdatePreview, } from "../../resources/scenarios.js";
|
|
2
2
|
import { jsonInput, num, } from "../coerce.js";
|
|
3
|
+
import { executionMode, } from "../flags.js";
|
|
3
4
|
import { encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
|
|
4
5
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
5
6
|
export const scenarioCommands = {
|
|
@@ -26,7 +27,7 @@ export const scenarioCommands = {
|
|
|
26
27
|
pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
|
|
27
28
|
timeoutMs: num(f["timeout"], "--timeout"),
|
|
28
29
|
};
|
|
29
|
-
if (f
|
|
30
|
+
if (executionMode(f).dryRun) {
|
|
30
31
|
return {
|
|
31
32
|
dryRun: true,
|
|
32
33
|
action: "run",
|
|
@@ -54,7 +55,7 @@ export const scenarioCommands = {
|
|
|
54
55
|
pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
|
|
55
56
|
timeoutMs: num(f["timeout"], "--timeout"),
|
|
56
57
|
};
|
|
57
|
-
if (f
|
|
58
|
+
if (executionMode(f).dryRun) {
|
|
58
59
|
return {
|
|
59
60
|
dryRun: true,
|
|
60
61
|
action: "run-and-wait",
|
|
@@ -87,11 +88,11 @@ export const scenarioCommands = {
|
|
|
87
88
|
handler: async (c, a, f) => {
|
|
88
89
|
requireArgs(a, 1, "dss scenario delete <id>");
|
|
89
90
|
const pk = f["project-key"];
|
|
90
|
-
if (f
|
|
91
|
+
if (executionMode(f).dryRun || f["if-exists"] === true) {
|
|
91
92
|
const current = await readIfExists(() => c.scenarios.get(a[0], { projectKey: pk, }));
|
|
92
93
|
if (!current)
|
|
93
94
|
return skipResult("scenario", a[0], "missing");
|
|
94
|
-
if (f
|
|
95
|
+
if (executionMode(f).dryRun) {
|
|
95
96
|
return { dryRun: true, action: "delete", resource: "scenario", id: a[0], current, };
|
|
96
97
|
}
|
|
97
98
|
}
|
|
@@ -112,13 +113,13 @@ export const scenarioCommands = {
|
|
|
112
113
|
scenarioType: f["type"],
|
|
113
114
|
projectKey: pk,
|
|
114
115
|
};
|
|
115
|
-
if (f["if-not-exists"] === true || f
|
|
116
|
+
if (f["if-not-exists"] === true || executionMode(f).dryRun) {
|
|
116
117
|
const list = await c.scenarios.list(pk);
|
|
117
118
|
const existing = list.find((s) => s.id === a[0]);
|
|
118
|
-
if (existing && f["if-not-exists"] === true && f
|
|
119
|
+
if (existing && f["if-not-exists"] === true && !executionMode(f).dryRun) {
|
|
119
120
|
return skipResult("scenario", a[0], "exists", { current: existing, });
|
|
120
121
|
}
|
|
121
|
-
if (f
|
|
122
|
+
if (executionMode(f).dryRun) {
|
|
122
123
|
return {
|
|
123
124
|
dryRun: true,
|
|
124
125
|
action: "create",
|
|
@@ -150,7 +151,7 @@ export const scenarioCommands = {
|
|
|
150
151
|
throw new UsageError("--data, --data-file, or --stdin is required. Usage: dss scenario update <id> [--data '{...}' | --data-file PATH | --stdin]");
|
|
151
152
|
}
|
|
152
153
|
const pk = f["project-key"];
|
|
153
|
-
if (f
|
|
154
|
+
if (executionMode(f).dryRun) {
|
|
154
155
|
const current = await c.scenarios.get(a[0], { projectKey: pk, });
|
|
155
156
|
const preview = scenarioUpdatePreview(current, data);
|
|
156
157
|
return {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFileSync, } from "node:fs";
|
|
2
|
-
import { mkdir,
|
|
2
|
+
import { mkdir, } from "node:fs/promises";
|
|
3
3
|
import { dirname, resolve, } from "node:path";
|
|
4
|
+
import { writeResponseToFile, } from "../../utils/response-file.js";
|
|
4
5
|
import { readStdinText, stripUtf8Bom, } from "../coerce.js";
|
|
5
6
|
import { enqueueCliWarning, } from "../output.js";
|
|
6
7
|
import { UsageError, } from "../usage.js";
|
|
@@ -121,7 +122,7 @@ export const sqlCommands = {
|
|
|
121
122
|
}
|
|
122
123
|
const outputPath = resolve(outputFile);
|
|
123
124
|
await mkdir(dirname(outputPath), { recursive: true, });
|
|
124
|
-
await
|
|
125
|
+
await writeResponseToFile(outputPath, new Response(`${JSON.stringify(result, null, 2)}\n`), "preserve");
|
|
125
126
|
return {
|
|
126
127
|
queryId: result.queryId,
|
|
127
128
|
schema: result.schema,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { requiredJsonInput, } from "../coerce.js";
|
|
2
|
+
import { executionMode, } from "../flags.js";
|
|
2
3
|
import { encodedProjectEndpoint, planResult, } from "../output.js";
|
|
3
4
|
import { requireArgs, } from "../usage.js";
|
|
4
5
|
const STATISTICS_PLAN_EXIT_CODES = { usage: 1, error: 2, transient: 3, };
|
|
@@ -51,7 +52,7 @@ export const statisticsCommands = {
|
|
|
51
52
|
requireArgs(a, 1, "dss statistics create-worksheet <dataset> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]");
|
|
52
53
|
const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (worksheet definition).");
|
|
53
54
|
const projectKey = f["project-key"];
|
|
54
|
-
if (f
|
|
55
|
+
if (executionMode(f).dryRun) {
|
|
55
56
|
return statisticsPlan("create-worksheet", {
|
|
56
57
|
method: "POST",
|
|
57
58
|
endpoint: statisticsWorksheetsEndpoint(c, a[0], projectKey),
|
|
@@ -72,7 +73,7 @@ export const statisticsCommands = {
|
|
|
72
73
|
requireArgs(a, 2, "dss statistics update-worksheet <dataset> <worksheetId> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]");
|
|
73
74
|
const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (worksheet definition).");
|
|
74
75
|
const projectKey = f["project-key"];
|
|
75
|
-
if (f
|
|
76
|
+
if (executionMode(f).dryRun) {
|
|
76
77
|
return statisticsPlan("update-worksheet", {
|
|
77
78
|
method: "PUT",
|
|
78
79
|
endpoint: statisticsWorksheetEndpoint(c, a[0], a[1], projectKey),
|
|
@@ -90,7 +91,7 @@ export const statisticsCommands = {
|
|
|
90
91
|
handler: async (c, a, f) => {
|
|
91
92
|
requireArgs(a, 2, "dss statistics delete-worksheet <dataset> <worksheetId> [--dry-run] [--project-key KEY]");
|
|
92
93
|
const projectKey = f["project-key"];
|
|
93
|
-
if (f
|
|
94
|
+
if (executionMode(f).dryRun) {
|
|
94
95
|
return statisticsPlan("delete-worksheet", {
|
|
95
96
|
method: "DELETE",
|
|
96
97
|
endpoint: statisticsWorksheetEndpoint(c, a[0], a[1], projectKey),
|
|
@@ -108,7 +109,7 @@ export const statisticsCommands = {
|
|
|
108
109
|
handler: async (c, a, f) => {
|
|
109
110
|
requireArgs(a, 2, "dss statistics run-worksheet <dataset> <worksheetId> [--dry-run] [--project-key KEY]");
|
|
110
111
|
const projectKey = f["project-key"];
|
|
111
|
-
if (f
|
|
112
|
+
if (executionMode(f).dryRun) {
|
|
112
113
|
return statisticsPlan("run-worksheet", {
|
|
113
114
|
method: "POST",
|
|
114
115
|
endpoint: `${statisticsWorksheetEndpoint(c, a[0], a[1], projectKey)}/actions/run-card`,
|
|
@@ -127,7 +128,7 @@ export const statisticsCommands = {
|
|
|
127
128
|
requireArgs(a, 2, "dss statistics run-card <dataset> <worksheetId> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]");
|
|
128
129
|
const card = requiredJsonInput(f, "--data, --data-file, or --stdin is required (card settings).");
|
|
129
130
|
const projectKey = f["project-key"];
|
|
130
|
-
if (f
|
|
131
|
+
if (executionMode(f).dryRun) {
|
|
131
132
|
return statisticsPlan("run-card", {
|
|
132
133
|
method: "POST",
|
|
133
134
|
endpoint: `${statisticsWorksheetEndpoint(c, a[0], a[1], projectKey)}/actions/run-card`,
|
|
@@ -147,7 +148,7 @@ export const statisticsCommands = {
|
|
|
147
148
|
requireArgs(a, 2, "dss statistics run-computation <dataset> <worksheetId> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]");
|
|
148
149
|
const computation = requiredJsonInput(f, "--data, --data-file, or --stdin is required (computation settings).");
|
|
149
150
|
const projectKey = f["project-key"];
|
|
150
|
-
if (f
|
|
151
|
+
if (executionMode(f).dryRun) {
|
|
151
152
|
return statisticsPlan("run-computation", {
|
|
152
153
|
method: "POST",
|
|
153
154
|
endpoint: `${statisticsWorksheetEndpoint(c, a[0], a[1], projectKey)}/actions/run-computation`,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { json, } from "../coerce.js";
|
|
2
|
+
import { executionMode, } from "../flags.js";
|
|
2
3
|
import { UsageError, } from "../usage.js";
|
|
3
4
|
export const variableCommands = {
|
|
4
5
|
get: {
|
|
@@ -15,7 +16,7 @@ export const variableCommands = {
|
|
|
15
16
|
if (standard === undefined && local === undefined) {
|
|
16
17
|
throw new UsageError("--standard and/or --local is required.");
|
|
17
18
|
}
|
|
18
|
-
if (f
|
|
19
|
+
if (executionMode(f).dryRun) {
|
|
19
20
|
const current = await c.variables.get(pk);
|
|
20
21
|
const next = f["replace"] === true
|
|
21
22
|
? { standard: standard ?? {}, local: local ?? {}, }
|
|
@@ -2,6 +2,7 @@ import { ClientValidationError, } from "../../errors.js";
|
|
|
2
2
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
3
3
|
import { stableHash, } from "../../utils/stable-hash.js";
|
|
4
4
|
import { num, requiredJsonInput, } from "../coerce.js";
|
|
5
|
+
import { executionMode, } from "../flags.js";
|
|
5
6
|
import { requireArgs, } from "../usage.js";
|
|
6
7
|
const UPDATE_SETTINGS_USAGE = "dss webapp update-settings <webappId> (--data JSON|--data-file PATH|--stdin) [--expect-hash SHA256] [--dry-run] [--project-key KEY]";
|
|
7
8
|
const RESTART_USAGE = "dss webapp restart-backend <webappId> [--wait] [--timeout MS] [--poll-interval MS] [--project-key KEY]";
|
|
@@ -44,7 +45,7 @@ export const webappCommands = {
|
|
|
44
45
|
const body = requiredJsonInput(f, "--data, --data-file, or --stdin is required (webapp settings).");
|
|
45
46
|
const projectKey = f["project-key"];
|
|
46
47
|
const expectHash = validateExpectHash(f["expect-hash"]);
|
|
47
|
-
if (f
|
|
48
|
+
if (executionMode(f).dryRun) {
|
|
48
49
|
const current = await c.webapps.getSettings(a[0], projectKey);
|
|
49
50
|
const currentHash = stableHash(current);
|
|
50
51
|
if (expectHash !== undefined && currentHash !== expectHash.toLowerCase()) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deepMerge, } from "../../utils/deep-merge.js";
|
|
2
2
|
import { jsonInput, textInput, } from "../coerce.js";
|
|
3
|
+
import { executionMode, } from "../flags.js";
|
|
3
4
|
import { readIfExists, skipResult, } from "../output.js";
|
|
4
5
|
import { requireArgs, UsageError, } from "../usage.js";
|
|
5
6
|
export const wikiCommands = {
|
|
@@ -31,12 +32,12 @@ export const wikiCommands = {
|
|
|
31
32
|
throw new UsageError("--name is required. Usage: dss wiki create --name NAME");
|
|
32
33
|
const content = textInput(f);
|
|
33
34
|
const pk = f["project-key"];
|
|
34
|
-
if (f["if-not-exists"] === true || f
|
|
35
|
+
if (f["if-not-exists"] === true || executionMode(f).dryRun) {
|
|
35
36
|
const existing = (await c.wiki.list(pk)).find((article) => article.article.name === name);
|
|
36
|
-
if (existing && f["if-not-exists"] === true && f
|
|
37
|
+
if (existing && f["if-not-exists"] === true && !executionMode(f).dryRun) {
|
|
37
38
|
return skipResult("wiki", existing.article.id, "exists", { current: existing, });
|
|
38
39
|
}
|
|
39
|
-
if (f
|
|
40
|
+
if (executionMode(f).dryRun) {
|
|
40
41
|
return {
|
|
41
42
|
dryRun: true,
|
|
42
43
|
action: "create",
|
|
@@ -75,7 +76,7 @@ export const wikiCommands = {
|
|
|
75
76
|
if (!data && content === undefined && name === undefined) {
|
|
76
77
|
throw new UsageError("--name, --content, --file, --data, --data-file, or --stdin is required.");
|
|
77
78
|
}
|
|
78
|
-
if (f
|
|
79
|
+
if (executionMode(f).dryRun) {
|
|
79
80
|
const current = await c.wiki.get(a[0], f["project-key"]);
|
|
80
81
|
const next = deepMerge(current, data ?? {});
|
|
81
82
|
if (name !== undefined) {
|
|
@@ -105,11 +106,11 @@ export const wikiCommands = {
|
|
|
105
106
|
handler: async (c, a, f) => {
|
|
106
107
|
requireArgs(a, 1, "dss wiki delete <id-or-name>");
|
|
107
108
|
const pk = f["project-key"];
|
|
108
|
-
if (f
|
|
109
|
+
if (executionMode(f).dryRun || f["if-exists"] === true) {
|
|
109
110
|
const current = await readIfExists(() => c.wiki.get(a[0], pk));
|
|
110
111
|
if (!current)
|
|
111
112
|
return skipResult("wiki", a[0], "missing");
|
|
112
|
-
if (f
|
|
113
|
+
if (executionMode(f).dryRun) {
|
|
113
114
|
return { dryRun: true, action: "delete", resource: "wiki", article: a[0], current, };
|
|
114
115
|
}
|
|
115
116
|
}
|
|
@@ -103,7 +103,7 @@ export declare function inferRequiresProject(resource: string, action: string, u
|
|
|
103
103
|
export declare function inferInputContract(usage: string): CommandInputContract;
|
|
104
104
|
export declare function supportsCleanupLedger(resource: string, action: string): boolean;
|
|
105
105
|
export declare function inferCleanupHint(resource: string, action: string): string | undefined;
|
|
106
|
-
export declare function buildCommandRegistry(): Record<string, Record<string, CommandRegistryEntry>>;
|
|
106
|
+
export declare function buildCommandRegistry(resourceFilter?: string): Record<string, Record<string, CommandRegistryEntry>>;
|
|
107
107
|
export declare function agentContractJsonSchema(): Record<string, unknown>;
|
|
108
108
|
export declare function commandActionSummary(registry: Record<string, Record<string, CommandRegistryEntry>>): Record<string, string[]>;
|
|
109
109
|
export declare function buildAgentContract(): Record<string, unknown>;
|
package/dist/src/cli/contract.js
CHANGED
|
@@ -13,7 +13,7 @@ import { commands, } from "./commands/index.js";
|
|
|
13
13
|
import { projectLibraryPutPayload, } from "./commands/project-library.js";
|
|
14
14
|
import { resolveSqlQueryInvocation, } from "./commands/sql.js";
|
|
15
15
|
import { dataikuEnvironmentEnabled, } from "./env.js";
|
|
16
|
-
import { BOOLEAN_FLAGS, FLAG_ALIASES, KNOWN_LONG_FLAGS, SHORT_FLAGS, } from "./flags.js";
|
|
16
|
+
import { BOOLEAN_FLAGS, executionMode, FLAG_ALIASES, KNOWN_LONG_FLAGS, SHORT_FLAGS, } from "./flags.js";
|
|
17
17
|
import { flowZoneColor, flowZoneMoveItems, flowZoneName, } from "./helpers/flow-zone.js";
|
|
18
18
|
import { recipeBackupPath, recipeRunShouldWait, } from "./helpers/recipe.js";
|
|
19
19
|
import { encodedProjectEndpointForPlan, planResult, } from "./output.js";
|
|
@@ -749,11 +749,11 @@ function unsafeOutputs(resource, action, producesLocalFile) {
|
|
|
749
749
|
condition: "--output or --output-file",
|
|
750
750
|
kind: "local-file",
|
|
751
751
|
detail: sensitivePermissions
|
|
752
|
-
? "
|
|
753
|
-
: "
|
|
752
|
+
? "Writes access-control identities and permissions to an owner-only local file."
|
|
753
|
+
: "Writes a local file; stdout contains JSON metadata.",
|
|
754
754
|
...(sensitivePermissions
|
|
755
755
|
? {
|
|
756
|
-
safeAlternative: "Keep
|
|
756
|
+
safeAlternative: "Keep owner-only and outside version control unless repository policy explicitly permits committing access-control data.",
|
|
757
757
|
}
|
|
758
758
|
: {}),
|
|
759
759
|
});
|
|
@@ -1293,10 +1293,10 @@ export function inferCleanupHint(resource, action) {
|
|
|
1293
1293
|
return undefined;
|
|
1294
1294
|
const key = `${resource}.${action}`;
|
|
1295
1295
|
if (key === "notebook.save-jupyter") {
|
|
1296
|
-
return "
|
|
1296
|
+
return "If created:true, delete with `dss notebook delete-jupyter <name> --if-exists`.";
|
|
1297
1297
|
}
|
|
1298
1298
|
if (key === "notebook.save-sql") {
|
|
1299
|
-
return "
|
|
1299
|
+
return "If created:true, delete with `dss notebook delete-sql <id> --if-exists`.";
|
|
1300
1300
|
}
|
|
1301
1301
|
if (!(action.startsWith("create") || action === "clone"))
|
|
1302
1302
|
return undefined;
|
|
@@ -1317,7 +1317,7 @@ export function inferCleanupHint(resource, action) {
|
|
|
1317
1317
|
if (resource === "data-quality") {
|
|
1318
1318
|
return `Delete with \`dss data-quality delete-rule <dataset> <rule-id>${ifExists}\`.`;
|
|
1319
1319
|
}
|
|
1320
|
-
return `
|
|
1320
|
+
return `For disposable creates: \`dss ${resource} delete <id>${ifExists}\`.`;
|
|
1321
1321
|
}
|
|
1322
1322
|
function buildRegistryEntry(resource, action, meta) {
|
|
1323
1323
|
const requiresAuth = meta.localHandler === undefined && inferRequiresAuth(resource);
|
|
@@ -1427,81 +1427,99 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
1427
1427
|
agentContractVersion: AGENT_CONTRACT_VERSION,
|
|
1428
1428
|
};
|
|
1429
1429
|
}
|
|
1430
|
-
export function buildCommandRegistry() {
|
|
1430
|
+
export function buildCommandRegistry(resourceFilter) {
|
|
1431
1431
|
const registry = {};
|
|
1432
1432
|
for (const [resource, actions,] of Object.entries(commands)) {
|
|
1433
|
+
if (resourceFilter !== undefined && resource !== resourceFilter)
|
|
1434
|
+
continue;
|
|
1433
1435
|
registry[resource] = {};
|
|
1434
1436
|
for (const [action, meta,] of Object.entries(actions)) {
|
|
1435
1437
|
registry[resource][action] = buildRegistryEntry(resource, action, meta);
|
|
1436
1438
|
}
|
|
1437
1439
|
}
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1440
|
+
if (resourceFilter === undefined || resourceFilter === "commands") {
|
|
1441
|
+
registry.commands = {
|
|
1442
|
+
run: buildRegistryEntry("commands", "run", {
|
|
1443
|
+
handler: async () => undefined,
|
|
1444
|
+
usage: COMMANDS_USAGE,
|
|
1445
|
+
description: COMMANDS_DESCRIPTION,
|
|
1446
|
+
examples: COMMANDS_EXAMPLES,
|
|
1447
|
+
}),
|
|
1448
|
+
};
|
|
1449
|
+
}
|
|
1450
|
+
if (resourceFilter === undefined || resourceFilter === "agent") {
|
|
1451
|
+
registry.agent = {
|
|
1452
|
+
contract: buildRegistryEntry("agent", "contract", {
|
|
1453
|
+
handler: async () => undefined,
|
|
1454
|
+
usage: AGENT_CONTRACT_USAGE,
|
|
1455
|
+
description: AGENT_CONTRACT_DESCRIPTION,
|
|
1456
|
+
examples: AGENT_CONTRACT_EXAMPLES,
|
|
1457
|
+
}),
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
if (resourceFilter === undefined || resourceFilter === "version") {
|
|
1461
|
+
registry.version = {
|
|
1462
|
+
run: buildRegistryEntry("version", "run", {
|
|
1463
|
+
handler: async () => undefined,
|
|
1464
|
+
usage: VERSION_USAGE,
|
|
1465
|
+
description: VERSION_DESCRIPTION,
|
|
1466
|
+
examples: VERSION_EXAMPLES,
|
|
1467
|
+
}),
|
|
1468
|
+
};
|
|
1469
|
+
}
|
|
1470
|
+
if (resourceFilter === undefined || resourceFilter === "install-skill") {
|
|
1471
|
+
registry["install-skill"] = {
|
|
1472
|
+
run: buildRegistryEntry("install-skill", "run", {
|
|
1473
|
+
handler: async () => undefined,
|
|
1474
|
+
usage: INSTALL_SKILL_USAGE,
|
|
1475
|
+
description: INSTALL_SKILL_DESCRIPTION,
|
|
1476
|
+
examples: INSTALL_SKILL_EXAMPLES,
|
|
1477
|
+
}),
|
|
1478
|
+
};
|
|
1479
|
+
}
|
|
1480
|
+
if (resourceFilter === undefined || resourceFilter === "cleanup") {
|
|
1481
|
+
registry.cleanup = {
|
|
1482
|
+
run: buildRegistryEntry("cleanup", "run", {
|
|
1483
|
+
handler: async () => undefined,
|
|
1484
|
+
usage: CLEANUP_USAGE,
|
|
1485
|
+
description: CLEANUP_DESCRIPTION,
|
|
1486
|
+
examples: CLEANUP_EXAMPLES,
|
|
1487
|
+
}),
|
|
1488
|
+
};
|
|
1489
|
+
}
|
|
1490
|
+
if (resourceFilter === undefined || resourceFilter === "fixtures") {
|
|
1491
|
+
registry.fixtures = {
|
|
1492
|
+
run: buildRegistryEntry("fixtures", "run", {
|
|
1493
|
+
handler: async () => undefined,
|
|
1494
|
+
usage: FIXTURES_USAGE,
|
|
1495
|
+
description: FIXTURES_DESCRIPTION,
|
|
1496
|
+
examples: FIXTURES_EXAMPLES,
|
|
1497
|
+
}),
|
|
1498
|
+
};
|
|
1499
|
+
}
|
|
1500
|
+
if (resourceFilter === undefined || resourceFilter === "batch") {
|
|
1501
|
+
registry.batch = {
|
|
1502
|
+
run: buildRegistryEntry("batch", "run", {
|
|
1503
|
+
handler: async () => undefined,
|
|
1504
|
+
usage: BATCH_USAGE,
|
|
1505
|
+
description: BATCH_DESCRIPTION,
|
|
1506
|
+
examples: BATCH_EXAMPLES,
|
|
1507
|
+
examplePayload: BATCH_EXAMPLE_PAYLOAD,
|
|
1508
|
+
payloadSchema: { stdin: true, dataFlag: true, dataFileFlag: true, jsonShape: "array", },
|
|
1509
|
+
}),
|
|
1510
|
+
};
|
|
1511
|
+
}
|
|
1512
|
+
if (resourceFilter === undefined || resourceFilter === "auth") {
|
|
1513
|
+
registry.auth = {};
|
|
1514
|
+
for (const [action, meta,] of Object.entries(AUTH_ACTIONS)) {
|
|
1515
|
+
registry.auth[action] = buildRegistryEntry("auth", action, {
|
|
1516
|
+
handler: async () => undefined,
|
|
1517
|
+
usage: meta.usage,
|
|
1518
|
+
description: meta.description,
|
|
1519
|
+
examples: meta.examples,
|
|
1520
|
+
requiredFlags: meta.requiredFlags,
|
|
1521
|
+
});
|
|
1522
|
+
}
|
|
1505
1523
|
}
|
|
1506
1524
|
return registry;
|
|
1507
1525
|
}
|
|
@@ -1680,7 +1698,7 @@ export function buildAgentContract() {
|
|
|
1680
1698
|
"dss commands run --fields dataset",
|
|
1681
1699
|
"dss commands run --fields dataset.create",
|
|
1682
1700
|
],
|
|
1683
|
-
scopedDiscoveryHint: "
|
|
1701
|
+
scopedDiscoveryHint: "Default: resource/action summary. --fields RESOURCE: all resource entries; RESOURCE.ACTION: one entry keyed by that path; append .FIELD for nested metadata. Comma-separate paths. --output PATH exports the full registry.",
|
|
1684
1702
|
actions: commandActionSummary(registry),
|
|
1685
1703
|
},
|
|
1686
1704
|
schemas: {
|
|
@@ -1697,8 +1715,8 @@ export function buildAgentContract() {
|
|
|
1697
1715
|
success: "single-json-value",
|
|
1698
1716
|
failure: "structured-error-object",
|
|
1699
1717
|
failureResultDetailLimitBytes: 65_536,
|
|
1700
|
-
fieldProjection: "Missing --fields paths
|
|
1701
|
-
richFailureResults: "doctor/batch/cleanup
|
|
1718
|
+
fieldProjection: "Missing --fields paths: null on stdout; field_projection_missing on stderr.",
|
|
1719
|
+
richFailureResults: "doctor/batch/cleanup failures: own compact {ok:false,...} result on stdout and command exit code; no wrapper.",
|
|
1702
1720
|
},
|
|
1703
1721
|
stderr: {
|
|
1704
1722
|
format: "jsonl",
|
|
@@ -1715,7 +1733,7 @@ export function buildAgentContract() {
|
|
|
1715
1733
|
},
|
|
1716
1734
|
compatibility: {
|
|
1717
1735
|
fieldsAreAdditiveWithinMajor: true,
|
|
1718
|
-
failFastWhenUnsupported: "Check agentContractVersion before planning
|
|
1736
|
+
failFastWhenUnsupported: "Check agentContractVersion before planning.",
|
|
1719
1737
|
},
|
|
1720
1738
|
};
|
|
1721
1739
|
}
|
|
@@ -3654,7 +3672,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3654
3672
|
wait: true,
|
|
3655
3673
|
})}`;
|
|
3656
3674
|
const guarded = flags["if-exists"] === true
|
|
3657
|
-
|| flags
|
|
3675
|
+
|| executionMode(flags).dryRun
|
|
3658
3676
|
|| expectedProjectIncarnation !== undefined;
|
|
3659
3677
|
if (!guarded) {
|
|
3660
3678
|
return {
|
|
@@ -3671,7 +3689,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
|
|
|
3671
3689
|
provided: true,
|
|
3672
3690
|
expectedHash: expectedProjectIncarnation,
|
|
3673
3691
|
};
|
|
3674
|
-
if (flags
|
|
3692
|
+
if (executionMode(flags).dryRun) {
|
|
3675
3693
|
return {
|
|
3676
3694
|
method: "GET",
|
|
3677
3695
|
endpoint: projectProbe,
|
|
@@ -4080,7 +4098,7 @@ export function buildMutationPlan(resource, action, meta, args, flags) {
|
|
|
4080
4098
|
asyncKind: entry.async,
|
|
4081
4099
|
exitCodesOnFailure: exitCodesOnFailure(entry),
|
|
4082
4100
|
idempotency: entry.idempotency,
|
|
4083
|
-
plannedAndDryRun: flags
|
|
4101
|
+
plannedAndDryRun: executionMode(flags).dryRun,
|
|
4084
4102
|
});
|
|
4085
4103
|
}
|
|
4086
4104
|
/**
|
package/dist/src/cli/flags.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
export declare function executionMode(flags: Record<string, string | boolean>): {
|
|
2
|
+
readonly plan: boolean;
|
|
3
|
+
readonly dryRun: boolean;
|
|
4
|
+
};
|
|
1
5
|
export declare const BOOLEAN_FLAGS: Set<string>;
|
|
2
6
|
export declare const SHORT_FLAGS: Record<string, string>;
|
|
3
7
|
/** Long-flag aliases: these are normalized to the canonical name in parseArgs. */
|
package/dist/src/cli/flags.js
CHANGED
|
@@ -1,4 +1,17 @@
|
|
|
1
|
+
import { parseBooleanOption, } from "./coerce.js";
|
|
1
2
|
import { unsupportedHelpFlag, UsageError, } from "./usage.js";
|
|
3
|
+
/** Planning wins dispatch; dryRun remains set for combined plan metadata. */
|
|
4
|
+
const EXECUTION_MODES = [
|
|
5
|
+
Object.freeze({ plan: false, dryRun: false, }),
|
|
6
|
+
Object.freeze({ plan: false, dryRun: true, }),
|
|
7
|
+
Object.freeze({ plan: true, dryRun: false, }),
|
|
8
|
+
Object.freeze({ plan: true, dryRun: true, }),
|
|
9
|
+
];
|
|
10
|
+
export function executionMode(flags) {
|
|
11
|
+
const plan = parseBooleanOption(flags["plan"], "--plan") ?? false;
|
|
12
|
+
const dryRun = parseBooleanOption(flags["dry-run"], "--dry-run") ?? false;
|
|
13
|
+
return EXECUTION_MODES[(plan ? 2 : 0) + (dryRun ? 1 : 0)];
|
|
14
|
+
}
|
|
2
15
|
export const BOOLEAN_FLAGS = new Set([
|
|
3
16
|
"verbose",
|
|
4
17
|
"version",
|
|
@@ -273,7 +286,13 @@ export function parseArgs(argv) {
|
|
|
273
286
|
if (eqIdx !== -1) {
|
|
274
287
|
const raw = arg.slice(2, eqIdx);
|
|
275
288
|
const flagName = normalizeLongFlag(raw);
|
|
276
|
-
|
|
289
|
+
const value = arg.slice(eqIdx + 1);
|
|
290
|
+
if (BOOLEAN_FLAGS.has(flagName)) {
|
|
291
|
+
flags[flagName] = parseBooleanOption(value, `--${flagName}`);
|
|
292
|
+
}
|
|
293
|
+
else {
|
|
294
|
+
setParsedFlagValue(flags, flagName, value);
|
|
295
|
+
}
|
|
277
296
|
}
|
|
278
297
|
else {
|
|
279
298
|
const rawFlagName = arg.slice(2);
|