dataiku-sdk 0.6.1 → 0.7.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 ADDED
@@ -0,0 +1,85 @@
1
+ # dataiku-sdk
2
+
3
+ Agent-only TypeScript SDK and `dss` CLI for Dataiku DSS automation.
4
+
5
+ Examples below assume the installed `dss` binary. From this checkout, use `./bin/dss ...` or `bun --no-env-file src/cli.ts ...` with the same arguments; from another working directory, call `/path/to/dataiku-sdk/bin/dss ...`.
6
+ `--no-env-file` disables Bun's automatic preloading only; the CLI still applies its documented `.env` handling unless `DATAIKU_DISABLE_ENV=1` is set.
7
+
8
+ ## CLI contract
9
+
10
+ - Success: stdout contains one JSON result.
11
+ - Failure: stderr contains one JSON error envelope with `ok:false`, `error`, `code`, and `exitCode`.
12
+ - `--verbose` may add HTTP trace lines to stderr.
13
+ - `--fields a,b,c` projects those fields from an object or array-of-objects result; dotted paths (`a.b.c`) drill into nested objects, and missing fields become `null`; string and scalar results pass through unchanged.
14
+ - No prompts, help screens, tables, banners, or prose output are part of the contract.
15
+ - Exit codes: `0` success, `1` usage/configuration error, `2` DSS/internal error, `3` transient DSS error, `4` completed command with failed long-running DSS work.
16
+ - The exit code is the success signal: chain mutations with `&&` and never infer success from piped output that discards the exit code (e.g. `dss ... 2>&1 | helper; echo done` reports success even when the command failed).
17
+ - `--raw` is only for recipe payload commands. Without `--output`, stdout is raw bytes; with `--output PATH`, stdout is the JSON string equal to `PATH` and the file contains the exact raw bytes.
18
+
19
+ Discover the complete machine-readable command surface:
20
+
21
+ ```bash
22
+ dss commands run
23
+ ```
24
+
25
+ Agents should parse `commands run` before choosing syntax; inspect `flags`, `requiresAuth`, `requiresProject`, `sideEffect`, and `outputShape` instead of guessing.
26
+
27
+ ## Agent skill installation
28
+
29
+ ```bash
30
+ dss install-skill --list-agents
31
+ dss install-skill --agent omp --target .
32
+ dss install-skill --agent omp --target . --dry-run
33
+ dss install-skill --global --agent omp
34
+ ```
35
+
36
+ `--list-agents` only reports targetable agents; it does not write files. Auto-detection checks supported agent binaries/config directories (`claude`, `codex`, `cursor`, `pi`, `omp`). Passing `--agent NAME` forces one entry and reports `via:"flag"`.
37
+
38
+ Project installs write `SKILL.md` under the target workspace:
39
+
40
+ - Claude: `.claude/skills/dataiku-dss/SKILL.md`
41
+ - Codex: `.codex/skills/dataiku-dss/SKILL.md`
42
+ - Cursor: `.cursor/skills/dataiku-dss/SKILL.md`
43
+ - Pi: `.pi/skills/dataiku-dss/SKILL.md`
44
+ - OMP: `.omp/skills/dataiku-dss/SKILL.md`
45
+
46
+ Global installs write under the agent's home config path, for example OMP: `~/.omp/agent/skills/dataiku-dss/SKILL.md`.
47
+
48
+ ## Credentials
49
+
50
+ Use environment variables for ephemeral runs:
51
+ For disposable agent tests, set `DSS_CONFIG_DIR` to a temporary directory so saved credentials never touch your real profile.
52
+ Credential precedence is flags first, then `DATAIKU_*` environment variables, then saved credentials in `DSS_CONFIG_DIR` or the platform config directory.
53
+ Set `DATAIKU_DISABLE_ENV=1` when a test must ignore both `.env` files and `DATAIKU_*` environment variables.
54
+ When `.env` loading is enabled, the CLI reads `.env` from the CLI build/root directory and from the command's current working directory; put test-specific `.env` files in the directory where you invoke `dss`.
55
+
56
+ ```bash
57
+ DATAIKU_URL=https://dss.example.com \
58
+ DATAIKU_API_KEY=your-api-key \
59
+ DATAIKU_PROJECT_KEY=MYPROJ \
60
+ dss project list
61
+ ```
62
+
63
+ Persist credentials when needed:
64
+
65
+ ```bash
66
+ dss auth login --url https://dss.example.com --api-key YOUR_KEY --project-key MYPROJ
67
+ ```
68
+
69
+ The command saves credentials and returns `{ "saved": true, "path": "..." }`.
70
+ `auth login` validates by listing accessible projects before saving credentials, so the API key must be allowed to call DSS project-list APIs.
71
+
72
+ ## Examples
73
+
74
+ ```bash
75
+ dss version
76
+ dss doctor --fast
77
+ dss project list
78
+ dss dataset list --project-key MYPROJ
79
+ dss recipe get-payload compute_orders --project-key MYPROJ
80
+ dss recipe get-payload compute_orders --raw --project-key MYPROJ
81
+ dss recipe get-payload compute_orders --raw --output code.py --project-key MYPROJ
82
+ dss install-skill --dry-run
83
+ ```
84
+
85
+ For fake-DSS smoke tests, return project lists as JSON arrays such as `[{ "projectKey": "MYPROJ", "name": "My Project" }]` from `/public/api/projects/`; recipe payload commands read `/public/api/projects/<PROJECT>/recipes/<NAME>?includePayload=true` and expect a JSON object shaped like `{ "recipe": { "name": "<NAME>", "type": "python" }, "payload": "..." }`.
package/bin/dss.js CHANGED
@@ -1,18 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import { spawnSync, } from "node:child_process";
3
+ import { existsSync, } from "node:fs";
3
4
  import { dirname, resolve, } from "node:path";
