dataiku-sdk 3.0.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/README.md +246 -19
  2. package/dist/build-metadata.json +1 -1
  3. package/dist/packages/types/src/index.d.ts +39 -4
  4. package/dist/packages/types/src/index.js +31 -2
  5. package/dist/src/auth.js +1 -1
  6. package/dist/src/cli/coerce.js +11 -2
  7. package/dist/src/cli/commands/analysis.js +4 -3
  8. package/dist/src/cli/commands/api-service.js +66 -18
  9. package/dist/src/cli/commands/app.js +4 -3
  10. package/dist/src/cli/commands/bundle.js +51 -16
  11. package/dist/src/cli/commands/code-env.js +219 -57
  12. package/dist/src/cli/commands/code.d.ts +19 -0
  13. package/dist/src/cli/commands/code.js +87 -15
  14. package/dist/src/cli/commands/dashboard.js +7 -6
  15. package/dist/src/cli/commands/data-quality.js +9 -8
  16. package/dist/src/cli/commands/dataset.js +17 -11
  17. package/dist/src/cli/commands/doctor.js +4 -2
  18. package/dist/src/cli/commands/flow-zone.js +42 -13
  19. package/dist/src/cli/commands/folder.js +9 -8
  20. package/dist/src/cli/commands/future.js +2 -1
  21. package/dist/src/cli/commands/insight.js +8 -7
  22. package/dist/src/cli/commands/job.js +4 -3
  23. package/dist/src/cli/commands/meaning.js +5 -4
  24. package/dist/src/cli/commands/ml-task.js +3 -2
  25. package/dist/src/cli/commands/model-evaluation-store.js +4 -3
  26. package/dist/src/cli/commands/notebook.js +82 -50
  27. package/dist/src/cli/commands/project-git.js +8 -5
  28. package/dist/src/cli/commands/project-library.d.ts +21 -0
  29. package/dist/src/cli/commands/project-library.js +128 -56
  30. package/dist/src/cli/commands/project.js +19 -4
  31. package/dist/src/cli/commands/recipe.js +51 -25
  32. package/dist/src/cli/commands/saved-model.js +4 -3
  33. package/dist/src/cli/commands/scenario.js +9 -8
  34. package/dist/src/cli/commands/sql.d.ts +10 -0
  35. package/dist/src/cli/commands/sql.js +42 -19
  36. package/dist/src/cli/commands/statistics.js +7 -6
  37. package/dist/src/cli/commands/variable.js +2 -1
  38. package/dist/src/cli/commands/webapp.js +68 -13
  39. package/dist/src/cli/commands/wiki.js +7 -6
  40. package/dist/src/cli/contract.d.ts +16 -1
  41. package/dist/src/cli/contract.js +967 -186
  42. package/dist/src/cli/env.d.ts +9 -0
  43. package/dist/src/cli/env.js +20 -2
  44. package/dist/src/cli/flags.d.ts +4 -0
  45. package/dist/src/cli/flags.js +29 -1
  46. package/dist/src/cli/helpers/cleanup.js +104 -3
  47. package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
  48. package/dist/src/cli/helpers/flow-zone.js +33 -3
  49. package/dist/src/cli/helpers/recipe.d.ts +20 -0
  50. package/dist/src/cli/helpers/recipe.js +158 -3
  51. package/dist/src/cli/output.d.ts +2 -0
  52. package/dist/src/cli/output.js +33 -6
  53. package/dist/src/cli/runtime.d.ts +35 -1
  54. package/dist/src/cli/runtime.js +125 -18
  55. package/dist/src/cli/types.d.ts +7 -0
  56. package/dist/src/cli.js +226 -95
  57. package/dist/src/client.d.ts +63 -1
  58. package/dist/src/client.js +305 -53
  59. package/dist/src/errors.d.ts +8 -2
  60. package/dist/src/errors.js +42 -0
  61. package/dist/src/index.d.ts +4 -3
  62. package/dist/src/index.js +2 -1
  63. package/dist/src/resources/api-services.d.ts +48 -6
  64. package/dist/src/resources/api-services.js +54 -8
  65. package/dist/src/resources/bundles.d.ts +51 -6
  66. package/dist/src/resources/bundles.js +39 -9
  67. package/dist/src/resources/code-envs.d.ts +25 -3
  68. package/dist/src/resources/code-envs.js +104 -2
  69. package/dist/src/resources/datasets.d.ts +20 -0
  70. package/dist/src/resources/datasets.js +232 -52
  71. package/dist/src/resources/folders.js +2 -1
  72. package/dist/src/resources/jobs.d.ts +35 -10
  73. package/dist/src/resources/jobs.js +92 -17
  74. package/dist/src/resources/notebooks.d.ts +77 -7
  75. package/dist/src/resources/notebooks.js +143 -19
  76. package/dist/src/resources/project-git.d.ts +12 -0
  77. package/dist/src/resources/project-git.js +39 -8
  78. package/dist/src/resources/project-library.d.ts +122 -7
  79. package/dist/src/resources/project-library.js +494 -25
  80. package/dist/src/resources/projects.d.ts +5 -4
  81. package/dist/src/resources/projects.js +21 -19
  82. package/dist/src/resources/scenarios.d.ts +30 -0
  83. package/dist/src/resources/scenarios.js +73 -27
  84. package/dist/src/resources/sql.d.ts +6 -0
  85. package/dist/src/resources/sql.js +23 -3
  86. package/dist/src/resources/webapps.d.ts +35 -4
  87. package/dist/src/resources/webapps.js +54 -5
  88. package/dist/src/schemas.d.ts +2 -2
  89. package/dist/src/schemas.js +1 -1
  90. package/dist/src/skill.d.ts +18 -0
  91. package/dist/src/skill.js +93 -9
  92. package/dist/src/utils/flow-analysis.d.ts +53 -0
  93. package/dist/src/utils/flow-analysis.js +382 -0
  94. package/dist/src/utils/project-archive.d.ts +41 -2
  95. package/dist/src/utils/project-archive.js +159 -16
  96. package/dist/src/utils/response-file.d.ts +2 -0
  97. package/dist/src/utils/response-file.js +34 -0
  98. package/package.json +9 -7
  99. package/packages/types/dist/index.d.ts +39 -4
  100. package/packages/types/dist/index.js +31 -2
  101. package/plugin.json +1 -1
  102. package/skills/dataiku-dss/SKILL.md +44 -197
  103. package/skills/dataiku-dss/references/app-releases.md +27 -0
  104. package/skills/dataiku-dss/references/authentication.md +39 -0
  105. package/skills/dataiku-dss/references/coding.md +8 -0
  106. package/skills/dataiku-dss/references/discovery.md +30 -0
  107. package/skills/dataiku-dss/references/flow-maps.md +12 -0
  108. package/skills/dataiku-dss/references/mutations.md +33 -0
  109. package/skills/dataiku-dss/references/troubleshooting.md +29 -0
