dataiku-sdk 4.0.0 → 4.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.
Files changed (66) hide show
  1. package/README.md +1 -0
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +5 -1
  4. package/dist/packages/types/src/index.js +5 -1
  5. package/dist/src/cli/command-syntax.json +4136 -2756
  6. package/dist/src/cli/commands/code-env.js +5 -3
  7. package/dist/src/cli/commands/dataset.js +6 -4
  8. package/dist/src/cli/commands/future.js +7 -2
  9. package/dist/src/cli/commands/index.js +4 -0
  10. package/dist/src/cli/commands/job.js +12 -9
  11. package/dist/src/cli/commands/messaging-channel.d.ts +17 -0
  12. package/dist/src/cli/commands/messaging-channel.js +385 -0
  13. package/dist/src/cli/commands/project-deployer.js +33 -0
  14. package/dist/src/cli/commands/project.js +30 -0
  15. package/dist/src/cli/commands/recipe.js +23 -2
  16. package/dist/src/cli/commands/scenario.d.ts +6 -0
  17. package/dist/src/cli/commands/scenario.js +495 -17
  18. package/dist/src/cli/contract.js +20 -4
  19. package/dist/src/cli/env.d.ts +6 -0
  20. package/dist/src/cli/env.js +8 -0
  21. package/dist/src/cli/flags.js +34 -0
  22. package/dist/src/cli/helpers/cleanup.js +11 -0
  23. package/dist/src/cli/list-shapes.js +5 -0
  24. package/dist/src/cli/output.d.ts +2 -0
  25. package/dist/src/cli/output.js +24 -4
  26. package/dist/src/cli/plans.js +94 -2
  27. package/dist/src/cli/read-shapes.js +92 -1
  28. package/dist/src/cli/result-shapes.d.ts +19 -1
  29. package/dist/src/cli/result-shapes.js +228 -4
  30. package/dist/src/cli/selector-suggestions.d.ts +14 -0
  31. package/dist/src/cli/selector-suggestions.js +56 -0
  32. package/dist/src/cli/usage.d.ts +1 -1
  33. package/dist/src/cli/usage.js +36 -4
  34. package/dist/src/cli/version.d.ts +2 -2
  35. package/dist/src/cli/version.js +2 -2
  36. package/dist/src/cli.js +62 -13
  37. package/dist/src/client.d.ts +16 -4
  38. package/dist/src/client.js +45 -9
  39. package/dist/src/errors.d.ts +2 -0
  40. package/dist/src/errors.js +12 -2
  41. package/dist/src/generated/action-output-schemas.json +296 -0
  42. package/dist/src/index.d.ts +1 -0
  43. package/dist/src/index.js +1 -0
  44. package/dist/src/resources/bundles.d.ts +18 -0
  45. package/dist/src/resources/bundles.js +26 -0
  46. package/dist/src/resources/futures.d.ts +3 -0
  47. package/dist/src/resources/futures.js +5 -1
  48. package/dist/src/resources/messaging-channels.d.ts +83 -0
  49. package/dist/src/resources/messaging-channels.js +108 -0
  50. package/dist/src/resources/projects.d.ts +24 -0
  51. package/dist/src/resources/projects.js +36 -0
  52. package/dist/src/resources/recipe-create.d.ts +4 -1
  53. package/dist/src/resources/recipe-create.js +11 -2
  54. package/dist/src/resources/scenario-authoring.d.ts +52 -0
  55. package/dist/src/resources/scenario-authoring.js +216 -0
  56. package/dist/src/resources/scenarios.d.ts +128 -11
  57. package/dist/src/resources/scenarios.js +273 -43
  58. package/dist/src/resources/sql.js +3 -3
  59. package/dist/src/utils/messaging-channel-secrets.d.ts +17 -0
  60. package/dist/src/utils/messaging-channel-secrets.js +114 -0
  61. package/package.json +2 -1
  62. package/plugin.json +1 -1
  63. package/skills/dataiku-dss/SKILL.md +15 -16
  64. package/skills/dataiku-dss/references/discovery.md +2 -2
  65. package/skills/dataiku-dss/references/notifications.md +29 -0
  66. package/skills/dataiku-dss/references/troubleshooting.md +1 -0