4
5
  import { fileURLToPath, pathToFileURL, } from "node:url";
5
6
 
6
7
  const args = process.argv.slice(2,);
8
+ const optionArgs = args.includes("--",) ? args.slice(0, args.indexOf("--",),) : args;
7
9
  const here = dirname(fileURLToPath(import.meta.url,),);
8
- const cliPath = resolve(here, "../dist/src/cli.js",);
10
+ const distCliPath = resolve(here, "../dist/src/cli.js",);
11
+ const sourceCliPath = resolve(here, "../src/cli.ts",);
12
+ const cliPath = existsSync(distCliPath,) ? distCliPath : sourceCliPath;
9
13
  const cliUrl = pathToFileURL(cliPath,).href;
10
14
 
11
15
  function flagValue(names,) {
12
- for (let i = 0; i < args.length; i++) {
13
- const arg = args[i];
16
+ for (let i = 0; i < optionArgs.length; i++) {
17
+ const arg = optionArgs[i];
14
18
  for (const name of names) {
15
- if (arg === name) return args[i + 1];
19
+ if (arg === name) return optionArgs[i + 1];
16
20
  if (arg.startsWith(`${name}=`,)) return arg.slice(name.length + 1,);
17
21
  }
18
22
  }
@@ -20,7 +24,7 @@ function flagValue(names,) {
20
24
  }
21
25
 
22
26
  function hasFlag(names,) {
23
- return names.some((name,) => args.includes(name,));
27
+ return names.some((name,) => optionArgs.includes(name,));
24
28
  }
25
29
 
26
30
  async function loadSavedTlsSettings() {
@@ -59,16 +63,38 @@ if (hasFlag(["--insecure", "--skip-tls-verify",],)) {
59
63
  }
60
64
 
61
65
  const nodeBin = process.versions.bun ? "node" : process.execPath;
62
- const nodeArgs = supportsSystemCa(nodeBin,) ? ["--use-system-ca",] : [];
63
- const result = spawnSync(nodeBin, [...nodeArgs, cliPath, ...args,], {
64
- stdio: "inherit",
65
- env,
66
- },);
66
+ const usesSourceCli = cliPath === sourceCliPath;
67
+ const nodeArgs = !usesSourceCli && supportsSystemCa(nodeBin,) ? ["--use-system-ca",] : [];
68
+ const result = spawnSync(
69
+ usesSourceCli ? "bun" : nodeBin,
70
+ [...(usesSourceCli ? ["--no-env-file",] : nodeArgs), cliPath, ...args,],
71
+ {
72
+ stdio: "inherit",
73
+ env,
74
+ },
75
+ );
67
76
 
68
77
  if (result.error) {
69
- process.stderr.write(
70
- `Unable to start Node runtime for packaged dss CLI (${result.error.message}); falling back to current runtime without Node system CA bootstrap.\n`,
71
- );
78
+ const message = usesSourceCli
79
+ ? `Unable to start Bun runtime for source dss CLI (${result.error.message}).`
80
+ : `Unable to start Node runtime for packaged dss CLI (${result.error.message}); falling back to current runtime without Node system CA bootstrap.`;
81
+ if (usesSourceCli) {
82
+ process.stderr.write(`${
83
+ JSON.stringify(
84
+ {
85
+ ok: false,
86
+ error: message,
87
+ code: "internal_error",
88
+ category: "internal",
89
+ message,
90
+ exitCode: 2,
91
+ },
92
+ null,
93
+ 2,
94
+ )
95
+ }\n`,);
96
+ process.exit(2,);
97
+ }
72
98
  await import(cliUrl);
73
99
  } else if (result.signal) {
74
100
  process.kill(process.pid, result.signal,);
@@ -282,6 +282,11 @@ export declare const FlowZoneItemSchema: import("@sinclair/typebox").TObject<{
282
282
  projectKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
283
283
  }>;
284
284
  export type FlowZoneItem = Static<typeof FlowZoneItemSchema>;
285
+ export declare const FlowZonePositionSchema: import("@sinclair/typebox").TObject<{
286
+ x: import("@sinclair/typebox").TNumber;
287
+ y: import("@sinclair/typebox").TNumber;
288
+ }>;
289
+ export type FlowZonePosition = Static<typeof FlowZonePositionSchema>;
285
290
  export declare const FlowZoneSchema: import("@sinclair/typebox").TObject<{
286
291
  id: import("@sinclair/typebox").TString;
287
292
  name: import("@sinclair/typebox").TString;
@@ -297,6 +302,10 @@ export declare const FlowZoneSchema: import("@sinclair/typebox").TObject<{
297
302
  objectType: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"DATASET">, import("@sinclair/typebox").TLiteral<"MANAGED_FOLDER">, import("@sinclair/typebox").TLiteral<"SAVED_MODEL">, import("@sinclair/typebox").TLiteral<"RECIPE">, import("@sinclair/typebox").TLiteral<"MODEL_EVALUATION_STORE">, import("@sinclair/typebox").TLiteral<"STREAMING_ENDPOINT">, import("@sinclair/typebox").TLiteral<"LABELING_TASK">, import("@sinclair/typebox").TLiteral<"RETRIEVABLE_KNOWLEDGE">]>;
298
303
  projectKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
299
304
  }>>>;
305
+ position: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
306
+ x: import("@sinclair/typebox").TNumber;
307
+ y: import("@sinclair/typebox").TNumber;
308
+ }>>;
300
309
  }>;
301
310
  export type FlowZone = Static<typeof FlowZoneSchema>;
302
311
  export declare const FlowZoneArraySchema: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
@@ -314,17 +323,29 @@ export declare const FlowZoneArraySchema: import("@sinclair/typebox").TArray<imp
314
323
  objectType: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"DATASET">, import("@sinclair/typebox").TLiteral<"MANAGED_FOLDER">, import("@sinclair/typebox").TLiteral<"SAVED_MODEL">, import("@sinclair/typebox").TLiteral<"RECIPE">, import("@sinclair/typebox").TLiteral<"MODEL_EVALUATION_STORE">, import("@sinclair/typebox").TLiteral<"STREAMING_ENDPOINT">, import("@sinclair/typebox").TLiteral<"LABELING_TASK">, import("@sinclair/typebox").TLiteral<"RETRIEVABLE_KNOWLEDGE">]>;
315
324
  projectKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
316
325
  }>>>;
