dataiku-sdk 0.9.0 → 0.10.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 +5 -4
- package/dist/src/cli.js +410 -29
- package/dist/src/client.d.ts +15 -2
- package/dist/src/client.js +26 -5
- package/dist/src/index.d.ts +1 -1
- package/dist/src/skill.js +6 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -8,21 +8,22 @@ Examples below assume the installed `dss` binary. From this checkout, use `./bin
|
|
|
8
8
|
## CLI contract
|
|
9
9
|
|
|
10
10
|
- Success: stdout contains one JSON result.
|
|
11
|
-
- Failure: stderr contains one
|
|
12
|
-
- `--verbose`
|
|
11
|
+
- Failure: stderr contains one JSONL error event with `type:"error"`, `ok:false`, `error`, `code`, and `exitCode`.
|
|
12
|
+
- Non-fatal diagnostics and `--verbose` traces are JSONL stderr events (`type:"warning"` / `type:"trace"`); no prose trace lines are part of the contract.
|
|
13
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
14
|
- No prompts, help screens, tables, banners, or prose output are part of the contract.
|
|
15
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
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
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
18
|
|
|
19
|
-
Discover the complete machine-readable command surface:
|
|
19
|
+
Discover the agent protocol and complete machine-readable command surface:
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
dss agent contract
|
|
22
23
|
dss commands run
|
|
23
24
|
```
|
|
24
25
|
|
|
25
|
-
Agents should parse `commands run` before choosing syntax; inspect `flags`, `requiresAuth`, `requiresProject`, `sideEffect`, and `outputShape` instead of guessing.
|
|
26
|
+
Agents should parse `agent contract` once for protocol/schema compatibility, then parse `commands run` before choosing syntax; inspect `flags`, `structuredExamples`, `schemas`, `requiresAuth`, `requiresProject`, `sideEffect`, `unsafeOutputs`, and `outputShape` instead of guessing.
|
|
26
27
|
|
|
27
28
|
## Agent skill installation
|
|
28
29
|
|
package/dist/src/cli.js
CHANGED
|
@@ -72,6 +72,9 @@ function gitRevision(packageRoot) {
|
|
|
72
72
|
const PACKAGE_ROOT = findPackageRoot();
|
|
73
73
|
const CLI_VERSION = packageVersion(PACKAGE_ROOT);
|
|
74
74
|
const CLI_GIT_REVISION = gitRevision(PACKAGE_ROOT);
|
|
75
|
+
const AGENT_CONTRACT_VERSION = 1;
|
|
76
|
+
const JSON_SCHEMA_DRAFT = "https://json-schema.org/draft/2020-12/schema";
|
|
77
|
+
const AGENT_CONTRACT_SCHEMA_ID = "https://clssck.github.io/dataiku-sdk/schemas/agent-contract-v1.json";
|
|
75
78
|
function cliVersionResult() {
|
|
76
79
|
return { version: CLI_VERSION, gitRevision: CLI_GIT_REVISION ?? null, };
|
|
77
80
|
}
|
|
@@ -1128,13 +1131,13 @@ let pendingCliWarnings = [];
|
|
|
1128
1131
|
function enqueueCliWarning(warning) {
|
|
1129
1132
|
pendingCliWarnings.push(warning);
|
|
1130
1133
|
}
|
|
1131
|
-
/** Emit queued warnings as
|
|
1134
|
+
/** Emit queued warnings as one JSONL warning event on stderr. Idempotent. */
|
|
1132
1135
|
function flushCliWarnings() {
|
|
1133
1136
|
if (pendingCliWarnings.length === 0)
|
|
1134
1137
|
return;
|
|
1135
1138
|
const warnings = pendingCliWarnings;
|
|
1136
1139
|
pendingCliWarnings = [];
|
|
1137
|
-
process.stderr.write(`${JSON.stringify({
|
|
1140
|
+
process.stderr.write(`${JSON.stringify({ type: "warning", warnings, })}\n`);
|
|
1138
1141
|
}
|
|
1139
1142
|
function resolveFieldPath(source, field) {
|
|
1140
1143
|
let current = source;
|
|
@@ -1499,6 +1502,7 @@ const BOOLEAN_FLAGS = new Set([
|
|
|
1499
1502
|
"errors-only",
|
|
1500
1503
|
"keep",
|
|
1501
1504
|
"full-log",
|
|
1505
|
+
"drop-data",
|
|
1502
1506
|
]);
|
|
1503
1507
|
const SHORT_FLAGS = {
|
|
1504
1508
|
v: "verbose",
|
|
@@ -1517,6 +1521,12 @@ const FLAG_ALIASES = {
|
|
|
1517
1521
|
};
|
|
1518
1522
|
const VALUE_FLAGS = new Set([
|
|
1519
1523
|
"fields",
|
|
1524
|
+
"owner",
|
|
1525
|
+
"topic",
|
|
1526
|
+
"reply",
|
|
1527
|
+
"text",
|
|
1528
|
+
"partitions",
|
|
1529
|
+
"since",
|
|
1520
1530
|
"activity",
|
|
1521
1531
|
"agent",
|
|
1522
1532
|
"api-key",
|
|
@@ -6473,6 +6483,8 @@ async function runFixtures(flags) {
|
|
|
6473
6483
|
const READ_ACTIONS = new Set([
|
|
6474
6484
|
"cat",
|
|
6475
6485
|
"contents",
|
|
6486
|
+
"deployment-settings",
|
|
6487
|
+
"deployment-status",
|
|
6476
6488
|
"diff",
|
|
6477
6489
|
"download",
|
|
6478
6490
|
"download-code",
|
|
@@ -6508,6 +6520,7 @@ const READ_ACTIONS = new Set([
|
|
|
6508
6520
|
"status",
|
|
6509
6521
|
"rules",
|
|
6510
6522
|
"settings",
|
|
6523
|
+
"settings-get",
|
|
6511
6524
|
"status-by-partition",
|
|
6512
6525
|
"usages",
|
|
6513
6526
|
]);
|
|
@@ -6539,6 +6552,9 @@ const AUTHENTICATED_AGENT_FLAGS = [
|
|
|
6539
6552
|
const COMMANDS_USAGE = "dss commands run [--json]";
|
|
6540
6553
|
const COMMANDS_DESCRIPTION = "Print the machine-readable command registry for agent planning.";
|
|
6541
6554
|
const COMMANDS_EXAMPLES = ["dss commands run", "dss commands run --json",];
|
|
6555
|
+
const AGENT_CONTRACT_USAGE = "dss agent contract";
|
|
6556
|
+
const AGENT_CONTRACT_DESCRIPTION = "Print the versioned JSON contract agents should use to drive dss.";
|
|
6557
|
+
const AGENT_CONTRACT_EXAMPLES = ["dss agent contract",];
|
|
6542
6558
|
const VERSION_USAGE = "dss version";
|
|
6543
6559
|
const VERSION_DESCRIPTION = "Print the CLI version and git revision as JSON.";
|
|
6544
6560
|
const VERSION_EXAMPLES = ["dss version", "dss --version",];
|
|
@@ -6585,6 +6601,118 @@ function flagKind(name) {
|
|
|
6585
6601
|
function registryKey(resource, action) {
|
|
6586
6602
|
return `${resource}.${action}`;
|
|
6587
6603
|
}
|
|
6604
|
+
function splitShellLike(input) {
|
|
6605
|
+
const tokens = [];
|
|
6606
|
+
let current = "";
|
|
6607
|
+
let quote;
|
|
6608
|
+
for (let index = 0; index < input.length; index++) {
|
|
6609
|
+
const char = input[index];
|
|
6610
|
+
if (quote) {
|
|
6611
|
+
if (char === quote) {
|
|
6612
|
+
quote = undefined;
|
|
6613
|
+
}
|
|
6614
|
+
else if (char === "\\" && quote === '"' && index + 1 < input.length) {
|
|
6615
|
+
current += input[++index];
|
|
6616
|
+
}
|
|
6617
|
+
else {
|
|
6618
|
+
current += char;
|
|
6619
|
+
}
|
|
6620
|
+
continue;
|
|
6621
|
+
}
|
|
6622
|
+
if (char === "'" || char === '"') {
|
|
6623
|
+
quote = char;
|
|
6624
|
+
continue;
|
|
6625
|
+
}
|
|
6626
|
+
if (/\s/.test(char)) {
|
|
6627
|
+
if (current.length > 0) {
|
|
6628
|
+
tokens.push(current);
|
|
6629
|
+
current = "";
|
|
6630
|
+
}
|
|
6631
|
+
continue;
|
|
6632
|
+
}
|
|
6633
|
+
if (char === "|" || char === "<" || char === ">" || char === ";" || char === "&") {
|
|
6634
|
+
return undefined;
|
|
6635
|
+
}
|
|
6636
|
+
current += char;
|
|
6637
|
+
}
|
|
6638
|
+
if (quote)
|
|
6639
|
+
return undefined;
|
|
6640
|
+
if (current.length > 0)
|
|
6641
|
+
tokens.push(current);
|
|
6642
|
+
return tokens;
|
|
6643
|
+
}
|
|
6644
|
+
function exampleArgv(example) {
|
|
6645
|
+
const tokens = splitShellLike(example);
|
|
6646
|
+
if (!tokens || tokens[0] !== "dss")
|
|
6647
|
+
return undefined;
|
|
6648
|
+
return tokens.slice(1);
|
|
6649
|
+
}
|
|
6650
|
+
function structuredExamples(examples, examplePayload) {
|
|
6651
|
+
return (examples ?? []).map((shell) => {
|
|
6652
|
+
const argv = exampleArgv(shell);
|
|
6653
|
+
return {
|
|
6654
|
+
shell,
|
|
6655
|
+
...(argv ? { argv, } : {}),
|
|
6656
|
+
...(examplePayload !== undefined && shell.includes("--data")
|
|
6657
|
+
? { payload: examplePayload, }
|
|
6658
|
+
: {}),
|
|
6659
|
+
};
|
|
6660
|
+
});
|
|
6661
|
+
}
|
|
6662
|
+
function outputJsonSchema(shape) {
|
|
6663
|
+
if (shape === "array")
|
|
6664
|
+
return { type: "array", items: true, };
|
|
6665
|
+
if (shape === "string")
|
|
6666
|
+
return { type: "string", };
|
|
6667
|
+
return { type: "object", additionalProperties: true, };
|
|
6668
|
+
}
|
|
6669
|
+
function payloadJsonSchema(payloadSchema) {
|
|
6670
|
+
if (!payloadSchema)
|
|
6671
|
+
return undefined;
|
|
6672
|
+
return payloadSchema.jsonShape === "array"
|
|
6673
|
+
? { type: "array", items: true, }
|
|
6674
|
+
: { type: "object", additionalProperties: true, };
|
|
6675
|
+
}
|
|
6676
|
+
function argvJsonSchema(resource, action, _flags, _positionals, _requiredFlags, _requiredOneOf) {
|
|
6677
|
+
return {
|
|
6678
|
+
type: "object",
|
|
6679
|
+
additionalProperties: true,
|
|
6680
|
+
required: ["argv",],
|
|
6681
|
+
properties: {
|
|
6682
|
+
argv: { type: "array", items: { type: "string", }, minItems: 1, },
|
|
6683
|
+
resource: { const: resource, },
|
|
6684
|
+
action: { const: action, },
|
|
6685
|
+
},
|
|
6686
|
+
};
|
|
6687
|
+
}
|
|
6688
|
+
function unsafeOutputs(resource, action, flags, producesLocalFile) {
|
|
6689
|
+
const outputs = [];
|
|
6690
|
+
if (flags.some((flag) => flag.name === "raw")) {
|
|
6691
|
+
outputs.push({
|
|
6692
|
+
condition: "--raw without --output",
|
|
6693
|
+
kind: "raw-stdout",
|
|
6694
|
+
detail: `${resource} ${action} can intentionally write raw payload bytes/text instead of JSON.`,
|
|
6695
|
+
safeAlternative: flags.some((flag) => flag.name === "output")
|
|
6696
|
+
? "Pass --output PATH so stdout remains a JSON string containing the path."
|
|
6697
|
+
: "Omit --raw when a JSON stdout value is required.",
|
|
6698
|
+
});
|
|
6699
|
+
}
|
|
6700
|
+
if (producesLocalFile) {
|
|
6701
|
+
outputs.push({
|
|
6702
|
+
condition: "--output or --output-file",
|
|
6703
|
+
kind: "local-file",
|
|
6704
|
+
detail: "Command writes bytes to a local path and returns JSON metadata on stdout.",
|
|
6705
|
+
});
|
|
6706
|
+
}
|
|
6707
|
+
return outputs.length > 0 ? outputs : undefined;
|
|
6708
|
+
}
|
|
6709
|
+
function buildCommandSchemas(resource, action, flags, positionals, requiredFlags, requiredOneOf, payloadSchema, outputShape) {
|
|
6710
|
+
return {
|
|
6711
|
+
argv: argvJsonSchema(resource, action, flags, positionals, requiredFlags, requiredOneOf),
|
|
6712
|
+
...(payloadSchema ? { input: payloadJsonSchema(payloadSchema), } : {}),
|
|
6713
|
+
output: outputJsonSchema(outputShape),
|
|
6714
|
+
};
|
|
6715
|
+
}
|
|
6588
6716
|
const EXPLICIT_REGISTRY_OVERRIDES = {
|
|
6589
6717
|
"dashboard.create": {
|
|
6590
6718
|
examplePayload: { pages: [], },
|
|
@@ -6640,7 +6768,8 @@ function extractPositionals(usage) {
|
|
|
6640
6768
|
function inferSideEffect(resource, action) {
|
|
6641
6769
|
if (resource === "auth")
|
|
6642
6770
|
return "auth";
|
|
6643
|
-
if (resource === "
|
|
6771
|
+
if (resource === "agent" || resource === "doctor" || resource === "commands"
|
|
6772
|
+
|| resource === "fixtures"
|
|
6644
6773
|
|| resource === "version") {
|
|
6645
6774
|
return "read";
|
|
6646
6775
|
}
|
|
@@ -6650,20 +6779,23 @@ function inferSideEffect(resource, action) {
|
|
|
6650
6779
|
return "write";
|
|
6651
6780
|
if (READ_ACTIONS.has(action))
|
|
6652
6781
|
return "read";
|
|
6653
|
-
if (/^(create|clone|restore|update|delete|set|save|upload|run|build|abort|move|refresh|clear|unload|install|login|logout|add|remove|publish|activate|deploy|import|export|preload|upgrade|stop|restart|duplicate|put|rename|reply|compute)/
|
|
6654
|
-
.test(action)
|
|
6782
|
+
if (/^(create|clone|restore|update|delete|set|save|upload|run|build|abort|move|refresh|clear|unload|install|login|logout|add|remove|publish|activate|deploy|import|export|preload|upgrade|start|stop|restart|duplicate|put|rename|reply|compute|organize)/
|
|
6783
|
+
.test(action)
|
|
6784
|
+
// Compound actions whose mutating verb is a suffix (e.g. permissions-set, dataset-compute).
|
|
6785
|
+
|| /-(set|compute)$/.test(action)) {
|
|
6655
6786
|
return "write";
|
|
6656
6787
|
}
|
|
6657
6788
|
return "read";
|
|
6658
6789
|
}
|
|
6659
6790
|
function inferRequiresAuth(resource) {
|
|
6660
|
-
return resource !== "
|
|
6791
|
+
return resource !== "agent"
|
|
6792
|
+
&& resource !== "auth"
|
|
6661
6793
|
&& resource !== "commands"
|
|
6662
6794
|
&& resource !== "install-skill"
|
|
6663
6795
|
&& resource !== "version";
|
|
6664
6796
|
}
|
|
6665
6797
|
function inferRequiresProject(resource, action, usage) {
|
|
6666
|
-
if (resource === "auth" || resource === "doctor" || resource === "commands"
|
|
6798
|
+
if (resource === "agent" || resource === "auth" || resource === "doctor" || resource === "commands"
|
|
6667
6799
|
|| resource === "install-skill" || resource === "version") {
|
|
6668
6800
|
return false;
|
|
6669
6801
|
}
|
|
@@ -6681,6 +6813,7 @@ const ARRAY_OUTPUT_ACTIONS = new Set([
|
|
|
6681
6813
|
"list",
|
|
6682
6814
|
"list-jupyter",
|
|
6683
6815
|
"list-sql",
|
|
6816
|
+
"project-timeline",
|
|
6684
6817
|
"rules",
|
|
6685
6818
|
"schemas",
|
|
6686
6819
|
"sessions-jupyter",
|
|
@@ -6696,14 +6829,19 @@ const STRING_OUTPUT_ACTIONS = new Set([
|
|
|
6696
6829
|
"log-url",
|
|
6697
6830
|
]);
|
|
6698
6831
|
function inferOutputShape(resource, action) {
|
|
6699
|
-
if (resource === "
|
|
6832
|
+
if (resource === "agent" || resource === "auth" || resource === "commands"
|
|
6833
|
+
|| resource === "install-skill"
|
|
6700
6834
|
|| resource === "version") {
|
|
6701
6835
|
return "object";
|
|
6702
6836
|
}
|
|
6837
|
+
if (/^list(-|$)/.test(action))
|
|
6838
|
+
return "array";
|
|
6703
6839
|
if (ARRAY_OUTPUT_ACTIONS.has(action))
|
|
6704
6840
|
return "array";
|
|
6705
6841
|
if (resource === "dataset" && action === "download")
|
|
6706
6842
|
return "object";
|
|
6843
|
+
if (resource === "project-library" && action === "get")
|
|
6844
|
+
return "string";
|
|
6707
6845
|
if (STRING_OUTPUT_ACTIONS.has(action))
|
|
6708
6846
|
return "string";
|
|
6709
6847
|
return "object";
|
|
@@ -6936,47 +7074,58 @@ function buildRegistryEntry(resource, action, meta) {
|
|
|
6936
7074
|
const cleanupCommand = meta.cleanupCommand
|
|
6937
7075
|
?? EXPLICIT_REGISTRY_OVERRIDES[registryKey(resource, action)]?.cleanupCommand
|
|
6938
7076
|
?? cleanupCommandFromDeleteUsage(resource, action);
|
|
7077
|
+
const flagMetadata = flags.map((name) => {
|
|
7078
|
+
const kind = flagKind(name);
|
|
7079
|
+
if (kind === "boolean")
|
|
7080
|
+
return { name, kind, };
|
|
7081
|
+
const hint = valueHints.get(name) ?? GLOBAL_FLAG_VALUE_HINTS[name];
|
|
7082
|
+
if (!hint)
|
|
7083
|
+
return { name, kind, };
|
|
7084
|
+
return {
|
|
7085
|
+
name,
|
|
7086
|
+
kind,
|
|
7087
|
+
valueType: hint.valueType,
|
|
7088
|
+
...(hint.enumValues ? { enumValues: hint.enumValues, } : {}),
|
|
7089
|
+
};
|
|
7090
|
+
});
|
|
7091
|
+
const positionals = extractPositionals(meta.usage);
|
|
7092
|
+
const outputShape = inferOutputShape(resource, action);
|
|
7093
|
+
const producesLocalFile = meta.usage.includes("--output PATH")
|
|
7094
|
+
|| meta.usage.includes("--output-file PATH");
|
|
7095
|
+
const uniqueRequiredFlags = uniqueStrings(requiredFlags);
|
|
7096
|
+
const uniqueOptionalFlags = uniqueStrings(optionalFlags);
|
|
7097
|
+
const unsafe = unsafeOutputs(resource, action, flagMetadata, producesLocalFile);
|
|
6939
7098
|
return {
|
|
6940
7099
|
resource,
|
|
6941
7100
|
action,
|
|
6942
7101
|
usage: meta.usage,
|
|
6943
7102
|
description: meta.description,
|
|
6944
7103
|
examples: meta.examples,
|
|
6945
|
-
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
return { name, kind, };
|
|
6949
|
-
const hint = valueHints.get(name) ?? GLOBAL_FLAG_VALUE_HINTS[name];
|
|
6950
|
-
if (!hint)
|
|
6951
|
-
return { name, kind, };
|
|
6952
|
-
return {
|
|
6953
|
-
name,
|
|
6954
|
-
kind,
|
|
6955
|
-
valueType: hint.valueType,
|
|
6956
|
-
...(hint.enumValues ? { enumValues: hint.enumValues, } : {}),
|
|
6957
|
-
};
|
|
6958
|
-
}),
|
|
6959
|
-
positionals: extractPositionals(meta.usage),
|
|
7104
|
+
structuredExamples: structuredExamples(meta.examples, examplePayload),
|
|
7105
|
+
flags: flagMetadata,
|
|
7106
|
+
positionals,
|
|
6960
7107
|
sideEffect,
|
|
6961
7108
|
requiresAuth,
|
|
6962
7109
|
requiresProject,
|
|
6963
|
-
outputShape
|
|
7110
|
+
outputShape,
|
|
6964
7111
|
inputContract,
|
|
6965
7112
|
destructive,
|
|
6966
|
-
producesLocalFile
|
|
6967
|
-
|| meta.usage.includes("--output-file PATH"),
|
|
7113
|
+
producesLocalFile,
|
|
6968
7114
|
mutatesDss,
|
|
6969
7115
|
async: asyncKind,
|
|
6970
7116
|
idempotency: inferIdempotency(sideEffect, action, meta.usage),
|
|
6971
7117
|
dryRun: meta.usage.includes("--dry-run"),
|
|
6972
|
-
requiredFlags:
|
|
6973
|
-
optionalFlags:
|
|
7118
|
+
requiredFlags: uniqueRequiredFlags,
|
|
7119
|
+
optionalFlags: uniqueOptionalFlags,
|
|
6974
7120
|
...(requiredOneOf.length > 0 ? { requiredOneOf, } : {}),
|
|
6975
7121
|
...(payloadSchema ? { payloadSchema, } : {}),
|
|
7122
|
+
schemas: buildCommandSchemas(resource, action, flagMetadata, positionals, uniqueRequiredFlags, requiredOneOf, payloadSchema, outputShape),
|
|
7123
|
+
...(unsafe ? { unsafeOutputs: unsafe, } : {}),
|
|
6976
7124
|
...(examplePayload !== undefined ? { examplePayload, } : {}),
|
|
6977
7125
|
...(cleanupCommand ? { cleanupCommand, } : {}),
|
|
6978
7126
|
exitCodes: inferExitCodes(asyncKind),
|
|
6979
7127
|
...(cleanupHint ? { cleanupHint, } : {}),
|
|
7128
|
+
agentContractVersion: AGENT_CONTRACT_VERSION,
|
|
6980
7129
|
};
|
|
6981
7130
|
}
|
|
6982
7131
|
function buildCommandRegistry() {
|
|
@@ -6995,6 +7144,14 @@ function buildCommandRegistry() {
|
|
|
6995
7144
|
examples: COMMANDS_EXAMPLES,
|
|
6996
7145
|
}),
|
|
6997
7146
|
};
|
|
7147
|
+
registry.agent = {
|
|
7148
|
+
contract: buildRegistryEntry("agent", "contract", {
|
|
7149
|
+
handler: async () => undefined,
|
|
7150
|
+
usage: AGENT_CONTRACT_USAGE,
|
|
7151
|
+
description: AGENT_CONTRACT_DESCRIPTION,
|
|
7152
|
+
examples: AGENT_CONTRACT_EXAMPLES,
|
|
7153
|
+
}),
|
|
7154
|
+
};
|
|
6998
7155
|
registry.version = {
|
|
6999
7156
|
run: buildRegistryEntry("version", "run", {
|
|
7000
7157
|
handler: async () => undefined,
|
|
@@ -7049,6 +7206,191 @@ function buildCommandRegistry() {
|
|
|
7049
7206
|
}
|
|
7050
7207
|
return registry;
|
|
7051
7208
|
}
|
|
7209
|
+
function commandFlagJsonSchema() {
|
|
7210
|
+
return {
|
|
7211
|
+
type: "object",
|
|
7212
|
+
required: ["name", "kind",],
|
|
7213
|
+
additionalProperties: false,
|
|
7214
|
+
properties: {
|
|
7215
|
+
name: { type: "string", },
|
|
7216
|
+
kind: { enum: ["boolean", "value",], },
|
|
7217
|
+
valueType: { type: "string", },
|
|
7218
|
+
enumValues: { type: "array", items: { type: "string", }, },
|
|
7219
|
+
},
|
|
7220
|
+
};
|
|
7221
|
+
}
|
|
7222
|
+
function commandRegistryEntryJsonSchema() {
|
|
7223
|
+
return {
|
|
7224
|
+
type: "object",
|
|
7225
|
+
required: [
|
|
7226
|
+
"resource",
|
|
7227
|
+
"action",
|
|
7228
|
+
"usage",
|
|
7229
|
+
"flags",
|
|
7230
|
+
"positionals",
|
|
7231
|
+
"sideEffect",
|
|
7232
|
+
"requiresAuth",
|
|
7233
|
+
"requiresProject",
|
|
7234
|
+
"outputShape",
|
|
7235
|
+
"inputContract",
|
|
7236
|
+
"schemas",
|
|
7237
|
+
"exitCodes",
|
|
7238
|
+
"agentContractVersion",
|
|
7239
|
+
],
|
|
7240
|
+
additionalProperties: true,
|
|
7241
|
+
properties: {
|
|
7242
|
+
resource: { type: "string", },
|
|
7243
|
+
action: { type: "string", },
|
|
7244
|
+
usage: { type: "string", },
|
|
7245
|
+
description: { type: "string", },
|
|
7246
|
+
examples: { type: "array", items: { type: "string", }, },
|
|
7247
|
+
structuredExamples: { type: "array", items: { type: "object", additionalProperties: true, }, },
|
|
7248
|
+
flags: { type: "array", items: commandFlagJsonSchema(), },
|
|
7249
|
+
positionals: { type: "array", items: { type: "string", }, },
|
|
7250
|
+
sideEffect: { enum: ["read", "write", "auth",], },
|
|
7251
|
+
requiresAuth: { type: "boolean", },
|
|
7252
|
+
requiresProject: { type: "boolean", },
|
|
7253
|
+
outputShape: { enum: ["object", "array", "string", "void",], },
|
|
7254
|
+
inputContract: { type: "object", additionalProperties: { type: "boolean", }, },
|
|
7255
|
+
destructive: { enum: ["none", "reversible", "destructive",], },
|
|
7256
|
+
producesLocalFile: { type: "boolean", },
|
|
7257
|
+
mutatesDss: { type: "boolean", },
|
|
7258
|
+
async: { enum: ["none", "job", "future",], },
|
|
7259
|
+
idempotency: { enum: ["safe", "convergent", "if-not-exists", "if-exists", "none",], },
|
|
7260
|
+
dryRun: { type: "boolean", },
|
|
7261
|
+
requiredFlags: { type: "array", items: { type: "string", }, },
|
|
7262
|
+
optionalFlags: { type: "array", items: { type: "string", }, },
|
|
7263
|
+
schemas: { type: "object", additionalProperties: true, },
|
|
7264
|
+
unsafeOutputs: { type: "array", items: { type: "object", additionalProperties: true, }, },
|
|
7265
|
+
exitCodes: { type: "object", additionalProperties: { type: "number", }, },
|
|
7266
|
+
agentContractVersion: { const: AGENT_CONTRACT_VERSION, },
|
|
7267
|
+
},
|
|
7268
|
+
};
|
|
7269
|
+
}
|
|
7270
|
+
function commandRegistryJsonSchema() {
|
|
7271
|
+
return {
|
|
7272
|
+
$schema: JSON_SCHEMA_DRAFT,
|
|
7273
|
+
type: "object",
|
|
7274
|
+
additionalProperties: {
|
|
7275
|
+
type: "object",
|
|
7276
|
+
additionalProperties: commandRegistryEntryJsonSchema(),
|
|
7277
|
+
},
|
|
7278
|
+
};
|
|
7279
|
+
}
|
|
7280
|
+
function errorEnvelopeJsonSchema() {
|
|
7281
|
+
return {
|
|
7282
|
+
type: "object",
|
|
7283
|
+
required: ["type", "ok", "error", "code", "category", "exitCode",],
|
|
7284
|
+
additionalProperties: true,
|
|
7285
|
+
properties: {
|
|
7286
|
+
type: { const: "error", },
|
|
7287
|
+
ok: { const: false, },
|
|
7288
|
+
error: { type: "string", },
|
|
7289
|
+
code: { type: "string", },
|
|
7290
|
+
category: { enum: ["usage", "dss", "internal",], },
|
|
7291
|
+
exitCode: { type: "number", },
|
|
7292
|
+
resource: { type: "string", },
|
|
7293
|
+
action: { type: "string", },
|
|
7294
|
+
projectKey: { type: "string", },
|
|
7295
|
+
},
|
|
7296
|
+
};
|
|
7297
|
+
}
|
|
7298
|
+
function warningEventJsonSchema() {
|
|
7299
|
+
return {
|
|
7300
|
+
type: "object",
|
|
7301
|
+
required: ["type", "warnings",],
|
|
7302
|
+
additionalProperties: false,
|
|
7303
|
+
properties: {
|
|
7304
|
+
type: { const: "warning", },
|
|
7305
|
+
warnings: { type: "array", items: { type: "object", additionalProperties: true, }, },
|
|
7306
|
+
},
|
|
7307
|
+
};
|
|
7308
|
+
}
|
|
7309
|
+
function traceEventJsonSchema() {
|
|
7310
|
+
return {
|
|
7311
|
+
type: "object",
|
|
7312
|
+
required: ["type", "phase", "method", "url", "attempt", "maxAttempts",],
|
|
7313
|
+
additionalProperties: false,
|
|
7314
|
+
properties: {
|
|
7315
|
+
type: { const: "trace", },
|
|
7316
|
+
phase: { enum: ["request", "response", "error",], },
|
|
7317
|
+
method: { type: "string", },
|
|
7318
|
+
url: { type: "string", },
|
|
7319
|
+
attempt: { type: "number", },
|
|
7320
|
+
maxAttempts: { type: "number", },
|
|
7321
|
+
status: { type: "number", },
|
|
7322
|
+
elapsedMs: { type: "number", },
|
|
7323
|
+
detail: { type: "string", },
|
|
7324
|
+
},
|
|
7325
|
+
};
|
|
7326
|
+
}
|
|
7327
|
+
function agentContractJsonSchema() {
|
|
7328
|
+
return {
|
|
7329
|
+
$schema: JSON_SCHEMA_DRAFT,
|
|
7330
|
+
$id: AGENT_CONTRACT_SCHEMA_ID,
|
|
7331
|
+
type: "object",
|
|
7332
|
+
required: ["protocol", "agentContractVersion", "cli", "commands", "schemas", "stdio",],
|
|
7333
|
+
additionalProperties: true,
|
|
7334
|
+
properties: {
|
|
7335
|
+
protocol: { const: "dataiku-sdk-agent", },
|
|
7336
|
+
agentContractVersion: { const: AGENT_CONTRACT_VERSION, },
|
|
7337
|
+
cli: { type: "object", additionalProperties: true, },
|
|
7338
|
+
commands: { type: "object", additionalProperties: true, },
|
|
7339
|
+
schemas: { type: "object", additionalProperties: true, },
|
|
7340
|
+
stdio: { type: "object", additionalProperties: true, },
|
|
7341
|
+
},
|
|
7342
|
+
};
|
|
7343
|
+
}
|
|
7344
|
+
function commandActionSummary(registry) {
|
|
7345
|
+
const summary = {};
|
|
7346
|
+
for (const [resource, actions,] of Object.entries(registry)) {
|
|
7347
|
+
summary[resource] = Object.keys(actions).sort();
|
|
7348
|
+
}
|
|
7349
|
+
return summary;
|
|
7350
|
+
}
|
|
7351
|
+
function buildAgentContract() {
|
|
7352
|
+
const registry = buildCommandRegistry();
|
|
7353
|
+
return {
|
|
7354
|
+
protocol: "dataiku-sdk-agent",
|
|
7355
|
+
agentContractVersion: AGENT_CONTRACT_VERSION,
|
|
7356
|
+
cli: cliVersionResult(),
|
|
7357
|
+
commands: {
|
|
7358
|
+
discoveryCommand: "dss commands run",
|
|
7359
|
+
actions: commandActionSummary(registry),
|
|
7360
|
+
},
|
|
7361
|
+
schemas: {
|
|
7362
|
+
agentContract: agentContractJsonSchema(),
|
|
7363
|
+
commandRegistry: commandRegistryJsonSchema(),
|
|
7364
|
+
commandRegistryEntry: commandRegistryEntryJsonSchema(),
|
|
7365
|
+
errorEnvelope: errorEnvelopeJsonSchema(),
|
|
7366
|
+
warningEvent: warningEventJsonSchema(),
|
|
7367
|
+
traceEvent: traceEventJsonSchema(),
|
|
7368
|
+
},
|
|
7369
|
+
stdio: {
|
|
7370
|
+
stdout: {
|
|
7371
|
+
success: "single-json-value",
|
|
7372
|
+
rawEscapeHatches: [
|
|
7373
|
+
"recipe get-payload --raw without --output",
|
|
7374
|
+
"recipe cat --raw without --output",
|
|
7375
|
+
],
|
|
7376
|
+
},
|
|
7377
|
+
stderr: {
|
|
7378
|
+
format: "jsonl",
|
|
7379
|
+
events: ["warning", "trace", "error",],
|
|
7380
|
+
error: "single-final-error-event-on-nonzero-exit",
|
|
7381
|
+
},
|
|
7382
|
+
},
|
|
7383
|
+
planning: {
|
|
7384
|
+
discoveryCommand: "dss commands run",
|
|
7385
|
+
contractCommand: AGENT_CONTRACT_USAGE,
|
|
7386
|
+
mutatingCommandsAdvertisePlan: true,
|
|
7387
|
+
},
|
|
7388
|
+
compatibility: {
|
|
7389
|
+
fieldsAreAdditiveWithinMajor: true,
|
|
7390
|
+
failFastWhenUnsupported: "Check agentContractVersion before planning commands.",
|
|
7391
|
+
},
|
|
7392
|
+
};
|
|
7393
|
+
}
|
|
7052
7394
|
function exitCodesOnFailure(entry) {
|
|
7053
7395
|
return {
|
|
7054
7396
|
usage: entry.exitCodes.usage,
|
|
@@ -7609,6 +7951,31 @@ function commandPlanShape(resource, action, args, flags, entry, projectKey) {
|
|
|
7609
7951
|
identifiers: { id, cellId: flags["cell-id"], },
|
|
7610
7952
|
payload: { retain: num(flags["retain"]), },
|
|
7611
7953
|
};
|
|
7954
|
+
case "project.permissions-set":
|
|
7955
|
+
return {
|
|
7956
|
+
method: "PUT",
|
|
7957
|
+
endpoint: projectEndpoint("/permissions"),
|
|
7958
|
+
payload: requiredPlanJsonInput(flags, entry.usage),
|
|
7959
|
+
};
|
|
7960
|
+
case "continuous-activity.start":
|
|
7961
|
+
return {
|
|
7962
|
+
method: "POST",
|
|
7963
|
+
endpoint: projectEndpoint(`/continuous-activities/${encodeURIComponent(id)}/start`),
|
|
7964
|
+
identifiers: { recipeId: id, },
|
|
7965
|
+
payload: jsonInput(flags) ?? {},
|
|
7966
|
+
};
|
|
7967
|
+
case "metrics.dataset-compute":
|
|
7968
|
+
return {
|
|
7969
|
+
method: "POST",
|
|
7970
|
+
endpoint: projectEndpoint(`/datasets/${encodeURIComponent(id)}/actions/computeMetrics?partition=`),
|
|
7971
|
+
identifiers: { dataset: id, },
|
|
7972
|
+
};
|
|
7973
|
+
case "flow-zone.organize":
|
|
7974
|
+
return {
|
|
7975
|
+
method: "POST",
|
|
7976
|
+
endpoint: projectEndpoint("/flow/zones"),
|
|
7977
|
+
payload: jsonInput(flags),
|
|
7978
|
+
};
|
|
7612
7979
|
default:
|
|
7613
7980
|
return {
|
|
7614
7981
|
method: action.startsWith("delete") || action === "abort" ? "DELETE" : "POST",
|
|
@@ -7958,6 +8325,7 @@ function buildErrorReport(err) {
|
|
|
7958
8325
|
const exitCode = errorExitCode(err);
|
|
7959
8326
|
if (err instanceof UsageError) {
|
|
7960
8327
|
return {
|
|
8328
|
+
type: "error",
|
|
7961
8329
|
ok: false,
|
|
7962
8330
|
error: err.message,
|
|
7963
8331
|
code: err.code,
|
|
@@ -7970,6 +8338,7 @@ function buildErrorReport(err) {
|
|
|
7970
8338
|
}
|
|
7971
8339
|
if (err instanceof CommandResultFailure) {
|
|
7972
8340
|
return {
|
|
8341
|
+
type: "error",
|
|
7973
8342
|
ok: false,
|
|
7974
8343
|
error: err.message,
|
|
7975
8344
|
code: "long_running_failure",
|
|
@@ -7981,6 +8350,7 @@ function buildErrorReport(err) {
|
|
|
7981
8350
|
}
|
|
7982
8351
|
if (err instanceof DataikuError) {
|
|
7983
8352
|
return {
|
|
8353
|
+
type: "error",
|
|
7984
8354
|
ok: false,
|
|
7985
8355
|
error: err.message,
|
|
7986
8356
|
code: dataikuErrorCode(err.category),
|
|
@@ -8001,6 +8371,7 @@ function buildErrorReport(err) {
|
|
|
8001
8371
|
}
|
|
8002
8372
|
const message = err instanceof Error ? err.message : String(err);
|
|
8003
8373
|
return {
|
|
8374
|
+
type: "error",
|
|
8004
8375
|
ok: false,
|
|
8005
8376
|
error: message,
|
|
8006
8377
|
code: "internal_error",
|
|
@@ -8010,7 +8381,7 @@ function buildErrorReport(err) {
|
|
|
8010
8381
|
};
|
|
8011
8382
|
}
|
|
8012
8383
|
function writeErrorReport(err) {
|
|
8013
|
-
process.stderr.write(`${JSON.stringify(buildErrorReport(err)
|
|
8384
|
+
process.stderr.write(`${JSON.stringify(buildErrorReport(err))}\n`);
|
|
8014
8385
|
}
|
|
8015
8386
|
// ---------------------------------------------------------------------------
|
|
8016
8387
|
// Main
|
|
@@ -8122,6 +8493,16 @@ async function main() {
|
|
|
8122
8493
|
});
|
|
8123
8494
|
return;
|
|
8124
8495
|
}
|
|
8496
|
+
if (resource === "agent") {
|
|
8497
|
+
const action = positional[1];
|
|
8498
|
+
if (!action)
|
|
8499
|
+
throw missingActionError("agent", ["contract",], AGENT_CONTRACT_USAGE);
|
|
8500
|
+
currentCommandContext.action = action;
|
|
8501
|
+
if (action !== "contract")
|
|
8502
|
+
throw unknownActionError("agent", action, ["contract",]);
|
|
8503
|
+
writeCommandResult(buildAgentContract());
|
|
8504
|
+
return;
|
|
8505
|
+
}
|
|
8125
8506
|
if (resource === "commands") {
|
|
8126
8507
|
const action = positional[1];
|
|
8127
8508
|
if (!action)
|
package/dist/src/client.d.ts
CHANGED
|
@@ -29,6 +29,17 @@ import { VariablesResource } from "./resources/variables.js";
|
|
|
29
29
|
import { WebappsResource } from "./resources/webapps.js";
|
|
30
30
|
import { WikiResource } from "./resources/wiki.js";
|
|
31
31
|
import { WorkspacesResource } from "./resources/workspaces.js";
|
|
32
|
+
export interface DataikuClientTraceEvent {
|
|
33
|
+
type: "trace";
|
|
34
|
+
phase: "request" | "response" | "error";
|
|
35
|
+
method: string;
|
|
36
|
+
url: string;
|
|
37
|
+
attempt: number;
|
|
38
|
+
maxAttempts: number;
|
|
39
|
+
status?: number;
|
|
40
|
+
elapsedMs?: number;
|
|
41
|
+
detail?: string;
|
|
42
|
+
}
|
|
32
43
|
export interface DataikuClientConfig {
|
|
33
44
|
/** DSS base URL (e.g. https://dss.example.com) */
|
|
34
45
|
url: string;
|
|
@@ -40,8 +51,9 @@ export interface DataikuClientConfig {
|
|
|
40
51
|
requestTimeoutMs?: number;
|
|
41
52
|
/** Max retry attempts for idempotent requests (default 4, capped at 10) */
|
|
42
53
|
retryMaxAttempts?: number;
|
|
43
|
-
/** Emit HTTP request/response
|
|
54
|
+
/** Emit HTTP request/response trace events. Defaults to JSONL on stderr when verbose is true. */
|
|
44
55
|
verbose?: boolean;
|
|
56
|
+
onTrace?: (event: DataikuClientTraceEvent) => void;
|
|
45
57
|
/** Override TLS certificate verification for HTTPS requests. */
|
|
46
58
|
tlsRejectUnauthorized?: boolean;
|
|
47
59
|
/** Extra PEM CA bundle to trust in addition to Bun's default trust store. */
|
|
@@ -62,6 +74,7 @@ export declare class DataikuClient {
|
|
|
62
74
|
private readonly retryMaxAttempts;
|
|
63
75
|
private readonly verbose;
|
|
64
76
|
private readonly tlsOptions;
|
|
77
|
+
private readonly onTrace;
|
|
65
78
|
private readonly onValidationWarning;
|
|
66
79
|
private projectsResource?;
|
|
67
80
|
private datasetsResource?;
|
|
@@ -143,7 +156,7 @@ export declare class DataikuClient {
|
|
|
143
156
|
stream(path: string): Promise<Response>;
|
|
144
157
|
private getHeaders;
|
|
145
158
|
private getAnyHeaders;
|
|
146
|
-
private
|
|
159
|
+
private logTrace;
|
|
147
160
|
/**
|
|
148
161
|
* Validate raw data against a TypeBox schema, throwing on structural mismatch.
|
|
149
162
|
* Resources call this instead of bare `as T` casts for validated responses.
|
package/dist/src/client.js
CHANGED
|
@@ -44,6 +44,9 @@ const DEFAULT_REQUEST_TIMEOUT_MS = 30_000;
|
|
|
44
44
|
/* ------------------------------------------------------------------ */
|
|
45
45
|
/* Helpers */
|
|
46
46
|
/* ------------------------------------------------------------------ */
|
|
47
|
+
function defaultTrace(event) {
|
|
48
|
+
process.stderr.write(`${JSON.stringify(event)}\n`);
|
|
49
|
+
}
|
|
47
50
|
function defaultValidationWarning(_method, _errors) {
|
|
48
51
|
}
|
|
49
52
|
function sleep(ms) {
|
|
@@ -139,6 +142,7 @@ export class DataikuClient {
|
|
|
139
142
|
retryMaxAttempts;
|
|
140
143
|
verbose;
|
|
141
144
|
tlsOptions;
|
|
145
|
+
onTrace;
|
|
142
146
|
onValidationWarning;
|
|
143
147
|
/* Resource namespaces — lazily initialized to break circular imports */
|
|
144
148
|
projectsResource;
|
|
@@ -280,6 +284,7 @@ export class DataikuClient {
|
|
|
280
284
|
this.retryMaxAttempts = Math.min(Math.max(1, rawMax), MAX_RETRY_ATTEMPTS_CAP);
|
|
281
285
|
this.verbose = config.verbose === true;
|
|
282
286
|
this.tlsOptions = buildFetchTlsOptions(config);
|
|
287
|
+
this.onTrace = config.onTrace ?? defaultTrace;
|
|
283
288
|
this.onValidationWarning = config.onValidationWarning ?? defaultValidationWarning;
|
|
284
289
|
}
|
|
285
290
|
getRequestTimeoutMs() {
|
|
@@ -423,9 +428,9 @@ export class DataikuClient {
|
|
|
423
428
|
Accept: "*/*",
|
|
424
429
|
};
|
|
425
430
|
}
|
|
426
|
-
|
|
431
|
+
logTrace(event) {
|
|
427
432
|
if (this.verbose)
|
|
428
|
-
|
|
433
|
+
this.onTrace({ type: "trace", ...event, });
|
|
429
434
|
}
|
|
430
435
|
/* ---- public: schema-validated parsing ---- */
|
|
431
436
|
/**
|
|
@@ -498,7 +503,7 @@ export class DataikuClient {
|
|
|
498
503
|
timedOut = true;
|
|
499
504
|
controller.abort();
|
|
500
505
|
}, this.requestTimeoutMs);
|
|
501
|
-
this.
|
|
506
|
+
this.logTrace({ phase: "request", method, url, attempt, maxAttempts, });
|
|
502
507
|
try {
|
|
503
508
|
const requestInit = {
|
|
504
509
|
...init,
|
|
@@ -508,7 +513,15 @@ export class DataikuClient {
|
|
|
508
513
|
if (this.tlsOptions)
|
|
509
514
|
requestInit.tls = this.tlsOptions;
|
|
510
515
|
const res = await fetch(url, requestInit);
|
|
511
|
-
this.
|
|
516
|
+
this.logTrace({
|
|
517
|
+
phase: "response",
|
|
518
|
+
method,
|
|
519
|
+
url,
|
|
520
|
+
attempt,
|
|
521
|
+
maxAttempts,
|
|
522
|
+
status: res.status,
|
|
523
|
+
elapsedMs: Date.now() - startedAt,
|
|
524
|
+
});
|
|
512
525
|
if (!res.ok) {
|
|
513
526
|
const text = await res.text();
|
|
514
527
|
const canRetry = retryEnabled && attempt < maxAttempts && isTransientError(res.status, text);
|
|
@@ -537,7 +550,15 @@ export class DataikuClient {
|
|
|
537
550
|
: error instanceof Error
|
|
538
551
|
? error.message
|
|
539
552
|
: "Unknown transport error";
|
|
540
|
-
this.
|
|
553
|
+
this.logTrace({
|
|
554
|
+
phase: "error",
|
|
555
|
+
method,
|
|
556
|
+
url,
|
|
557
|
+
attempt,
|
|
558
|
+
maxAttempts,
|
|
559
|
+
elapsedMs: Date.now() - startedAt,
|
|
560
|
+
detail,
|
|
561
|
+
});
|
|
541
562
|
const statusText = timedOut ? "Request Timeout" : "Network Error";
|
|
542
563
|
throw new DataikuError(0, statusText, detail, buildRetryMetadata(method, retryEnabled, maxAttempts, attempt, delaysMs, timedOut));
|
|
543
564
|
}
|
package/dist/src/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { DataikuClient, type DataikuClientConfig, } from "./client.js";
|
|
1
|
+
export { DataikuClient, type DataikuClientConfig, type DataikuClientTraceEvent, } from "./client.js";
|
|
2
2
|
export { type CredentialValidationOptions, type CredentialValidationResult, validateCredentials, } from "./auth.js";
|
|
3
3
|
export { type DssCredentials, getConfigDir, getCredentialsPath, loadCredentials, saveCredentials, } from "./config.js";
|
|
4
4
|
export { DataikuError, type DataikuErrorCategory, type DataikuErrorTaxonomy, type DataikuRetryMetadata, } from "./errors.js";
|
package/dist/src/skill.js
CHANGED
|
@@ -11,8 +11,8 @@ If the installed \`dss\` binary is unavailable but the repository checkout is th
|
|
|
11
11
|
## Contract
|
|
12
12
|
|
|
13
13
|
- Success writes exactly one JSON result to stdout.
|
|
14
|
-
- Failure writes exactly one
|
|
15
|
-
- \`--verbose\`
|
|
14
|
+
- Failure writes exactly one JSONL error event to stderr with \`type:"error"\`, \`ok:false\`, \`error\`, \`code\`, and \`exitCode\`.
|
|
15
|
+
- Non-fatal warnings and \`--verbose\` HTTP traces are JSONL stderr events (\`type:"warning"\` / \`type:"trace"\`), never prose.
|
|
16
16
|
- No prompts, help screens, tables, banners, or prose output are part of the contract.
|
|
17
17
|
- Exit codes: 0 success, 1 usage/configuration error, 2 DSS or internal error, 3 transient/retryable DSS error, 4 completed command with failed long-running DSS work.
|
|
18
18
|
- \`--raw\` is the only stdout escape hatch: recipe payload commands emit raw bytes to stdout unless \`--output PATH\` is also set; with \`--output\`, stdout is the JSON string equal to \`PATH\` and the file receives exact raw bytes.
|
|
@@ -21,10 +21,11 @@ If the installed \`dss\` binary is unavailable but the repository checkout is th
|
|
|
21
21
|
## Discover commands
|
|
22
22
|
|
|
23
23
|
\`\`\`bash
|
|
24
|
+
dss agent contract
|
|
24
25
|
dss commands run
|
|
25
26
|
\`\`\`
|
|
26
27
|
|
|
27
|
-
The registry is the canonical schema for resources, actions, flags, positional arguments, side effects, auth requirements, output shape, idempotency, dry-run support, payload schemas, cleanup hints, and exit codes. Use it before choosing command syntax.
|
|
28
|
+
Use \`dss agent contract\` once to check \`agentContractVersion\`, stderr event schemas, non-JSON escape hatches, and compatibility rules. The command registry from \`dss commands run\` is the canonical schema for resources, actions, flags, positional arguments, side effects, auth requirements, output shape, idempotency, dry-run support, structured examples, payload schemas, unsafe outputs, cleanup hints, and exit codes. Use it before choosing command syntax.
|
|
28
29
|
Credential lookup order is flags first, then \`DATAIKU_*\` environment variables, then saved credentials.
|
|
29
30
|
Set \`DATAIKU_DISABLE_ENV=1\` when a test must ignore both \`.env\` files and \`DATAIKU_*\` environment variables.
|
|
30
31
|
When \`.env\` loading is enabled, the CLI reads \`.env\` from the command's current working directory first and then the CLI build/root directory; the invocation directory wins on conflicting keys. Put test-specific \`.env\` files in the directory where you invoke \`dss\`.
|
|
@@ -91,10 +92,11 @@ Mutations print a small JSON ack to stdout and exit 0 on success (e.g. \`{"updat
|
|
|
91
92
|
|
|
92
93
|
## Error envelope
|
|
93
94
|
|
|
94
|
-
Parse stderr as JSON
|
|
95
|
+
Parse each stderr line as JSON; on non-zero exit the final line is an error event:
|
|
95
96
|
|
|
96
97
|
\`\`\`json
|
|
97
98
|
{
|
|
99
|
+
"type": "error",
|
|
98
100
|
"ok": false,
|
|
99
101
|
"error": "Missing API key.",
|
|
100
102
|
"code": "usage_error",
|