@@ -253,6 +253,7 @@ const ALLOWED_CLEANUP_ACTIONS = new Set([
253
253
  "data-collection delete",
254
254
  "plugin delete",
255
255
  "connection delete",
256
+ "messaging-channel delete",
256
257
  "user delete",
257
258
  "group delete",
258
259
  ]);
@@ -669,6 +670,9 @@ function inferSideEffect(resource, action) {
669
670
  }
670
671
  if (resource === "install-skill")
671
672
  return "write";
673
+ // `send` matches no mutating verb, yet delivers real mail through the channel.
674
+ if (resource === "messaging-channel" && action === "send")
675
+ return "write";
672
676
  if (resource === "sql" && action === "query")
673
677
  return "write";
674
678
  if (resource === "ml-task" && action === "train")
@@ -735,7 +739,7 @@ function inferSideEffect(resource, action) {
735
739
  .test(action)
736
740
  // Compound actions whose mutating verb is a suffix (e.g. permissions-set,
737
741
  // dataset-compute, saved-model external-metadata-put).
738
- || /-(set|compute|restore|put)$/.test(action)) {
742
+ || /-(set|compute|restore|put|add|remove)$/.test(action)) {
739
743
  return "write";
740
744
  }
741
745
  return "read";
@@ -779,10 +783,16 @@ const STRING_OUTPUT_ACTIONS = new Set([
779
783
  */
780
784
  const SCOPED_OUTPUT_SHAPES = {
781
785
  "folder.contents": "array",
786
+ "scenario.last-runs": "array",
787
+ "scenario.runs-by-date": "array",
788
+ "scenario.trigger-list": "array",
789
+ "scenario.reporter-list": "array",
790
+ "scenario.run-report": "string",
782
791
  "plugin.usages": "object",
783
792
  "plugin.download": "object",
784
793
  "dataset.download": "object",
785
794
  "project-library.get": "string",
795
+ "messaging-channel.permissions-get": "array",
786
796
  "project-library.diff": "object",
787
797
  };
788
798
  function inferOutputShape(resource, action) {
@@ -919,6 +929,11 @@ const EXPLICIT_DESTRUCTIVE_KEYS = {
919
929
  // MLflow cleanup permanently erases experiment-tracking data.
920
930
  "mlflow.garbage-collect": true,
921
931
  "mlflow.clean-db": true,
932
+ // Removing a trigger or reporter drops its configuration; no public route restores it.
933
+ "scenario.trigger-remove": true,
934
+ "scenario.reporter-remove": true,
935
+ // A sent mail is delivered to external recipients and cannot be recalled.
936
+ "messaging-channel.send": true,
922
937
  };
923
938
  function inferDestructiveLevel(resource, sideEffect, action) {
924
939
  if (sideEffect !== "write")
@@ -945,7 +960,8 @@ function inferAsyncKind(resource, action) {
945
960
  return "job";
946
961
  if (resource === "future" && ["get", "peek", "wait", "abort",].includes(action))
947
962
  return "future";
948
- if (resource === "scenario" && ["run", "run-and-wait", "status",].includes(action)) {
963
+ if (resource === "scenario"
964
+ && ["run", "run-and-wait", "status", "get-run-for-trigger",].includes(action)) {
949
965
  return "future";
950
966
  }
951
967
  if (resource === "user" && ADMIN_SECURITY_FUTURE_ACTIONS[action] === true)
@@ -1518,7 +1534,7 @@ export function buildAgentContract() {
1518
1534
  "dss commands run --fields dataset",
1519
1535
  "dss commands run --fields dataset.create",
1520
1536
  ],
1521
- scopedDiscoveryHint: "Default: resource/action summary. --contains TEXT: top 5 actions by concept. --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.",
1537
+ scopedDiscoveryHint: "Default: resource/action summary. --contains TEXT: top 5 actions by concept. --fields RESOURCE: each action's usage, description, and side effect; RESOURCE.ACTION: one full entry keyed by that path; append .FIELD for nested metadata. Comma-separate paths. --output PATH exports full entries (the full registry without --fields).",
1522
1538
  // Accepted by every command and absent from per-entry `flags`; the
1523
1539
  // connection flags matter only for commands that call DSS.
1524
1540
  globalFlags: [...GLOBAL_AGENT_FLAGS, ...AUTHENTICATED_AGENT_FLAGS,].map((name) => {
@@ -1545,7 +1561,7 @@ export function buildAgentContract() {
1545
1561
  failure: "structured-error-object",
1546
1562
  failureResultDetailLimitBytes: 65_536,
1547
1563
  fieldProjection: "Missing --fields paths: null on stdout; field_projection_missing on stderr.",
1548
- compactResults: "*.list, job get, dataset get/info, project get: compact; --full/--fields use DSS objects; lists take --contains/--limit (list_truncated warning).",
1564
+ compactResults: "*.list, job get, dataset get/info, project get, scenario get-run/last-runs: compact; --full/--fields use DSS objects; lists take --contains/--limit (list_truncated warning).",
1549
1565
  richFailureResults: "doctor/batch/cleanup failures: own compact {ok:false,...} result on stdout and command exit code; no wrapper.",
1550
1566
  },
1551
1567
  stderr: {
@@ -10,4 +10,10 @@ export declare function envFileProvenance(name: string): EnvFileProvenance | und
10
10
  export declare function dataikuEnvironmentEnabled(): boolean;
11
11
  /** DATAIKU_PROJECT_KEY from the environment, unless `DATAIKU_DISABLE_ENV=1`. */
12
12
  export declare function ambientProjectKey(): string | undefined;
13
+ /**
14
+ * `DSS_PRETTY=1` indents stdout JSON. Agent shells that cut long lines (omp at
15
+ * 768 bytes) truncate a one-line result; indented output keeps each line short.
16
+ * Read from the process environment only, never from a `.env` file.
17
+ */
18
+ export declare function prettyOutputEnabled(): boolean;
13
19
  export declare function loadEnvFile(): void;
@@ -23,6 +23,14 @@ export function dataikuEnvironmentEnabled() {
23
23
  export function ambientProjectKey() {
24
24
  return dataikuEnvironmentEnabled() ? process.env.DATAIKU_PROJECT_KEY : undefined;
25
25
  }
26
+ /**
27
+ * `DSS_PRETTY=1` indents stdout JSON. Agent shells that cut long lines (omp at
28
+ * 768 bytes) truncate a one-line result; indented output keeps each line short.
29
+ * Read from the process environment only, never from a `.env` file.
30
+ */
31
+ export function prettyOutputEnabled() {
32
+ return process.env.DSS_PRETTY === "1";
33
+ }
26
34
  const allowedEnvKeys = new Set(["NODE_EXTRA_CA_CERTS", "NODE_TLS_REJECT_UNAUTHORIZED",]);
27
35
  /**
28
36
  * `.env` files are untrusted input: only the CLI's own `DATAIKU_*` variables and
@@ -76,6 +76,9 @@ export const BOOLEAN_FLAGS = new Set([
76
76
  "no-auto-rebuild",
77
77
  "all-users",
78
78
  "with-scenarios",
79
+ "scenarios-only",
80
+ "only-finished",
81
+ "clear",
79
82
  "for-everybody",
80
83
  "payload-only",
81
84
  "allow-same-path",
@@ -102,6 +105,8 @@ export const BOOLEAN_FLAGS = new Set([
102
105
  "conda",
103
106
  "force",
104
107
  "partitioning-folder",
108
+ "plain-text",
109
+ "single-message",
105
110
  ]);
106
111
  export const SHORT_FLAGS = {
107
112
  v: "verbose",
@@ -231,6 +236,24 @@ export const VALUE_FLAGS = new Set([
231
236
  "repository",
232
237
  "request-timeout",
233
238
  "params",
239
+ "params-file",
240
+ "frequency",
241
+ "every",
242
+ "hour",
243
+ "minute",
244
+ "days",
245
+ "day-of-month",
246
+ "run-on",
247
+ "start-date",
248
+ "timezone",
249
+ "index",
250
+ "channel",
251
+ "recipient",
252
+ "subject",
253
+ "condition",
254
+ "phase",
255
+ "user",
256
+ "trigger-id",
234
257
  "password-env",
235
258
  "results-per-page",
236
259
  "record-cleanup",
@@ -324,6 +347,16 @@ export const VALUE_FLAGS = new Set([
324
347
  "time-variable",
325
348
  "timeseries-ids",
326
349
  "full-reguess",
350
+ "cc",
351
+ "bcc",
352
+ "subject",
353
+ "body",
354
+ "body-file",
355
+ "attachment",
356
+ "family",
357
+ "permissions",
358
+ "automation-node-id",
359
+ "id",
327
360
  ]);
328
361
  export const REPEATABLE_VALUE_FLAGS = new Set([
329
362
  "dataset",
@@ -337,6 +370,7 @@ export const REPEATABLE_VALUE_FLAGS = new Set([
337
370
  "replace-input",
338
371
  "replace-output",
339
372
  "replace-payload-text",
373
+ "attachment",
340
374
  ]);
341
375
  export const KNOWN_LONG_FLAGS = new Set([
342
376
  ...BOOLEAN_FLAGS,
@@ -345,6 +345,17 @@ export function cleanupLedgerEntry(resource, action, args, flags, result, projec
345
345
  cleanup: { argv: ["streaming-endpoint", "delete", id, ...withProject,], },
346
346
  };
347
347
  }
348
+ case "messaging-channel.create": {
349
+ // DSS echoes the id it allocated; an explicit --id is the fallback.
350
+ const id = stringField(record, ["id",]) ?? flags["id"];
351
+ if (!id)
352
+ return undefined;
353
+ return {
354
+ ...base,
355
+ id,
356
+ cleanup: { argv: ["messaging-channel", "delete", id, "--if-exists",], },
357
+ };
358
+ }
348
359
  case "meaning.create": {
349
360
  const id = args[0];
350
361
  return {
@@ -100,6 +100,11 @@ export const COMPACT_LIST_FIELDS = {
100
100
  label: field("label", STRING),
101
101
  type: field("type", STRING),
102
102
  },
103
+ "messaging-channel": {
104
+ id: field("id", STRING),
105
+ type: field("type", STRING),
106
+ family: field("family", STRING),
107
+ },
103
108
  };
104
109
  /** Discovery output schemas of the compact `RESOURCE.list` defaults. */
105
110
  export function compactListOutputSchemas() {
@@ -11,6 +11,8 @@ export declare function pickResultFields(item: unknown, fields: string[]): unkno
11
11
  * that are absent become null so every row keeps a stable, predictable shape.
12
12
  */
13
13
  export declare function projectResultFields(result: unknown, fields: string[], availableFieldNames?: () => string[]): unknown;
14
+ /** One JSON value plus newline for stdout; indented when `DSS_PRETTY=1`. */
15
+ export declare function stdoutJson(value: unknown): string;
14
16
  export declare function writeCommandResult(result: unknown): void;
15
17
  export declare function addTransientTargetContext(error: unknown, target: string, elapsedMs: number): never;
16
18
  export declare function isFailedWaitResult(result: unknown): boolean;
@@ -1,4 +1,5 @@
1
1
  import { DataikuError, } from "../errors.js";
2
+ import { prettyOutputEnabled, } from "./env.js";
2
3
  let outputFieldProjection;
3
4
  export function setOutputFieldProjection(fields) {
4
5
  outputFieldProjection = fields;
@@ -98,12 +99,16 @@ export function projectResultFields(result, fields, availableFieldNames) {
98
99
  return result.map((item) => pickResultFields(item, fields));
99
100
  return pickResultFields(result, fields);
100
101
  }
102
+ /** One JSON value plus newline for stdout; indented when `DSS_PRETTY=1`. */
103
+ export function stdoutJson(value) {
104
+ return `${JSON.stringify(value, null, prettyOutputEnabled() ? 2 : undefined)}\n`;
105
+ }
101
106
  export function writeCommandResult(result) {
102
107
  const projected = outputFieldProjection
103
108
  ? projectResultFields(result, outputFieldProjection)
104
109
  : result;
105
110
  flushCliWarnings();
106
- process.stdout.write(`${JSON.stringify(projected ?? { ok: true, })}\n`);
111
+ process.stdout.write(stdoutJson(projected ?? { ok: true, }));
107
112
  }
108
113
  export function addTransientTargetContext(error, target, elapsedMs) {
109
114
  if (error instanceof DataikuError && error.category === "transient") {
@@ -200,13 +205,28 @@ export function commandFailureMessage(result) {
200
205
  const resume = typeof record.resume === "string" ? ` Resume with: ${record.resume}` : "";
201
206
  return `Timed out waiting for job ${record.jobId} after ${record.elapsedMs}ms (last known state: ${record.state}); the job is still running in DSS and was not cancelled.${resume}`;
202
207
  }
208
+ if (record.timedOut === true) {
209
+ // ML training, scenario runs, futures, code run: the client stopped waiting. Only a
210
+ // result that says `cancelled: false` proves nothing was stopped; `code run` cleans up
211
+ // its throwaway scenario, so its `cleanup` status is what tells.
212
+ const known = typeof record.state === "string"
213
+ ? record.state
214
+ : typeof record.outcome === "string"
215
+ ? record.outcome
216
+ : undefined;
217
+ const elapsed = typeof record.elapsedMs === "number" ? ` after ${record.elapsedMs}ms` : "";
218
+ const after = record.cancelled === false
219
+ ? "the operation was not cancelled and may still be running in DSS."
220
+ : record.cleanup !== undefined
221
+ ? "the client stopped waiting; see `cleanup` for what happened to the run."
222
+ : "the client stopped waiting; the operation may still be running in DSS.";
223
+ return `Timed out waiting${elapsed}${known ? ` (last known state: ${known})` : ""}; ${after}`;
224
+ }
203
225
  const state = typeof record.state === "string"
204
226
  ? record.state
205
227
  : typeof record.outcome === "string"
206
228
  ? record.outcome
207
- : typeof record.timedOut === "boolean"
208
- ? "timed out"
209
- : undefined;
229
+ : undefined;
210
230
  return `Command completed with failed long-running result${state ? `: ${state}` : ""}.`;
211
231
  }
212
232
  if (isAssertionFailureResult(result)) {
@@ -10,13 +10,16 @@ import { encodeLibraryPath, PROJECT_LIBRARY_CONCURRENCY_CONTROL, validateLibrary
10
10
  import { buildRecipeCreateRequest, } from "../resources/recipe-create.js";
11
11
  import { modelDiagnosticsBody, } from "../resources/trained-model.js";
12
12
  import { encodeGitReferencePath, validateGitReferencePath, } from "../utils/git-reference.js";
13
+ import { sanitizeMessagingChannelSecrets, } from "../utils/messaging-channel-secrets.js";
13
14
  import { jobBuildTargetTypeFromFlags, json, jsonInput, num, parseBooleanOption, parseJsonObject, requiredJsonInput, rewritePairsFromFlags, schemaColumnsInput, sha256Hex, stableHash, stringField, textInput, unknownJsonInput, } from "./coerce.js";
14
15
  import { parseCodeRunIntegerFlag, resolveCodeInputWithSource, } from "./commands/code.js";
15
16
  import { schemaPropagationOptionsFromFlags, } from "./commands/flow.js";
17
+ import { messagingChannelPlanShape, } from "./commands/messaging-channel.js";
16
18
  import { mlTaskFieldsFromFlags, mlTaskReguessOptionsFromFlags, } from "./commands/ml-task.js";
17
19
  import { deployRunOptionsFromFlags, experimentsDatasetOptionsFromFlags, inferenceInfoFromFlags, } from "./commands/mlflow.js";
18
20
  import { projectLibraryPutPayload, } from "./commands/project-library.js";
19
21
  import { enqueueRecipeCreateWarnings, recipeCreateOptionsFromFlags, } from "./commands/recipe.js";
22
+ import { scenarioReporterFromFlags, scenarioRunParams, scenarioTriggerFromFlags, } from "./commands/scenario.js";
20
23
  import { resolveSqlQueryInvocation, } from "./commands/sql.js";
21
24
  import { buildRegistryEntry, splitPackageSpec, } from "./contract.js";
22
25
  import { ambientProjectKey, } from "./env.js";
@@ -1209,7 +1212,7 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
1209
1212
  method: "POST",
1210
1213
  endpoint: projectEndpoint(`/scenarios/${encodeURIComponent(id)}/run/`),
1211
1214
  identifiers: { id, },
1212
- payload: {},
1215
+ payload: scenarioRunParams(flags) ?? {},
1213
1216
  wait: action === "run-and-wait" || flags["wait"] === true,
1214
1217
  };
1215
1218
  case "scenario.delete":
@@ -1230,10 +1233,84 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
1230
1233
  name: args[1],
1231
1234
  projectKey,
1232
1235
  type,
1233
- params: type === "step_based" ? { steps: [], triggers: [], reporters: [], } : {},
1236
+ ...(type === "step_based"
1237
+ ? { params: { steps: [], }, triggers: [], reporters: [], }
1238
+ : { params: {}, }),
1239
+ ...jsonInput(flags),
1234
1240
  },
1235
1241
  };
1236
1242
  }
1243
+ case "scenario.trigger-add":
1244
+ case "scenario.reporter-add": {
1245
+ const isTrigger = action === "trigger-add";
1246
+ const field = isTrigger ? "triggers" : "reporters";
1247
+ const item = isTrigger
1248
+ ? scenarioTriggerFromFlags(flags)
1249
+ : sanitizeMessagingChannelSecrets(scenarioReporterFromFlags(flags));
1250
+ const endpoint = projectEndpoint(`/scenarios/${encodeURIComponent(id)}/`);
1251
+ return {
1252
+ exact: false,
1253
+ reason: `Apply GETs the scenario, appends this element to ${field} (the others are kept), PUTs the full scenario, then GETs it back to verify; the stored element gains DSS-assigned ids.`,
1254
+ method: "PUT",
1255
+ endpoint,
1256
+ identifiers: { id, },
1257
+ payload: item,
1258
+ requests: [
1259
+ { sequence: 1, method: "GET", endpoint, },
1260
+ { sequence: 2, method: "PUT", endpoint, payloadEdits: { [field]: { append: item, }, }, },
1261
+ { sequence: 3, method: "GET", endpoint, },
1262
+ ],
1263
+ };
1264
+ }
1265
+ case "scenario.trigger-remove":
1266
+ case "scenario.reporter-remove": {
1267
+ const field = action === "trigger-remove" ? "triggers" : "reporters";
1268
+ const selector = flags["index"] !== undefined
1269
+ ? { index: num(flags["index"], "--index"), }
1270
+ : { name: flags["name"], };
1271
+ if ((flags["index"] === undefined) === (flags["name"] === undefined)) {
1272
+ throw new UsageError(`Pass exactly one of --index or --name. Usage: ${entry.usage}`);
1273
+ }
1274
+ const endpoint = projectEndpoint(`/scenarios/${encodeURIComponent(id)}/`);
1275
+ return {
1276
+ exact: false,
1277
+ reason: `Apply GETs the scenario, drops the selected element from ${field} (the others are kept), PUTs the full scenario, then GETs it back to verify.`,
1278
+ method: "PUT",
1279
+ endpoint,
1280
+ identifiers: { id, },
1281
+ payload: selector,
1282
+ requests: [
1283
+ { sequence: 1, method: "GET", endpoint, },
1284
+ { sequence: 2, method: "PUT", endpoint, payloadEdits: { [field]: { remove: selector, }, }, },
1285
+ { sequence: 3, method: "GET", endpoint, },
1286
+ ],
1287
+ };
1288
+ }
1289
+ case "scenario.run-as-set": {
1290
+ const user = flags["user"];
1291
+ if ((typeof user === "string") === (flags["clear"] === true)) {
1292
+ throw new UsageError(`Pass exactly one of --user LOGIN or --clear. Usage: ${entry.usage}`);
1293
+ }
1294
+ const endpoint = projectEndpoint(`/scenarios/${encodeURIComponent(id)}/`);
1295
+ return {
1296
+ exact: false,
1297
+ reason: "Apply GETs the scenario, sets (or, with --clear, removes) runAsUser, PUTs the full scenario, then GETs it back to verify.",
1298
+ method: "PUT",
1299
+ endpoint,
1300
+ identifiers: { id, },
1301
+ payload: { runAsUser: typeof user === "string" ? user : null, },
1302
+ requests: [
1303
+ { sequence: 1, method: "GET", endpoint, },
1304
+ {
1305
+ sequence: 2,
1306
+ method: "PUT",
1307
+ endpoint,
1308
+ payloadEdits: { runAsUser: typeof user === "string" ? user : "<removed>", },
1309
+ },
1310
+ { sequence: 3, method: "GET", endpoint, },
1311
+ ],
1312
+ };
1313
+ }
1237
1314
  case "scenario.update":
1238
1315
  return {
1239
1316
  method: "PUT",
@@ -1345,6 +1422,21 @@ export function commandPlanShape(resource, action, args, flags, entry, projectKe
1345
1422
  endpoint: `/public/api/project-deployer/infras/${encodeURIComponent(id)}`,
1346
1423
  identifiers: { infraId: id, },
1347
1424
  };
1425
+ case "project-deployer.run-test-scenarios": {
1426
+ const nodeFlag = flags["automation-node-id"];
1427
+ const automationNodeId = typeof nodeFlag === "string" && nodeFlag !== "" ? nodeFlag : undefined;
1428
+ return {
1429
+ method: "POST",
1430
+ endpoint: `/public/api/project-deployer/deployments/${encodeURIComponent(id)}/run-test-scenarios${querySuffix({ automationNodeId, })}`,
1431
+ identifiers: { deploymentId: id, },
1432
+ };
1433
+ }
1434
+ case "messaging-channel.create":
1435
+ case "messaging-channel.settings-set":
1436
+ case "messaging-channel.permissions-set":
1437
+ case "messaging-channel.delete":
1438
+ case "messaging-channel.send":
1439
+ return messagingChannelPlanShape(action, args, flags, projectKey);
1348
1440
  case "project-deployer.delete-project":
1349
1441
  return {
1350
1442
  method: "DELETE",
@@ -32,7 +32,29 @@ export function compactReadOutputSchemas() {
32
32
  additionalProperties: false,
33
33
  properties: { type: STRING, message: STRING, },
34
34
  };
35
- return {
35
+ const triggerSchema = {
36
+ type: "object",
37
+ additionalProperties: false,
38
+ properties: { type: STRING, name: STRING, },
39
+ };
40
+ const failureSchema = {
41
+ type: "object",
42
+ additionalProperties: false,
43
+ properties: {
44
+ stepId: STRING,
45
+ jobId: STRING,
46
+ dataset: STRING,
47
+ recipe: STRING,
48
+ inputs: { type: "array", items: { type: "string", }, },
49
+ message: STRING,
50
+ },
51
+ };
52
+ const nextSchema = {
53
+ type: "array",
54
+ description: "Next commands to run, each as an argv array.",
55
+ items: { type: "array", items: STRING, },
56
+ };
57
+ const schemas = {
36
58
  "job.get": {
37
59
  type: "object",
38
60
  additionalProperties: false,
@@ -110,5 +132,74 @@ export function compactReadOutputSchemas() {
110
132
  lastModifiedBy: STRING,
111
133
  },
112
134
  },
135
+ "scenario.get-run": {
136
+ type: "object",
137
+ additionalProperties: false,
138
+ required: ["runId", "steps",],
139
+ properties: {
140
+ runId: STRING,
141
+ scenarioId: STRING,
142
+ projectKey: STRING,
143
+ outcome: STRING,
144
+ start: NUMBER,
145
+ end: NUMBER,
146
+ durationMs: NUMBER,
147
+ trigger: triggerSchema,
148
+ steps: {
149
+ type: "array",
150
+ items: {
151
+ type: "object",
152
+ additionalProperties: false,
153
+ properties: {
154
+ id: STRING,
155
+ name: STRING,
156
+ type: STRING,
157
+ outcome: STRING,
158
+ message: STRING,
159
+ datasets: {
160
+ type: "array",
161
+ items: {
162
+ type: "object",
163
+ additionalProperties: false,
164
+ properties: { dataset: STRING, projectKey: STRING, partition: STRING, outcome: STRING, },
165
+ },
166
+ },
167
+ jobs: {
168
+ type: "array",
169
+ items: {
170
+ type: "object",
171
+ additionalProperties: false,
172
+ properties: { jobId: STRING, outcome: STRING, message: STRING, },
173
+ },
174
+ },
175
+ },
176
+ },
177
+ },
178
+ failure: failureSchema,
179
+ next: nextSchema,
180
+ hint: {
181
+ type: "string",
182
+ description: "Edit-and-rerun commands when the failed recipe is known.",
183
+ },
184
+ },
185
+ },
186
+ "scenario.last-runs": {
187
+ type: "array",
188
+ items: {
189
+ type: "object",
190
+ additionalProperties: false,
191
+ required: ["runId",],
192
+ properties: {
193
+ runId: STRING,
194
+ outcome: STRING,
195
+ start: NUMBER,
196
+ end: NUMBER,
197
+ trigger: triggerSchema,
198
+ failure: { type: "object", additionalProperties: false, properties: { message: STRING, }, },
199
+ next: nextSchema,
200
+ },
201
+ },
202
+ },
113
203
  };
204
+ return { ...schemas, "scenario.runs-by-date": schemas["scenario.last-runs"], };
114
205
  }
@@ -1,6 +1,24 @@
1
+ type Item = Record<string, unknown>;
2
+ /** The failed activity of a job: the recipe that failed and the datasets it read. */
3
+ export interface FailedActivity {
4
+ recipe: string;
5
+ inputs: string[];
6
+ }
7
+ /**
8
+ * Failure diagnosis of a raw `scenario get-run` report: the first failure
9
+ * (`{ stepId, jobId, dataset, message }`) and the next command(s) to run as
10
+ * argv arrays. With the failed recipe known, `hint` names the edit-and-rerun
11
+ * loop, so the agent does not look up the write commands. Empty when the run did not fail.
12
+ */
13
+ export declare function scenarioRunDiagnosis(details: unknown, activity?: FailedActivity): {
14
+ failure?: Item;
15
+ next?: string[][];
16
+ hint?: string;
17
+ };
1
18
  /**
2
19
  * Compact a command result for agents: `*.list` items (filter, cap, compact
3
- * fields) and the four large read commands. `--full` and `--fields` bypass
20
+ * fields) and the large read commands. `--full` and `--fields` bypass
4
21
  * the read shapers so the DSS object (or a projection of it) is returned.
5
22
  */
6
23
  export declare function shapeCommandResult(resource: string, action: string, result: unknown, flags: Record<string, string | boolean>): unknown;
24
+ export {};