Skip to content

clssck/dataiku-sdk

v4.2.1LicenseRef-Dataiku-SDK-Limited-Use-1.0

Dataiku DSS SDK and agent-oriented CLI for programmatic access to DSS REST APIs.

Changelog

Unreleased

4.2.1

  • Fix: an HTML page answering with 401/403 is unexpected_response (exit 2), not permission_denied. DSS answers those statuses with a JSON error document, so the page came from an intermediary, e.g. a corporate proxy that intercepts GETs for browser authentication (Zscaler) while POSTs pass. The error reads "HTML error page from an intermediary, not DSS" and the hint points at the network path instead of the API key and project permissions. doctor --capabilities reports such probes as unknown instead of no, and the target-absence guard of app create-instance / create-successor-instance surfaces the intercepted probe instead of target_absence_unverifiable (still creating nothing). Verified live behind a simulated intercepting proxy; DSS's own 401/403 stay permission_denied.

4.2.0

  • Fix: scenario canonicalEditableFields named params.triggers and params.reporters; DSS (and dataikuapi) keep triggers and reporters at the top level (triggers, reporters), so an agent following the advertised path wrote fields DSS ignores. Verified live: an email reporter (messaging.type: mail-scenario) and a daily trigger set through scenario update persist.
  • A scenario update that DSS did not persist as sent now carries details.mismatches in the CLI error: each mismatched field with the paths that differ (e.g. reporters.0.messaging.channelId), never the values, since reporter and step settings can hold credentials.
  • scenario reporter-add --channel ID warns reporter_channel_unknown (with the visible channel ids) when no messaging channel has that id: DSS saves such a reporter, but it never sends.
  • A mistyped resource with no close match (dss pipelines list) no longer suggests the same action under unrelated resources.
  • The skill names dss commands run --contains TEXT for finding commands by concept.
  • New messaging-channel resource: list (--type, --family), get, create, settings-get, settings-set (merge, optional --expect-hash), permissions-get, permissions-set, delete, send (multipart mail with --attachment). Credentials (passwords, tokens, webhook URLs, SMTP session secrets) are redacted in output, plans, dry-runs, and errors.
  • New project test-report (JUnit XML or --format html, --output PATH) and project testing-status for the last test-scenario runs; project-deployer testing-status and run-test-scenarios.
  • New skill reference notifications.md: attaching a mail channel to a scenario end to end, direct sends, and test reports.
  • Breaking: agent contract v7. scenario run (without --wait) returns {triggerId, triggerRunId, cancelled, next} instead of {runId}: the id DSS returns from a run request is a trigger run id, not a scenario run id (get-run/log do not accept it). Resolve it with the new scenario get-run-for-trigger SCENARIO TRIGGER_RUN_ID (state PENDING, RUNNING, FINISHED with runId and outcome, or CANCELLED; --trigger-id for non-manual fires); next names it.
  • Fix: a trigger fire DSS cancels because the scenario is already running now ends scenario run-and-wait / run --wait at once with outcome CANCELLED (exit 4, cancelled: true, triggerRunId, a failure.message and next), instead of waiting out the timeout and reporting TIMEOUT.
  • scenario run, run-and-wait: --params JSON / --params-file PATH are the run parameters (the POST body; they appear in the run's trigger.params).
  • scenario last-runs --only-finished (DSS onlyFinishedRuns: skips in-progress runs; --only-finished --limit 1 is the last finished run). New scenario runs-by-date --from DAY [--to DAY] (compact like last-runs; DSS treats --to as exclusive, default tomorrow). New scenario run-report SCENARIO RUNID [--step-id ID] [--output PATH]: the JUnit XML of a test (markedAsTest) scenario run.
  • Scenario authoring: scenario create --data/--data-file/--stdin merges fields (triggers, reporters, steps, runAsUser) into the create body. New scenario trigger-add|trigger-list|trigger-remove (schedules built from --frequency minutely|hourly|daily|weekly|monthly with --every/--hour/--minute/--days/--day-of-month/--run-on/--start-date/--timezone, or any trigger via --data) and reporter-add|reporter-list|reporter-remove (mail reporter from --channel/--recipient/--subject/--message/--condition/--phase, other channel types via --data; credentials are redacted in output and plans). They read, change and write the whole list with the other elements untouched, verify it, and support --dry-run/--plan. New scenario run-as-set --user LOGIN|--clear reports the effective run-as; scenario status shows runAsUser.
  • future list --scenarios-only lists only scenario futures (withNotScenarios=false).

4.1.0

  • Breaking: agent contract v6. scenario get-run and scenario last-runs print compact results by default (--full/--fields return the DSS objects). get-run keeps the run identity, outcome, timing, trigger, per-step built datasets and executed jobs with their error message, plus failure {stepId, jobId, dataset, message} and next argv (e.g. dss job log JOB --errors-only); the raw report's trigger auth context, permission flags, API-key metadata, and log tails are gone (a failed run went from ~5 KB of noise to ~1 KB). A failed last-runs item carries next pointing at scenario get-run. scenario run-and-wait / run --wait failures include failure and next.

  • commands run --fields returns the known selectors when some are unknown and warns unknown_fields with did-you-mean suggestions (flow.map → project.map); it fails only when none are known, now with details.suggestions.

  • commands run --fields RESOURCE (a bare resource, on stdout) lists each action's usage, description, and sideEffect instead of every full entry: --fields recipe is 6 KB instead of 49 KB. In an eval run the agent got a 49 KB, middle-elided result and spent four calls exporting the registry and filtering it with jq. RESOURCE.ACTION and --output PATH still return full entries.

  • --full is accepted on every get read whose output is already the DSS object (recipe, scenario, folder, wiki, …), so "--full returns the DSS object" holds everywhere agents try it; code-env get --full returns the raw definition. connection get/info (secrets redacted), future get, and project-library get do not take it.

  • dataset preview --max-rows above 500 returns the first 500 rows instead of failing; the preview hint points to dss dataset download --limit N --output PATH for more.

  • When the failed recipe is known, scenario get-run and a failed scenario run-and-wait add a hint that spells out the edit-and-rerun loop (recipe get-payload … --output FILE, edit, recipe set-payload … --file FILE, scenario run-and-wait). In evals, agents spent two or three commands run lookups finding those commands.

  • recipe create for a join, grouping, or prepare recipe configured from flags returns next: dss job build-and-wait OUTPUT --build-mode RECURSIVE_BUILD --summary. In evals, agents spent up to four calls looking for how to build a dataset.

  • recipe create --type grouping --aggregate … outputs only the group keys and the requested aggregates: DSS's implicit per-group count column (globalCount) is turned off; add COL:count for a count. With --group-by alone the count stays, as the only aggregate. In 2 of 3 eval runs agents rewrote the payload (3–4 calls) to drop the unrequested count column.

  • A mistyped resource or action (dss flow map, dss recipes list, dss scenario get-runs) fails with "Did you mean dss project map?" in the hint and details.suggestions, so the agent fixes the call without a commands run lookup.

  • DSS_PRETTY=1 indents stdout JSON (results and errors; still one JSON value). Agent shells that cut long lines (omp at 768 bytes) truncated 5–7 one-line results per eval case, and the agent spent calls on artifact reads and jq to recover them.

  • Contributors: bun run eval:agents runs headless coding agents (omp -p) against cases on a live DSS (scenario-fix, data-question, build-flow), verifies the outcome against DSS state, and reports success, tool calls, dss calls, failed dss calls (with argv and error code), and tokens per case in .agent-eval/<run>/ — live feedback on how navigable the CLI is for agents.

  • scenario get-run and failed scenario run-and-wait also name the recipe that failed and the datasets it read (failure.recipe, failure.inputs, from one extra job get only on failure), and next lists recipe cat, dataset schema for those inputs, then job log --errors-only. scenario last-runs shows an in-progress run as outcome: "RUNNING" instead of end: 0 with no outcome. The skill entrypoint tells agents to follow next/hint before exploring, to run reads directly (errors carry the usage line), and to fetch commands run --fields entries only before a first write, batched in one call.

  • Fix: a response that exceeds a client-side size limit ("Response Too Large": buffered bodies over 50 MiB, SQL results over the stream cap) is a non-retryable validation_failed with a hint to narrow the request, not a retryable transient error.

  • Wait timeouts for ML training, scenario runs, futures, and code run say the wait timed out with the last known state, instead of "failed long-running result: RUNNING". They claim the operation was not cancelled only when the result carries cancelled: false; code run points to its cleanup status.

  • Job wait timeouts add resumeArgv (the resume command as an argv array, runnable without shell quoting on Windows); resume stays as the POSIX display form.

  • job log keeps its per-chunk stall timeout and also caps the whole read at 10x --request-timeout, with an error naming that limit, so a log that never stops trickling cannot hang a caller.

4.0.0

  • Breaking: agent contract v5 (agentContractVersion: 5), for the corrected outputShapes and error classifications below.
  • Breaking: Bun 1.4.3 is now the minimum supported version (engines.bun >=1.4.3); CI and release run 1.4.3. On an older Bun, dss exits 2 with a JSON error that tells you to run bun upgrade.
  • Breaking: dataset TSV cell/row limits (a single cell over 16 MiB, a row over 64 MiB) fail as validation_failed (exit 1, not retryable) naming the column and pointing to --columns. They used to surface as a retryable transient "0 Network Error" (exit 3) that no retry could fix. SDK: these are now ClientValidationError, not DataikuError.
  • Breaking: code run reads the tail of the scenario log, and --max-log-bytes / --full-log keep the last N bytes instead of the first; script output keeps its last quarter of that budget. Output over the budget no longer disappears: output holds the tail, with outputTruncated/outputOmittedBytes and a code_run_output_truncated warning. Printed lines containing CR, U+2028 or U+2029 are no longer dropped.
  • Breaking: recipe update rejects envSelection placed at the payload root or under recipe (outside recipe.params) with validation_failed; it was silently ignored. A patch's recipe.params.envSelection now replaces the stored object instead of deep-merging, so switching EXPLICIT_ENV → INHERIT no longer keeps a stale envName. --dry-run previews the exact merged recipe the update sends.
  • Breaking: discovery outputShape is corrected for folder.contents (array), plugin.usages, plugin.download, and project-library.diff (object).
  • Fix: dataset create-managed --record-cleanup records its ledger entry; it used to create the dataset and then fail ambiguous_outcome. Every action that advertises --record-cleanup now derives a cleanup entry (also streaming-endpoint create-managed, ml-task create-for-dataset, saved-model create-external, project-folder create-child, data-collection create, plugin create-dev, and connection/user/group create), enforced by a registry test. If recording still fails after a successful mutation, the error carries details.mutationSucceeded: true, cleanupRecorded: false, and the created identifier and project, so a caller never has to retry the create.
  • project export inspects the written archive and warns (export_contains_credentials, stderr) when it contains credential-bearing structures — project_config API-key/secret files, secret-named project variables (object and list form), web-app apiKey-style fields — listing member paths and key names only, never values; the result adds credentialFindings. project inspect-archive gains the same structural credentialFindings inventory and a residue_scan_skipped warning for scanned members over 1 MiB instead of skipping them silently. Archives are not redacted.
  • Fix: job wait, job build-and-wait, job build --wait, monitor, and watch timeouts say the wait timed out and the job is still running in DSS, keep the last known state, and add cancelled: false and a resume command (dss job wait ID [--project-key KEY]). Before, the error read "failed long-running result: RUNNING" and a deadline during a poll reported state unknown.
  • Fix: job log no longer fails after 30 s on a large log that is still arriving: the request timeout now applies per stalled read, not to the whole transfer. When only the tail fits the 10 MiB buffer, job log warns log_truncated (earlyLinesDropped: true); --errors-only with no matches warns no_error_lines with the scanned line count instead of printing a silent empty string, and keeps the job-level outcome line in logs without DSS record headers too.
  • Fix: job summary returns the log summary plus detailsError when the job-detail response exceeds the 50 MiB buffered limit, instead of failing outright.
  • Fix: job list shows in-progress jobs as state: "RUNNING", and job list --state RUNNING finds them. DSS (verified on 15.0.1) lists a job that is computing dependencies or running with stableState: false and no state, so these jobs printed without a state and the filter matched nothing. --full still returns the DSS objects; job get reports the exact phase.
  • Fix: plugin list keeps isDev in its compact items, so development plugins (editable with contents-*, Git actions) are distinguishable from installed ones without --full.
  • project import reports the DSS status and sanitized details.dssMessage/dssErrorType behind an ambiguous_outcome failure (process step or post-import re-read). DSS 15.0.1 answers an import into a taken project key with 500 Project key KEY is already used; before, only "the project may or may not have been created" was shown. Any ambiguous_outcome/assertion_failed/long_running_failure error that carries a DSS response as its cause now shows the same fields.
  • Fix: dataset preview, dataset download, and dataset assert-count verify that a data stream which ended before the row cap was complete, as dataikuapi does: each read sends a readSessionId and then asks DSS finish-streaming; a server-side read failure now fails the command (and removes the partial download) instead of returning silently short data. Streams stopped at the row cap are not checked.
  • Fix: job log --errors-only (and --log-filter errors) keeps DSS's job-level outcome line, e.g. Job is incompatible with build state: [...] when another running job already builds the target. It has no level word, so the filter used to drop the only reason DSS gives.
  • A client configured with --insecure or --ca-cert sends its requests through its own Bun.FetchSession, so its relaxed or custom TLS connections are never pooled with plain fetch or another client's; HTTP(S)_PROXY/NO_PROXY still apply.
  • More Bun-native APIs: output files are written with Bun.write (paths such as job log --output, recipe get-payload --output, commands run --output now create missing parent directories), dataset TSV decoding uses streaming TextDecoder, hashing uses Bun.CryptoHasher, and scripts use import.meta.dir.
  • Examples use current Python env names (PYTHON311 for plugin code-env-create; DSS 15 rejects new Python 3.6–3.8 code envs).
  • Fix: downloads to a file (project export, folder download, bundle download-exported, plugin/saved-model downloads) create missing parent directories, and stream through a node FileHandle: on Windows, Bun 1.4.3 could end the process with exit 0 in the middle of Bun.write(Bun.file(fd), response), leaving no file. User-supplied files (--file, cleanup ledgers) are read through node:fs, because Bun 1.4.3 Bun.file() reads of a missing path crashed the CLI on Windows instead of reporting ENOENT.
  • Contributors: type checking runs on Bun's built-in bun check (about 3x faster than tsc --noEmit here); the combined gate script is renamed bun run check → bun run verify, because a script named check shadows the built-in. tsc is still used to emit dist/. cross-env is removed (Bun's script runner sets inline env vars on every OS); @types/bun ^1.4.3, dprint ^0.63.0, @dprint/json 0.25.2.
  • Contributors: bun run lint is about 35% faster (1.95 s → 1.29 s) because the dss/* JS-plugin rules are scoped in .oxlintrc.json to the code they guard and no longer run on tests; no-restricted-imports now bans node:string_decoder, node:child_process, and fileURLToPath outside tests and scripts. The SDK/CLI parity integration suite compares through the CLI's compact output shapes.

3.9.0

  • Agent contract v4: job get, dataset info, dataset get, and project get print compact results by default; --full returns the DSS object and --fields still projects from it. job get keeps state, outputs, progress, the error, and per-activity status, and never the log tail: a failed job is 240 tokens instead of 15,908, a finished one 173 instead of 1,170. dataset info keeps type, connection, format, schema, recipes, buildability, data quality, and freshness (1,464 → 131). dataset get and project get keep the settings structure (so get → edit → update still works) without metrics/checks configuration, version stamps, checklists, and empty values; project get lists only the permissions you lack in deniedPermissions instead of ~20 can* booleans (770 → 358, 551 → 149). Discovery output schemas describe the compact shapes; stdio.stdout.lists is now compactResults.
  • job log prints the last 100 lines by default and emits a log_truncated warning with the total; --max-lines N sets the tail, 0 prints everything, --output PATH is unchanged. A finished one-recipe job's log is 4,460 tokens instead of 9,950.
  • Fix: job logs no longer expose secrets. DSS writes the job ticket secret ("jobTicketSecret":"...") into every job log; job log, job summary, job log-url, and --include-logs builds/waits (SDK jobs.log) now redact credential-like JSON values as [redacted].
  • Fix: job log --errors-only and --log-filter errors no longer keep INFO records whose JSON payload merely contains a level word, such as the visual recipe SQL status {"statusWarnLevel":"ERROR",...} line logged by every successful grouping job.
  • project map stops repeating itself: node name is omitted when it equals id, per-node zoneName and the nodeIds lists of zones and components are gone (membership is each node's zoneId/componentId), and empty warnings and an untruncated truncation block are omitted. topologyFingerprint is unchanged. A 7-node map is 513 tokens instead of 701.
  • Error envelopes drop ok:false (same as type:"error") and the echoed resource/action; batch steps keep them at step level.

3.8.0

  • Fix: recipe create --type vstack (and join, geojoin, generate_features) sends the inputs as DSS creationSettings.virtualInputs, as dataikuapi does. DSS builds these recipes' inputs and payload only from virtual inputs, so a Stack recipe was created with inputs: {}, an empty payload, and outputSchemaUpdateError: 500 Internal Error; it now has every input, a UNION payload, and a computed output schema.
  • recipe create --rename/--fill-empty/--formula/--filter/--drop-columns/--keep-columns runs prepare steps in the order the flags are given (the first use of a flag sets its position; SDK stepOrder); before, renames always ran first. A --formula or --filter that still names a column an earlier --rename removed emits recipe_formula_uses_renamed_column, also on --plan.
  • recipe create --name N reports requestedName and a recipe_renamed warning (reason: name_taken for DSS's N_1 suffix, otherwise dss_chose_name) when DSS returns a different recipe name, instead of differing silently. The public API cannot rename a recipe afterwards.
  • Fix: sql query failures that DSS answers with a database error (JDBC/SQL exception, permission denied, object not found) are reported as definite, non-retryable failures carrying the DSS message. Before, a 5xx with e.g. Schema ... does not exist or not authorized came back as ambiguous_outcome ("the mutation outcome is unknown") and was retried as transient. Connection resets, timeouts, generic 5xx answers, and JDBC errors reporting a lost or timed-out database connection (SQLRecoverableException, SQLTimeoutException, I/O error, communication errors) stay ambiguous, since a DML statement may have committed.
  • Fix: a value flag accepts a value that starts with -- when it is not flag-shaped, so --sql "-- comment\nselect ..." works; a missing value whose next token is a flag now hints --flag=VALUE (and --sql-file / --stdin for --sql).
  • Fix: job build-and-wait, job build --wait, and job wait/monitor/watch fail (exit 4, long_running_failure, failure.code: nothing_to_build) when a job ran no activity because a target is a managed dataset that no recipe writes; DSS ends such a job DONE like an up-to-date build. Up-to-date builds and source datasets stay successful. A built_dataset_has_no_columns check that cannot read the schema now emits built_dataset_schema_unchecked instead of passing silently.
  • Fix: dss doctor failing checks include the error message and retry hint, so an untrusted corporate CA shows the TLS code (UNABLE_TO_VERIFY_LEAF_SIGNATURE, self-signed) and the --ca-cert / NODE_EXTRA_CA_CERTS guidance instead of a bare Network Error. Self-signed certificate failures are classified as non-retryable TLS trust failures everywhere.
  • New: dss wiki attach ARTICLE FILE uploads a local file to a wiki article and returns its smartId; dss wiki detach ARTICLE SMART_ID [--if-exists] removes exactly that attachment (DSS has no delete endpoint: the article is saved without it and re-read to verify). Both support --dry-run/--plan; SDK wiki.attach / wiki.detach.
  • New: dataset create creates SQL datasets over an existing table (--table T [--schema S] [--catalog C]) or a query (--query SQL / --query-file PATH) on any SQL connection type. DSS detects the schema (testAndDetectSettings/externalSQL) and it is stored; the result reports schemaDetected and columns. A failed detection keeps the dataset and emits dataset_schema_not_detected. Flag combinations are validated before any request.
  • Fix: flow-zone organize no longer reports a moved zone that DSS left in place. DSS's public API applies a zone position only when the zone is created and ignores it on update (name and color still save), so a plan that moves an existing zone now fails before any change with validation_failed, listing each zone's current and requested position. New --recreate-on-move creates a replacement zone at the requested position, carries over items, shared items, tags, custom fields, and checklists, deletes the old zone, and reports recreated (replacedZoneId -> new zone); the zone id changes. SDK: flowZones.update no longer accepts position; flowZones.recreate moves a zone and fails with ambiguous_outcome and both zone ids if a step breaks partway.
  • Fix: flow-zone organize honors DSS's rule that a recipe and its outputs share a zone. A plan that splits them (which DSS overrides, so every rerun moved them back) is rejected with validation_failed and the conflicting details.conflicts. Listing a recipe or one of its outputs places the whole unit, reported per zone as impliedItems, so --sync no longer sends an unlisted output back to Default and drags its recipe with it.
  • Fix: flow-zone organize zone positions now land where the plan says. DSS stores a position sent on zone creation only while the project's zonesManualPositioning setting is off (with it on, DSS auto-places the zone) and draws positions only while it is on. Organize therefore switches the setting off while it creates or recreates zones and restores it afterwards (manualPositioning, suspendManualPositioning in the result), checks each stored position (assertion_failed with positionsNotApplied otherwise), and warns (zone_manual_positioning_disabled, or zone_manual_positioning_unverified if the settings cannot be read) when positions will not display; the hint is the project settings-set command that enables it.
  • flow-zone plan adds unassigned: Default-zone recipes and source objects still to place (recipe outputs follow their recipe). flow-zone organize publishes its plan JSON Schema as schemas.input in commands run/agent contract. project map --render mermaid colors each zone subgraph with its DSS color.
  • Fix: recipe create --output-connection no longer leaves orphaned output datasets behind when DSS rejects the recipe (e.g. 500 Root path of the dataset ... does not exist for an unbuilt input). The datasets the command created are deleted before the original error is rethrown, and the error details list createdDatasetsDeleted and createdDatasetsNotDeleted (with the delete error) so a failed cleanup is visible. Because a failure can be ambiguous (DSS may have committed the recipe, possibly under another name), a created dataset that a recipe already writes in the flow graph, or every created dataset when the graph cannot be read, is kept and listed in createdDatasetsKept with the reason. Pre-existing datasets are never touched.

3.7.0

  • Fix: recipe create --output-connection creates missing outputs through DSS's managed-dataset endpoint (POST /datasets/managed, as the UI and dataikuapi do), so DSS picks the dataset type, storage path, and format from the connection. Before, the CLI guessed: an S3 connection with no existing dataset got a Filesystem dataset (builds failed with Unexpected connection type ... EC2), and once one S3 dataset existed the next output got SQL-table params with no path (Placing a managed dataset at the root of a connection is not permitted; DSS then answered recipe create --type shaker and dataset refresh-schema with an empty-body 500).
  • Fix: recipe create asks DSS to compute the output schema of visual and SQL query recipes (GET /recipes/{name}/schema-update) after creating and configuring them, and writes it to outputs the command created or whose schema is empty. Join and grouping outputs no longer keep columns: [] and build to an empty dataset. The result reports outputSchemaUpdated; if DSS cannot compute the schema, the recipe is kept and outputSchemaUpdateError plus a recipe_output_schema_not_computed warning explain why. This replaces the sync-only input-schema copy: syncOutputSchemaPropagated is now outputSchemaUpdated.
  • New: dss recipe update-schema NAME (SDK recipes.updateSchema, recipes.computeSchemaUpdates) writes the DSS-computed schema to every output whose schema differs, like the UI's "Update schema" and dataikuapi compute_schema_updates().apply(); --dry-run lists them under pending. Code recipes are rejected up front because DSS cannot compute their schema.
  • recipe set-payload on a visual or SQL query recipe keeps DSS-derived output schemas in step with the new payload: outputs whose schema was empty or matched the DSS-computed one before the upload get the newly computed schema (outputSchemaUpdated), so a grouping created with recipe create and then given keys and aggregations builds with those columns. Hand-edited output schemas are kept and reported in a recipe_output_schema_outdated warning.
  • New: job build / job build-and-wait --auto-update-schema sets DSS's autoUpdateSchemaBeforeEachRecipeRun. A successful dataset build that leaves the target with an empty schema (no columns, no rows) now emits a built_dataset_has_no_columns warning instead of passing silently. The --plan builder had read the unrelated --force-rebuild flag for this setting.
  • Fix: join and fuzzy-join configuration and the managed-folder output swap after recipe create address the recipe by the name DSS returned, not the requested one.
  • dataset create --type Inline explains why editable datasets are rejected (the public API cannot write their rows, and an empty one fails downstream builds) and what to use instead.
  • Fix: job log --errors-only and --log-filter errors keep the exception lines of a failed DSS record (java.lang.IllegalArgumentException: ... Unexpected connection type ..., Caused by: chains, Python traceback frames and the failing line) and drop JVM at frames. Before, an Activity unexpectedly failed header came without its cause: class names such as ClassCastException did not match the keyword filter.
  • field_projection_missing warnings for a nested --fields path now list the keys that exist under the deepest parent that resolved (missing recipe.params lists recipe.type, recipe.name, ...), so an absent key no longer reads as "nested paths are not supported".
  • New: dss connection info NAME (SDK connections.info) reads the non-admin usage view of a connection (GET /connections/{name}/info, dataikuapi DSSConnection.get_info()); connection get reads the admin definition, and its 403 now hints at connection info. Credential fields, including resolved AWS sessionTokens, are redacted.
  • dss doctor reports the identity the API key acts as (identity: authSource, authIdentifier, groups, userProfile from /auth/info), to explain 403s on objects the user's UI profile can use. DSS versions without that route simply omit it.
  • The TLS verification hint names dss auth login --ca-cert PATH for subprocesses: a project .env applies only when dss runs in that directory.
  • Fix: a missing required positional is a missing_required_arg usage error with the usage line for every command. dss knowledge-bank search without an id used to crash as internal_error.
  • Unknown-flag errors carry the command's usage line in hint (and --json says stdout is always JSON), instead of pointing to a ~850-token commands run --fields lookup.
  • CLI DSS error envelopes are one line and carry the DSS message: error is STATUS Text: DSS message (credentials redacted, bounded), where it used to repeat category, retryability, hint, and retry counters as prose and drop the DSS message. details keeps only content (elapsedMs/target, dssErrorType, bodyTruncated, and retry when a retry or timeout happened); dssCategory (same as code), statusText (same as status), and the body metadata string are gone. A 403 names the project (DSS answers 403 for a project that does not exist) and a 404 names the resource and its list command. SDK DataikuError.message is one line too; category, retryability, hint, and retry stay structured fields. A 403 now costs ~100 tokens instead of ~180.
  • A refused connection, unknown host, bad URL, or untrusted certificate fails at once as validation_failed (exit 2) instead of retrying for ~6 s and exiting transient. Timeouts, resets, 429, and 5xx retry as before.
  • New: dss commands run --contains TEXT returns the top 5 actions for a concept ("propagate schema" → flow.propagate-schema, recipe.update-schema; whoami → doctor) with usage and description.
  • Agent contract v3: registry entries list command flags only; the global flags appear once under agent contract commands.globalFlags. structuredExamples drop the shell copy of examples, and the positionals name list (a copy of positionalArguments) is gone. dataset.get is 697 tokens instead of 847, the full registry 275k instead of 347k.
  • *.list commands print compact items by default (identifiers, kind, and next-step fields such as recipe inputs/outputs or dataset connection): a 6-dataset list is 118 tokens instead of 4,490, a project list 51 instead of 1,076. --full returns the DSS objects, --fields still projects from them, --contains TEXT filters on identifiers, and --limit N caps the count with a list_truncated warning. Discovery output schemas describe the compact items.
  • Bun 1.4.2 is now the minimum supported version (engines.bun >=1.4.2); CI tests 1.4.2 only. On an older Bun, dss exits 2 with a JSON error that tells you to run bun upgrade.
  • Fix: when dss runs under Bun itself (bunx --bun, bun --no-env-file), canary builds such as 1.4.3-canary.12 pass the minimum-version check again; Bun.semver range matching rejected every prerelease. The Node and Bun launch paths now share one release-part comparison (bin/bun-version.js).
  • Faster startup (min of 21 runs, source checkout): dss version 100 → 49 ms, commands run 138 → 47 ms, dataset create --plan 111 → 62 ms, dataset list 130 → 108 ms. Flag validation loads only the command registry: plan builders moved to src/cli/plans.ts and load only for --plan. The commands run summary reads action names from command-syntax.json without loading command modules. DataikuClient loads each resource module on first use. node:crypto, node:stream, and node:zlib are gone from the common paths, and node:tls loads only for a custom CA bundle. Registry, summary, and agent-contract output are byte-identical.
  • datasets.download / dss dataset download stream through Web Streams (TransformStream, CompressionStream("gzip")) into Bun.write: a 200k-row gzip export takes 345 ms instead of 571 ms (same bytes), and reaching the row limit now cancels the response instead of draining it.
  • Binary downloads (writeResponseToFile) stream with Bun.write into the exclusive owner-only temp file before the atomic rename. A temp file that cannot be created still cancels the response body.
  • New: dss flow propagate-schema DATASET (SDK flow.propagateSchema) runs the UI's schema propagation through every downstream recipe, rebuilding as needed unless --no-auto-rebuild; --stop-at/--mark-ok RECIPES bound it and --wait waits. dss flow generate-documentation exports the flow documentation (docx) from the default template, --template-file, or --folder/--path; --output PATH waits and downloads it.
  • New: recipe create builds grouping and prepare payloads from flags: --group-by, --aggregate COL:FN[+FN], --order-by for grouping; --rename, --fill-empty, --formula, --filter, --drop-columns, --keep-columns for prepare (--type prepare maps to shaker). Builder flags on another recipe type are a usage error; --plan lists the payload edits.
  • New: dataset preview/download --columns COLS --partitions P read a column or partition subset (POST /data/); dataset sync-hive-metastore and update-from-hive; metrics dataset-run-checks; data-quality instance-status, partitions-status (defaults to NP), and delete-history --partition.
  • New: dss mlflow wraps the DSS MLflow extension (/api/2.0/mlflow/extension/*): list-models RUN_ID, set-inference-info, deploy-run RUN_ID SAVED_MODEL_ID (synchronous; raise --request-timeout), create-experiments-dataset, and the destructive garbage-collect and clean-db. SDK client.mlflowExtension; DataikuClient.get/post accept extra request headers for the x-dku-mlflow-project-key header.
  • New: Project Deployer list-stages, get-infra, infra-settings, save-infra-settings, delete-infra, deployment-settings, governance-status, delete-project, project-settings, save-project-settings, delete-bundle; bundle get-exported and bundle create-project (Automation node, --file upload or --archive-path).
  • New: Visual ML diagnostics and documentation. ml-task and saved-model share diagnostics --kind (subpopulation analyses, partial dependencies, timeseries residuals, per-timeseries metrics and forecasts), compute-diagnostics --kind ... [--features COLS] [--wait], generate-documentation [--output PATH], download-documentation, set-user-meta, and the license-gated download-scoring-jar/download-scoring-pmml; SDK mlTasks.model(a, t, m) and savedModels.version(sm, v) return one TrainedModel. Also ml-task list, create-for-dataset (new analysis, time series forecasting with --time-variable/--timeseries-ids), reguess, reguess-forecasting, and analysis update/list-ml-tasks. GET .../models-snippets stays unwrapped: DSS requires a body on that GET, which fetch cannot send.
  • New: workspace remove-object, webapp trust [--for-everybody], future list [--all-users] [--with-scenarios], discussion update --topic, wiki update-settings, streaming-endpoint create-managed/schema/set-schema, and project push-to-git-remote REMOTE.
  • Fix: a 403 hints that the project may not exist only when DSS's message is about the project; "You are not allowed to trust this webapp" keeps the generic permission hint.
  • The DSS 15 coverage matrix covers 371 of 372 documented operations; Project Deployer stages and create infra rows now carry their documented paths.
  • Dev tooling: oxlint and @oxlint/plugins 1.86.0, dprint 0.60.1 with its npm-published TypeScript 0.96.1 and JSON 0.25.1 plugins (the JSON plugin orders package.json keys canonically). The editor language server is TypeScript 7's native tsc --lsp --stdio; typescript-language-server and the TypeScript 5.9.3 tsserver alias are gone, so TypeScript 7 is the only TypeScript in the repo. bun run lint reports no warnings.
  • Live tests cover the DSS 15 gap actions: column/partition dataset reads, dataset checks, flow schema propagation and documentation, the MLflow extension, Visual ML diagnostics, documentation, re-guessing and time series forecasting, the new Project Deployer settings, governance and delete actions, workspace object removal, discussion topic edits, future listing, wiki settings, and data-quality instance/partition status. Lab teardown deletes Project Deployer infras and published projects through project-deployer delete-infra/delete-project instead of raw API calls.

3.6.1

  • Fix: the Node-launched dss checks the Bun version (release part only, so canary builds pass) before spawning Bun, so an old Bun gets the JSON error instead of its own argument-parsing failure.
  • batch --dry-run has a regression test proving it applies the same meta-command flag checks as a direct run.
  • Remove the unused DSS_LOAD_SOURCE launcher variable; load source comes only from where the CLI module actually lives.

3.6.0

  • Fix: a non-2xx response whose body misses the request deadline keeps its real HTTP status instead of becoming a bare network timeout.
  • Fix: target_absence_unverifiable (a masked 403 on an explicit target key) exits 2 like other permission/environment failures; exit 1 is reserved for usage errors.
  • Fix: an environment variable set to "" counts as set everywhere, so .env can no longer fill it (DATAIKU_URL="" clears a .env value).
  • Fix: bin/dss.js runs source in a checkout instead of a leftover dist/, never trusts an inherited DSS_LOAD_SOURCE/DSS_BUILD_REVISION, and checks the Bun version against engines.bun before running, with a JSON error.
  • Release: the version lifecycle moves ## Unreleased entries under the new version heading, and bun run check fails when the current version has no section; the history is split into 3.2.0–3.5.0 sections by release tag.
  • Packaging: stop building and shipping the unreachable packages/types/dist/; prepublishOnly reuses prepack; drop the duplicate bundledDependencies.
  • Internal: one meta-command validator for direct and batch runs; one argv positional scanner; no in-loop re-check of cleanup incarnation bindings; one isRecord/asRecord; saved-model validators live in resources/base.ts; Content-Type is sent only with a body; retryMaxAttempts is documented as total attempts.
  • Docs: skill names dss doctor, drops SDK test-fixture text, and states the one empty-variable rule; README token figures defer to bun run test:tokens; a test now machine-checks the API coverage matrix counts and every CLI/SDK mapping; .gitignore covers install-skill project targets.

3.5.0

  • CI tests both the minimum supported Bun (1.4.0) and the latest (1.4.2) on all three operating systems; the release workflow runs 1.4.2; @types/bun ^1.4.2.
  • Lint: dss/no-uncoded-errors rejects built-in Error/TypeError/RangeError/SyntaxError throws and reject(new Error(...)) anywhere in src/; no-raw-json-parse-in-resources requires resource JSON.parse to sit in the try block of a try/catch; no-usage-literals rejects hand-written usage text; no-direct-process-env confines environment reads to env.ts, runtime.ts, and config.ts (the few other reads carry a justified disable comment). node:crypto createHash is restricted to sha256Hex in src/. bun run lint now covers all of tests/ and scripts/.
  • Every error the SDK and CLI raise now carries a stable code; nothing reaches agents as an uncoded internal_error by accident. Caller and state problems are validation_failed (exit 1); a missing project key, URL, or API key from the SDK client is missing_required_flag (exit 1, matched by type instead of by message text); a bad CA bundle path is invalid_flag_value; malformed 2xx DSS responses (missing body, id, job id, recipe name, archive member) are one canonical DataikuError classified unexpected_response (exit 2) via unexpectedResponseError, and non-JSON bodies use the existing nonJsonResponseBody form; Project Git future failures and timeouts are long_running_failure (exit 4); genuine invariants (missing bundled skill, missing command syntax, stalled local writes) are explicit internal_error (exit 2).
  • Fix: 113 more hand-written usage strings in requireArgs calls and Usage: messages are rendered from the command syntax; many had drifted from the real syntax.
  • Security: .env files now supply only DATAIKU_*, NODE_TLS_REJECT_UNAUTHORIZED, and NODE_EXTRA_CA_CERTS; other keys are ignored, so a project .env can no longer redirect DSS_CONFIG_DIR (and with it saved credentials).
  • Fix: cleanup --dry-run --apply is now a usage error instead of running the destructive replay; auth login --dry-run is rejected instead of logging in and saving credentials; meta commands (doctor, auth, install-skill, agent, version, cleanup, fixtures, batch) now reject flags they do not support.
  • Fix: --expect-hash accepts uppercase hex in both the SDK and CLI code-env set-definition paths (including --dry-run); commands without a plan mode (e.g. doctor, fixtures) reject --plan instead of running live; auth login advertises its --plan preview.
  • Fix: SQL query failures surface as DSS validation_failed errors (exit 2, true 2xx status) and non-JSON SQL result streams as unexpected_response, instead of internal_error; non-JSON bodies are summarized by one shared helper.
  • Fix: batch --dry-run step errors report their own step's resource/action instead of a concurrently validated sibling's.
  • Fix: --plan now matches the request actually sent for scenario create (default params), scenario active-set (merged light status, listed under requests), flow-zone create (default color, no stray projectKey), dataset create and recipe create (both built by the same body builders as the real request), folder create (full params), saved-model evaluate-version (query flags), plugin install-from-git/update-from-git/create-dev (null git fields), plugin rename/move (leading-slash paths), bundle export (no body), and wiki create (content is a follow-up update, listed under requests). A test now runs every documented write example with --plan and for real against a mock server and requires identical method, endpoint, and body, skipping plans marked exact: false and deliberately redacted payloads.
  • Security: plugin create-dev --plan no longer echoes credentials embedded in --repository; the URL is validated like install-from-git.
  • Command syntax is now structured data: src/cli/command-syntax.json holds a syntax tree per command (words, positionals, flags with value/enum/note, optional groups, required choices). Every usage line is rendered from it, and the contract fields (flags, required flags and choices, value hints, positionals, stdin/data inputs, dry-run, local-file output, aliases, project scope, idempotency flags, cleanup commands) are derived by walking it; the regex parsing of usage prose is gone, as are 281 hand-copied usage strings in handler error messages (now rendered) and 26 abbreviated Usage: messages that had drifted (e.g. scenario active-set <id> <true|false>). The registry is byte-identical except: recipe clone now advertises its optional source positional (the old parser only recognized uppercase positionals in choices), and wiki update/insight create render their required choice with uniform | separators.
  • Fix: batch --dry-run accepts notebook unload-jupyter --all; the CLI's required-positional count had treated <name> <sessionId> as required even though --all replaces them, contradicting the registry.
  • Plans that depend on live DSS state (dataset clone, folder create without --connection, variable set, app create-instance with a generated key, saved-model import-mlflow-version-from-folder) now say so with exact: false and a reason, like recipe run and api-service add-prediction-endpoint, instead of placeholder values.
  • Remove the unused src/utils/pagination.ts, the stray Product_Aggregated.csv.gz and VALIDATION-2026-09-14.md; share one SHA-256 helper and case-insensitive hash pattern, one set of poll defaults, and one schema export surface (export *), which also restores the previously dropped CodeEnvLogSummaryArray and SqlNotebookHistory exports.
  • CI runs on pull requests and pushes to main; SECURITY.md covers the current 3.x line; docs no longer claim --dry-run never contacts DSS, list the removed --json flag, or deny the dss plugin authoring commands. CLI test harness defaults to DATAIKU_DISABLE_ENV=1 so the checkout .env cannot leak into tests.
  • Direct skill agents to always invoke the installed dss command instead of calling bin/dss.js through Bun; clarify source/built .env lookup and environment-only login, reducing skill and authentication guidance without removing safety requirements.

3.4.0

  • Flush dataset CSV exports in bounded batches (64 KiB) at row boundaries, before truncation limits, and at EOF: byte-identical output while a 200k-row (8.96 MB) export drops from 16.6 s to 0.5 s.
  • Honor DataikuGetOptions.noRetry in the client get path and Git transport, and give every futures, jobs, ML-training, and Project Git wait loop a spent-budget single observation: the first request always happens (capped by the per-request timeout), no later request starts after the budget expires, and the structured timeout reports the last observed state without clamping the first request.
  • Serve CLI discovery output schemas from the committed src/generated/action-output-schemas.json: build regenerates it ahead of tsc, while check and prepack/prepublishOnly verify freshness (after and before compilation respectively); full-registry and scoped contract bytes are unchanged, source checkouts work without dist, and scoped discovery latency drops by about half.
  • Enforce the project map metadata budget through the client's total request timeout (1500 ms), distinguishing deadline expiry from earlier per-request failures; FlowZones.list accepts DataikuGetOptions.
  • Correct skill release examples to snapshot permissions before mutations and reserve cleanup for rollback; remove the blanket credential-free planning claim and document schema file input and unfiltered log export.
  • Honor Retry-After seconds and HTTP dates within existing retry eligibility, the 30-second automatic wait cap, and total request deadlines.
  • Materialize discovery entries per action and schemas on access; defer runtime-only SDK imports while preserving full registry output.
  • Extract the first visible HTML error line without allocating an array for every line, retaining carriage returns, decoding, and sanitization.
  • Serialize releases around one versioned, integrity-checked tarball tested on every platform; verify npm metadata and canonical download availability before pushing the candidate commit/tag atomically. Preserve candidates for safe failed-job recovery without automatic republishing.

3.3.0

  • Use platform-aware basenames for local MLflow archive uploads, keeping Windows parent directories out of multipart filenames.
  • Build scoped discovery metadata only for requested resources, generate action indexes without payload schemas, and lazily materialize bootstrap sections; preserve registry bytes and global missing-field recovery hints.
  • Bound SDK HTTP error bodies using the configured response limit, preserve UTF-8 boundaries and retry/deadline rules, and expose trusted truncation state through error wrappers and CLI diagnostics.
  • Route skill discovery directly to full entries for writes and resource-only action indexes; accelerate optional native token measurements while retaining pinned JS parity and validation checks.
  • Validate real Application Designer download-folder and form-variable references; report deleted download folders instead of silently skipping them.
  • Self-provision owned Application Designer templates in the live suite, exercise variable/scenario/download and version workflows, and retire only proven unused creation reservations without cleanup requests or project-key reuse.
  • Let app create-instance generate a cryptographically random project key when targetProjectKey is omitted, preserving the display name without requiring global project visibility. Keep strict checks for explicit keys, future/cleanup identity guards, and allocation-free plans; expose fresh-key creation in masked-403 recovery guidance.
  • Let app successor-preflight and app create-successor-instance omit --to and generate the successor target key during apply: preflight, plan, and dry-run stay targetless and allocation-free (targetProjectKeyGeneratedDuringApply, targetPreflight:"not-applicable-generated-key"), source/template/optional-ACL gates still run, the key is generated once before the single POST, cleanup binds the creation future plus creationTag, and an explicit --to keeps the strict masked-403 absence guard with no POST.
  • Preserve bounded, credential-redacted DSS messages and error types in ambiguous mutation failures without enabling retries or weakening unknown-outcome handling.
  • Require app-release sharing checks: snapshot and compare intended users, groups, and roles; restore approved missing access without dropping newer grants, then verify with the intended identities.
  • Preserve guarded app-deletion receipts and host ownership markers across cleanup failures; remove empty private host directories without widening their permissions.
  • Use owned Filesystem fixtures with two-principal inherited ACLs, DSS-selected managed-folder storage, and native-only code-environment rebuilds in live verification.
  • Keep unavailable dashboard rendering and meaning deletion explicitly blocked, but optional in current-capability live runs.
  • Exercise App catalog reads against owned templates and attribute successful group reads to the read-only directory case instead of blocked account creation.
  • Make the app-release rollback example apply cleanup explicitly; distinguish mutation with --apply from the default preview.
  • Enforce project-owned accumulator-copy, widen-then-assert, and chained-assertion lint rules alongside the native accumulating-spread check. Remove double assertions through typed merge results, direct schema assignments, shared raw-body/Git transport methods, and iterable response streams.
  • Add 113 CLI actions across eight new resource families and expanded scenario, metadata, dataset, saved-model, and connection APIs, with SDK exports and mutation preview contracts.
  • Add LLMs, knowledge banks, project folders, data collections, users, groups, macros, and plugin administration; include MLflow imports and scoring exports.
  • Bound ML training and macro status waits across requests, retries, and response bodies; preserve per-request timeout caps and distinguish request expiry from overall wait expiry. Use adaptive future and Project Git polling unless an interval is explicit.
  • Keep early CLI usage errors lightweight with resource-local command loading while preserving structured errors.
  • Reject malformed directory and scenario-history responses and missing run identifiers; consolidate SDK identifier validation and recursive secret sanitization.
  • Use next consistently in metadata previews. Normalize commands to project-folder settings-get/settings-set, data-collection settings-set, and scenario payload-get/payload-set/active-set; remove the old names.
  • Remeasure and verify native cross-model discovery-token baselines after API expansion and command renames.
  • Publish the DSS 15 API-to-SDK-to-CLI coverage matrix, including remaining gaps and documented endpoint discrepancies.
  • Expand the self-provisioning live runner with an --profile all selector that widens run-case availability to every profile inside one persistent lab (distinct from the destructive all lifecycle verb), persistent --state-dir demo labs, retained trained-ML state across iterations, and new expanded case families (bundles, Project Git, scenario statistics/payloads, application manifests, webapp backend state, infrastructure reads, disposable folders/notebooks, disposable global lifecycles).
  • Add isolated-disposable global case families (users, groups, meanings, workspaces, data collections, API-deployer infra/services/deployments, plugins, project folders) guarded by exact lab-manifest reservations and ownership markers (ctx.markerFor; code-envs bind on the server desc.creationTag incarnation snapshot), with per-command identity re-verification, never-delete-blind conflict handling, and no modification of pre-existing accounts or configuration.
  • Record explicit per-action unavailability for licensed or disabled instance features, external deployment/auth backends, plugin-store access, and cost-bearing LLM/macro surfaces; every registered action stays enumerated as demonstrated, blocked with a recorded prerequisite, or uncovered, with no silent omissions.
  • Serve plugin git-branches with GET: DSS 15 rejects POST on that route with 405 rawMethodPOSTnotsupported despite the public documentation listing POST.
  • Clarify code-env set-packages clearing semantics: the package list is replaced wholesale, so an explicitly empty --packages value (or an empty --file) clears the requested specs, while a call with no package source flag is a usage error.
  • Exercise plugin-managed code environments explicitly in the live harness: derived environments are deleted before the parent plugin (no server-side cascade) and plugin updates link the settings.codeEnvName association created after plugin creation; MLflow import fixtures use canonical code/data/env packaging inside owned runtime environments.
  • Require the DSS 15 containerExecConfigName parameter explicitly on MLflow imports and evaluations: send NONE for archive imports, folder imports, and evaluation bodies (folder imports no longer inherit), with plan parity and regression coverage.

3.2.0

  • Optimize all seven skill references, cutting their combined OpenAI text-token count by 15.2% while preserving runnable examples and safety conditions; add per-reference budgets.
  • Reduce installed-skill tokens by about 12% across model encodings and shorten discovery prose, retaining safety guidance, schema contracts, and reference links; tighten the skill budget to prevent regrowth.
  • Add opt-in cross-model discovery token budgets using an external OMP native module, preserving the mandatory pinned OpenAI gate and adding no production dependency.
  • Preserve request IDs and trusted target/timing metadata when enriching SQL failures.
  • Treat SQLite missing-column and missing-table errors as nonretryable validation failures, including when SQL start retries are explicitly enabled; preserve ambiguous mutation outcomes.
  • Decode bounded HTTP text incrementally to reduce large-response allocations while retaining byte limits, read deadlines, and UTF-8 truncation behavior.
  • Load CLI command dependencies lazily and build only the selected resource registry during validation, preserving full discovery contracts.
  • Publish SQL JSON exports atomically after query completion, retaining existing permission bits and using the process umask for new files; preserve existing destinations on failure and avoid iterable-string file writes.
  • Add a separate, self-provisioning test:live runner with persistent setup/run/clean, upfront case validation, optional capability profiles, guarded ownership and local outputs, failure-preserving cleanup journals, deterministic fixtures, explicit registry coverage reports, and regular type/lint gates.
  • Normalize explicit boolean flag values and aliases before dispatch; share plan/dry-run resolution across direct, batch, and local commands.
  • Bound stalled streaming body reads without imposing a total-duration limit on healthy archive transfers; use backpressure-aware file streaming and publish archive/folder outputs only after completion, preserving existing files on failure.
  • Report unreadable JSON/text input files as structured usage errors rather than internal failures.
  • Report the actual home target for global skill installation.
  • Split the Dataiku skill into a short entrypoint and seven on-demand references; install and hash the complete bundle, detect incomplete reference trees, and preserve unrelated destination files.