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.
Files changed (131) hide show
  1. package/README.md +4 -4
  2. package/bin/dss.js +28 -2
  3. package/dist/build-metadata.json +1 -1
  4. package/dist/src/cli/coerce.d.ts +0 -1
  5. package/dist/src/cli/coerce.js +0 -5
  6. package/dist/src/cli/command-syntax.json +14524 -0
  7. package/dist/src/cli/commands/analysis.js +6 -9
  8. package/dist/src/cli/commands/api-deployer.js +15 -33
  9. package/dist/src/cli/commands/api-service.js +17 -27
  10. package/dist/src/cli/commands/app.js +25 -41
  11. package/dist/src/cli/commands/bundle.js +15 -24
  12. package/dist/src/cli/commands/business-app.js +10 -17
  13. package/dist/src/cli/commands/code-env.js +23 -36
  14. package/dist/src/cli/commands/code.js +4 -4
  15. package/dist/src/cli/commands/connection.js +12 -22
  16. package/dist/src/cli/commands/continuous-activity.js +6 -9
  17. package/dist/src/cli/commands/dashboard.js +8 -13
  18. package/dist/src/cli/commands/data-collection.js +9 -16
  19. package/dist/src/cli/commands/data-quality.js +14 -26
  20. package/dist/src/cli/commands/dataset.js +29 -54
  21. package/dist/src/cli/commands/discussion.js +7 -10
  22. package/dist/src/cli/commands/doctor.js +3 -3
  23. package/dist/src/cli/commands/flow-zone.js +8 -17
  24. package/dist/src/cli/commands/folder.js +12 -20
  25. package/dist/src/cli/commands/future.js +7 -10
  26. package/dist/src/cli/commands/group.js +7 -11
  27. package/dist/src/cli/commands/insight.js +7 -11
  28. package/dist/src/cli/commands/job.js +17 -26
  29. package/dist/src/cli/commands/knowledge-bank.js +5 -6
  30. package/dist/src/cli/commands/llm.js +5 -8
  31. package/dist/src/cli/commands/macro.js +9 -16
  32. package/dist/src/cli/commands/meaning.js +7 -11
  33. package/dist/src/cli/commands/metrics.js +7 -10
  34. package/dist/src/cli/commands/ml-task.js +12 -20
  35. package/dist/src/cli/commands/model-evaluation-store.js +7 -11
  36. package/dist/src/cli/commands/notebook.js +15 -27
  37. package/dist/src/cli/commands/plugin.js +35 -68
  38. package/dist/src/cli/commands/project-deployer.js +10 -22
  39. package/dist/src/cli/commands/project-folder.js +10 -17
  40. package/dist/src/cli/commands/project-git.js +38 -70
  41. package/dist/src/cli/commands/project-library.js +15 -23
  42. package/dist/src/cli/commands/project.js +9 -26
  43. package/dist/src/cli/commands/recipe.d.ts +16 -0
  44. package/dist/src/cli/commands/recipe.js +83 -94
  45. package/dist/src/cli/commands/saved-model.js +23 -39
  46. package/dist/src/cli/commands/scenario.js +20 -34
  47. package/dist/src/cli/commands/sql.js +4 -4
  48. package/dist/src/cli/commands/statistics.js +11 -18
  49. package/dist/src/cli/commands/streaming-endpoint.js +7 -11
  50. package/dist/src/cli/commands/user.js +11 -22
  51. package/dist/src/cli/commands/variable.js +3 -4
  52. package/dist/src/cli/commands/webapp.js +10 -16
  53. package/dist/src/cli/commands/wiki.js +9 -13
  54. package/dist/src/cli/commands/workspace.js +8 -14
  55. package/dist/src/cli/contract.d.ts +5 -15
  56. package/dist/src/cli/contract.js +157 -254
  57. package/dist/src/cli/doctor.js +1 -0
  58. package/dist/src/cli/env.d.ts +2 -0
  59. package/dist/src/cli/env.js +16 -1
  60. package/dist/src/cli/flags.d.ts +1 -0
  61. package/dist/src/cli/flags.js +4 -9
  62. package/dist/src/cli/helpers/app-permissions.js +7 -5
  63. package/dist/src/cli/helpers/flow-zone.js +8 -6
  64. package/dist/src/cli/helpers/recipe.js +2 -1
  65. package/dist/src/cli/syntax.d.ts +83 -0
  66. package/dist/src/cli/syntax.js +217 -0
  67. package/dist/src/cli/types.d.ts +3 -0
  68. package/dist/src/cli/usage.d.ts +1 -1
  69. package/dist/src/cli/usage.js +4 -2
  70. package/dist/src/cli/version.d.ts +0 -2
  71. package/dist/src/cli/version.js +6 -7
  72. package/dist/src/cli.js +132 -274
  73. package/dist/src/client.d.ts +2 -1
  74. package/dist/src/client.js +32 -17
  75. package/dist/src/errors.d.ts +12 -1
  76. package/dist/src/errors.js +28 -3
  77. package/dist/src/index.d.ts +1 -3
  78. package/dist/src/index.js +2 -2
  79. package/dist/src/resources/api-services.js +2 -3
  80. package/dist/src/resources/applications.js +2 -4
  81. package/dist/src/resources/base.d.ts +2 -0
  82. package/dist/src/resources/base.js +14 -2
  83. package/dist/src/resources/code-envs.js +3 -5
  84. package/dist/src/resources/data-quality.js +14 -13
  85. package/dist/src/resources/datasets.d.ts +13 -0
  86. package/dist/src/resources/datasets.js +5 -4
  87. package/dist/src/resources/flow-zones.js +4 -2
  88. package/dist/src/resources/folders.js +4 -2
  89. package/dist/src/resources/futures.js +1 -3
  90. package/dist/src/resources/insights.js +3 -2
  91. package/dist/src/resources/jobs.js +4 -6
  92. package/dist/src/resources/macros.d.ts +1 -1
  93. package/dist/src/resources/macros.js +3 -7
  94. package/dist/src/resources/notebooks.js +2 -3
  95. package/dist/src/resources/project-git.js +9 -11
  96. package/dist/src/resources/project-library.d.ts +0 -2
  97. package/dist/src/resources/project-library.js +2 -7
  98. package/dist/src/resources/projects.js +4 -3
  99. package/dist/src/resources/recipes.d.ts +28 -0
  100. package/dist/src/resources/recipes.js +117 -89
  101. package/dist/src/resources/saved-models.js +1 -13
  102. package/dist/src/resources/scenarios.js +1 -3
  103. package/dist/src/resources/sql.js +9 -8
  104. package/dist/src/resources/statistics.js +3 -4
  105. package/dist/src/resources/variables.js +2 -1
  106. package/dist/src/resources/webapps.js +2 -3
  107. package/dist/src/schemas.d.ts +1 -2
  108. package/dist/src/schemas.js +1 -1
  109. package/dist/src/skill.js +6 -7
  110. package/dist/src/utils/cleanup-ledger.js +9 -8
  111. package/dist/src/utils/deep-merge.js +2 -4
  112. package/dist/src/utils/flow-map.js +1 -6
  113. package/dist/src/utils/polling.d.ts +3 -0
  114. package/dist/src/utils/polling.js +3 -0
  115. package/dist/src/utils/project-archive.js +10 -14
  116. package/dist/src/utils/project-incarnation.js +3 -7
  117. package/dist/src/utils/records.d.ts +4 -0
  118. package/dist/src/utils/records.js +8 -0
  119. package/dist/src/utils/stable-hash.d.ts +3 -1
  120. package/dist/src/utils/stable-hash.js +2 -0
  121. package/package.json +10 -14
  122. package/plugin.json +1 -1
  123. package/skills/dataiku-dss/SKILL.md +3 -4
  124. package/skills/dataiku-dss/references/authentication.md +3 -3
  125. package/skills/dataiku-dss/references/coding.md +1 -1
  126. package/skills/dataiku-dss/references/discovery.md +1 -1
  127. package/skills/dataiku-dss/references/mutations.md +0 -1
  128. package/dist/src/utils/pagination.d.ts +0 -8
  129. package/dist/src/utils/pagination.js +0 -23
  130. package/packages/types/dist/index.d.ts +0 -1062
  131. package/packages/types/dist/index.js +0 -871