326
+ position: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
327
+ x: import("@sinclair/typebox").TNumber;
328
+ y: import("@sinclair/typebox").TNumber;
329
+ }>>;
317
330
  }>>;
318
331
  export declare const FlowZoneCreateOptionsSchema: import("@sinclair/typebox").TObject<{
319
332
  name: import("@sinclair/typebox").TString;
320
333
  color: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
321
334
  projectKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
335
+ position: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
336
+ x: import("@sinclair/typebox").TNumber;
337
+ y: import("@sinclair/typebox").TNumber;
338
+ }>>;
322
339
  }>;
323
340
  export type FlowZoneCreateOptions = Static<typeof FlowZoneCreateOptionsSchema>;
324
341
  export declare const FlowZoneUpdateOptionsSchema: import("@sinclair/typebox").TObject<{
325
342
  name: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
326
343
  color: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
327
344
  projectKey: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
345
+ position: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TObject<{
346
+ x: import("@sinclair/typebox").TNumber;
347
+ y: import("@sinclair/typebox").TNumber;
348
+ }>>;
328
349
  }>;
329
350
  export type FlowZoneUpdateOptions = Static<typeof FlowZoneUpdateOptionsSchema>;
330
351
  export declare const FolderCreateOptionsSchema: import("@sinclair/typebox").TObject<{
@@ -340,6 +340,10 @@ export const FlowZoneItemSchema = Type.Object({
340
340
  objectType: FlowZoneObjectTypeSchema,
341
341
  projectKey: Type.Optional(Type.String()),
342
342
  }, { additionalProperties: true, });
343
+ export const FlowZonePositionSchema = Type.Object({
344
+ x: Type.Number(),
345
+ y: Type.Number(),
346
+ }, { additionalProperties: false, });
343
347
  export const FlowZoneSchema = Type.Object({
344
348
  id: Type.String(),
345
349
  name: Type.String(),
@@ -347,17 +351,20 @@ export const FlowZoneSchema = Type.Object({
347
351
  projectKey: Type.Optional(Type.String()),
348
352
  items: Type.Optional(Type.Array(FlowZoneItemSchema)),
349
353
  shared: Type.Optional(Type.Array(FlowZoneItemSchema)),
354
+ position: Type.Optional(FlowZonePositionSchema),
350
355
  }, { additionalProperties: true, });
351
356
  export const FlowZoneArraySchema = Type.Array(FlowZoneSchema);
352
357
  export const FlowZoneCreateOptionsSchema = Type.Object({
353
358
  name: Type.String(),
354
359
  color: Type.Optional(Type.String()),
355
360
  projectKey: Type.Optional(Type.String()),
361
+ position: Type.Optional(FlowZonePositionSchema),
356
362
  }, { additionalProperties: false, });
357
363
  export const FlowZoneUpdateOptionsSchema = Type.Object({
358
364
  name: Type.Optional(Type.String()),
359
365
  color: Type.Optional(Type.String()),
360
366
  projectKey: Type.Optional(Type.String()),
367
+ position: Type.Optional(FlowZonePositionSchema),
361
368
  }, { additionalProperties: false, });
362
369
  // ---------------------------------------------------------------------------
363
370
  // Folders