@@ -1,5 +1,7 @@
1
1
  import { ClientValidationError, DataikuError, } from "../errors.js";
2
+ import { writeResponseToFile, } from "../utils/response-file.js";
2
3
  import { ProjectDetailsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, } from "../schemas.js";
4
+ import { analyzeFlowMap, flowTopologyFingerprint, renderFlowMap, } from "../utils/flow-analysis.js";
3
5
  import { normalizeFlowGraph, } from "../utils/flow-map.js";
4
6
  import { assertImportableProjectArchive, } from "../utils/project-archive.js";
5
7
  import { projectIncarnationHash, } from "../utils/project-incarnation.js";
@@ -103,21 +105,6 @@ const DEFAULT_MAX_EDGES = 600;
103
105
  const DEFAULT_METADATA_TIMEOUT_MS = 1_500;
104
106
  const PROJECT_IMPORT_AMBIGUOUS_REMEDIATION = "Import processing left DSS state indeterminate. Inspect the archive with `dss project inspect-archive <file>` and the live projects with `dss project list` before retrying the import.";
105
107
  export class ProjectsResource extends BaseResource {
106
- httpInternals() {
107
- return this.client;
108
- }
109
- async postStream(path, body) {
110
- const http = this.httpInternals();
111
- return http.fetchWithRetry(`${http.baseUrl}${path}`, {
112
- method: "POST",
113
- headers: {
114
- Authorization: `Bearer ${http.apiKey}`,
115
- Accept: "*/*",
116
- "Content-Type": "application/json",
117
- },
118
- body: JSON.stringify(body),
119
- });
120
- }
121
108
  /** Create a new project. */
122
109
  async createProject(projectKey, name, ownerLogin, settings) {
123
110
  return this.client.post("/public/api/projects/", {
@@ -154,10 +141,10 @@ export class ProjectsResource extends BaseResource {
154
141
  }
155
142
  /** Export a project archive to a local file. */
156
143
  async exportArchive(projectKey, filePath, options) {
157
- const res = await this.postStream(`/public/api/projects/${encodeURIComponent(projectKey)}/export`, options ?? {});
144
+ const res = await this.client.postStream(`/public/api/projects/${encodeURIComponent(projectKey)}/export`, options ?? {});
158
145
  if (!res.body)
159
146
  throw new Error("projects.exportArchive response did not include a body");
160
- await Bun.write(filePath, new Response(res.body), { createPath: false, });
147
+ await writeResponseToFile(filePath, res);
161
148
  }
162
149
  /** Upload a project archive and return its temporary import handle. */
163
150
  async prepareProjectImport(filePath) {
@@ -320,6 +307,12 @@ export class ProjectsResource extends BaseResource {
320
307
  const enc = this.enc(projectKey);
321
308
  return this.client.get(`/public/api/projects/${enc}/flow/graph/`);
322
309
  }
310
+ /** Compute a stable fingerprint of flow nodes and edges, excluding visual metadata. */
311
+ async topologyFingerprint(projectKey) {
312
+ const pk = this.resolveProjectKey(projectKey);
313
+ const rawGraph = await this.flow(pk);
314
+ return flowTopologyFingerprint(normalizeFlowGraph(rawGraph, pk));
315
+ }
323
316
  /**
324
317
  * Build a normalized, optionally truncated flow map for a project.
325
318
  *
@@ -331,11 +324,12 @@ export class ProjectsResource extends BaseResource {
331
324
  const enc = this.enc(opts?.projectKey);
332
325
  const pk = this.resolveProjectKey(opts?.projectKey);
333
326
  const timeoutMs = DEFAULT_METADATA_TIMEOUT_MS;
334
- const [rawGraph, foldersMeta, datasetsMeta, recipesMeta,] = await Promise.all([
327
+ const [rawGraph, foldersMeta, datasetsMeta, recipesMeta, zonesMeta,] = await Promise.all([
335
328
  this.client.get(`/public/api/projects/${enc}/flow/graph/`),
336
329
  fetchWithTimeout("Managed folders", timeoutMs, () => this.client.get(`/public/api/projects/${enc}/managedfolders/`)),
337
330
  fetchWithTimeout("Datasets", timeoutMs, () => this.client.get(`/public/api/projects/${enc}/datasets/`)),
338
331
  fetchWithTimeout("Recipes", timeoutMs, () => this.client.get(`/public/api/projects/${enc}/recipes/`)),
332
+ fetchWithTimeout("Flow zones", timeoutMs, () => this.client.flowZones.list(pk)),
339
333
  ]);
340
334
  // Build folder name lookup
341
335
  const folderNamesById = {};
@@ -364,6 +358,7 @@ export class ProjectsResource extends BaseResource {
364
358
  foldersMeta.warning,
365
359
  datasetsMeta.warning,
366
360
  recipesMeta.warning,
361
+ zonesMeta.warning,
367
362
  ].filter((w) => typeof w === "string" && w.length > 0);
368
363
  const normalized = metadataWarnings.length > 0
369
364
  ? {
@@ -374,8 +369,15 @@ export class ProjectsResource extends BaseResource {
374
369
  // Truncate
375
370
  const effectiveMaxNodes = opts?.maxNodes ?? DEFAULT_MAX_NODES;
376
371
  const effectiveMaxEdges = opts?.maxEdges ?? DEFAULT_MAX_EDGES;
372
+ const topologyFingerprint = flowTopologyFingerprint(normalizeFlowGraph(rawGraph, pk));
377
373
  const { map, truncation, } = truncateFlowMap(normalized, effectiveMaxNodes, effectiveMaxEdges);
378
- const result = { map, truncation, };
374
+ const analyzed = analyzeFlowMap(map, zonesMeta.value ?? [], {
375
+ topologyFingerprint,
376
+ truncated: truncation.truncated,
377
+ });
378
+ const result = { map: analyzed, truncation, };
379
+ if (opts?.render)
380
+ result.rendering = renderFlowMap(analyzed, opts.render);
379
381
  if (opts?.includeRaw) {
380
382
  result.raw = rawGraph;
381
383
  }
@@ -31,6 +31,25 @@ export interface ScenarioUpdateResult extends ScenarioUpdatePreview {
31
31
  verified: true;
32
32
  mismatches: [];
33
33
  }
34
+ export interface ScenarioScriptRunCleanup {
35
+ status: "deleted" | "kept" | "failed";
36
+ error?: string;
37
+ }
38
+ /** Cleanup failure carried on errors thrown from {@link ScenariosResource.runScript}. */
39
+ export interface ScenarioScriptRunCleanupFailure {
40
+ scenarioId: string;
41
+ error: string;
42
+ }
43
+ /**
44
+ * Wraps a primary code-run failure so the original error (and its taxonomy:
45
+ * category, exit-code semantics) stays intact while the concurrent throwaway
46
+ * cleanup failure remains observable via {@link cleanupFailure}.
47
+ */
48
+ export declare class ScenarioScriptRunWithCleanupFailureError extends Error {
49
+ readonly cause: unknown;
50
+ readonly cleanupFailure: ScenarioScriptRunCleanupFailure;
51
+ constructor(cause: unknown, cleanupFailure: ScenarioScriptRunCleanupFailure);
52
+ }
34
53
  export interface ScenarioScriptRunResult {
35
54
  scenarioId: string;
36
55
  runId: string;
@@ -43,6 +62,10 @@ export interface ScenarioScriptRunResult {
43
62
  logTruncated: boolean;
44
63
  maxLogBytes: number;
45
64
  envName?: string;
65
+ timedOut?: boolean;
66
+ timeoutMs?: number;
67
+ /** Observable throwaway-scenario cleanup outcome; never silently swallowed here. */
68
+ cleanup: ScenarioScriptRunCleanup;
46
69
  }
47
70
  export declare function normalizeScenarioUpdateData(data: Record<string, unknown>): {
48
71
  normalizedData: Record<string, unknown>;
@@ -95,4 +118,11 @@ export declare class ScenariosResource extends BaseResource {
95
118
  keepScenario?: boolean;
96
119
  maxLogBytes?: number;
97
120
  }): Promise<ScenarioScriptRunResult>;
121
+ /**
122
+ * Delete the throwaway scenario at the end of a code run, or report the
123
+ * explicit keep outcome. Never throws: delete failures are surfaced in the
124
+ * returned cleanup outcome instead of being swallowed. A 404 is idempotent
125
+ * success — the scenario is already gone.
126
+ */
127
+ private removeThrowawayScenario;
98
128
  }
@@ -12,6 +12,21 @@ export const SCENARIO_CANONICAL_EDITABLE_FIELDS = [
12
12
  "active",
13
13
  "name",
14
14
  ];
15
+ /**
16
+ * Wraps a primary code-run failure so the original error (and its taxonomy:
17
+ * category, exit-code semantics) stays intact while the concurrent throwaway
18
+ * cleanup failure remains observable via {@link cleanupFailure}.
19
+ */
20
+ export class ScenarioScriptRunWithCleanupFailureError extends Error {
21
+ cause;
22
+ cleanupFailure;
23
+ constructor(cause, cleanupFailure) {
24
+ super("Code run failed and its throwaway scenario cleanup also failed.");
25
+ this.cause = cause;
26
+ this.cleanupFailure = cleanupFailure;
27
+ this.name = "ScenarioScriptRunWithCleanupFailureError";
28
+ }
29
+ }
15
30
  const DEFAULT_CODE_RUN_MAX_LOG_BYTES = 1_048_576;
16
31
  const CODE_RUN_OUTPUT_START = "<<<DSS_CODE_RUN_OUTPUT_b7e3a1>>>";
17
32
  const CODE_RUN_OUTPUT_END = "<<<DSS_CODE_RUN_OUTPUT_END_b7e3a1>>>";
@@ -421,6 +436,13 @@ export class ScenariosResource extends BaseResource {
421
436
  const adaptivePolling = opts?.pollIntervalMs === undefined;
422
437
  const timeout = Math.max(baseIntervalMs, opts?.timeoutMs ?? 120_000);
423
438
  const maxLogBytes = Math.max(0, Math.floor(opts?.maxLogBytes ?? DEFAULT_CODE_RUN_MAX_LOG_BYTES));
439
+ let outcome = "UNKNOWN";
440
+ let runId = "";
441
+ let pollCount = 0;
442
+ let timedOut = false;
443
+ let log = "";
444
+ let logTruncated = false;
445
+ let primaryError;
424
446
  try {
425
447
  await this.client.post(`/public/api/projects/${pkEnc}/scenarios/`, {
426
448
  id: scenarioId,
@@ -438,12 +460,10 @@ export class ScenariosResource extends BaseResource {
438
460
  throw new DataikuError(500, "Scenario run not started", `Scenario "${scenarioId}" run trigger returned no run id; cannot track the run.`);
439
461
  }
440
462
  const trigQuery = `triggerId=${encodeURIComponent(triggerId)}&triggerRunId=${encodeURIComponent(triggerRunId)}`;
441
- let runId = "";
442
- let outcome = "UNKNOWN";
443
- let pollCount = 0;
444
463
  while (true) {
445
464
  if (Date.now() - startedAt >= timeout) {
446
465
  outcome = "TIMEOUT";
466
+ timedOut = true;
447
467
  break;
448
468
  }
449
469
  pollCount += 1;
@@ -465,37 +485,63 @@ export class ScenariosResource extends BaseResource {
465
485
  });
466
486
  await new Promise((r) => setTimeout(r, Math.min(nextDelayMs, Math.max(1, timeout - (Date.now() - startedAt)))));
467
487
  }
468
- let log = "";
469
- let logTruncated = false;
470
488
  if (runId && outcome !== "TIMEOUT") {
471
489
  const limitedLog = await this.client.getTextLimited(`${base}/${encodeURIComponent(runId)}/log`, maxLogBytes);
472
490
  log = limitedLog.text;
473
491
  logTruncated = limitedLog.truncated;
474
492
  }
475
- const output = extractCodeRunOutput(log);
476
- return {
477
- scenarioId,
478
- runId,
479
- outcome,
480
- success: outcome === "SUCCESS",
481
- elapsedMs: Date.now() - startedAt,
482
- pollCount,
483
- output,
484
- log,
485
- logTruncated,
486
- maxLogBytes,
487
- ...(opts?.envName ? { envName: opts.envName, } : {}),
488
- };
489
493
  }
490
- finally {
491
- if (opts?.keepScenario !== true) {
492
- try {
493
- await this.client.del(base);
494
- }
495
- catch {
496
- // Best-effort cleanup of the throwaway scenario.
497
- }
494
+ catch (error) {
495
+ primaryError = error;
496
+ }
497
+ const cleanup = await this.removeThrowawayScenario(base, opts?.keepScenario === true);
498
+ if (primaryError !== undefined) {
499
+ if (cleanup.status === "failed") {
500
+ throw new ScenarioScriptRunWithCleanupFailureError(primaryError, {
501
+ scenarioId,
502
+ error: cleanup.error ?? "unknown cleanup error",
503
+ });
498
504
  }
505
+ throw primaryError;
506
+ }
507
+ const output = extractCodeRunOutput(log);
508
+ return {
509
+ scenarioId,
510
+ runId,
511
+ outcome,
512
+ success: outcome === "SUCCESS",
513
+ elapsedMs: Date.now() - startedAt,
514
+ pollCount,
515
+ output,
516
+ log,
517
+ logTruncated,
518
+ maxLogBytes,
519
+ ...(opts?.envName ? { envName: opts.envName, } : {}),
520
+ ...(timedOut ? { timedOut: true, timeoutMs: timeout, } : {}),
521
+ cleanup,
522
+ };
523
+ }
524
+ /**
525
+ * Delete the throwaway scenario at the end of a code run, or report the
526
+ * explicit keep outcome. Never throws: delete failures are surfaced in the
527
+ * returned cleanup outcome instead of being swallowed. A 404 is idempotent
528
+ * success — the scenario is already gone.
529
+ */
530
+ async removeThrowawayScenario(base, keep) {
531
+ if (keep)
532
+ return { status: "kept", };
533
+ try {
534
+ await this.client.del(base);
535
+ return { status: "deleted", };
536
+ }
537
+ catch (error) {
538
+ if (error instanceof DataikuError && error.category === "not_found") {
539
+ return { status: "deleted", };
540
+ }
541
+ return {
542
+ status: "failed",
543
+ error: error instanceof Error ? error.message : String(error),
544
+ };
499
545
  }
500
546
  }
501
547
  }
@@ -25,6 +25,12 @@ export declare class SqlResource extends BaseResource {
25
25
  startQuery(opts: SqlQueryOptions): Promise<SqlQueryResult>;
26
26
  /**
27
27
  * Stream results of a started query as parsed JSON (array of arrays).
28
+ *
29
+ * The result body is buffered under the client's response body limit
30
+ * (default 50 MiB, `maxResponseBodyBytes`) and the request deadline. A
31
+ * response exceeding the limit is cancelled and rejected instead of being
32
+ * parsed — otherwise a collaborator-controlled result set (or a stalled
33
+ * stream) could exhaust client memory or hang unbounded.
28
34
  */
29
35
  streamResults(queryId: string): Promise<unknown[][]>;
30
36
  /**
@@ -1,6 +1,12 @@
1
1
  import { ClientValidationError, DataikuError, } from "../errors.js";
2
2
  import { BaseResource, } from "./base.js";
3
3
  const UNSUPPORTED_SQL_DATASET_CONNECTION_DETAIL = "neither of sql nor hdfs type";
4
+ /**
5
+ * Cap on the finish-streaming status text behind the client's response body
6
+ * limit: the payload is a short status message, so any larger body is a
7
+ * misbehaving endpoint and must not be buffered further.
8
+ */
9
+ const MAX_SQL_FINISH_TEXT_BYTES = 1024 * 1024;
4
10
  function isUnsupportedSqlDatasetConnectionError(error) {
5
11
  if (!(error instanceof DataikuError))
6
12
  return false;
@@ -95,7 +101,7 @@ function withSqlErrorContext(error) {
95
101
  catch {
96
102
  body = `SQL query failed: ${detail}\n${error.body}`;
97
103
  }
98
- throw new DataikuError(error.status, error.statusText, body, error.retry);
104
+ throw new DataikuError(error.status, error.statusText, body, error.retry, error.requestId, { target: error.trustedTarget, elapsedMs: error.trustedElapsedMs, });
99
105
  }
100
106
  }
101
107
  throw error;
@@ -135,10 +141,20 @@ export class SqlResource extends BaseResource {
135
141
  }
136
142
  /**
137
143
  * Stream results of a started query as parsed JSON (array of arrays).
144
+ *
145
+ * The result body is buffered under the client's response body limit
146
+ * (default 50 MiB, `maxResponseBodyBytes`) and the request deadline. A
147
+ * response exceeding the limit is cancelled and rejected instead of being
148
+ * parsed — otherwise a collaborator-controlled result set (or a stalled
149
+ * stream) could exhaust client memory or hang unbounded.
138
150
  */
139
151
  async streamResults(queryId) {
140
152
  const id = encodeURIComponent(queryId);
141
- const text = await this.client.getText(`/public/api/sql/queries/${id}/stream?format=json`);
153
+ const maxBytes = this.client.getMaxResponseBodyBytes();
154
+ const { text, truncated, } = await this.client.getTextLimited(`/public/api/sql/queries/${id}/stream?format=json`, maxBytes);
155
+ if (truncated) {
156
+ throw new DataikuError(0, "Response Too Large", `SQL stream results exceeded the ${maxBytes}-byte response limit and were not parsed.`);
157
+ }
142
158
  return JSON.parse(text);
143
159
  }
144
160
  /**
@@ -147,7 +163,11 @@ export class SqlResource extends BaseResource {
147
163
  */
148
164
  async finishStreaming(queryId) {
149
165
  const id = encodeURIComponent(queryId);
150
- const text = await this.client.getText(`/public/api/sql/queries/${id}/finish-streaming`);
166
+ const maxBytes = Math.min(this.client.getMaxResponseBodyBytes(), MAX_SQL_FINISH_TEXT_BYTES);
167
+ const { text, truncated, } = await this.client.getTextLimited(`/public/api/sql/queries/${id}/finish-streaming`, maxBytes);
168
+ if (truncated) {
169
+ throw new DataikuError(0, "Response Too Large", `SQL finish-streaming response exceeded the ${maxBytes}-byte response limit.`);
170
+ }
151
171
  if (text.length > 0) {
152
172
  throw new Error(`SQL query ${queryId} failed: ${text}`);
153
173
  }
@@ -1,3 +1,4 @@
1
+ import type { FutureWaitResult } from "../schemas.js";
1
2
  import { BaseResource } from "./base.js";
2
3
  export interface WebappListItem {
3
4
  id?: string;
@@ -9,6 +10,20 @@ export interface WebappListItem {
9
10
  export interface WebappCreateResult {
10
11
  webAppId: string;
11
12
  }
13
+ /**
14
+ * 64-hex SHA-256 hash of the webapp object as last fetched, used as a
15
+ * non-atomic stale-read guard: the write is refused when the object already
16
+ * differs at the verification read. DSS exposes no conditional write (no
17
+ * ETag, no If-Match), so a writer committing between that read and the PUT
18
+ * is still not detected.
19
+ */
20
+ export interface WebappUpdateOptions {
21
+ expectHash?: string;
22
+ }
23
+ export interface WebappWaitOptions {
24
+ pollIntervalMs?: number;
25
+ timeoutMs?: number;
26
+ }
12
27
  export declare class WebappsResource extends BaseResource {
13
28
  /** List all webapps in a project. */
14
29
  list(projectKey?: string): Promise<WebappListItem[]>;
@@ -16,12 +31,28 @@ export declare class WebappsResource extends BaseResource {
16
31
  getSettings(webappId: string, projectKey?: string): Promise<Record<string, unknown>>;
17
32
  /** Create a webapp. */
18
33
  create(body: Record<string, unknown>, projectKey?: string): Promise<WebappCreateResult>;
19
- /** Update one webapp's settings. */
20
- updateSettings(webappId: string, body: Record<string, unknown>, projectKey?: string): Promise<Record<string, unknown>>;
34
+ /**
35
+ * Update one webapp's settings via GET-merge-PUT. The public API requires
36
+ * the object passed to a PUT call to have been obtained from a GET call at
37
+ * the same URL, so the current object is fetched first, the supplied
38
+ * fields are merged over it (fields absent from `body` are preserved), and
39
+ * the whole merged object is PUT back.
40
+ *
41
+ * With `expectHash` armed, the fresh GET doubles as the stale-read guard:
42
+ * the stable hash of the fetched object must match, or the write is
43
+ * refused before any PUT.
44
+ */
45
+ updateSettings(webappId: string, body: Record<string, unknown>, projectKey?: string, options?: WebappUpdateOptions): Promise<Record<string, unknown>>;
21
46
  /** Stop a webapp backend. */
22
47
  stopBackend(webappId: string, projectKey?: string): Promise<void>;
23
- /** Start or restart a webapp backend. */
24
- startOrRestartBackend(webappId: string, projectKey?: string): Promise<void>;
48
+ /**
49
+ * Start or restart a webapp backend. The documented endpoint returns a
50
+ * reference to a future, which is surfaced as-is; settle it with
51
+ * {@link restartBackendAndWait} or `client.futures.wait`.
52
+ */
53
+ startOrRestartBackend(webappId: string, projectKey?: string): Promise<Record<string, unknown>>;
54
+ /** Restart a webapp backend and wait for the returned future to settle. */
55
+ restartBackendAndWait(webappId: string, projectKey?: string, options?: WebappWaitOptions): Promise<FutureWaitResult>;
25
56
  /** Get a webapp backend's state. */
26
57
  getBackendState(webappId: string, projectKey?: string): Promise<Record<string, unknown>>;
27
58
  }
@@ -1,4 +1,22 @@
1
+ import { ClientValidationError, } from "../errors.js";
2
+ import { deepMerge, } from "../utils/deep-merge.js";
3
+ import { stableHash, } from "../utils/stable-hash.js";
1
4
  import { BaseResource, } from "./base.js";
5
+ const EXPECT_HASH_PATTERN = /^[0-9a-fA-F]{64}$/;
6
+ function assertExpectedHash(id, expectHash, current, projectKey) {
7
+ if (!EXPECT_HASH_PATTERN.test(expectHash)) {
8
+ throw new ClientValidationError("Expected webapp hash must be a 64-character SHA-256 hex digest.", "validation_failed", "Use the hash value returned by a previous read.", { projectKey, id, });
9
+ }
10
+ const actual = stableHash(current);
11
+ if (actual !== expectHash.toLowerCase()) {
12
+ throw new ClientValidationError(`The webapp ${JSON.stringify(id)} changed since it was read.`, "validation_failed", "Re-read the webapp settings and retry with the current hash value.", {
13
+ projectKey,
14
+ id,
15
+ expectedHash: expectHash.toLowerCase(),
16
+ actualHash: actual,
17
+ });
18
+ }
19
+ }
2
20
  export class WebappsResource extends BaseResource {
3
21
  /** List all webapps in a project. */
4
22
  async list(projectKey) {
@@ -13,20 +31,51 @@ export class WebappsResource extends BaseResource {
13
31
  async create(body, projectKey) {
14
32
  return this.client.post(`/public/api/projects/${this.enc(projectKey)}/webapps/`, body);
15
33
  }
16
- /** Update one webapp's settings. */
17
- async updateSettings(webappId, body, projectKey) {
34
+ /**
35
+ * Update one webapp's settings via GET-merge-PUT. The public API requires
36
+ * the object passed to a PUT call to have been obtained from a GET call at
37
+ * the same URL, so the current object is fetched first, the supplied
38
+ * fields are merged over it (fields absent from `body` are preserved), and
39
+ * the whole merged object is PUT back.
40
+ *
41
+ * With `expectHash` armed, the fresh GET doubles as the stale-read guard:
42
+ * the stable hash of the fetched object must match, or the write is
43
+ * refused before any PUT.
44
+ */
45
+ async updateSettings(webappId, body, projectKey, options = {}) {
46
+ const current = await this.getSettings(webappId, projectKey);
47
+ if (options.expectHash !== undefined) {
48
+ assertExpectedHash(webappId, options.expectHash, current, projectKey);
49
+ }
50
+ const next = deepMerge(current, body);
18
51
  const id = encodeURIComponent(webappId);
19
- return this.client.put(`/public/api/projects/${this.enc(projectKey)}/webapps/${id}`, body);
52
+ return this.client.put(`/public/api/projects/${this.enc(projectKey)}/webapps/${id}`, next);
20
53
  }
21
54
  /** Stop a webapp backend. */
22
55
  async stopBackend(webappId, projectKey) {
23
56
  const id = encodeURIComponent(webappId);
24
57
  await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/webapps/${id}/backend/actions/stop`, {});
25
58
  }
26
- /** Start or restart a webapp backend. */
59
+ /**
60
+ * Start or restart a webapp backend. The documented endpoint returns a
61
+ * reference to a future, which is surfaced as-is; settle it with
62
+ * {@link restartBackendAndWait} or `client.futures.wait`.
63
+ */
27
64
  async startOrRestartBackend(webappId, projectKey) {
28
65
  const id = encodeURIComponent(webappId);
29
- await this.client.putVoid(`/public/api/projects/${this.enc(projectKey)}/webapps/${id}/backend/actions/restart`, {});
66
+ return this.client.put(`/public/api/projects/${this.enc(projectKey)}/webapps/${id}/backend/actions/restart`, {});
67
+ }
68
+ /** Restart a webapp backend and wait for the returned future to settle. */
69
+ async restartBackendAndWait(webappId, projectKey, options = {}) {
70
+ const future = await this.startOrRestartBackend(webappId, projectKey);
71
+ const jobId = future.jobId;
72
+ if (typeof jobId !== "string" || jobId.length === 0) {
73
+ throw new Error("Webapp backend restart did not return a future jobId.");
74
+ }
75
+ return this.client.futures.wait(jobId, {
76
+ pollIntervalMs: options.pollIntervalMs,
77
+ timeoutMs: options.timeoutMs,
78
+ });
30
79
  }
31
80
  /** Get a webapp backend's state. */
32
81
  async getBackendState(webappId, projectKey) {
@@ -3,5 +3,5 @@
3
3
  * The types package (packages/types/) owns the TypeBox schema definitions.
4
4
  * SDK consumers get everything through this re-export.
5
5
  */
6
- export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "../packages/types/src/index.js";
7
- export type { BuildMode, CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdatePackagesOptions, CodeEnvUsage, CodeEnvWaitOptions, ConnectionSummary, DashboardDetails, DashboardSummary, DataQualityComputeResult, DataQualityProjectStatus, DataQualityRule, DataQualityRuleResult, DataQualityRules, DataQualityStatus, DataQualityStatusByPartition, DataQualityTimeline, DataQualityTimelineEntry, DatasetCreateOptions, DatasetDetails, DatasetSchema, DatasetSummary, FlowMapOptions, FlowZone, FlowZoneCreateOptions, FlowZoneItem, FlowZoneObjectType, FlowZonePosition, FlowZoneUpdateOptions, FolderCreateOptions, FolderDetails, FolderItem, FolderSummary, FutureState, FutureWaitResult, InsightDetails, InsightSummary, JobSummary, JobWaitResult, JupyterCell, JupyterNotebookContent, JupyterNotebookSummary, NotebookSession, ProjectDetails, ProjectGitActionResult, ProjectGitDiffResult, ProjectGitFutureResponse, ProjectGitFutureState, ProjectGitLibraries, ProjectGitLibrary, ProjectGitLogResult, ProjectGitRemote, ProjectGitStatus, ProjectGitTag, ProjectGitTags, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, SafeParseResult, ScenarioDetails, ScenarioStatus, ScenarioStepRun, ScenarioSummary, ScenarioWaitResult, SqlNotebookCell, SqlNotebookContent, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "../packages/types/src/index.js";
6
+ export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvGetLogOptionsSchema, CodeEnvLogResultSchema, CodeEnvLogSummaryArraySchema, CodeEnvLogSummarySchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdateImagesOptionsSchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookHistorySchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "../packages/types/src/index.js";
7
+ export type { BuildMode, CodeEnvActionResult, CodeEnvCreateOptions, CodeEnvDetails, CodeEnvGetLogOptions, CodeEnvLogResult, CodeEnvLogSummary, CodeEnvPackageList, CodeEnvSetPackagesOptions, CodeEnvSummary, CodeEnvUpdateImagesOptions, CodeEnvUpdatePackagesOptions, CodeEnvUsage, CodeEnvVersionForProject, CodeEnvWaitOptions, ConnectionSummary, DashboardDetails, DashboardSummary, DataQualityComputeResult, DataQualityProjectStatus, DataQualityRule, DataQualityRuleResult, DataQualityRules, DataQualityStatus, DataQualityStatusByPartition, DataQualityTimeline, DataQualityTimelineEntry, DatasetCreateOptions, DatasetDetails, DatasetSchema, DatasetSummary, FlowMapOptions, FlowZone, FlowZoneCreateOptions, FlowZoneItem, FlowZoneObjectType, FlowZonePosition, FlowZoneUpdateOptions, FolderCreateOptions, FolderDetails, FolderItem, FolderSummary, FutureState, FutureWaitResult, InsightDetails, InsightSummary, JobSummary, JobWaitResult, JupyterCell, JupyterNotebookContent, JupyterNotebookSummary, NotebookSession, ProjectDetails, ProjectGitActionResult, ProjectGitDiffResult, ProjectGitFutureResponse, ProjectGitFutureState, ProjectGitLibraries, ProjectGitLibrary, ProjectGitLogResult, ProjectGitRemote, ProjectGitStatus, ProjectGitTag, ProjectGitTags, ProjectMetadata, ProjectSummary, ProjectVariables, RecipeCreateOptions, RecipeCreateResult, RecipeDetails, RecipeSummary, SafeParseResult, ScenarioDetails, ScenarioStatus, ScenarioStepRun, ScenarioSummary, ScenarioWaitResult, SqlNotebookCell, SqlNotebookContent, SqlNotebookHistory, SqlNotebookSummary, SqlQueryResponse, SqlQueryResult, SqlQuerySchema, WikiArticleData, WikiArticleMetadata, WikiSettings, WikiTaxonomyNode, } from "../packages/types/src/index.js";
@@ -3,4 +3,4 @@
3
3
  * The types package (packages/types/) owns the TypeBox schema definitions.
4
4
  * SDK consumers get everything through this re-export.
5
5
  */
6
- export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "../packages/types/src/index.js";
6
+ export { BuildModeSchema, CodeEnvActionResultSchema, CodeEnvCreateOptionsSchema, CodeEnvDetailsSchema, CodeEnvGetLogOptionsSchema, CodeEnvLogResultSchema, CodeEnvLogSummaryArraySchema, CodeEnvLogSummarySchema, CodeEnvPackageListSchema, CodeEnvSetPackagesOptionsSchema, CodeEnvSummaryArraySchema, CodeEnvSummarySchema, CodeEnvUpdateImagesOptionsSchema, CodeEnvUpdatePackagesOptionsSchema, CodeEnvUsageArraySchema, CodeEnvVersionForProjectSchema, CodeEnvWaitOptionsSchema, ConnectionSummarySchema, DashboardDetailsSchema, DashboardSummaryArraySchema, DashboardSummarySchema, DataQualityComputeResultSchema, DataQualityProjectStatusSchema, DataQualityRuleArraySchema, DataQualityRuleResultArraySchema, DataQualityRuleResultSchema, DataQualityRuleSchema, DataQualityRulesSchema, DataQualityStatusByPartitionSchema, DataQualityStatusSchema, DataQualityTimelineEntrySchema, DataQualityTimelineSchema, DatasetCreateOptionsSchema, DatasetDetailsSchema, DatasetSchemaSchema, DatasetSummaryArraySchema, DatasetSummarySchema, FlowMapOptionsSchema, FlowZoneArraySchema, FlowZoneCreateOptionsSchema, FlowZoneItemSchema, FlowZoneObjectTypeSchema, FlowZonePositionSchema, FlowZoneSchema, FlowZoneUpdateOptionsSchema, FolderCreateOptionsSchema, FolderDetailsSchema, FolderItemArraySchema, FolderItemSchema, FolderSummaryArraySchema, FolderSummarySchema, FutureStateSchema, FutureWaitResultSchema, InsightDetailsSchema, InsightSummaryArraySchema, InsightSummarySchema, JobSummaryArraySchema, JobSummarySchema, JobWaitResultSchema, JupyterCellSchema, JupyterNotebookContentSchema, JupyterNotebookSummaryArraySchema, JupyterNotebookSummarySchema, NotebookSessionArraySchema, NotebookSessionSchema, parseSchema, ProjectDetailsSchema, ProjectGitActionResultSchema, ProjectGitDiffResultSchema, ProjectGitFutureResponseSchema, ProjectGitFutureStateSchema, ProjectGitLibrariesSchema, ProjectGitLibrarySchema, ProjectGitLogResultSchema, ProjectGitRemoteSchema, ProjectGitStatusSchema, ProjectGitTagSchema, ProjectGitTagsSchema, ProjectMetadataSchema, ProjectSummaryArraySchema, ProjectSummarySchema, ProjectVariablesSchema, RecipeCreateOptionsSchema, RecipeCreateResultSchema, RecipeDetailsSchema, RecipeSummaryArraySchema, RecipeSummarySchema, safeParseSchema, ScenarioDetailsSchema, ScenarioStatusSchema, ScenarioStepRunSchema, ScenarioSummaryArraySchema, ScenarioSummarySchema, ScenarioWaitResultSchema, SqlNotebookCellSchema, SqlNotebookContentSchema, SqlNotebookHistorySchema, SqlNotebookSummaryArraySchema, SqlNotebookSummarySchema, SqlQueryResponseSchema, SqlQueryResultSchema, SqlQuerySchemaSchema, WikiArticleDataArraySchema, WikiArticleDataSchema, WikiArticleMetadataSchema, WikiSettingsSchema, WikiTaxonomyNodeSchema, } from "../packages/types/src/index.js";
@@ -28,10 +28,28 @@ export declare function detectAgents(): DetectedAgent[];
28
28
  * Agent config directories are install targets, not workspace roots.
29
29
  */
30
30
  export declare function findWorkspaceRoot(startDir: string): string;
31
+ export type SkillStatus = "missing" | "stale" | "current";
32
+ export interface InstalledSkillFile {
33
+ relativePath: string;
34
+ path: string;
35
+ status: SkillStatus;
36
+ changed: boolean;
37
+ expectedSha256: string;
38
+ actualSha256?: string;
39
+ }
31
40
  export interface InstallResult {
32
41
  agent: string;
33
42
  path: string;
34
43
  via: DetectedAgent["via"];
44
+ /** Missing entrypoint, incomplete/different bundle, or entirely current bundle. */
45
+ status: SkillStatus;
46
+ /** Whether any bundled file would (or did) change. Unmanaged files are preserved. */
47
+ changed: boolean;
48
+ /** SHA-256 of the canonical SKILL.md entrypoint, not the whole bundle. */
49
+ expectedSha256: string;
50
+ /** Hash of the existing entrypoint; absent when that file is missing. */
51
+ actualSha256?: string;
52
+ files: InstalledSkillFile[];
35
53
  }
36
54
  export declare function planSkillInstalls(agents: DetectedAgent[], opts: {
37
55
  global: boolean;