@@ -2,14 +2,14 @@ import { deepMerge, } from "../../utils/deep-merge.js";
2
2
  import { jsonInput, } from "../coerce.js";
3
3
  import { executionMode, } from "../flags.js";
4
4
  import { addTransientTargetContext, encodedProjectEndpoint, readIfExists, skipResult, } from "../output.js";
5
+ import { commandUsage, withUsage, } from "../syntax.js";
5
6
  import { requireArgs, UsageError, } from "../usage.js";
6
7
  async function resolveFolderId(client, nameOrId, flags) {
7
8
  return client.folders.resolveId(nameOrId, flags["project-key"]);
8
9
  }
9
- export const folderCommands = {
10
+ export const folderCommands = withUsage("folder", {
10
11
  list: {
11
12
  handler: (c, _a, f) => c.folders.list(f["project-key"]),
12
- usage: "dss folder list [--project-key KEY]",
13
13
  description: "List managed folders in a project.",
14
14
  examples: ["dss folder list",],
15
15
  },
@@ -20,7 +20,7 @@ export const folderCommands = {
20
20
  const connection = f["connection"];
21
21
  const pk = f["project-key"];
22
22
  if (!name) {
23
- throw new UsageError("--name is required. Usage: dss folder create --name NAME [--type TYPE] [--connection CONN] [--path PATH]");
23
+ throw new UsageError(`--name is required. Usage: ${commandUsage("folder", "create")}`);
24
24
  }
25
25
  const payload = {
26
26
  name,
@@ -49,7 +49,6 @@ export const folderCommands = {
49
49
  const created = await c.folders.create(payload);
50
50
  return { created: created.id ?? name, resource: "folder", ...created, };
51
51
  },
52
- usage: "dss folder create --name NAME [--type TYPE] [--connection CONN] [--path PATH] [--if-not-exists] [--dry-run] [--project-key KEY]",
53
52
  description: "Create a managed folder; when omitted, the connection is selected from writable managed-folder storage and DSS infers the folder type.",
54
53
  examples: [
55
54
  "dss folder create --name exports",
@@ -59,19 +58,18 @@ export const folderCommands = {
59
58
  },
60
59
  get: {
61
60
  handler: async (c, a, f) => {
62
- requireArgs(a, 1, "dss folder get <name-or-id>");
61
+ requireArgs(a, 1, commandUsage("folder", "get"));
63
62
  return c.folders.get(await resolveFolderId(c, a[0], f), f["project-key"]);
64
63
  },
65
- usage: "dss folder get <name-or-id> [--project-key KEY]",
66
64
  description: "Get managed folder settings.",
67
65
  examples: ["dss folder get my_folder",],
68
66
  },
69
67
  update: {
70
68
  handler: async (c, a, f) => {
71
- requireArgs(a, 1, "dss folder update <name-or-id> [--data '{...}' | --data-file PATH | --stdin]");
69
+ requireArgs(a, 1, commandUsage("folder", "update"));
72
70
  const data = jsonInput(f);
73
71
  if (!data) {
74
- throw new UsageError("--data, --data-file, or --stdin is required. Usage: dss folder update <name-or-id> [--data '{...}' | --data-file PATH | --stdin]");
72
+ throw new UsageError(`--data, --data-file, or --stdin is required. Usage: ${commandUsage("folder", "update")}`);
75
73
  }
76
74
  const pk = f["project-key"];
77
75
  const folderId = await resolveFolderId(c, a[0], f);
@@ -91,7 +89,6 @@ export const folderCommands = {
91
89
  await c.folders.update(folderId, data, pk);
92
90
  return { updated: folderId, resource: "folder", };
93
91
  },
94
- usage: "dss folder update <name-or-id> (--data JSON | --data-file PATH | --stdin) [--dry-run] [--project-key KEY]",
95
92
  description: "Update managed folder settings by deep-merging a JSON patch.",
96
93
  examples: [
97
94
  'dss folder update exports --data \'{"tags":["agent"]}\' --dry-run',
@@ -100,7 +97,7 @@ export const folderCommands = {
100
97
  },
101
98
  delete: {
102
99
  handler: async (c, a, f) => {
103
- requireArgs(a, 1, "dss folder delete <name-or-id>");
100
+ requireArgs(a, 1, commandUsage("folder", "delete"));
104
101
  const pk = f["project-key"];
105
102
  const folderId = await resolveFolderId(c, a[0], f);
106
103
  if (executionMode(f).dryRun || f["if-exists"] === true) {
@@ -121,13 +118,12 @@ export const folderCommands = {
121
118
  await c.folders.delete(folderId, pk);
122
119
  return { deleted: folderId, resource: "folder", };
123
120
  },
124
- usage: "dss folder delete <name-or-id> [--if-exists] [--dry-run] [--project-key KEY]",
125
121
  description: "Delete a managed folder.",
126
122
  examples: ["dss folder delete exports --if-exists",],
127
123
  },
128
124
  contents: {
129
125
  handler: async (c, a, f) => {
130
- requireArgs(a, 1, "dss folder contents <name-or-id>");
126
+ requireArgs(a, 1, commandUsage("folder", "contents"));
131
127
  const startedAt = Date.now();
132
128
  let folderId = a[0];
133
129
  try {
@@ -140,7 +136,6 @@ export const folderCommands = {
140
136
  addTransientTargetContext(error, `folder:${folderId}`, Date.now() - startedAt);
141
137
  }
142
138
  },
143
- usage: "dss folder contents <name-or-id> [--retries N] [--request-timeout MS] [--project-key KEY]",
144
139
  description: "List files in a managed folder.",
145
140
  examples: [
146
141
  "dss folder contents my_folder",
@@ -149,14 +144,13 @@ export const folderCommands = {
149
144
  },
150
145
  download: {
151
146
  handler: async (c, a, f) => {
152
- requireArgs(a, 2, "dss folder download <name-or-id> <remote-path> [local-path]");
147
+ requireArgs(a, 2, commandUsage("folder", "download"));
153
148
  const localPath = a[2] ?? f["output"];
154
149
  return c.folders.download(await resolveFolderId(c, a[0], f), a[1], {
155
150
  localPath,
156
151
  projectKey: f["project-key"],
157
152
  });
158
153
  },
159
- usage: "dss folder download <name-or-id> <remote-path> [local-path] [--output PATH] [--project-key KEY]",
160
154
  description: "Download a file from a managed folder.",
161
155
  examples: [
162
156
  "dss folder download my_folder /data/report.csv",
@@ -165,7 +159,7 @@ export const folderCommands = {
165
159
  },
166
160
  upload: {
167
161
  handler: async (c, a, f) => {
168
- requireArgs(a, 3, "dss folder upload <name-or-id> <path> <localPath>");
162
+ requireArgs(a, 3, commandUsage("folder", "upload"));
169
163
  const pk = f["project-key"];
170
164
  const folderId = await resolveFolderId(c, a[0], f);
171
165
  if (executionMode(f).dryRun) {
@@ -184,21 +178,19 @@ export const folderCommands = {
184
178
  await c.folders.upload(folderId, a[1], a[2], pk);
185
179
  return { uploaded: a[1], folder: a[0], localPath: a[2], resource: "folder", };
186
180
  },
187
- usage: "dss folder upload <name-or-id> <path> <localPath> [--dry-run] [--project-key KEY]",
188
181
  description: "Upload a local file to a managed folder.",
189
182
  examples: ["dss folder upload my_folder /data/report.csv ./report.csv --dry-run",],
190
183
  },
191
184
  "delete-file": {
192
185
  handler: async (c, a, f) => {
193
- requireArgs(a, 2, "dss folder delete-file <name-or-id> <path>");
186
+ requireArgs(a, 2, commandUsage("folder", "delete-file"));
194
187
  if (executionMode(f).dryRun) {
195
188
  return { dryRun: true, action: "delete-file", resource: "folder", folder: a[0], path: a[1], };
196
189
  }
197
190
  await c.folders.deleteFile(await resolveFolderId(c, a[0], f), a[1], f["project-key"]);
198
191
  return { deleted: a[1], folder: a[0], resource: "folder", };
199
192
  },
200
- usage: "dss folder delete-file <name-or-id> <path> [--dry-run] [--project-key KEY]",
201
193
  description: "Delete a file from a managed folder.",
202
194
  examples: ["dss folder delete-file my_folder /data/report.csv",],
203
195
  },
204
- };
196
+ });
@@ -1,41 +1,39 @@
1
1
  import { num, } from "../coerce.js";
2
2
  import { executionMode, } from "../flags.js";
3
3
  import { planResult, } from "../output.js";
4
+ import { commandUsage, withUsage, } from "../syntax.js";
4
5
  import { requireArgs, } from "../usage.js";
5
- export const futureCommands = {
6
+ export const futureCommands = withUsage("future", {
6
7
  get: {
7
8
  handler: (c, a) => {
8
- requireArgs(a, 1, "dss future get <id>");
9
+ requireArgs(a, 1, commandUsage("future", "get"));
9
10
  return c.futures.get(a[0]);
10
11
  },
11
- usage: "dss future get <id>",
12
12
  description: "Get a DSS future state and retrieve the result if ready.",
13
13
  examples: ["dss future get FUTURE_ID",],
14
14
  },
15
15
  peek: {
16
16
  handler: (c, a) => {
17
- requireArgs(a, 1, "dss future peek <id>");
17
+ requireArgs(a, 1, commandUsage("future", "peek"));
18
18
  return c.futures.peek(a[0]);
19
19
  },
20
- usage: "dss future peek <id>",
21
20
  description: "Peek at a DSS future state without consuming its result.",
22
21
  examples: ["dss future peek FUTURE_ID",],
23
22
  },
24
23
  wait: {
25
24
  handler: (c, a, f) => {
26
- requireArgs(a, 1, "dss future wait <id>");
25
+ requireArgs(a, 1, commandUsage("future", "wait"));
27
26
  return c.futures.wait(a[0], {
28
27
  pollIntervalMs: num(f["poll-interval"], "--poll-interval"),
29
28
  timeoutMs: num(f["timeout"], "--timeout"),
30
29
  });
31
30
  },
32
- usage: "dss future wait <id> [--timeout MS] [--poll-interval MS]",
33
31
  description: "Wait for a DSS future to finish.",
34
32
  examples: ["dss future wait FUTURE_ID --timeout 60000",],
35
33
  },
36
34
  abort: {
37
35
  handler: async (c, a, f) => {
38
- requireArgs(a, 1, "dss future abort <id>");
36
+ requireArgs(a, 1, commandUsage("future", "abort"));
39
37
  const id = a[0];
40
38
  if (executionMode(f).dryRun) {
41
39
  return planResult("future", "abort", {
@@ -51,8 +49,7 @@ export const futureCommands = {
51
49
  await c.futures.abort(id);
52
50
  return { aborted: id, resource: "future", };
53
51
  },
54
- usage: "dss future abort <id> [--dry-run]",
55
52
  description: "Abort a DSS future.",
56
53
  examples: ["dss future abort FUTURE_ID --dry-run",],
57
54
  },
58
- };
55
+ });
@@ -1,6 +1,7 @@
1
1
  import { requiredJsonInput, } from "../coerce.js";
2
2
  import { executionMode, } from "../flags.js";
3
3
  import { readIfExists, skipResult, } from "../output.js";
4
+ import { commandUsage, withUsage, } from "../syntax.js";
4
5
  import { requireArgs, UsageError, } from "../usage.js";
5
6
  /** Group identifiers must be non-empty before any request or dry-run preview. */
6
7
  function requireGroupName(value, usage) {
@@ -10,26 +11,24 @@ function requireGroupName(value, usage) {
10
11
  }
11
12
  return trimmed;
12
13
  }
13
- export const groupCommands = {
14
+ export const groupCommands = withUsage("group", {
14
15
  list: {
15
16
  handler: (c) => c.groups.list(),
16
- usage: "dss group list",
17
17
  description: "List DSS groups (admin).",
18
18
  examples: ["dss group list",],
19
19
  },
20
20
  get: {
21
21
  handler: (c, a) => {
22
- const usage = "dss group get <name>";
22
+ const usage = commandUsage("group", "get");
23
23
  requireArgs(a, 1, usage);
24
24
  return c.groups.get(requireGroupName(a[0], usage));
25
25
  },
26
- usage: "dss group get <name>",
27
26
  description: "Get a DSS group (admin).",
28
27
  examples: ["dss group get administrators",],
29
28
  },
30
29
  create: {
31
30
  handler: async (c, _a, f) => {
32
- const usage = "dss group create (--data JSON|--data-file PATH|--stdin)";
31
+ const usage = commandUsage("group", "create");
33
32
  const body = requiredJsonInput(f, `--data, --data-file, or --stdin is required (group definition). Usage: ${usage}`);
34
33
  if (executionMode(f).dryRun) {
35
34
  return {
@@ -44,7 +43,6 @@ export const groupCommands = {
44
43
  }
45
44
  return c.groups.create(body);
46
45
  },
47
- usage: "dss group create (--data JSON|--data-file PATH|--stdin) [--dry-run]",
48
46
  description: 'Create a DSS group (admin). Body follows the DSS Group schema, e.g. {"name":"analysts","admin":false,"description":"..."}.',
49
47
  examples: [
50
48
  `dss group create --data '{"name":"analysts","admin":false,"description":"Business analysts"}'`,
@@ -52,7 +50,7 @@ export const groupCommands = {
52
50
  },
53
51
  update: {
54
52
  handler: async (c, a, f) => {
55
- const usage = "dss group update <name> (--data JSON|--data-file PATH|--stdin) [--dry-run]";
53
+ const usage = commandUsage("group", "update");
56
54
  requireArgs(a, 1, usage);
57
55
  const name = requireGroupName(a[0], usage);
58
56
  const body = requiredJsonInput(f, `--data, --data-file, or --stdin is required (group definition). Usage: ${usage}`);
@@ -71,7 +69,6 @@ export const groupCommands = {
71
69
  await c.groups.update(name, body);
72
70
  return { updated: name, };
73
71
  },
74
- usage: "dss group update <name> (--data JSON|--data-file PATH|--stdin) [--dry-run]",
75
72
  description: "Update a DSS group (admin). The body MUST be the Group object obtained from `dss group get` (PUT semantics); pass undocumented attributes through unchanged. Use --dry-run to preview the merged result without writing.",
76
73
  examples: [
77
74
  `dss group update analysts --data '{"name":"ANALYSTS","admin":false,"description":"Business analysts"}'`,
@@ -79,7 +76,7 @@ export const groupCommands = {
79
76
  },
80
77
  delete: {
81
78
  handler: async (c, a, f) => {
82
- const usage = "dss group delete <name> [--if-exists] [--dry-run]";
79
+ const usage = commandUsage("group", "delete");
83
80
  requireArgs(a, 1, usage);
84
81
  const name = requireGroupName(a[0], usage);
85
82
  if (executionMode(f).dryRun) {
@@ -102,8 +99,7 @@ export const groupCommands = {
102
99
  }
103
100
  return c.groups.delete(name);
104
101
  },
105
- usage: "dss group delete <name> [--if-exists] [--dry-run]",
106
102
  description: "Delete a DSS group (admin). Destructive and irreversible.",
107
103
  examples: ["dss group delete analysts", "dss group delete analysts --if-exists",],
108
104
  },
109
- };
105
+ });
@@ -2,20 +2,19 @@ import { deepMerge, } from "../../utils/deep-merge.js";
2
2
  import { json, jsonInput, parseBooleanOption, textInput, } from "../coerce.js";
3
3
  import { executionMode, } from "../flags.js";
4
4
  import { readIfExists, skipResult, } from "../output.js";
5
+ import { commandUsage, withUsage, } from "../syntax.js";
5
6
  import { requireArgs, UsageError, } from "../usage.js";
6
- export const insightCommands = {
7
+ export const insightCommands = withUsage("insight", {
7
8
  list: {
8
9
  handler: (c, _a, f) => c.insights.list(f["project-key"]),
9
- usage: "dss insight list [--project-key KEY]",
10
10
  description: "List project insights.",
11
11
  examples: ["dss insight list",],
12
12
  },
13
13
  get: {
14
14
  handler: (c, a, f) => {
15
- requireArgs(a, 1, "dss insight get <id>");
15
+ requireArgs(a, 1, commandUsage("insight", "get"));
16
16
  return c.insights.get(a[0], f["project-key"]);
17
17
  },
18
- usage: "dss insight get <id> [--project-key KEY]",
19
18
  description: "Get insight definition.",
20
19
  examples: ["dss insight get INSIGHT_ID",],
21
20
  },
@@ -29,7 +28,7 @@ export const insightCommands = {
29
28
  const contentType = f["content-type"];
30
29
  const payload = textInput(f);
31
30
  if (!data && (!name || !type)) {
32
- throw new UsageError("--data or both --name and --type are required. Usage: dss insight create --name NAME --type TYPE");
31
+ throw new UsageError(`--data or both --name and --type are required. Usage: ${commandUsage("insight", "create")}`);
33
32
  }
34
33
  const prototype = { ...data, };
35
34
  if (name !== undefined)
@@ -76,7 +75,6 @@ export const insightCommands = {
76
75
  });
77
76
  return { created: created.id, resource: "insight", ...created, };
78
77
  },
79
- usage: "dss insight create (--data JSON|--data-file PATH|--stdin | --name NAME --type TYPE [--params JSON] [--listed true|false]) [--content TEXT|--file PATH --content-type MIME] [--if-not-exists] [--dry-run] [--project-key KEY]",
80
78
  description: "Create an insight from a raw prototype or minimal name/type fields.",
81
79
  examples: [
82
80
  "dss insight create --name 'Agent chart' --type chart --params '{\"dataset\":\"orders\"}' --dry-run",
@@ -85,7 +83,7 @@ export const insightCommands = {
85
83
  },
86
84
  update: {
87
85
  handler: async (c, a, f) => {
88
- requireArgs(a, 1, "dss insight update <id> (--name NAME|--listed true|false|--params JSON|--content TEXT|--file PATH|--content-type MIME|--data JSON|--data-file PATH|--stdin)");
86
+ requireArgs(a, 1, commandUsage("insight", "update"));
89
87
  const data = jsonInput(f);
90
88
  const name = f["name"];
91
89
  const params = json(f["params"]);
@@ -131,13 +129,12 @@ export const insightCommands = {
131
129
  projectKey: f["project-key"],
132
130
  });
133
131
  },
134
- usage: "dss insight update <id> (--name NAME|--listed true|false|--params JSON|--content TEXT|--file PATH|--content-type MIME|--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]",
135
132
  description: "Update an insight using GET-before-POST merge semantics.",
136
133
  examples: ["dss insight update INSIGHT_ID --name 'Updated' --dry-run",],
137
134
  },
138
135
  delete: {
139
136
  handler: async (c, a, f) => {
140
- requireArgs(a, 1, "dss insight delete <id>");
137
+ requireArgs(a, 1, commandUsage("insight", "delete"));
141
138
  const pk = f["project-key"];
142
139
  if (executionMode(f).dryRun || f["if-exists"] === true) {
143
140
  const current = await readIfExists(() => c.insights.get(a[0], pk));
@@ -150,8 +147,7 @@ export const insightCommands = {
150
147
  await c.insights.delete(a[0], pk);
151
148
  return { deleted: a[0], resource: "insight", };
152
149
  },
153
- usage: "dss insight delete <id> [--if-exists] [--dry-run] [--project-key KEY]",
154
150
  description: "Delete an insight.",
155
151
  examples: ["dss insight delete INSIGHT_ID --dry-run",],
156
152
  },
157
- };
153
+ });
@@ -1,8 +1,10 @@
1
1
  import { mkdir, writeFile, } from "node:fs/promises";
2
2
  import { dirname, resolve, } from "node:path";
3
- import { jobBuildTargetTypeFromFlags, jobLogFilterFromFlag, maxLogLinesFromFlags, num, plainRecord, } from "../coerce.js";
3
+ import { asRecord, } from "../../utils/records.js";
4
+ import { jobBuildTargetTypeFromFlags, jobLogFilterFromFlag, maxLogLinesFromFlags, num, } from "../coerce.js";
4
5
  import { executionMode, } from "../flags.js";
5
6
  import { encodedProjectEndpoint, } from "../output.js";
7
+ import { commandUsage, withUsage, } from "../syntax.js";
6
8
  import { requireArgs, UsageError, } from "../usage.js";
7
9
  // ---------------------------------------------------------------------------
8
10
  // Utility helpers
@@ -10,7 +12,7 @@ import { requireArgs, UsageError, } from "../usage.js";
10
12
  function nestedValue(value, path) {
11
13
  let current = value;
12
14
  for (const key of path) {
13
- const record = plainRecord(current);
15
+ const record = asRecord(current);
14
16
  if (!record)
15
17
  return undefined;
16
18
  current = record[key];
@@ -94,7 +96,7 @@ function collectWarningCounts(value, inActivity, counts) {
94
96
  collectWarningCounts(item, inActivity, counts);
95
97
  return;
96
98
  }
97
- const record = plainRecord(value);
99
+ const record = asRecord(value);
98
100
  if (!record)
99
101
  return;
100
102
  for (const [key, item,] of Object.entries(record)) {
@@ -190,34 +192,31 @@ async function jobInspectionSummary(client, jobId, flags) {
190
192
  },
191
193
  };
192
194
  }
193
- export const jobCommands = {
195
+ export const jobCommands = withUsage("job", {
194
196
  list: {
195
197
  handler: async (c, _a, f) => filteredJobList(await c.jobs.list(f["project-key"]), f),
196
- usage: "dss job list [--state STATE] [--contains TEXT] [--output ID] [--latest] [--limit N] [--project-key KEY]",
197
198
  description: "List recent jobs, optionally filtered for automation.",
198
199
  examples: ["dss job list --state DONE --latest", "dss job list --contains WLM225S --limit 10",],
199
200
  },
200
201
  get: {
201
202
  handler: (c, a, f) => {
202
- requireArgs(a, 1, "dss job get <id>");
203
+ requireArgs(a, 1, commandUsage("job", "get"));
203
204
  return c.jobs.get(a[0], f["project-key"]);
204
205
  },
205
- usage: "dss job get <id> [--project-key KEY]",
206
206
  description: "Get job details.",
207
207
  examples: ["dss job get JOB_ID",],
208
208
  },
209
209
  summary: {
210
210
  handler: (c, a, f) => {
211
- requireArgs(a, 1, "dss job summary <id>");
211
+ requireArgs(a, 1, commandUsage("job", "summary"));
212
212
  return jobInspectionSummary(c, a[0], f);
213
213
  },
214
- usage: "dss job summary <id> [--activity ACTIVITY_ID] [--log-id LOG_ID] [--max-lines N|--max-log-lines N] [--project-key KEY]",
215
214
  description: "Summarize job state, outputs, warnings, progress, and useful terminal log lines.",
216
215
  examples: ["dss job summary JOB_ID --max-log-lines 200",],
217
216
  },
218
217
  log: {
219
218
  handler: async (c, a, f) => {
220
- requireArgs(a, 1, "dss job log <id>");
219
+ requireArgs(a, 1, commandUsage("job", "log"));
221
220
  const logFilter = f["errors-only"] === true
222
221
  ? "errors"
223
222
  : jobLogFilterFromFlag(f["log-filter"]);
@@ -237,7 +236,6 @@ export const jobCommands = {
237
236
  await writeFile(outputPath, log.endsWith("\n") ? log : `${log}\n`, "utf-8");
238
237
  return outputPath;
239
238
  },
240
- usage: "dss job log <id> [--activity ACTIVITY_ID] [--log-id LOG_ID] [--log-filter stdout|stderr|user|errors] [--errors-only] [--max-lines N|--max-log-lines N] [--output PATH] [--project-key KEY]",
241
239
  description: "Get public API job log output. Use --errors-only (or --log-filter errors) to surface just error/traceback lines, and --output PATH to write the log to a file (stdout returns the path). --log-id is accepted for UI parity but DSS API-key auth cannot select browser-only cat-activity-log files.",
242
240
  examples: [
243
241
  "dss job log JOB_ID",
@@ -246,7 +244,7 @@ export const jobCommands = {
246
244
  },
247
245
  "log-url": {
248
246
  handler: (c, a, f) => {
249
- requireArgs(a, 1, "dss job log-url <url>");
247
+ requireArgs(a, 1, commandUsage("job", "log-url"));
250
248
  let parsed;
251
249
  try {
252
250
  parsed = new URL(a[0], "http://dss.local");
@@ -262,7 +260,6 @@ export const jobCommands = {
262
260
  }
263
261
  return c.jobs.logFromUrl(a[0], { maxLogLines: maxLogLinesFromFlags(f), });
264
262
  },
265
- usage: "dss job log-url <url> [--max-lines N|--max-log-lines N]",
266
263
  description: "Fetch a DSS cat-activity-log URL pasted from the UI.",
267
264
  examples: [
268
265
  'dss job log-url "https://dss/dip/api/flow/jobs/cat-activity-log?projectKey=TEST&jobId=JOB&activityId=A&logId=L"',
@@ -270,7 +267,7 @@ export const jobCommands = {
270
267
  },
271
268
  build: {
272
269
  handler: async (c, a, f) => {
273
- requireArgs(a, 1, "dss job build <target>");
270
+ requireArgs(a, 1, commandUsage("job", "build"));
274
271
  const pk = f["project-key"];
275
272
  const options = {
276
273
  buildMode: f["build-mode"],
@@ -295,7 +292,6 @@ export const jobCommands = {
295
292
  }
296
293
  return c.jobs.build(a[0], { ...options, projectKey: pk, });
297
294
  },
298
- usage: "dss job build <target> [--target-type dataset|managed-folder] [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--wait] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
299
295
  description: "Start a dataset or managed-folder build, optionally waiting for completion.",
300
296
  examples: [
301
297
  "dss job build orders",
@@ -305,7 +301,7 @@ export const jobCommands = {
305
301
  },
306
302
  "build-and-wait": {
307
303
  handler: async (c, a, f) => {
308
- requireArgs(a, 1, "dss job build-and-wait <target>");
304
+ requireArgs(a, 1, commandUsage("job", "build-and-wait"));
309
305
  const pk = f["project-key"];
310
306
  const options = {
311
307
  buildMode: f["build-mode"],
@@ -331,7 +327,6 @@ export const jobCommands = {
331
327
  }
332
328
  return c.jobs.buildAndWait(a[0], { ...options, projectKey: pk, });
333
329
  },
334
- usage: "dss job build-and-wait <target> [--target-type dataset|managed-folder] [--type DATASET|MANAGED_FOLDER] [--build-mode MODE] [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--partition PARTITION] [--dry-run] [--project-key KEY]",
335
330
  description: "Build a dataset or managed folder and wait for completion.",
336
331
  examples: [
337
332
  "dss job build-and-wait orders",
@@ -342,7 +337,7 @@ export const jobCommands = {
342
337
  },
343
338
  wait: {
344
339
  handler: (c, a, f) => {
345
- requireArgs(a, 1, "dss job wait <id>");
340
+ requireArgs(a, 1, commandUsage("job", "wait"));
346
341
  return c.jobs.wait(a[0], {
347
342
  includeLogs: f["include-logs"] === true,
348
343
  logFilter: jobLogFilterFromFlag(f["log-filter"]),
@@ -353,7 +348,6 @@ export const jobCommands = {
353
348
  projectKey: f["project-key"],
354
349
  });
355
350
  },
356
- usage: "dss job wait <id> [--include-logs] [--log-filter stdout|stderr|user|errors] [--summary] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--project-key KEY]",
357
351
  description: "Wait for an existing job to complete.",
358
352
  examples: [
359
353
  "dss job wait JOB_ID",
@@ -362,7 +356,7 @@ export const jobCommands = {
362
356
  },
363
357
  monitor: {
364
358
  handler: async (c, a, f) => {
365
- requireArgs(a, 1, "dss job monitor <id...>");
359
+ requireArgs(a, 1, commandUsage("job", "monitor"));
366
360
  const options = {
367
361
  includeLogs: f["include-logs"] === true,
368
362
  logFilter: jobLogFilterFromFlag(f["log-filter"]),
@@ -375,13 +369,12 @@ export const jobCommands = {
375
369
  const jobs = await Promise.all(a.map((jobId) => c.jobs.wait(jobId, options)));
376
370
  return aggregateJobWaitResults(jobs, String(f["until"] ?? "all-done"));
377
371
  },
378
- usage: "dss job monitor <id...> [--summary] [--include-logs] [--log-filter stdout|stderr|user|errors] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--until all-done] [--project-key KEY]",
379
372
  description: "Monitor one or more existing jobs and summarize progress counters from logs.",
380
373
  examples: ["dss job monitor JOB_ID --summary", "dss job monitor JOB1 JOB2 --until all-done",],
381
374
  },
382
375
  watch: {
383
376
  handler: async (c, a, f) => {
384
- requireArgs(a, 1, "dss job watch <id...>");
377
+ requireArgs(a, 1, commandUsage("job", "watch"));
385
378
  const options = {
386
379
  includeLogs: f["include-logs"] === true,
387
380
  logFilter: jobLogFilterFromFlag(f["log-filter"]),
@@ -394,13 +387,12 @@ export const jobCommands = {
394
387
  const jobs = await Promise.all(a.map((jobId) => c.jobs.wait(jobId, options)));
395
388
  return aggregateJobWaitResults(jobs, String(f["until"] ?? "all-done"));
396
389
  },
397
- usage: "dss job watch <id...> [--include-logs] [--log-filter stdout|stderr|user|errors] [--max-log-lines N] [--timeout MS] [--poll-interval MS] [--until all-done] [--project-key KEY]",
398
390
  description: "Watch one or more existing jobs with progress extraction enabled.",
399
391
  examples: ["dss job watch JOB_ID", "dss job watch JOB1 JOB2 --until all-done",],
400
392
  },
401
393
  abort: {
402
394
  handler: async (c, a, f) => {
403
- requireArgs(a, 1, "dss job abort <id>");
395
+ requireArgs(a, 1, commandUsage("job", "abort"));
404
396
  const pk = f["project-key"];
405
397
  if (executionMode(f).dryRun) {
406
398
  return {
@@ -415,8 +407,7 @@ export const jobCommands = {
415
407
  await c.jobs.abort(a[0], pk);
416
408
  return { aborted: a[0], resource: "job", };
417
409
  },
418
- usage: "dss job abort <id> [--dry-run] [--project-key KEY]",
419
410
  description: "Abort a running job.",
420
411
  examples: ["dss job abort JOB_ID", "dss job abort JOB_ID --dry-run",],
421
412
  },
422
- };
413
+ });
@@ -1,10 +1,11 @@
1
1
  import { requiredJsonInput, } from "../coerce.js";
2
2
  import { executionMode, } from "../flags.js";
3
3
  import { planResult, } from "../output.js";
4
+ import { commandUsage, withUsage, } from "../syntax.js";
4
5
  import { requireArgs, UsageError, } from "../usage.js";
5
6
  const KB_PLAN_EXIT_CODES = { usage: 1, error: 2, transient: 3, };
6
- const KB_SEARCH_USAGE = "dss knowledge-bank search <knowledgeBankId> (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]";
7
- const KB_CLEAR_USAGE = "dss knowledge-bank clear <knowledgeBankId> [--dry-run] [--project-key KEY]";
7
+ const KB_SEARCH_USAGE = commandUsage("knowledge-bank", "search");
8
+ const KB_CLEAR_USAGE = commandUsage("knowledge-bank", "clear");
8
9
  /**
9
10
  * Validate a search body before any execution mode: the same check runs for
10
11
  * live, --plan, and --dry-run so planning can never succeed for a body the
@@ -24,7 +25,7 @@ function requireNonEmptyPositional(value, usage) {
24
25
  }
25
26
  return value;
26
27
  }
27
- export const knowledgeBankCommands = {
28
+ export const knowledgeBankCommands = withUsage("knowledge-bank", {
28
29
  search: {
29
30
  handler: async (c, a, f) => {
30
31
  const knowledgeBankId = requireNonEmptyPositional(a[0], KB_SEARCH_USAGE);
@@ -44,7 +45,6 @@ export const knowledgeBankCommands = {
44
45
  }
45
46
  return c.knowledgeBanks.search(knowledgeBankId, body, projectKey);
46
47
  },
47
- usage: KB_SEARCH_USAGE,
48
48
  description: "Search a knowledge bank for documents matching a query. Runs retrieval against the backing vector store. Body: { query, params?: { maxDocuments, searchType, similarityThreshold, mmrK, mmrDiversity, useAdvancedReranking, rrfRankConstant, rrfRankWindowSize } }.",
49
49
  examples: [
50
50
  'dss knowledge-bank search my-kb --data \'{"query":"Hello, world!"}\'',
@@ -70,11 +70,10 @@ export const knowledgeBankCommands = {
70
70
  await c.knowledgeBanks.clear(knowledgeBankId, projectKey);
71
71
  return { cleared: knowledgeBankId, resource: "knowledge-bank", };
72
72
  },
73
- usage: KB_CLEAR_USAGE,
74
73
  description: "DESTRUCTIVE: clear all data from a knowledge bank. The stored content is removed and cannot be recovered from this command.",
75
74
  examples: [
76
75
  "dss knowledge-bank clear my-kb --dry-run",
77
76
  "dss knowledge-bank clear my-kb",
78
77
  ],
79
78
  },
80
- };
79
+ });
@@ -1,11 +1,11 @@
1
1
  import { requiredJsonInput, } from "../coerce.js";
2
2
  import { executionMode, } from "../flags.js";
3
3
  import { planResult, } from "../output.js";
4
+ import { commandUsage, withUsage, } from "../syntax.js";
4
5
  import { UsageError, } from "../usage.js";
5
6
  const LLM_PLAN_EXIT_CODES = { usage: 1, error: 2, transient: 3, };
6
- const LLM_LIST_USAGE = "dss llm list [--purpose GENERIC_COMPLETION|TEXT_EMBEDDING_EXTRACTION|IMAGE_GENERATION|NAME] [--project-key KEY]";
7
- const LLM_COMPLETIONS_USAGE = "dss llm completions (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]";
8
- const LLM_EMBEDDINGS_USAGE = "dss llm embeddings (--data JSON|--data-file PATH|--stdin) [--dry-run] [--project-key KEY]";
7
+ const LLM_COMPLETIONS_USAGE = commandUsage("llm", "completions");
8
+ const LLM_EMBEDDINGS_USAGE = commandUsage("llm", "embeddings");
9
9
  /**
10
10
  * Validate a completions/embeddings payload before any execution mode: the
11
11
  * same check runs for live, --plan, and --dry-run so planning can never
@@ -23,7 +23,7 @@ function requireLlmInferenceBody(flags, usage) {
23
23
  }
24
24
  return body;
25
25
  }
26
- export const llmCommands = {
26
+ export const llmCommands = withUsage("llm", {
27
27
  list: {
28
28
  handler: (c, _a, f) => {
29
29
  const purpose = f["purpose"];
@@ -32,7 +32,6 @@ export const llmCommands = {
32
32
  projectKey: f["project-key"],
33
33
  });
34
34
  },
35
- usage: LLM_LIST_USAGE,
36
35
  description: "List LLMs available in a project (includes Retrieval-Augmented Generation ones). Does not invoke any LLM.",
37
36
  examples: ["dss llm list", "dss llm list --purpose TEXT_EMBEDDING_EXTRACTION",],
38
37
  },
@@ -56,7 +55,6 @@ export const llmCommands = {
56
55
  }
57
56
  return c.llms.completions(body, projectKey);
58
57
  },
59
- usage: LLM_COMPLETIONS_USAGE,
60
58
  description: "Perform completions on an LLM. COST-BEARING: invokes the LLM provider and may incur charges. Body: { llmId, queries: [{ messages: [...] }], settings?: {...} }.",
61
59
  examples: [
62
60
  'dss llm completions --data \'{"llmId":"openai:openai1:gpt-4","queries":[{"messages":[{"role":"user","content":"Hello"}]}]}\'',
@@ -83,11 +81,10 @@ export const llmCommands = {
83
81
  }
84
82
  return c.llms.embeddings(body, projectKey);
85
83
  },
86
- usage: LLM_EMBEDDINGS_USAGE,
87
84
  description: 'Perform embeddings on an LLM. COST-BEARING: invokes the LLM provider and may incur charges. Body: { llmId, queries: [{ text: "..." }] }.',
88
85
  examples: [
89
86
  'dss llm embeddings --data \'{"llmId":"openai:openai1:ada002-text-embedding","queries":[{"text":"Who wrote Beethoven 9th?"}]}\'',
90
87
  'dss llm embeddings --data \'{"llmId":"x","queries":[{"text":"y"}]}\' --dry-run',
91
88
  ],
92
89
  },
93
- };
90
+ });