@kortyx/cli 0.11.0 → 0.11.2
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/CHANGELOG.md +26 -0
- package/dist/index.js +156 -72
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.11.2](https://github.com/kortyx-io/kortyx/compare/cli-v0.11.1...cli-v0.11.2) (2026-09-22)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Dependencies
|
|
7
|
+
|
|
8
|
+
* The following workspace dependencies were updated
|
|
9
|
+
* dependencies
|
|
10
|
+
* @kortyx/agent bumped to 0.26.2
|
|
11
|
+
* @kortyx/core bumped to 0.11.0
|
|
12
|
+
|
|
13
|
+
## [0.11.1](https://github.com/kortyx-io/kortyx/compare/cli-v0.11.0...cli-v0.11.1) (2026-09-21)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* preserve interrupt control flow and Studio compatibility ([#226](https://github.com/kortyx-io/kortyx/issues/226)) ([72ba7c2](https://github.com/kortyx-io/kortyx/commit/72ba7c2b9a467db0e54b5a4ab5844c8d7f895135))
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Dependencies
|
|
22
|
+
|
|
23
|
+
* The following workspace dependencies were updated
|
|
24
|
+
* dependencies
|
|
25
|
+
* @kortyx/agent bumped to 0.26.1
|
|
26
|
+
* @kortyx/core bumped to 0.10.1
|
|
27
|
+
* @kortyx/telemetry-contracts bumped to 0.11.1
|
|
28
|
+
|
|
3
29
|
## [0.11.0](https://github.com/kortyx-io/kortyx/compare/cli-v0.10.1...cli-v0.11.0) (2026-09-21)
|
|
4
30
|
|
|
5
31
|
|
package/dist/index.js
CHANGED
|
@@ -29,12 +29,12 @@ var import_node_os3 = require("os");
|
|
|
29
29
|
var import_node_path4 = require("path");
|
|
30
30
|
var import_agent = require("@kortyx/agent");
|
|
31
31
|
var import_errors = require("@kortyx/core/errors");
|
|
32
|
-
var
|
|
32
|
+
var import_telemetry_contracts6 = require("@kortyx/telemetry-contracts");
|
|
33
33
|
var import_commander4 = require("commander");
|
|
34
34
|
var import_api = require("tsx/cjs/api");
|
|
35
35
|
|
|
36
36
|
// src/connections-command.ts
|
|
37
|
-
var
|
|
37
|
+
var import_telemetry_contracts2 = require("@kortyx/telemetry-contracts");
|
|
38
38
|
var import_commander = require("commander");
|
|
39
39
|
|
|
40
40
|
// src/connections.ts
|
|
@@ -45,6 +45,7 @@ var import_node_path2 = require("path");
|
|
|
45
45
|
var import_zod2 = require("zod");
|
|
46
46
|
|
|
47
47
|
// src/studio/read-client.ts
|
|
48
|
+
var import_telemetry_contracts = require("@kortyx/telemetry-contracts");
|
|
48
49
|
var StudioReadError = class extends Error {
|
|
49
50
|
constructor(code, message, status, requestId) {
|
|
50
51
|
super(message);
|
|
@@ -101,6 +102,10 @@ var StudioReadClient = class {
|
|
|
101
102
|
apiKey;
|
|
102
103
|
request;
|
|
103
104
|
apiUrl;
|
|
105
|
+
compatibility = {
|
|
106
|
+
protocolVersion: null,
|
|
107
|
+
release: null
|
|
108
|
+
};
|
|
104
109
|
async get(path, schema, query = {}) {
|
|
105
110
|
if (!/^\/v1\/studio\/(?:context|catalogs|workflows|(?:runs|sessions|interrupts)(?:\/[^/?#]+)?)$/.test(
|
|
106
111
|
path
|
|
@@ -119,7 +124,8 @@ var StudioReadClient = class {
|
|
|
119
124
|
method: "GET",
|
|
120
125
|
headers: {
|
|
121
126
|
authorization: `Bearer ${this.apiKey}`,
|
|
122
|
-
accept: "application/json"
|
|
127
|
+
accept: "application/json",
|
|
128
|
+
"x-kortyx-studio-api-version": import_telemetry_contracts.STUDIO_API_PROTOCOL_VERSION
|
|
123
129
|
},
|
|
124
130
|
redirect: "error",
|
|
125
131
|
signal: AbortSignal.timeout(15e3)
|
|
@@ -131,6 +137,19 @@ var StudioReadClient = class {
|
|
|
131
137
|
);
|
|
132
138
|
}
|
|
133
139
|
const requestId = response.headers.get("x-request-id") ?? void 0;
|
|
140
|
+
this.compatibility = {
|
|
141
|
+
protocolVersion: response.headers.get("x-kortyx-studio-api-version"),
|
|
142
|
+
release: response.headers.get("x-kortyx-studio-release")
|
|
143
|
+
};
|
|
144
|
+
if (this.compatibility.protocolVersion && this.compatibility.protocolVersion !== import_telemetry_contracts.STUDIO_API_PROTOCOL_VERSION) {
|
|
145
|
+
await response.body?.cancel();
|
|
146
|
+
throw new StudioReadError(
|
|
147
|
+
"incompatible_studio_api",
|
|
148
|
+
`This CLI supports Studio API v${import_telemetry_contracts.STUDIO_API_PROTOCOL_VERSION}, but the server reports v${this.compatibility.protocolVersion}${this.compatibility.release ? ` (${this.compatibility.release})` : ""}. Install a CLI and Studio release that use the same Studio API major.`,
|
|
149
|
+
response.status,
|
|
150
|
+
requestId
|
|
151
|
+
);
|
|
152
|
+
}
|
|
134
153
|
if (!response.ok) {
|
|
135
154
|
await response.body?.cancel();
|
|
136
155
|
const message = response.status === 401 ? "Invalid, expired, or revoked Studio read key." : response.status === 403 ? "The API key lacks studio:read permission." : response.status === 404 ? "Entity not found in this connection's project. Check the URL and selected connection." : `Studio API returned HTTP ${response.status}.`;
|
|
@@ -180,9 +199,10 @@ var StudioReadClient = class {
|
|
|
180
199
|
}
|
|
181
200
|
const result = schema.safeParse(value);
|
|
182
201
|
if (!result.success) {
|
|
202
|
+
const server = this.compatibility.protocolVersion ? `Studio API v${this.compatibility.protocolVersion}${this.compatibility.release ? ` (${this.compatibility.release})` : ""}` : "a server that did not report its Studio API version";
|
|
183
203
|
throw new StudioReadError(
|
|
184
204
|
"schema_mismatch",
|
|
185
|
-
|
|
205
|
+
`Studio response does not match this CLI's Studio API v${import_telemetry_contracts.STUDIO_API_PROTOCOL_VERSION} contracts. The response came from ${server}. Upgrade both components if this server predates protocol negotiation; otherwise report this as an API compatibility regression.`,
|
|
186
206
|
response.status,
|
|
187
207
|
requestId
|
|
188
208
|
);
|
|
@@ -245,6 +265,7 @@ services:
|
|
|
245
265
|
NODE_ENV: production
|
|
246
266
|
API_HOST: 0.0.0.0
|
|
247
267
|
API_PORT: 6400
|
|
268
|
+
KORTYX_STUDIO_RELEASE: \${KORTYX_STUDIO_IMAGE_TAG:-latest}
|
|
248
269
|
ports:
|
|
249
270
|
- "127.0.0.1:\${API_PORT:-6400}:6400"
|
|
250
271
|
depends_on:
|
|
@@ -447,6 +468,29 @@ var writePrivateFileAtomically = async (path, contents) => {
|
|
|
447
468
|
}
|
|
448
469
|
}
|
|
449
470
|
};
|
|
471
|
+
var readOptionalFile = async (path) => {
|
|
472
|
+
try {
|
|
473
|
+
return await (0, import_promises.readFile)(path, "utf8");
|
|
474
|
+
} catch (error) {
|
|
475
|
+
if (isMissingFile(error)) return null;
|
|
476
|
+
throw error;
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
var captureStudioState = async (home) => ({
|
|
480
|
+
config: await readOptionalFile(studioConfigPath(home)),
|
|
481
|
+
environment: await readOptionalFile(studioEnvPath(home)),
|
|
482
|
+
compose: await readOptionalFile(studioComposePath(home))
|
|
483
|
+
});
|
|
484
|
+
var restoreStudioState = async (home, snapshot) => {
|
|
485
|
+
for (const [path, contents] of [
|
|
486
|
+
[studioConfigPath(home), snapshot.config],
|
|
487
|
+
[studioEnvPath(home), snapshot.environment],
|
|
488
|
+
[studioComposePath(home), snapshot.compose]
|
|
489
|
+
]) {
|
|
490
|
+
if (contents === null) await (0, import_promises.unlink)(path).catch(() => void 0);
|
|
491
|
+
else await writePrivateFileAtomically(path, contents);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
450
494
|
var readStudioEnvironment = async (home) => {
|
|
451
495
|
const path = studioEnvPath(home);
|
|
452
496
|
return parseEnvironmentFile(await (0, import_promises.readFile)(path, "utf8"), path);
|
|
@@ -490,17 +534,15 @@ var ensureStudioState = async (options, runtime) => {
|
|
|
490
534
|
await (0, import_promises.mkdir)((0, import_node_path.join)(options.home, ".updates"), { recursive: true, mode: 448 });
|
|
491
535
|
const existing = await readStudioConfig(options.home);
|
|
492
536
|
const config = resolveConfig(existing, options, runtime);
|
|
493
|
-
await (
|
|
537
|
+
await writePrivateFileAtomically(
|
|
494
538
|
studioConfigPath(options.home),
|
|
495
539
|
`${JSON.stringify(config, null, 2)}
|
|
496
|
-
|
|
497
|
-
|
|
540
|
+
`
|
|
541
|
+
);
|
|
542
|
+
await writePrivateFileAtomically(
|
|
543
|
+
studioComposePath(options.home),
|
|
544
|
+
STUDIO_COMPOSE_FILE
|
|
498
545
|
);
|
|
499
|
-
await (0, import_promises.chmod)(studioConfigPath(options.home), 384);
|
|
500
|
-
await (0, import_promises.writeFile)(studioComposePath(options.home), STUDIO_COMPOSE_FILE, {
|
|
501
|
-
mode: 384
|
|
502
|
-
});
|
|
503
|
-
await (0, import_promises.chmod)(studioComposePath(options.home), 384);
|
|
504
546
|
let environment;
|
|
505
547
|
try {
|
|
506
548
|
environment = await readStudioEnvironment(options.home);
|
|
@@ -772,7 +814,7 @@ var createConnectionsCommand = (log = console.log, request = fetch) => {
|
|
|
772
814
|
);
|
|
773
815
|
const context = await client.get(
|
|
774
816
|
"/v1/studio/context",
|
|
775
|
-
|
|
817
|
+
import_telemetry_contracts2.StudioContextResponseSchema
|
|
776
818
|
);
|
|
777
819
|
if (!context.apiKey.scopes.includes("studio:read"))
|
|
778
820
|
throw new StudioReadError(
|
|
@@ -838,6 +880,7 @@ var import_commander3 = require("commander");
|
|
|
838
880
|
|
|
839
881
|
// src/studio/local-stack.ts
|
|
840
882
|
var import_promises3 = require("fs/promises");
|
|
883
|
+
var import_telemetry_contracts3 = require("@kortyx/telemetry-contracts");
|
|
841
884
|
var composeArgs = (home, args) => [
|
|
842
885
|
"compose",
|
|
843
886
|
"--env-file",
|
|
@@ -980,45 +1023,63 @@ var rotateStudioCredentials = async (home, runtime) => {
|
|
|
980
1023
|
};
|
|
981
1024
|
var startStudio = async (options, runtime) => {
|
|
982
1025
|
await preflightDocker(runtime);
|
|
983
|
-
const
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
environment
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
"
|
|
996
|
-
|
|
997
|
-
"
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1026
|
+
const snapshot = await captureStudioState(options.home);
|
|
1027
|
+
try {
|
|
1028
|
+
const config = await ensureStudioState(options, runtime);
|
|
1029
|
+
const environment = await readStudioEnvironment(options.home);
|
|
1030
|
+
const apiImage = String(
|
|
1031
|
+
environment.KORTYX_API_IMAGE_REF ?? `${environment.KORTYX_API_IMAGE ?? "ghcr.io/kortyx-io/kortyx-api"}:${config.imageTag}`
|
|
1032
|
+
);
|
|
1033
|
+
const studioImage = String(
|
|
1034
|
+
environment.KORTYX_STUDIO_IMAGE_REF ?? `${environment.KORTYX_STUDIO_IMAGE ?? "ghcr.io/kortyx-io/kortyx-studio"}:${config.imageTag}`
|
|
1035
|
+
);
|
|
1036
|
+
await runtime.run("docker", ["pull", apiImage], { inherit: true });
|
|
1037
|
+
if (studioImage !== apiImage)
|
|
1038
|
+
await runtime.run("docker", ["pull", studioImage], { inherit: true });
|
|
1039
|
+
const capability = await runtime.run(
|
|
1040
|
+
"docker",
|
|
1041
|
+
[
|
|
1042
|
+
"run",
|
|
1043
|
+
"--rm",
|
|
1044
|
+
"--entrypoint",
|
|
1045
|
+
"node",
|
|
1046
|
+
apiImage,
|
|
1047
|
+
"-e",
|
|
1048
|
+
'if (require("node:fs").existsSync("/app/apps/api/dist/updater.js")) console.log("supported")'
|
|
1049
|
+
],
|
|
1050
|
+
{ inherit: false }
|
|
1051
|
+
);
|
|
1052
|
+
await (0, import_promises3.writeFile)(
|
|
1053
|
+
studioComposePath(options.home),
|
|
1054
|
+
studioComposeFile(
|
|
1055
|
+
process.platform !== "win32" && capability.stdout.trim() === "supported"
|
|
1056
|
+
),
|
|
1057
|
+
{ mode: 384 }
|
|
1058
|
+
);
|
|
1059
|
+
if (!await hasRunningServices(options.home, runtime)) {
|
|
1060
|
+
await assertPortsAvailable(config, runtime);
|
|
1061
|
+
}
|
|
1062
|
+
runtime.log(
|
|
1063
|
+
"Starting Kortyx Studio. The first image pull can take a few minutes."
|
|
1064
|
+
);
|
|
1065
|
+
await runCompose(
|
|
1066
|
+
options.home,
|
|
1067
|
+
["up", "-d", "--remove-orphans", "--wait", "--wait-timeout", "180"],
|
|
1068
|
+
runtime
|
|
1069
|
+
);
|
|
1070
|
+
runtime.log("Kortyx Studio is ready.");
|
|
1071
|
+
await printStudioConnection(options.home, config, runtime);
|
|
1072
|
+
} catch (error) {
|
|
1073
|
+
try {
|
|
1074
|
+
await restoreStudioState(options.home, snapshot);
|
|
1075
|
+
} catch (rollbackError) {
|
|
1076
|
+
throw new AggregateError(
|
|
1077
|
+
[error, rollbackError],
|
|
1078
|
+
`Studio startup failed and the previous configuration could not be restored. Inspect "${options.home}" before retrying.`
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
throw error;
|
|
1011
1082
|
}
|
|
1012
|
-
runtime.log(
|
|
1013
|
-
"Starting Kortyx Studio. The first image pull can take a few minutes."
|
|
1014
|
-
);
|
|
1015
|
-
await runCompose(
|
|
1016
|
-
options.home,
|
|
1017
|
-
["up", "-d", "--remove-orphans", "--wait", "--wait-timeout", "180"],
|
|
1018
|
-
runtime
|
|
1019
|
-
);
|
|
1020
|
-
runtime.log("Kortyx Studio is ready.");
|
|
1021
|
-
await printStudioConnection(options.home, config, runtime);
|
|
1022
1083
|
};
|
|
1023
1084
|
var stopStudio = async (home, runtime) => {
|
|
1024
1085
|
await preflightDocker(runtime);
|
|
@@ -1046,6 +1107,24 @@ var showStudioStatus = async (home, runtime) => {
|
|
|
1046
1107
|
runtime.log();
|
|
1047
1108
|
runtime.log(`Studio: http://localhost:${config.studioPort}`);
|
|
1048
1109
|
runtime.log(`API: http://localhost:${config.apiPort}`);
|
|
1110
|
+
if (runtime.request) {
|
|
1111
|
+
const environment = await readStudioEnvironment(home);
|
|
1112
|
+
const client = new StudioReadClient(
|
|
1113
|
+
`http://localhost:${config.apiPort}`,
|
|
1114
|
+
environment.KORTYX_STUDIO_API_KEY,
|
|
1115
|
+
runtime.request
|
|
1116
|
+
);
|
|
1117
|
+
try {
|
|
1118
|
+
await client.get("/v1/studio/context", import_telemetry_contracts3.StudioContextResponseSchema);
|
|
1119
|
+
runtime.log(
|
|
1120
|
+
client.compatibility.protocolVersion ? `Compatibility: Studio API v${client.compatibility.protocolVersion} (${client.compatibility.release ?? config.imageTag}) is compatible with CLI API v${import_telemetry_contracts3.STUDIO_API_PROTOCOL_VERSION}.` : `Compatibility: response is compatible with CLI API v${import_telemetry_contracts3.STUDIO_API_PROTOCOL_VERSION}; this older server does not report its protocol version.`
|
|
1121
|
+
);
|
|
1122
|
+
} catch (error) {
|
|
1123
|
+
runtime.log(
|
|
1124
|
+
`Compatibility: ${error instanceof StudioReadError ? error.message : "could not query the Studio API."}`
|
|
1125
|
+
);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1049
1128
|
runtime.log(`State: ${home}`);
|
|
1050
1129
|
};
|
|
1051
1130
|
var showStudioLogs = async (home, follow, runtime) => {
|
|
@@ -1072,11 +1151,11 @@ var resetStudio = async (home, confirm, runtime) => {
|
|
|
1072
1151
|
};
|
|
1073
1152
|
|
|
1074
1153
|
// src/studio/read-command.ts
|
|
1075
|
-
var
|
|
1154
|
+
var import_telemetry_contracts5 = require("@kortyx/telemetry-contracts");
|
|
1076
1155
|
var import_commander2 = require("commander");
|
|
1077
1156
|
|
|
1078
1157
|
// src/studio/read-analysis.ts
|
|
1079
|
-
var
|
|
1158
|
+
var import_telemetry_contracts4 = require("@kortyx/telemetry-contracts");
|
|
1080
1159
|
var stringValue = (value) => typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1081
1160
|
var numberValue = (value) => typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : void 0;
|
|
1082
1161
|
var recordValue = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -1192,7 +1271,7 @@ var focusStudioEvents = (events, target) => {
|
|
|
1192
1271
|
"The URL has no event, trace, node, branch, or call selector to focus."
|
|
1193
1272
|
);
|
|
1194
1273
|
const callEventIds = new Set(
|
|
1195
|
-
selection.call ? (0,
|
|
1274
|
+
selection.call ? (0, import_telemetry_contracts4.projectWorkflowCalls)(events).filter(
|
|
1196
1275
|
(call) => call.id === selection.call || call.callId === selection.call || call.invocationId === selection.call
|
|
1197
1276
|
).flatMap((call) => call.events.map((event) => event.id)) : []
|
|
1198
1277
|
);
|
|
@@ -1480,8 +1559,12 @@ var sanitizeStudioData = (value, includeContent, key = "") => {
|
|
|
1480
1559
|
var summarizeEvidence = (events) => {
|
|
1481
1560
|
const findings = events.flatMap((event) => {
|
|
1482
1561
|
const payload = event.payload;
|
|
1483
|
-
const
|
|
1484
|
-
const
|
|
1562
|
+
const error = payload.error && typeof payload.error === "object" && !Array.isArray(payload.error) ? payload.error : {};
|
|
1563
|
+
const suspension = event.type === "span.failed" && (error.controlFlow === true || ["GraphInterrupt", "NodeInterrupt", "ParallelChildWaiting"].includes(
|
|
1564
|
+
String(error.name)
|
|
1565
|
+
));
|
|
1566
|
+
const failed = !suspension && (/(?:failed|error|fault)/i.test(event.type) || payload.outcome === "fault" || payload.status === "failed");
|
|
1567
|
+
const warning = suspension || /(?:retry|cancel|interrupt|limit_reached|denied|suspended|waiting)/i.test(
|
|
1485
1568
|
event.type
|
|
1486
1569
|
) || ["denied", "cancelled"].includes(String(payload.outcome));
|
|
1487
1570
|
if (!failed && !warning) return [];
|
|
@@ -1567,10 +1650,10 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1567
1650
|
const { connection, client } = await clientFor(options, target.url);
|
|
1568
1651
|
const context = await client.get(
|
|
1569
1652
|
"/v1/studio/context",
|
|
1570
|
-
|
|
1653
|
+
import_telemetry_contracts5.StudioContextResponseSchema
|
|
1571
1654
|
);
|
|
1572
1655
|
const path = `/v1/studio/${target.entity}/${encodeURIComponent(target.id)}`;
|
|
1573
|
-
const detail = target.entity === "runs" ? await client.get(path,
|
|
1656
|
+
const detail = target.entity === "runs" ? await client.get(path, import_telemetry_contracts5.StudioRunDetailResponseSchema) : target.entity === "sessions" ? await client.get(path, import_telemetry_contracts5.StudioSessionDetailResponseSchema) : await client.get(path, import_telemetry_contracts5.StudioInterruptDetailResponseSchema);
|
|
1574
1657
|
const limit = options.eventLimit;
|
|
1575
1658
|
const events = [...detail.events].sort(
|
|
1576
1659
|
(a, b) => Date.parse(a.occurredAt) - Date.parse(b.occurredAt) || Date.parse(a.receivedAt) - Date.parse(b.receivedAt) || a.id.localeCompare(b.id)
|
|
@@ -1594,13 +1677,13 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1594
1677
|
),
|
|
1595
1678
|
...analyzedFindings
|
|
1596
1679
|
];
|
|
1597
|
-
const calls = (0,
|
|
1680
|
+
const calls = (0, import_telemetry_contracts5.projectWorkflowCalls)(selectedEvents);
|
|
1598
1681
|
let catalog;
|
|
1599
1682
|
if (target.entity === "runs" && run2) {
|
|
1600
1683
|
try {
|
|
1601
1684
|
const workflows2 = await client.get(
|
|
1602
1685
|
"/v1/studio/workflows",
|
|
1603
|
-
|
|
1686
|
+
import_telemetry_contracts5.StudioWorkflowsResponseSchema,
|
|
1604
1687
|
{ range: "All time", workflow: run2.workflowId }
|
|
1605
1688
|
);
|
|
1606
1689
|
catalog = compareCatalogRuntime(run2, workflows2.workflows);
|
|
@@ -1685,7 +1768,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1685
1768
|
const { connection, client } = await clientFor(options);
|
|
1686
1769
|
const context = await client.get(
|
|
1687
1770
|
"/v1/studio/context",
|
|
1688
|
-
|
|
1771
|
+
import_telemetry_contracts5.StudioContextResponseSchema
|
|
1689
1772
|
);
|
|
1690
1773
|
print(
|
|
1691
1774
|
{
|
|
@@ -1709,7 +1792,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1709
1792
|
connection: connection.name,
|
|
1710
1793
|
data: await client.get(
|
|
1711
1794
|
"/v1/studio/catalogs",
|
|
1712
|
-
|
|
1795
|
+
import_telemetry_contracts5.StudioCatalogsResponseSchema
|
|
1713
1796
|
)
|
|
1714
1797
|
},
|
|
1715
1798
|
options
|
|
@@ -1724,7 +1807,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1724
1807
|
"Studio time range: 1h, 24h, 7d, 30d, all (or Studio preset name)."
|
|
1725
1808
|
).choices([
|
|
1726
1809
|
...Object.keys(rangeAliases),
|
|
1727
|
-
...
|
|
1810
|
+
...import_telemetry_contracts5.StudioTimeRangeSchema.options
|
|
1728
1811
|
]).default("24h")
|
|
1729
1812
|
).option(
|
|
1730
1813
|
"--started-after <iso>",
|
|
@@ -1736,7 +1819,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1736
1819
|
const timeQuery = (options) => {
|
|
1737
1820
|
const custom = Boolean(options.startedAfter || options.startedBefore);
|
|
1738
1821
|
const range = custom ? "Custom range" : rangeAliases[options.range] ?? options.range;
|
|
1739
|
-
const resolution = (0,
|
|
1822
|
+
const resolution = (0, import_telemetry_contracts5.resolveStudioTimeRange)({
|
|
1740
1823
|
range,
|
|
1741
1824
|
startedAfter: options.startedAfter,
|
|
1742
1825
|
startedBefore: options.startedBefore
|
|
@@ -1780,23 +1863,23 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1780
1863
|
);
|
|
1781
1864
|
const context = await client.get(
|
|
1782
1865
|
"/v1/studio/context",
|
|
1783
|
-
|
|
1866
|
+
import_telemetry_contracts5.StudioContextResponseSchema
|
|
1784
1867
|
);
|
|
1785
1868
|
const [leftDetail, rightDetail] = await Promise.all([
|
|
1786
1869
|
client.get(
|
|
1787
1870
|
`/v1/studio/runs/${encodeURIComponent(leftTarget.id)}`,
|
|
1788
|
-
|
|
1871
|
+
import_telemetry_contracts5.StudioRunDetailResponseSchema
|
|
1789
1872
|
),
|
|
1790
1873
|
client.get(
|
|
1791
1874
|
`/v1/studio/runs/${encodeURIComponent(rightTarget.id)}`,
|
|
1792
|
-
|
|
1875
|
+
import_telemetry_contracts5.StudioRunDetailResponseSchema
|
|
1793
1876
|
)
|
|
1794
1877
|
]);
|
|
1795
1878
|
const catalogFor = async (detail) => {
|
|
1796
1879
|
try {
|
|
1797
1880
|
const response = await client.get(
|
|
1798
1881
|
"/v1/studio/workflows",
|
|
1799
|
-
|
|
1882
|
+
import_telemetry_contracts5.StudioWorkflowsResponseSchema,
|
|
1800
1883
|
{ range: "All time", workflow: detail.run.workflowId }
|
|
1801
1884
|
);
|
|
1802
1885
|
return compareCatalogRuntime(detail.run, response.workflows);
|
|
@@ -1902,7 +1985,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1902
1985
|
query.cursor = String(options.cursor);
|
|
1903
1986
|
if (options.includeChildren) query.includeChildren = "true";
|
|
1904
1987
|
const path = `/v1/studio/${entity}`;
|
|
1905
|
-
const data = entity === "runs" ? await client.get(path,
|
|
1988
|
+
const data = entity === "runs" ? await client.get(path, import_telemetry_contracts5.StudioRunsResponseSchema, query) : entity === "sessions" ? await client.get(path, import_telemetry_contracts5.StudioSessionsResponseSchema, query) : await client.get(path, import_telemetry_contracts5.StudioInterruptsResponseSchema, query);
|
|
1906
1989
|
const items = "runs" in data ? data.runs : "sessions" in data ? data.sessions : data.interrupts;
|
|
1907
1990
|
const next = options.cursor + items.length;
|
|
1908
1991
|
print(
|
|
@@ -1939,7 +2022,7 @@ var registerStudioReadCommands = (studio, log, request = fetch) => {
|
|
|
1939
2022
|
connection: connection.name,
|
|
1940
2023
|
data: await client.get(
|
|
1941
2024
|
"/v1/studio/workflows",
|
|
1942
|
-
|
|
2025
|
+
import_telemetry_contracts5.StudioWorkflowsResponseSchema,
|
|
1943
2026
|
query
|
|
1944
2027
|
),
|
|
1945
2028
|
note: "Workflow metrics span environments; connection environment defaults are not applied by this API."
|
|
@@ -1990,6 +2073,7 @@ var defaultStudioRuntime = {
|
|
|
1990
2073
|
portAvailable,
|
|
1991
2074
|
now: () => (/* @__PURE__ */ new Date()).toISOString(),
|
|
1992
2075
|
random: (bytes) => (0, import_node_crypto2.randomBytes)(bytes).toString("base64url"),
|
|
2076
|
+
request: fetch,
|
|
1993
2077
|
log: (message = "") => console.log(message),
|
|
1994
2078
|
error: (message = "") => console.error(message)
|
|
1995
2079
|
};
|
|
@@ -2748,7 +2832,7 @@ var pushSnapshot = async (apiUrl, apiKey, snapshot) => {
|
|
|
2748
2832
|
}
|
|
2749
2833
|
);
|
|
2750
2834
|
}
|
|
2751
|
-
return
|
|
2835
|
+
return import_telemetry_contracts6.EnsureWorkflowTopologyResponseSchema.parse(await response.json());
|
|
2752
2836
|
};
|
|
2753
2837
|
var printResults = (results, options) => {
|
|
2754
2838
|
if (options.json) {
|
|
@@ -2828,7 +2912,7 @@ var runTopologyPush = async (rawOptions) => {
|
|
|
2828
2912
|
}
|
|
2829
2913
|
}
|
|
2830
2914
|
const parsedSnapshots = snapshots.map(
|
|
2831
|
-
(snapshot) =>
|
|
2915
|
+
(snapshot) => import_telemetry_contracts6.EnsureWorkflowTopologyRequestSchema.parse(snapshot)
|
|
2832
2916
|
);
|
|
2833
2917
|
const results = [];
|
|
2834
2918
|
for (const snapshot of parsedSnapshots) {
|