dataiku-sdk 3.0.0 → 3.1.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 +132 -17
- package/dist/build-metadata.json +1 -1
- package/dist/packages/types/src/index.d.ts +39 -4
- package/dist/packages/types/src/index.js +31 -2
- package/dist/src/cli/commands/api-service.js +62 -16
- package/dist/src/cli/commands/bundle.js +49 -15
- package/dist/src/cli/commands/code-env.js +210 -49
- package/dist/src/cli/commands/code.d.ts +19 -0
- package/dist/src/cli/commands/code.js +87 -15
- package/dist/src/cli/commands/dataset.js +8 -3
- package/dist/src/cli/commands/flow-zone.js +33 -5
- package/dist/src/cli/commands/notebook.js +72 -41
- package/dist/src/cli/commands/project-git.js +8 -5
- package/dist/src/cli/commands/project-library.d.ts +21 -0
- package/dist/src/cli/commands/project-library.js +121 -50
- package/dist/src/cli/commands/project.js +16 -2
- package/dist/src/cli/commands/recipe.js +37 -12
- package/dist/src/cli/commands/sql.d.ts +10 -0
- package/dist/src/cli/commands/sql.js +39 -17
- package/dist/src/cli/commands/webapp.js +67 -13
- package/dist/src/cli/contract.d.ts +15 -0
- package/dist/src/cli/contract.js +870 -107
- package/dist/src/cli/env.d.ts +9 -0
- package/dist/src/cli/env.js +20 -2
- package/dist/src/cli/flags.js +9 -0
- package/dist/src/cli/helpers/cleanup.js +104 -3
- package/dist/src/cli/helpers/flow-zone.d.ts +3 -0
- package/dist/src/cli/helpers/flow-zone.js +33 -3
- package/dist/src/cli/helpers/recipe.d.ts +20 -0
- package/dist/src/cli/helpers/recipe.js +158 -3
- package/dist/src/cli/output.d.ts +2 -0
- package/dist/src/cli/output.js +33 -6
- package/dist/src/cli/runtime.d.ts +35 -1
- package/dist/src/cli/runtime.js +125 -18
- package/dist/src/cli/types.d.ts +7 -0
- package/dist/src/cli.js +135 -28
- package/dist/src/client.d.ts +60 -0
- package/dist/src/client.js +237 -42
- package/dist/src/errors.d.ts +8 -2
- package/dist/src/errors.js +40 -0
- package/dist/src/index.d.ts +4 -3
- package/dist/src/index.js +2 -1
- package/dist/src/resources/api-services.d.ts +48 -6
- package/dist/src/resources/api-services.js +54 -8
- package/dist/src/resources/bundles.d.ts +51 -6
- package/dist/src/resources/bundles.js +39 -9
- package/dist/src/resources/code-envs.d.ts +25 -3
- package/dist/src/resources/code-envs.js +104 -2
- package/dist/src/resources/datasets.d.ts +20 -0
- package/dist/src/resources/datasets.js +232 -52
- package/dist/src/resources/jobs.d.ts +35 -10
- package/dist/src/resources/jobs.js +92 -17
- package/dist/src/resources/notebooks.d.ts +77 -7
- package/dist/src/resources/notebooks.js +143 -19
- package/dist/src/resources/project-git.d.ts +12 -0
- package/dist/src/resources/project-git.js +39 -8
- package/dist/src/resources/project-library.d.ts +122 -7
- package/dist/src/resources/project-library.js +494 -25
- package/dist/src/resources/projects.d.ts +5 -2
- package/dist/src/resources/projects.js +18 -2
- package/dist/src/resources/scenarios.d.ts +30 -0
- package/dist/src/resources/scenarios.js +73 -27
- package/dist/src/resources/sql.d.ts +6 -0
- package/dist/src/resources/sql.js +22 -2
- package/dist/src/resources/webapps.d.ts +35 -4
- package/dist/src/resources/webapps.js +54 -5
- package/dist/src/schemas.d.ts +2 -2
- package/dist/src/schemas.js +1 -1
- package/dist/src/skill.d.ts +9 -0
- package/dist/src/skill.js +37 -4
- package/dist/src/utils/flow-analysis.d.ts +53 -0
- package/dist/src/utils/flow-analysis.js +382 -0
- package/dist/src/utils/project-archive.d.ts +41 -2
- package/dist/src/utils/project-archive.js +159 -16
- package/package.json +4 -4
- package/packages/types/dist/index.d.ts +39 -4
- package/packages/types/dist/index.js +31 -2
- package/plugin.json +1 -1
- package/skills/dataiku-dss/SKILL.md +74 -47
|
@@ -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
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
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;
|
|
@@ -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
|
|
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
|
|
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
|
-
/**
|
|
20
|
-
|
|
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
|
-
/**
|
|
24
|
-
|
|
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
|
-
/**
|
|
17
|
-
|
|
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}`,
|
|
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
|
-
/**
|
|
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
|
-
|
|
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) {
|
package/dist/src/schemas.d.ts
CHANGED
|
@@ -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";
|
package/dist/src/schemas.js
CHANGED
|
@@ -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";
|
package/dist/src/skill.d.ts
CHANGED
|
@@ -28,10 +28,19 @@ 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";
|
|
31
32
|
export interface InstallResult {
|
|
32
33
|
agent: string;
|
|
33
34
|
path: string;
|
|
34
35
|
via: DetectedAgent["via"];
|
|
36
|
+
/** Deterministic state of the destination file relative to the canonical skill content. */
|
|
37
|
+
status: SkillStatus;
|
|
38
|
+
/** Whether an install run would (or did) write the destination file. */
|
|
39
|
+
changed: boolean;
|
|
40
|
+
/** SHA-256 hex of the canonical skill bytes this installation writes. */
|
|
41
|
+
expectedSha256: string;
|
|
42
|
+
/** SHA-256 hex of the destination file when it exists; absent when status is "missing". */
|
|
43
|
+
actualSha256?: string;
|
|
35
44
|
}
|
|
36
45
|
export declare function planSkillInstalls(agents: DetectedAgent[], opts: {
|
|
37
46
|
global: boolean;
|
package/dist/src/skill.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash, } from "node:crypto";
|
|
1
2
|
import * as fs from "node:fs";
|
|
2
3
|
import * as os from "node:os";
|
|
3
4
|
import * as path from "node:path";
|
|
@@ -97,6 +98,18 @@ export function findWorkspaceRoot(startDir) {
|
|
|
97
98
|
}
|
|
98
99
|
return startDir;
|
|
99
100
|
}
|
|
101
|
+
function sha256Hex(value) {
|
|
102
|
+
return createHash("sha256").update(value).digest("hex");
|
|
103
|
+
}
|
|
104
|
+
function skillState(target, expectedSha256) {
|
|
105
|
+
if (!fs.existsSync(target))
|
|
106
|
+
return { status: "missing", };
|
|
107
|
+
const actualSha256 = sha256Hex(fs.readFileSync(target));
|
|
108
|
+
return {
|
|
109
|
+
status: actualSha256 === expectedSha256 ? "current" : "stale",
|
|
110
|
+
actualSha256,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
100
113
|
export function planSkillInstalls(agents, opts) {
|
|
101
114
|
const home = os.homedir();
|
|
102
115
|
const results = [];
|
|
@@ -108,7 +121,17 @@ export function planSkillInstalls(agents, opts) {
|
|
|
108
121
|
: undefined;
|
|
109
122
|
if (!dir)
|
|
110
123
|
continue;
|
|
111
|
-
|
|
124
|
+
const target = path.join(dir, def.filename);
|
|
125
|
+
const expectedSha256 = sha256Hex(def.content());
|
|
126
|
+
const state = skillState(target, expectedSha256);
|
|
127
|
+
results.push({
|
|
128
|
+
agent: id,
|
|
129
|
+
path: target,
|
|
130
|
+
via,
|
|
131
|
+
...state,
|
|
132
|
+
changed: state.status !== "current",
|
|
133
|
+
expectedSha256,
|
|
134
|
+
});
|
|
112
135
|
}
|
|
113
136
|
return results;
|
|
114
137
|
}
|
|
@@ -116,10 +139,20 @@ export function installSkill(agents, opts) {
|
|
|
116
139
|
const results = planSkillInstalls(agents, opts);
|
|
117
140
|
for (const result of results) {
|
|
118
141
|
const def = AGENTS[result.agent];
|
|
119
|
-
if (!def)
|
|
142
|
+
if (!def || !result.changed)
|
|
120
143
|
continue;
|
|
121
|
-
|
|
122
|
-
|
|
144
|
+
const content = def.content();
|
|
145
|
+
const dir = path.dirname(result.path);
|
|
146
|
+
fs.mkdirSync(dir, { recursive: true, });
|
|
147
|
+
const tmpPath = path.join(dir, `.${path.basename(result.path)}.tmp-${process.pid}-${Date.now().toString(36)}`);
|
|
148
|
+
fs.writeFileSync(tmpPath, content, "utf-8");
|
|
149
|
+
try {
|
|
150
|
+
fs.renameSync(tmpPath, result.path);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
fs.rmSync(tmpPath, { force: true, });
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
123
156
|
}
|
|
124
157
|
return results;
|
|
125
158
|
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { FlowZone } from "../schemas.js";
|
|
2
|
+
import type { NormalizedFlowMap, NormalizedFlowNode } from "./flow-map.js";
|
|
3
|
+
export type FlowRenderFormat = "ascii" | "mermaid";
|
|
4
|
+
export type FlowDiagnosticSeverity = "info" | "warning";
|
|
5
|
+
export interface AnalyzedFlowNode extends NormalizedFlowNode {
|
|
6
|
+
componentId: string;
|
|
7
|
+
layer: number;
|
|
8
|
+
zoneId: string;
|
|
9
|
+
zoneName: string;
|
|
10
|
+
}
|
|
11
|
+
export interface FlowMapZone {
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
color?: string;
|
|
15
|
+
position?: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
};
|
|
19
|
+
itemCount: number;
|
|
20
|
+
nodeIds: string[];
|
|
21
|
+
}
|
|
22
|
+
export interface FlowMapComponent {
|
|
23
|
+
id: string;
|
|
24
|
+
nodeIds: string[];
|
|
25
|
+
rootIds: string[];
|
|
26
|
+
leafIds: string[];
|
|
27
|
+
cyclic: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface FlowMapDiagnostic {
|
|
30
|
+
code: string;
|
|
31
|
+
severity: FlowDiagnosticSeverity;
|
|
32
|
+
message: string;
|
|
33
|
+
nodeIds?: string[];
|
|
34
|
+
componentIds?: string[];
|
|
35
|
+
edgeCount?: number;
|
|
36
|
+
}
|
|
37
|
+
export interface AnalyzedFlowMap extends Omit<NormalizedFlowMap, "nodes"> {
|
|
38
|
+
nodes: AnalyzedFlowNode[];
|
|
39
|
+
zones: FlowMapZone[];
|
|
40
|
+
components: FlowMapComponent[];
|
|
41
|
+
diagnostics: FlowMapDiagnostic[];
|
|
42
|
+
topologyFingerprint: string;
|
|
43
|
+
}
|
|
44
|
+
export interface FlowMapRendering {
|
|
45
|
+
format: FlowRenderFormat;
|
|
46
|
+
content: string;
|
|
47
|
+
}
|
|
48
|
+
export declare function flowTopologyFingerprint(map: NormalizedFlowMap): string;
|
|
49
|
+
export declare function analyzeFlowMap(map: NormalizedFlowMap, flowZones: FlowZone[], options?: {
|
|
50
|
+
topologyFingerprint?: string;
|
|
51
|
+
truncated?: boolean;
|
|
52
|
+
}): AnalyzedFlowMap;
|
|
53
|
+
export declare function renderFlowMap(map: AnalyzedFlowMap, format: FlowRenderFormat): FlowMapRendering;
|