deepline 0.1.298 → 0.1.300
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/dist/bundling-sources/sdk/src/client.ts +10 -3
- package/dist/bundling-sources/sdk/src/http.ts +48 -30
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +4 -45
- package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +43 -3
- package/dist/cli/index.js +78 -42
- package/dist/cli/index.mjs +78 -42
- package/dist/index.js +55 -19
- package/dist/index.mjs +55 -19
- package/package.json +1 -1
|
@@ -93,6 +93,7 @@ import {
|
|
|
93
93
|
normalizePlayRuntimeSelection,
|
|
94
94
|
type PlayRuntimeSelection,
|
|
95
95
|
} from '../../shared_libs/play-runtime/runtime-environment.js';
|
|
96
|
+
import { decodePlayRunPublicStatus } from '../../shared_libs/play-runtime/run-lifecycle-policy.js';
|
|
96
97
|
|
|
97
98
|
const TERMINAL_PLAY_STATUSES = new Set(['completed', 'failed', 'cancelled']);
|
|
98
99
|
const INCLUDE_TOOL_METADATA_HEADER = 'x-deepline-include-tool-metadata';
|
|
@@ -991,12 +992,18 @@ function normalizePlayStatus(raw: Record<string, unknown>): PlayStatus {
|
|
|
991
992
|
? raw.package
|
|
992
993
|
: null;
|
|
993
994
|
const packageRun = runPackage?.run;
|
|
994
|
-
const
|
|
995
|
+
const rawStatus =
|
|
995
996
|
typeof raw.status === 'string'
|
|
996
997
|
? raw.status
|
|
997
998
|
: typeof packageRun?.status === 'string'
|
|
998
999
|
? packageRun.status
|
|
999
|
-
:
|
|
1000
|
+
: null;
|
|
1001
|
+
const status = decodePlayRunPublicStatus(rawStatus);
|
|
1002
|
+
if (!status) {
|
|
1003
|
+
throw new Error(
|
|
1004
|
+
`Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`,
|
|
1005
|
+
);
|
|
1006
|
+
}
|
|
1000
1007
|
const runId =
|
|
1001
1008
|
typeof raw.runId === 'string'
|
|
1002
1009
|
? raw.runId
|
|
@@ -1007,7 +1014,7 @@ function normalizePlayStatus(raw: Record<string, unknown>): PlayStatus {
|
|
|
1007
1014
|
...(raw as unknown as Omit<PlayStatus, 'runId' | 'status'>),
|
|
1008
1015
|
runId,
|
|
1009
1016
|
...(runPackage ? { package: runPackage, outputs: runPackage.outputs } : {}),
|
|
1010
|
-
status
|
|
1017
|
+
status,
|
|
1011
1018
|
};
|
|
1012
1019
|
}
|
|
1013
1020
|
|
|
@@ -54,8 +54,8 @@ interface RequestOptions {
|
|
|
54
54
|
* Treat HTTP 403 as a regular API error instead of a generic {@link AuthError}.
|
|
55
55
|
* Use for endpoints that return 403 with a meaningful server error message
|
|
56
56
|
* (e.g. feature-flagged-off billing subscription checkout) so the server
|
|
57
|
-
* message is preserved and surfaced loudly. HTTP 401
|
|
58
|
-
*
|
|
57
|
+
* message is preserved and surfaced loudly. A provider-originated HTTP 401
|
|
58
|
+
* remains a regular API error when its response envelope says so.
|
|
59
59
|
*/
|
|
60
60
|
forbiddenAsApiError?: boolean;
|
|
61
61
|
/**
|
|
@@ -311,7 +311,7 @@ export class HttpClient {
|
|
|
311
311
|
* @param path - API path (e.g. `"/api/v2/tools"`)
|
|
312
312
|
* @param options - HTTP method, body, headers, and timeout
|
|
313
313
|
* @returns Parsed JSON response body
|
|
314
|
-
* @throws {@link AuthError} on HTTP 401/403 (immediate, no retry)
|
|
314
|
+
* @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
|
|
315
315
|
* @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
|
|
316
316
|
* @throws {@link DeeplineError} on other API errors or connection failures
|
|
317
317
|
*/
|
|
@@ -374,13 +374,6 @@ export class HttpClient {
|
|
|
374
374
|
|
|
375
375
|
clearTimeout(timeoutId);
|
|
376
376
|
|
|
377
|
-
if (
|
|
378
|
-
response.status === 401 ||
|
|
379
|
-
(response.status === 403 && !options?.forbiddenAsApiError)
|
|
380
|
-
) {
|
|
381
|
-
throw new AuthError();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
377
|
if (response.status === 429) {
|
|
385
378
|
const retryAfter = parseRetryAfter(response);
|
|
386
379
|
lastError = new RateLimitError(retryAfter);
|
|
@@ -392,11 +385,14 @@ export class HttpClient {
|
|
|
392
385
|
}
|
|
393
386
|
|
|
394
387
|
const body = await response.text();
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
388
|
+
const parsed = parseResponseBody(body);
|
|
389
|
+
|
|
390
|
+
if (
|
|
391
|
+
(response.status === 401 &&
|
|
392
|
+
!isProviderOriginatedHttpError(parsed)) ||
|
|
393
|
+
(response.status === 403 && !options?.forbiddenAsApiError)
|
|
394
|
+
) {
|
|
395
|
+
throw new AuthError();
|
|
400
396
|
}
|
|
401
397
|
|
|
402
398
|
if (!response.ok) {
|
|
@@ -451,16 +447,7 @@ export class HttpClient {
|
|
|
451
447
|
'string'
|
|
452
448
|
? (parsed as Record<string, string>).message
|
|
453
449
|
: `HTTP ${response.status}`;
|
|
454
|
-
const apiErrorCode =
|
|
455
|
-
errorValue &&
|
|
456
|
-
typeof errorValue === 'object' &&
|
|
457
|
-
typeof (errorValue as Record<string, unknown>).code === 'string'
|
|
458
|
-
? (errorValue as Record<string, string>).code
|
|
459
|
-
: typeof parsed === 'object' &&
|
|
460
|
-
parsed &&
|
|
461
|
-
typeof (parsed as Record<string, unknown>).code === 'string'
|
|
462
|
-
? (parsed as Record<string, string>).code
|
|
463
|
-
: 'API_ERROR';
|
|
450
|
+
const apiErrorCode = apiErrorCodeFromResponse(parsed);
|
|
464
451
|
lastError = new DeeplineError(msg, response.status, apiErrorCode, {
|
|
465
452
|
response: parsed,
|
|
466
453
|
});
|
|
@@ -547,11 +534,16 @@ export class HttpClient {
|
|
|
547
534
|
signal: options?.signal,
|
|
548
535
|
});
|
|
549
536
|
|
|
550
|
-
if (response.status === 401 || response.status === 403) {
|
|
551
|
-
throw new AuthError();
|
|
552
|
-
}
|
|
553
537
|
if (!response.ok) {
|
|
554
538
|
const body = await response.text();
|
|
539
|
+
const parsed = parseResponseBody(body);
|
|
540
|
+
if (
|
|
541
|
+
(response.status === 401 &&
|
|
542
|
+
!isProviderOriginatedHttpError(parsed)) ||
|
|
543
|
+
response.status === 403
|
|
544
|
+
) {
|
|
545
|
+
throw new AuthError();
|
|
546
|
+
}
|
|
555
547
|
const htmlError = detectHtmlErrorBody(
|
|
556
548
|
body,
|
|
557
549
|
response.headers.get('content-type'),
|
|
@@ -570,11 +562,10 @@ export class HttpClient {
|
|
|
570
562
|
},
|
|
571
563
|
);
|
|
572
564
|
}
|
|
573
|
-
const parsed = parseResponseBody(body);
|
|
574
565
|
throw new DeeplineError(
|
|
575
566
|
apiErrorMessage(parsed, response.status),
|
|
576
567
|
response.status,
|
|
577
|
-
|
|
568
|
+
apiErrorCodeFromResponse(parsed),
|
|
578
569
|
{ response: parsed },
|
|
579
570
|
);
|
|
580
571
|
}
|
|
@@ -679,6 +670,33 @@ function parseResponseBody(body: string): unknown {
|
|
|
679
670
|
}
|
|
680
671
|
}
|
|
681
672
|
|
|
673
|
+
/**
|
|
674
|
+
* A provider can reject its own credential with HTTP 401 while the caller's
|
|
675
|
+
* Deepline API key remains valid. The API envelope is authoritative in that
|
|
676
|
+
* case, so preserve it as a regular DeeplineError rather than prompting the
|
|
677
|
+
* caller to replace DEEPLINE_API_KEY.
|
|
678
|
+
*/
|
|
679
|
+
function isProviderOriginatedHttpError(parsed: unknown): boolean {
|
|
680
|
+
const response = asRecord(parsed);
|
|
681
|
+
const error = asRecord(response?.error);
|
|
682
|
+
const failureOrigin = error?.failure_origin ?? response?.failure_origin;
|
|
683
|
+
const code = error?.code ?? response?.code;
|
|
684
|
+
return failureOrigin === 'provider' || code === 'UPSTREAM_BLOCKED';
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function apiErrorCodeFromResponse(parsed: unknown): string {
|
|
688
|
+
const response = asRecord(parsed);
|
|
689
|
+
const error = asRecord(response?.error);
|
|
690
|
+
const code = error?.code ?? response?.code;
|
|
691
|
+
return typeof code === 'string' ? code : 'API_ERROR';
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
695
|
+
return typeof value === 'object' && value !== null
|
|
696
|
+
? (value as Record<string, unknown>)
|
|
697
|
+
: null;
|
|
698
|
+
}
|
|
699
|
+
|
|
682
700
|
function isRetryableApiErrorResponse(status: number): boolean {
|
|
683
701
|
return status === 408 || status === 425 || (status >= 500 && status < 600);
|
|
684
702
|
}
|
|
@@ -155,7 +155,7 @@ export const SDK_RELEASE = {
|
|
|
155
155
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
156
156
|
// 0.1.254 removes the internal operations tree from the published SDK CLI.
|
|
157
157
|
// Operators use the checkout-local deepline-admin binary instead.
|
|
158
|
-
version: '0.1.
|
|
158
|
+
version: '0.1.300',
|
|
159
159
|
contracts: {
|
|
160
160
|
api: {
|
|
161
161
|
name: 'sdk-http-api',
|
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
PLATFORM_DEPLOY_INTERRUPTED_MESSAGE,
|
|
4
4
|
} from './run-failure';
|
|
5
5
|
import {
|
|
6
|
-
isAuthoritativePlayRunTerminalSource,
|
|
7
6
|
nextPlayRunLedgerTerminalSource,
|
|
8
7
|
normalizePlayRunLedgerTerminalSource,
|
|
9
8
|
} from './run-terminal-source';
|
|
@@ -643,16 +642,6 @@ function nextTerminalSource(
|
|
|
643
642
|
});
|
|
644
643
|
}
|
|
645
644
|
|
|
646
|
-
function shouldUpgradeFromCoordinatorTerminal(
|
|
647
|
-
base: PlayRunLedgerSnapshot,
|
|
648
|
-
eventSource: PlayRunLedgerEventSource,
|
|
649
|
-
): boolean {
|
|
650
|
-
return (
|
|
651
|
-
base.terminalSource === 'coordinator' &&
|
|
652
|
-
isAuthoritativePlayRunTerminalSource(eventSource)
|
|
653
|
-
);
|
|
654
|
-
}
|
|
655
|
-
|
|
656
645
|
function shouldIgnoreNonTerminalAfterStickyTerminal(
|
|
657
646
|
base: PlayRunLedgerSnapshot,
|
|
658
647
|
): boolean {
|
|
@@ -908,13 +897,10 @@ function appendLogLines(
|
|
|
908
897
|
}
|
|
909
898
|
|
|
910
899
|
/**
|
|
911
|
-
* Terminal-status precedence.
|
|
912
|
-
*
|
|
913
|
-
*
|
|
914
|
-
*
|
|
915
|
-
* an earlier partial terminal snapshot. Retryable platform-deploy failures are
|
|
916
|
-
* the narrow exception: they are never allowed to replace a real terminal
|
|
917
|
-
* result from the runtime.
|
|
900
|
+
* Terminal-status precedence. The first accepted run terminal is immutable:
|
|
901
|
+
* later events may enrich the same terminal payload, but may never change its
|
|
902
|
+
* outcome. Attempt retries are not authority to rewrite a terminal run, and
|
|
903
|
+
* producer timestamps are telemetry rather than an ordering mechanism.
|
|
918
904
|
*/
|
|
919
905
|
function conflictingTerminalSnapshot(
|
|
920
906
|
base: PlayRunLedgerSnapshot,
|
|
@@ -923,26 +909,12 @@ function conflictingTerminalSnapshot(
|
|
|
923
909
|
eventError?: string | null,
|
|
924
910
|
options?: {
|
|
925
911
|
allowStaleSameStatusPayloadMerge?: boolean;
|
|
926
|
-
allowCoordinatorTerminalUpgrade?: boolean;
|
|
927
912
|
},
|
|
928
913
|
): PlayRunLedgerSnapshot | null {
|
|
929
914
|
if (!isTerminalPlayRunLedgerStatus(base.status)) {
|
|
930
915
|
return null;
|
|
931
916
|
}
|
|
932
917
|
const terminalAt = base.finishedAt ?? base.updatedAt ?? 0;
|
|
933
|
-
if (base.status === 'cancelled' && eventType !== 'run.cancelled') {
|
|
934
|
-
if (occurredAt <= terminalAt) {
|
|
935
|
-
return withTiming(
|
|
936
|
-
appendLogLines(base, [
|
|
937
|
-
`[ledger] stale conflicting terminal event ${eventType} ignored; status already ${base.status}`,
|
|
938
|
-
]),
|
|
939
|
-
);
|
|
940
|
-
}
|
|
941
|
-
return withTiming(base);
|
|
942
|
-
}
|
|
943
|
-
if (options?.allowCoordinatorTerminalUpgrade === true) {
|
|
944
|
-
return null;
|
|
945
|
-
}
|
|
946
918
|
if (
|
|
947
919
|
base.status === 'completed' &&
|
|
948
920
|
eventType === 'run.failed' &&
|
|
@@ -970,12 +942,6 @@ function conflictingTerminalSnapshot(
|
|
|
970
942
|
}
|
|
971
943
|
return null;
|
|
972
944
|
}
|
|
973
|
-
if (occurredAt > terminalAt) {
|
|
974
|
-
// Newer terminal evidence reconciles the run. This covers replay/receipt
|
|
975
|
-
// races where an earlier attempt failed but a later attempt recovered and
|
|
976
|
-
// completed with the durable result.
|
|
977
|
-
return null;
|
|
978
|
-
}
|
|
979
945
|
return withTiming(
|
|
980
946
|
appendLogLines(base, [
|
|
981
947
|
`[ledger] stale conflicting terminal event ${eventType} ignored; status already ${base.status}`,
|
|
@@ -1205,12 +1171,7 @@ export function reducePlayRunLedgerEvent(
|
|
|
1205
1171
|
case 'run.completed':
|
|
1206
1172
|
return (
|
|
1207
1173
|
conflictingTerminalSnapshot(base, event.type, occurredAt, null, {
|
|
1208
|
-
allowCoordinatorTerminalUpgrade: shouldUpgradeFromCoordinatorTerminal(
|
|
1209
|
-
base,
|
|
1210
|
-
event.source,
|
|
1211
|
-
),
|
|
1212
1174
|
allowStaleSameStatusPayloadMerge:
|
|
1213
|
-
shouldUpgradeFromCoordinatorTerminal(base, event.source) ||
|
|
1214
1175
|
(base.result === undefined && event.result !== undefined) ||
|
|
1215
1176
|
(base.resultSummary === undefined &&
|
|
1216
1177
|
event.resultSummary !== undefined),
|
|
@@ -1234,7 +1195,6 @@ export function reducePlayRunLedgerEvent(
|
|
|
1234
1195
|
retryablePlatformDeployFailureSnapshot(base, event.error) ??
|
|
1235
1196
|
conflictingTerminalSnapshot(base, event.type, occurredAt, event.error, {
|
|
1236
1197
|
allowStaleSameStatusPayloadMerge:
|
|
1237
|
-
shouldUpgradeFromCoordinatorTerminal(base, event.source) ||
|
|
1238
1198
|
(base.error == null && event.error != null) ||
|
|
1239
1199
|
(base.result === undefined && event.result !== undefined),
|
|
1240
1200
|
}) ??
|
|
@@ -1258,7 +1218,6 @@ export function reducePlayRunLedgerEvent(
|
|
|
1258
1218
|
return (
|
|
1259
1219
|
conflictingTerminalSnapshot(base, event.type, occurredAt, event.error, {
|
|
1260
1220
|
allowStaleSameStatusPayloadMerge:
|
|
1261
|
-
shouldUpgradeFromCoordinatorTerminal(base, event.source) ||
|
|
1262
1221
|
(base.error == null && event.error != null) ||
|
|
1263
1222
|
(base.result === undefined && event.result !== undefined),
|
|
1264
1223
|
}) ??
|
|
@@ -9,6 +9,15 @@ export type PlayRunLifecycleStatus =
|
|
|
9
9
|
| 'timed_out'
|
|
10
10
|
| 'unknown';
|
|
11
11
|
|
|
12
|
+
/** The only lifecycle states exposed by the API, SDK, CLI, and UI. */
|
|
13
|
+
export type PlayRunPublicStatus =
|
|
14
|
+
| 'queued'
|
|
15
|
+
| 'running'
|
|
16
|
+
| 'waiting'
|
|
17
|
+
| 'completed'
|
|
18
|
+
| 'failed'
|
|
19
|
+
| 'cancelled';
|
|
20
|
+
|
|
12
21
|
const TERMINAL_PLAY_RUN_STATUSES = new Set<PlayRunLifecycleStatus>([
|
|
13
22
|
'completed',
|
|
14
23
|
'failed',
|
|
@@ -33,7 +42,7 @@ export function normalizePlayRunLifecycleStatus(
|
|
|
33
42
|
switch (normalized) {
|
|
34
43
|
case 'queued':
|
|
35
44
|
case 'pending':
|
|
36
|
-
return '
|
|
45
|
+
return 'queued';
|
|
37
46
|
case 'running':
|
|
38
47
|
case 'started':
|
|
39
48
|
return 'running';
|
|
@@ -60,12 +69,43 @@ export function normalizePlayRunLifecycleStatus(
|
|
|
60
69
|
}
|
|
61
70
|
|
|
62
71
|
export function isTerminalPlayRunLifecycleStatus(status: unknown): boolean {
|
|
63
|
-
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
72
|
+
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
73
|
+
normalizePlayRunLifecycleStatus(status),
|
|
74
|
+
);
|
|
64
75
|
}
|
|
65
76
|
|
|
66
77
|
export function isActivePlayRunLifecycleStatus(status: unknown): boolean {
|
|
67
78
|
const normalized = normalizePlayRunLifecycleStatus(status);
|
|
68
|
-
return
|
|
79
|
+
return (
|
|
80
|
+
normalized === 'queued' ||
|
|
81
|
+
normalized === 'running' ||
|
|
82
|
+
normalized === 'waiting'
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Decode a public lifecycle value without inventing progress. Internal
|
|
88
|
+
* termination reasons intentionally collapse to the one public cancellation
|
|
89
|
+
* outcome at this Adapter boundary. Unknown/missing values are invalid.
|
|
90
|
+
*/
|
|
91
|
+
export function decodePlayRunPublicStatus(
|
|
92
|
+
value: unknown,
|
|
93
|
+
): PlayRunPublicStatus | null {
|
|
94
|
+
const status = normalizePlayRunLifecycleStatus(value);
|
|
95
|
+
switch (status) {
|
|
96
|
+
case 'queued':
|
|
97
|
+
case 'running':
|
|
98
|
+
case 'waiting':
|
|
99
|
+
case 'completed':
|
|
100
|
+
case 'failed':
|
|
101
|
+
case 'cancelled':
|
|
102
|
+
return status;
|
|
103
|
+
case 'terminated':
|
|
104
|
+
case 'timed_out':
|
|
105
|
+
return 'cancelled';
|
|
106
|
+
case 'unknown':
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
69
109
|
}
|
|
70
110
|
|
|
71
111
|
export function isRecoverableDatasetRowStatus(status: unknown): boolean {
|
package/dist/cli/index.js
CHANGED
|
@@ -718,7 +718,7 @@ var SDK_RELEASE = {
|
|
|
718
718
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
719
719
|
// 0.1.254 removes the internal operations tree from the published SDK CLI.
|
|
720
720
|
// Operators use the checkout-local deepline-admin binary instead.
|
|
721
|
-
version: "0.1.
|
|
721
|
+
version: "0.1.300",
|
|
722
722
|
contracts: {
|
|
723
723
|
api: {
|
|
724
724
|
name: "sdk-http-api",
|
|
@@ -1063,7 +1063,7 @@ var HttpClient = class {
|
|
|
1063
1063
|
* @param path - API path (e.g. `"/api/v2/tools"`)
|
|
1064
1064
|
* @param options - HTTP method, body, headers, and timeout
|
|
1065
1065
|
* @returns Parsed JSON response body
|
|
1066
|
-
* @throws {@link AuthError} on HTTP 401/403 (immediate, no retry)
|
|
1066
|
+
* @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
|
|
1067
1067
|
* @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
|
|
1068
1068
|
* @throws {@link DeeplineError} on other API errors or connection failures
|
|
1069
1069
|
*/
|
|
@@ -1102,9 +1102,6 @@ var HttpClient = class {
|
|
|
1102
1102
|
signal: controller.signal
|
|
1103
1103
|
});
|
|
1104
1104
|
clearTimeout(timeoutId);
|
|
1105
|
-
if (response.status === 401 || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
1106
|
-
throw new AuthError();
|
|
1107
|
-
}
|
|
1108
1105
|
if (response.status === 429) {
|
|
1109
1106
|
const retryAfter = parseRetryAfter(response);
|
|
1110
1107
|
lastError = new RateLimitError(retryAfter);
|
|
@@ -1115,11 +1112,9 @@ var HttpClient = class {
|
|
|
1115
1112
|
throw lastError;
|
|
1116
1113
|
}
|
|
1117
1114
|
const body = await response.text();
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
} catch {
|
|
1122
|
-
parsed = body;
|
|
1115
|
+
const parsed = parseResponseBody(body);
|
|
1116
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
1117
|
+
throw new AuthError();
|
|
1123
1118
|
}
|
|
1124
1119
|
if (!response.ok) {
|
|
1125
1120
|
const retryableApiError = options?.retryApiErrors === true && isRetryableApiErrorResponse(response.status);
|
|
@@ -1146,7 +1141,7 @@ var HttpClient = class {
|
|
|
1146
1141
|
}
|
|
1147
1142
|
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
1148
1143
|
const msg = typeof errorValue === "string" ? errorValue : errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string" ? errorValue.message : typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `HTTP ${response.status}`;
|
|
1149
|
-
const apiErrorCode2 =
|
|
1144
|
+
const apiErrorCode2 = apiErrorCodeFromResponse(parsed);
|
|
1150
1145
|
lastError = new DeeplineError(msg, response.status, apiErrorCode2, {
|
|
1151
1146
|
response: parsed
|
|
1152
1147
|
});
|
|
@@ -1220,11 +1215,12 @@ var HttpClient = class {
|
|
|
1220
1215
|
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
1221
1216
|
signal: options?.signal
|
|
1222
1217
|
});
|
|
1223
|
-
if (response.status === 401 || response.status === 403) {
|
|
1224
|
-
throw new AuthError();
|
|
1225
|
-
}
|
|
1226
1218
|
if (!response.ok) {
|
|
1227
1219
|
const body = await response.text();
|
|
1220
|
+
const parsed = parseResponseBody(body);
|
|
1221
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403) {
|
|
1222
|
+
throw new AuthError();
|
|
1223
|
+
}
|
|
1228
1224
|
const htmlError = detectHtmlErrorBody(
|
|
1229
1225
|
body,
|
|
1230
1226
|
response.headers.get("content-type")
|
|
@@ -1241,11 +1237,10 @@ var HttpClient = class {
|
|
|
1241
1237
|
}
|
|
1242
1238
|
);
|
|
1243
1239
|
}
|
|
1244
|
-
const parsed = parseResponseBody(body);
|
|
1245
1240
|
throw new DeeplineError(
|
|
1246
1241
|
apiErrorMessage(parsed, response.status),
|
|
1247
1242
|
response.status,
|
|
1248
|
-
|
|
1243
|
+
apiErrorCodeFromResponse(parsed),
|
|
1249
1244
|
{ response: parsed }
|
|
1250
1245
|
);
|
|
1251
1246
|
}
|
|
@@ -1320,6 +1315,22 @@ function parseResponseBody(body) {
|
|
|
1320
1315
|
return body;
|
|
1321
1316
|
}
|
|
1322
1317
|
}
|
|
1318
|
+
function isProviderOriginatedHttpError(parsed) {
|
|
1319
|
+
const response = asRecord(parsed);
|
|
1320
|
+
const error = asRecord(response?.error);
|
|
1321
|
+
const failureOrigin = error?.failure_origin ?? response?.failure_origin;
|
|
1322
|
+
const code = error?.code ?? response?.code;
|
|
1323
|
+
return failureOrigin === "provider" || code === "UPSTREAM_BLOCKED";
|
|
1324
|
+
}
|
|
1325
|
+
function apiErrorCodeFromResponse(parsed) {
|
|
1326
|
+
const response = asRecord(parsed);
|
|
1327
|
+
const error = asRecord(response?.error);
|
|
1328
|
+
const code = error?.code ?? response?.code;
|
|
1329
|
+
return typeof code === "string" ? code : "API_ERROR";
|
|
1330
|
+
}
|
|
1331
|
+
function asRecord(value) {
|
|
1332
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
1333
|
+
}
|
|
1323
1334
|
function isRetryableApiErrorResponse(status) {
|
|
1324
1335
|
return status === 408 || status === 425 || status >= 500 && status < 600;
|
|
1325
1336
|
}
|
|
@@ -2113,7 +2124,7 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
2113
2124
|
switch (normalized) {
|
|
2114
2125
|
case "queued":
|
|
2115
2126
|
case "pending":
|
|
2116
|
-
return "
|
|
2127
|
+
return "queued";
|
|
2117
2128
|
case "running":
|
|
2118
2129
|
case "started":
|
|
2119
2130
|
return "running";
|
|
@@ -2139,7 +2150,26 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
2139
2150
|
}
|
|
2140
2151
|
}
|
|
2141
2152
|
function isTerminalPlayRunLifecycleStatus(status) {
|
|
2142
|
-
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
2153
|
+
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
2154
|
+
normalizePlayRunLifecycleStatus(status)
|
|
2155
|
+
);
|
|
2156
|
+
}
|
|
2157
|
+
function decodePlayRunPublicStatus(value) {
|
|
2158
|
+
const status = normalizePlayRunLifecycleStatus(value);
|
|
2159
|
+
switch (status) {
|
|
2160
|
+
case "queued":
|
|
2161
|
+
case "running":
|
|
2162
|
+
case "waiting":
|
|
2163
|
+
case "completed":
|
|
2164
|
+
case "failed":
|
|
2165
|
+
case "cancelled":
|
|
2166
|
+
return status;
|
|
2167
|
+
case "terminated":
|
|
2168
|
+
case "timed_out":
|
|
2169
|
+
return "cancelled";
|
|
2170
|
+
case "unknown":
|
|
2171
|
+
return null;
|
|
2172
|
+
}
|
|
2143
2173
|
}
|
|
2144
2174
|
|
|
2145
2175
|
// ../shared_libs/play-runtime/run-snapshot-stream.ts
|
|
@@ -3080,7 +3110,13 @@ function isPlayRunPackage(value) {
|
|
|
3080
3110
|
function normalizePlayStatus(raw) {
|
|
3081
3111
|
const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
|
|
3082
3112
|
const packageRun = runPackage?.run;
|
|
3083
|
-
const
|
|
3113
|
+
const rawStatus = typeof raw.status === "string" ? raw.status : typeof packageRun?.status === "string" ? packageRun.status : null;
|
|
3114
|
+
const status = decodePlayRunPublicStatus(rawStatus);
|
|
3115
|
+
if (!status) {
|
|
3116
|
+
throw new Error(
|
|
3117
|
+
`Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`
|
|
3118
|
+
);
|
|
3119
|
+
}
|
|
3084
3120
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : packageRun?.id ?? "";
|
|
3085
3121
|
return {
|
|
3086
3122
|
...raw,
|
|
@@ -24940,7 +24976,7 @@ function monitorsErrorExitCode(error) {
|
|
|
24940
24976
|
}
|
|
24941
24977
|
function monitorsFailureNextCommand(error, exitCode) {
|
|
24942
24978
|
if (error instanceof DeeplineError) {
|
|
24943
|
-
const response =
|
|
24979
|
+
const response = asRecord2(asRecord2(error.details)?.response);
|
|
24944
24980
|
const serverNextAction = asString(response?.next_action);
|
|
24945
24981
|
if (serverNextAction) return serverNextAction;
|
|
24946
24982
|
}
|
|
@@ -24956,10 +24992,10 @@ function monitorsFailureNextCommand(error, exitCode) {
|
|
|
24956
24992
|
}
|
|
24957
24993
|
function readValidationIssues(error) {
|
|
24958
24994
|
if (!(error instanceof DeeplineError)) return [];
|
|
24959
|
-
const response =
|
|
24995
|
+
const response = asRecord2(asRecord2(error.details)?.response);
|
|
24960
24996
|
const issues = Array.isArray(response?.issues) ? response.issues : [];
|
|
24961
24997
|
return issues.flatMap((raw) => {
|
|
24962
|
-
const issue =
|
|
24998
|
+
const issue = asRecord2(raw);
|
|
24963
24999
|
if (!issue) return [];
|
|
24964
25000
|
return [
|
|
24965
25001
|
{
|
|
@@ -25052,7 +25088,7 @@ or from a file / stdin:
|
|
|
25052
25088
|
cat monitor.json | ${input2.command} --file -`
|
|
25053
25089
|
);
|
|
25054
25090
|
}
|
|
25055
|
-
function
|
|
25091
|
+
function asRecord2(value) {
|
|
25056
25092
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
25057
25093
|
}
|
|
25058
25094
|
function asString(value) {
|
|
@@ -25062,7 +25098,7 @@ function asFiniteNumber(value) {
|
|
|
25062
25098
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
25063
25099
|
}
|
|
25064
25100
|
function monitorPricingLine(rawPricing) {
|
|
25065
|
-
const pricing =
|
|
25101
|
+
const pricing = asRecord2(rawPricing);
|
|
25066
25102
|
if (!pricing) return void 0;
|
|
25067
25103
|
const display = asString(pricing.display);
|
|
25068
25104
|
if (display) return display;
|
|
@@ -25077,16 +25113,16 @@ function yesNo(value) {
|
|
|
25077
25113
|
return "unknown";
|
|
25078
25114
|
}
|
|
25079
25115
|
function readDeployOutputContract(payload) {
|
|
25080
|
-
const contract =
|
|
25116
|
+
const contract = asRecord2(payload.output_contract);
|
|
25081
25117
|
if (!contract) return { streams: [] };
|
|
25082
25118
|
const rawOutputs = Array.isArray(contract.outputs) ? contract.outputs : [];
|
|
25083
25119
|
const streams = rawOutputs.flatMap((raw) => {
|
|
25084
|
-
const output2 =
|
|
25120
|
+
const output2 = asRecord2(raw);
|
|
25085
25121
|
const stream = output2 ? asString(output2.stream) : void 0;
|
|
25086
25122
|
const table = output2 ? asString(output2.table) : void 0;
|
|
25087
25123
|
if (!output2 || !stream || !table) return [];
|
|
25088
25124
|
const columns = Array.isArray(output2.columns) ? output2.columns.flatMap((rawColumn) => {
|
|
25089
|
-
const column =
|
|
25125
|
+
const column = asRecord2(rawColumn);
|
|
25090
25126
|
const name = column ? asString(column.name) : void 0;
|
|
25091
25127
|
return name ? [name] : [];
|
|
25092
25128
|
}) : [];
|
|
@@ -25103,7 +25139,7 @@ function readDeployOutputContract(payload) {
|
|
|
25103
25139
|
return { tool: asString(contract.tool), streams };
|
|
25104
25140
|
}
|
|
25105
25141
|
function renderMonitorDeployCompletion(payload) {
|
|
25106
|
-
const monitor =
|
|
25142
|
+
const monitor = asRecord2(payload.monitor);
|
|
25107
25143
|
const key = monitor ? asString(monitor.key) : void 0;
|
|
25108
25144
|
const { tool, streams } = readDeployOutputContract(payload);
|
|
25109
25145
|
if (!key || streams.length === 0) return void 0;
|
|
@@ -25154,13 +25190,13 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25154
25190
|
if (!valid) {
|
|
25155
25191
|
const issues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
25156
25192
|
for (const raw of issues) {
|
|
25157
|
-
const issue =
|
|
25193
|
+
const issue = asRecord2(raw);
|
|
25158
25194
|
const path = issue ? asString(issue.path) : void 0;
|
|
25159
25195
|
const message = issue ? asString(issue.message) : void 0;
|
|
25160
25196
|
if (message) lines.push(` - ${path ? `${path}: ` : ""}${message}`);
|
|
25161
25197
|
}
|
|
25162
25198
|
}
|
|
25163
|
-
const estimate =
|
|
25199
|
+
const estimate = asRecord2(payload.deploy_cost_estimate);
|
|
25164
25200
|
const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
|
|
25165
25201
|
if (credits !== void 0) {
|
|
25166
25202
|
const note = estimate ? asString(estimate.note) : void 0;
|
|
@@ -25178,7 +25214,7 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25178
25214
|
}
|
|
25179
25215
|
const candidates = Array.isArray(payload.reuse_candidates) ? payload.reuse_candidates : [];
|
|
25180
25216
|
const candidateLines = candidates.flatMap((raw) => {
|
|
25181
|
-
const candidate =
|
|
25217
|
+
const candidate = asRecord2(raw);
|
|
25182
25218
|
const key = candidate ? asString(candidate.key) : void 0;
|
|
25183
25219
|
if (!candidate || !key) return [];
|
|
25184
25220
|
const name = asString(candidate.name);
|
|
@@ -25204,7 +25240,7 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25204
25240
|
`;
|
|
25205
25241
|
}
|
|
25206
25242
|
function renderMonitorDeletePlan(payload, fallbackKey) {
|
|
25207
|
-
const plan =
|
|
25243
|
+
const plan = asRecord2(payload.plan);
|
|
25208
25244
|
const key = (plan ? asString(plan.monitor_key) : void 0) ?? fallbackKey;
|
|
25209
25245
|
const lines = [
|
|
25210
25246
|
"DRY RUN \u2014 nothing was deleted.",
|
|
@@ -25218,7 +25254,7 @@ function renderMonitorDeletePlan(payload, fallbackKey) {
|
|
|
25218
25254
|
`;
|
|
25219
25255
|
}
|
|
25220
25256
|
function renderMonitorReactivatePlan(payload, key) {
|
|
25221
|
-
const estimate =
|
|
25257
|
+
const estimate = asRecord2(payload.cost_estimate);
|
|
25222
25258
|
const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
|
|
25223
25259
|
const lines = [
|
|
25224
25260
|
"DRY RUN \u2014 nothing was reactivated.",
|
|
@@ -25270,7 +25306,7 @@ function renderAvailableToolsText(payload) {
|
|
|
25270
25306
|
];
|
|
25271
25307
|
let currentProvider;
|
|
25272
25308
|
for (const raw of tools) {
|
|
25273
|
-
const entry =
|
|
25309
|
+
const entry = asRecord2(raw);
|
|
25274
25310
|
const id = entry ? asString(entry.tool) : void 0;
|
|
25275
25311
|
if (!entry || !id) continue;
|
|
25276
25312
|
const name = asString(entry.name) ?? asString(entry.display_name);
|
|
@@ -25340,7 +25376,7 @@ function renderDeployedListText(payload, requestedStatus) {
|
|
|
25340
25376
|
const header = monitors.length === 0 ? "No deployed monitors matched." : total !== void 0 && total > monitors.length ? `Deployed monitors (${monitors.length} of ${total}):` : `Deployed monitors (${monitors.length}):`;
|
|
25341
25377
|
const lines = [header];
|
|
25342
25378
|
for (const raw of monitors) {
|
|
25343
|
-
const entry =
|
|
25379
|
+
const entry = asRecord2(raw);
|
|
25344
25380
|
const key = entry ? asString(entry.key) ?? asString(entry.monitor_key) : void 0;
|
|
25345
25381
|
if (!entry || !key) continue;
|
|
25346
25382
|
const status = asString(entry.status);
|
|
@@ -25425,11 +25461,11 @@ function renderMonitorGet(payload) {
|
|
|
25425
25461
|
const tool = asString(payload.tool);
|
|
25426
25462
|
if (!key || !tool) return void 0;
|
|
25427
25463
|
const status = asString(payload.status);
|
|
25428
|
-
const definition =
|
|
25464
|
+
const definition = asRecord2(payload.definition);
|
|
25429
25465
|
const pricingLine = monitorPricingLine(payload.pricing);
|
|
25430
|
-
const billing =
|
|
25466
|
+
const billing = asRecord2(payload.billing);
|
|
25431
25467
|
const nextRenewalAt = billing ? asString(billing.next_renewal_at) : void 0;
|
|
25432
|
-
const dependents =
|
|
25468
|
+
const dependents = asRecord2(payload.dependents);
|
|
25433
25469
|
const plays = dependents && Array.isArray(dependents.plays) ? dependents.plays : [];
|
|
25434
25470
|
const lines = [
|
|
25435
25471
|
`Monitor: ${key}`,
|
|
@@ -25446,7 +25482,7 @@ function renderMonitorGet(payload) {
|
|
|
25446
25482
|
lines.push(" none");
|
|
25447
25483
|
} else {
|
|
25448
25484
|
for (const raw of plays) {
|
|
25449
|
-
const play =
|
|
25485
|
+
const play = asRecord2(raw);
|
|
25450
25486
|
const name = play ? asString(play.name) : void 0;
|
|
25451
25487
|
if (!play || !name) continue;
|
|
25452
25488
|
const listener = asString(play.listener_key);
|
|
@@ -31191,7 +31227,7 @@ function parseCapturedJson(stdout) {
|
|
|
31191
31227
|
return null;
|
|
31192
31228
|
}
|
|
31193
31229
|
}
|
|
31194
|
-
function
|
|
31230
|
+
function asRecord3(value) {
|
|
31195
31231
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
31196
31232
|
}
|
|
31197
31233
|
function safeRead(path) {
|
|
@@ -31893,8 +31929,8 @@ async function runSetupCommand(options) {
|
|
|
31893
31929
|
status: "complete",
|
|
31894
31930
|
phases
|
|
31895
31931
|
});
|
|
31896
|
-
const doctorChecks =
|
|
31897
|
-
const apiCheck =
|
|
31932
|
+
const doctorChecks = asRecord3(doctorPayload?.checks);
|
|
31933
|
+
const apiCheck = asRecord3(doctorChecks?.api);
|
|
31898
31934
|
printCommandEnvelope(
|
|
31899
31935
|
{
|
|
31900
31936
|
ok: true,
|
package/dist/cli/index.mjs
CHANGED
|
@@ -703,7 +703,7 @@ var SDK_RELEASE = {
|
|
|
703
703
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
704
704
|
// 0.1.254 removes the internal operations tree from the published SDK CLI.
|
|
705
705
|
// Operators use the checkout-local deepline-admin binary instead.
|
|
706
|
-
version: "0.1.
|
|
706
|
+
version: "0.1.300",
|
|
707
707
|
contracts: {
|
|
708
708
|
api: {
|
|
709
709
|
name: "sdk-http-api",
|
|
@@ -1048,7 +1048,7 @@ var HttpClient = class {
|
|
|
1048
1048
|
* @param path - API path (e.g. `"/api/v2/tools"`)
|
|
1049
1049
|
* @param options - HTTP method, body, headers, and timeout
|
|
1050
1050
|
* @returns Parsed JSON response body
|
|
1051
|
-
* @throws {@link AuthError} on HTTP 401/403 (immediate, no retry)
|
|
1051
|
+
* @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
|
|
1052
1052
|
* @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
|
|
1053
1053
|
* @throws {@link DeeplineError} on other API errors or connection failures
|
|
1054
1054
|
*/
|
|
@@ -1087,9 +1087,6 @@ var HttpClient = class {
|
|
|
1087
1087
|
signal: controller.signal
|
|
1088
1088
|
});
|
|
1089
1089
|
clearTimeout(timeoutId);
|
|
1090
|
-
if (response.status === 401 || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
1091
|
-
throw new AuthError();
|
|
1092
|
-
}
|
|
1093
1090
|
if (response.status === 429) {
|
|
1094
1091
|
const retryAfter = parseRetryAfter(response);
|
|
1095
1092
|
lastError = new RateLimitError(retryAfter);
|
|
@@ -1100,11 +1097,9 @@ var HttpClient = class {
|
|
|
1100
1097
|
throw lastError;
|
|
1101
1098
|
}
|
|
1102
1099
|
const body = await response.text();
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
} catch {
|
|
1107
|
-
parsed = body;
|
|
1100
|
+
const parsed = parseResponseBody(body);
|
|
1101
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
1102
|
+
throw new AuthError();
|
|
1108
1103
|
}
|
|
1109
1104
|
if (!response.ok) {
|
|
1110
1105
|
const retryableApiError = options?.retryApiErrors === true && isRetryableApiErrorResponse(response.status);
|
|
@@ -1131,7 +1126,7 @@ var HttpClient = class {
|
|
|
1131
1126
|
}
|
|
1132
1127
|
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
1133
1128
|
const msg = typeof errorValue === "string" ? errorValue : errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string" ? errorValue.message : typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `HTTP ${response.status}`;
|
|
1134
|
-
const apiErrorCode2 =
|
|
1129
|
+
const apiErrorCode2 = apiErrorCodeFromResponse(parsed);
|
|
1135
1130
|
lastError = new DeeplineError(msg, response.status, apiErrorCode2, {
|
|
1136
1131
|
response: parsed
|
|
1137
1132
|
});
|
|
@@ -1205,11 +1200,12 @@ var HttpClient = class {
|
|
|
1205
1200
|
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
1206
1201
|
signal: options?.signal
|
|
1207
1202
|
});
|
|
1208
|
-
if (response.status === 401 || response.status === 403) {
|
|
1209
|
-
throw new AuthError();
|
|
1210
|
-
}
|
|
1211
1203
|
if (!response.ok) {
|
|
1212
1204
|
const body = await response.text();
|
|
1205
|
+
const parsed = parseResponseBody(body);
|
|
1206
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403) {
|
|
1207
|
+
throw new AuthError();
|
|
1208
|
+
}
|
|
1213
1209
|
const htmlError = detectHtmlErrorBody(
|
|
1214
1210
|
body,
|
|
1215
1211
|
response.headers.get("content-type")
|
|
@@ -1226,11 +1222,10 @@ var HttpClient = class {
|
|
|
1226
1222
|
}
|
|
1227
1223
|
);
|
|
1228
1224
|
}
|
|
1229
|
-
const parsed = parseResponseBody(body);
|
|
1230
1225
|
throw new DeeplineError(
|
|
1231
1226
|
apiErrorMessage(parsed, response.status),
|
|
1232
1227
|
response.status,
|
|
1233
|
-
|
|
1228
|
+
apiErrorCodeFromResponse(parsed),
|
|
1234
1229
|
{ response: parsed }
|
|
1235
1230
|
);
|
|
1236
1231
|
}
|
|
@@ -1305,6 +1300,22 @@ function parseResponseBody(body) {
|
|
|
1305
1300
|
return body;
|
|
1306
1301
|
}
|
|
1307
1302
|
}
|
|
1303
|
+
function isProviderOriginatedHttpError(parsed) {
|
|
1304
|
+
const response = asRecord(parsed);
|
|
1305
|
+
const error = asRecord(response?.error);
|
|
1306
|
+
const failureOrigin = error?.failure_origin ?? response?.failure_origin;
|
|
1307
|
+
const code = error?.code ?? response?.code;
|
|
1308
|
+
return failureOrigin === "provider" || code === "UPSTREAM_BLOCKED";
|
|
1309
|
+
}
|
|
1310
|
+
function apiErrorCodeFromResponse(parsed) {
|
|
1311
|
+
const response = asRecord(parsed);
|
|
1312
|
+
const error = asRecord(response?.error);
|
|
1313
|
+
const code = error?.code ?? response?.code;
|
|
1314
|
+
return typeof code === "string" ? code : "API_ERROR";
|
|
1315
|
+
}
|
|
1316
|
+
function asRecord(value) {
|
|
1317
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
1318
|
+
}
|
|
1308
1319
|
function isRetryableApiErrorResponse(status) {
|
|
1309
1320
|
return status === 408 || status === 425 || status >= 500 && status < 600;
|
|
1310
1321
|
}
|
|
@@ -2098,7 +2109,7 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
2098
2109
|
switch (normalized) {
|
|
2099
2110
|
case "queued":
|
|
2100
2111
|
case "pending":
|
|
2101
|
-
return "
|
|
2112
|
+
return "queued";
|
|
2102
2113
|
case "running":
|
|
2103
2114
|
case "started":
|
|
2104
2115
|
return "running";
|
|
@@ -2124,7 +2135,26 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
2124
2135
|
}
|
|
2125
2136
|
}
|
|
2126
2137
|
function isTerminalPlayRunLifecycleStatus(status) {
|
|
2127
|
-
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
2138
|
+
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
2139
|
+
normalizePlayRunLifecycleStatus(status)
|
|
2140
|
+
);
|
|
2141
|
+
}
|
|
2142
|
+
function decodePlayRunPublicStatus(value) {
|
|
2143
|
+
const status = normalizePlayRunLifecycleStatus(value);
|
|
2144
|
+
switch (status) {
|
|
2145
|
+
case "queued":
|
|
2146
|
+
case "running":
|
|
2147
|
+
case "waiting":
|
|
2148
|
+
case "completed":
|
|
2149
|
+
case "failed":
|
|
2150
|
+
case "cancelled":
|
|
2151
|
+
return status;
|
|
2152
|
+
case "terminated":
|
|
2153
|
+
case "timed_out":
|
|
2154
|
+
return "cancelled";
|
|
2155
|
+
case "unknown":
|
|
2156
|
+
return null;
|
|
2157
|
+
}
|
|
2128
2158
|
}
|
|
2129
2159
|
|
|
2130
2160
|
// ../shared_libs/play-runtime/run-snapshot-stream.ts
|
|
@@ -3065,7 +3095,13 @@ function isPlayRunPackage(value) {
|
|
|
3065
3095
|
function normalizePlayStatus(raw) {
|
|
3066
3096
|
const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
|
|
3067
3097
|
const packageRun = runPackage?.run;
|
|
3068
|
-
const
|
|
3098
|
+
const rawStatus = typeof raw.status === "string" ? raw.status : typeof packageRun?.status === "string" ? packageRun.status : null;
|
|
3099
|
+
const status = decodePlayRunPublicStatus(rawStatus);
|
|
3100
|
+
if (!status) {
|
|
3101
|
+
throw new Error(
|
|
3102
|
+
`Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`
|
|
3103
|
+
);
|
|
3104
|
+
}
|
|
3069
3105
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : packageRun?.id ?? "";
|
|
3070
3106
|
return {
|
|
3071
3107
|
...raw,
|
|
@@ -24976,7 +25012,7 @@ function monitorsErrorExitCode(error) {
|
|
|
24976
25012
|
}
|
|
24977
25013
|
function monitorsFailureNextCommand(error, exitCode) {
|
|
24978
25014
|
if (error instanceof DeeplineError) {
|
|
24979
|
-
const response =
|
|
25015
|
+
const response = asRecord2(asRecord2(error.details)?.response);
|
|
24980
25016
|
const serverNextAction = asString(response?.next_action);
|
|
24981
25017
|
if (serverNextAction) return serverNextAction;
|
|
24982
25018
|
}
|
|
@@ -24992,10 +25028,10 @@ function monitorsFailureNextCommand(error, exitCode) {
|
|
|
24992
25028
|
}
|
|
24993
25029
|
function readValidationIssues(error) {
|
|
24994
25030
|
if (!(error instanceof DeeplineError)) return [];
|
|
24995
|
-
const response =
|
|
25031
|
+
const response = asRecord2(asRecord2(error.details)?.response);
|
|
24996
25032
|
const issues = Array.isArray(response?.issues) ? response.issues : [];
|
|
24997
25033
|
return issues.flatMap((raw) => {
|
|
24998
|
-
const issue =
|
|
25034
|
+
const issue = asRecord2(raw);
|
|
24999
25035
|
if (!issue) return [];
|
|
25000
25036
|
return [
|
|
25001
25037
|
{
|
|
@@ -25088,7 +25124,7 @@ or from a file / stdin:
|
|
|
25088
25124
|
cat monitor.json | ${input2.command} --file -`
|
|
25089
25125
|
);
|
|
25090
25126
|
}
|
|
25091
|
-
function
|
|
25127
|
+
function asRecord2(value) {
|
|
25092
25128
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
25093
25129
|
}
|
|
25094
25130
|
function asString(value) {
|
|
@@ -25098,7 +25134,7 @@ function asFiniteNumber(value) {
|
|
|
25098
25134
|
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
25099
25135
|
}
|
|
25100
25136
|
function monitorPricingLine(rawPricing) {
|
|
25101
|
-
const pricing =
|
|
25137
|
+
const pricing = asRecord2(rawPricing);
|
|
25102
25138
|
if (!pricing) return void 0;
|
|
25103
25139
|
const display = asString(pricing.display);
|
|
25104
25140
|
if (display) return display;
|
|
@@ -25113,16 +25149,16 @@ function yesNo(value) {
|
|
|
25113
25149
|
return "unknown";
|
|
25114
25150
|
}
|
|
25115
25151
|
function readDeployOutputContract(payload) {
|
|
25116
|
-
const contract =
|
|
25152
|
+
const contract = asRecord2(payload.output_contract);
|
|
25117
25153
|
if (!contract) return { streams: [] };
|
|
25118
25154
|
const rawOutputs = Array.isArray(contract.outputs) ? contract.outputs : [];
|
|
25119
25155
|
const streams = rawOutputs.flatMap((raw) => {
|
|
25120
|
-
const output2 =
|
|
25156
|
+
const output2 = asRecord2(raw);
|
|
25121
25157
|
const stream = output2 ? asString(output2.stream) : void 0;
|
|
25122
25158
|
const table = output2 ? asString(output2.table) : void 0;
|
|
25123
25159
|
if (!output2 || !stream || !table) return [];
|
|
25124
25160
|
const columns = Array.isArray(output2.columns) ? output2.columns.flatMap((rawColumn) => {
|
|
25125
|
-
const column =
|
|
25161
|
+
const column = asRecord2(rawColumn);
|
|
25126
25162
|
const name = column ? asString(column.name) : void 0;
|
|
25127
25163
|
return name ? [name] : [];
|
|
25128
25164
|
}) : [];
|
|
@@ -25139,7 +25175,7 @@ function readDeployOutputContract(payload) {
|
|
|
25139
25175
|
return { tool: asString(contract.tool), streams };
|
|
25140
25176
|
}
|
|
25141
25177
|
function renderMonitorDeployCompletion(payload) {
|
|
25142
|
-
const monitor =
|
|
25178
|
+
const monitor = asRecord2(payload.monitor);
|
|
25143
25179
|
const key = monitor ? asString(monitor.key) : void 0;
|
|
25144
25180
|
const { tool, streams } = readDeployOutputContract(payload);
|
|
25145
25181
|
if (!key || streams.length === 0) return void 0;
|
|
@@ -25190,13 +25226,13 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25190
25226
|
if (!valid) {
|
|
25191
25227
|
const issues = Array.isArray(payload.issues) ? payload.issues : [];
|
|
25192
25228
|
for (const raw of issues) {
|
|
25193
|
-
const issue =
|
|
25229
|
+
const issue = asRecord2(raw);
|
|
25194
25230
|
const path = issue ? asString(issue.path) : void 0;
|
|
25195
25231
|
const message = issue ? asString(issue.message) : void 0;
|
|
25196
25232
|
if (message) lines.push(` - ${path ? `${path}: ` : ""}${message}`);
|
|
25197
25233
|
}
|
|
25198
25234
|
}
|
|
25199
|
-
const estimate =
|
|
25235
|
+
const estimate = asRecord2(payload.deploy_cost_estimate);
|
|
25200
25236
|
const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
|
|
25201
25237
|
if (credits !== void 0) {
|
|
25202
25238
|
const note = estimate ? asString(estimate.note) : void 0;
|
|
@@ -25214,7 +25250,7 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25214
25250
|
}
|
|
25215
25251
|
const candidates = Array.isArray(payload.reuse_candidates) ? payload.reuse_candidates : [];
|
|
25216
25252
|
const candidateLines = candidates.flatMap((raw) => {
|
|
25217
|
-
const candidate =
|
|
25253
|
+
const candidate = asRecord2(raw);
|
|
25218
25254
|
const key = candidate ? asString(candidate.key) : void 0;
|
|
25219
25255
|
if (!candidate || !key) return [];
|
|
25220
25256
|
const name = asString(candidate.name);
|
|
@@ -25240,7 +25276,7 @@ function renderMonitorDeployPlan(payload) {
|
|
|
25240
25276
|
`;
|
|
25241
25277
|
}
|
|
25242
25278
|
function renderMonitorDeletePlan(payload, fallbackKey) {
|
|
25243
|
-
const plan =
|
|
25279
|
+
const plan = asRecord2(payload.plan);
|
|
25244
25280
|
const key = (plan ? asString(plan.monitor_key) : void 0) ?? fallbackKey;
|
|
25245
25281
|
const lines = [
|
|
25246
25282
|
"DRY RUN \u2014 nothing was deleted.",
|
|
@@ -25254,7 +25290,7 @@ function renderMonitorDeletePlan(payload, fallbackKey) {
|
|
|
25254
25290
|
`;
|
|
25255
25291
|
}
|
|
25256
25292
|
function renderMonitorReactivatePlan(payload, key) {
|
|
25257
|
-
const estimate =
|
|
25293
|
+
const estimate = asRecord2(payload.cost_estimate);
|
|
25258
25294
|
const credits = estimate ? asFiniteNumber(estimate.credits) : void 0;
|
|
25259
25295
|
const lines = [
|
|
25260
25296
|
"DRY RUN \u2014 nothing was reactivated.",
|
|
@@ -25306,7 +25342,7 @@ function renderAvailableToolsText(payload) {
|
|
|
25306
25342
|
];
|
|
25307
25343
|
let currentProvider;
|
|
25308
25344
|
for (const raw of tools) {
|
|
25309
|
-
const entry =
|
|
25345
|
+
const entry = asRecord2(raw);
|
|
25310
25346
|
const id = entry ? asString(entry.tool) : void 0;
|
|
25311
25347
|
if (!entry || !id) continue;
|
|
25312
25348
|
const name = asString(entry.name) ?? asString(entry.display_name);
|
|
@@ -25376,7 +25412,7 @@ function renderDeployedListText(payload, requestedStatus) {
|
|
|
25376
25412
|
const header = monitors.length === 0 ? "No deployed monitors matched." : total !== void 0 && total > monitors.length ? `Deployed monitors (${monitors.length} of ${total}):` : `Deployed monitors (${monitors.length}):`;
|
|
25377
25413
|
const lines = [header];
|
|
25378
25414
|
for (const raw of monitors) {
|
|
25379
|
-
const entry =
|
|
25415
|
+
const entry = asRecord2(raw);
|
|
25380
25416
|
const key = entry ? asString(entry.key) ?? asString(entry.monitor_key) : void 0;
|
|
25381
25417
|
if (!entry || !key) continue;
|
|
25382
25418
|
const status = asString(entry.status);
|
|
@@ -25461,11 +25497,11 @@ function renderMonitorGet(payload) {
|
|
|
25461
25497
|
const tool = asString(payload.tool);
|
|
25462
25498
|
if (!key || !tool) return void 0;
|
|
25463
25499
|
const status = asString(payload.status);
|
|
25464
|
-
const definition =
|
|
25500
|
+
const definition = asRecord2(payload.definition);
|
|
25465
25501
|
const pricingLine = monitorPricingLine(payload.pricing);
|
|
25466
|
-
const billing =
|
|
25502
|
+
const billing = asRecord2(payload.billing);
|
|
25467
25503
|
const nextRenewalAt = billing ? asString(billing.next_renewal_at) : void 0;
|
|
25468
|
-
const dependents =
|
|
25504
|
+
const dependents = asRecord2(payload.dependents);
|
|
25469
25505
|
const plays = dependents && Array.isArray(dependents.plays) ? dependents.plays : [];
|
|
25470
25506
|
const lines = [
|
|
25471
25507
|
`Monitor: ${key}`,
|
|
@@ -25482,7 +25518,7 @@ function renderMonitorGet(payload) {
|
|
|
25482
25518
|
lines.push(" none");
|
|
25483
25519
|
} else {
|
|
25484
25520
|
for (const raw of plays) {
|
|
25485
|
-
const play =
|
|
25521
|
+
const play = asRecord2(raw);
|
|
25486
25522
|
const name = play ? asString(play.name) : void 0;
|
|
25487
25523
|
if (!play || !name) continue;
|
|
25488
25524
|
const listener = asString(play.listener_key);
|
|
@@ -31256,7 +31292,7 @@ function parseCapturedJson(stdout) {
|
|
|
31256
31292
|
return null;
|
|
31257
31293
|
}
|
|
31258
31294
|
}
|
|
31259
|
-
function
|
|
31295
|
+
function asRecord3(value) {
|
|
31260
31296
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
31261
31297
|
}
|
|
31262
31298
|
function safeRead(path) {
|
|
@@ -31958,8 +31994,8 @@ async function runSetupCommand(options) {
|
|
|
31958
31994
|
status: "complete",
|
|
31959
31995
|
phases
|
|
31960
31996
|
});
|
|
31961
|
-
const doctorChecks =
|
|
31962
|
-
const apiCheck =
|
|
31997
|
+
const doctorChecks = asRecord3(doctorPayload?.checks);
|
|
31998
|
+
const apiCheck = asRecord3(doctorChecks?.api);
|
|
31963
31999
|
printCommandEnvelope(
|
|
31964
32000
|
{
|
|
31965
32001
|
ok: true,
|
package/dist/index.js
CHANGED
|
@@ -438,7 +438,7 @@ var SDK_RELEASE = {
|
|
|
438
438
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
439
439
|
// 0.1.254 removes the internal operations tree from the published SDK CLI.
|
|
440
440
|
// Operators use the checkout-local deepline-admin binary instead.
|
|
441
|
-
version: "0.1.
|
|
441
|
+
version: "0.1.300",
|
|
442
442
|
contracts: {
|
|
443
443
|
api: {
|
|
444
444
|
name: "sdk-http-api",
|
|
@@ -783,7 +783,7 @@ var HttpClient = class {
|
|
|
783
783
|
* @param path - API path (e.g. `"/api/v2/tools"`)
|
|
784
784
|
* @param options - HTTP method, body, headers, and timeout
|
|
785
785
|
* @returns Parsed JSON response body
|
|
786
|
-
* @throws {@link AuthError} on HTTP 401/403 (immediate, no retry)
|
|
786
|
+
* @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
|
|
787
787
|
* @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
|
|
788
788
|
* @throws {@link DeeplineError} on other API errors or connection failures
|
|
789
789
|
*/
|
|
@@ -822,9 +822,6 @@ var HttpClient = class {
|
|
|
822
822
|
signal: controller.signal
|
|
823
823
|
});
|
|
824
824
|
clearTimeout(timeoutId);
|
|
825
|
-
if (response.status === 401 || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
826
|
-
throw new AuthError();
|
|
827
|
-
}
|
|
828
825
|
if (response.status === 429) {
|
|
829
826
|
const retryAfter = parseRetryAfter(response);
|
|
830
827
|
lastError = new RateLimitError(retryAfter);
|
|
@@ -835,11 +832,9 @@ var HttpClient = class {
|
|
|
835
832
|
throw lastError;
|
|
836
833
|
}
|
|
837
834
|
const body = await response.text();
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
} catch {
|
|
842
|
-
parsed = body;
|
|
835
|
+
const parsed = parseResponseBody(body);
|
|
836
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
837
|
+
throw new AuthError();
|
|
843
838
|
}
|
|
844
839
|
if (!response.ok) {
|
|
845
840
|
const retryableApiError = options?.retryApiErrors === true && isRetryableApiErrorResponse(response.status);
|
|
@@ -866,7 +861,7 @@ var HttpClient = class {
|
|
|
866
861
|
}
|
|
867
862
|
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
868
863
|
const msg = typeof errorValue === "string" ? errorValue : errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string" ? errorValue.message : typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `HTTP ${response.status}`;
|
|
869
|
-
const apiErrorCode =
|
|
864
|
+
const apiErrorCode = apiErrorCodeFromResponse(parsed);
|
|
870
865
|
lastError = new DeeplineError(msg, response.status, apiErrorCode, {
|
|
871
866
|
response: parsed
|
|
872
867
|
});
|
|
@@ -940,11 +935,12 @@ var HttpClient = class {
|
|
|
940
935
|
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
941
936
|
signal: options?.signal
|
|
942
937
|
});
|
|
943
|
-
if (response.status === 401 || response.status === 403) {
|
|
944
|
-
throw new AuthError();
|
|
945
|
-
}
|
|
946
938
|
if (!response.ok) {
|
|
947
939
|
const body = await response.text();
|
|
940
|
+
const parsed = parseResponseBody(body);
|
|
941
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403) {
|
|
942
|
+
throw new AuthError();
|
|
943
|
+
}
|
|
948
944
|
const htmlError = detectHtmlErrorBody(
|
|
949
945
|
body,
|
|
950
946
|
response.headers.get("content-type")
|
|
@@ -961,11 +957,10 @@ var HttpClient = class {
|
|
|
961
957
|
}
|
|
962
958
|
);
|
|
963
959
|
}
|
|
964
|
-
const parsed = parseResponseBody(body);
|
|
965
960
|
throw new DeeplineError(
|
|
966
961
|
apiErrorMessage(parsed, response.status),
|
|
967
962
|
response.status,
|
|
968
|
-
|
|
963
|
+
apiErrorCodeFromResponse(parsed),
|
|
969
964
|
{ response: parsed }
|
|
970
965
|
);
|
|
971
966
|
}
|
|
@@ -1040,6 +1035,22 @@ function parseResponseBody(body) {
|
|
|
1040
1035
|
return body;
|
|
1041
1036
|
}
|
|
1042
1037
|
}
|
|
1038
|
+
function isProviderOriginatedHttpError(parsed) {
|
|
1039
|
+
const response = asRecord(parsed);
|
|
1040
|
+
const error = asRecord(response?.error);
|
|
1041
|
+
const failureOrigin = error?.failure_origin ?? response?.failure_origin;
|
|
1042
|
+
const code = error?.code ?? response?.code;
|
|
1043
|
+
return failureOrigin === "provider" || code === "UPSTREAM_BLOCKED";
|
|
1044
|
+
}
|
|
1045
|
+
function apiErrorCodeFromResponse(parsed) {
|
|
1046
|
+
const response = asRecord(parsed);
|
|
1047
|
+
const error = asRecord(response?.error);
|
|
1048
|
+
const code = error?.code ?? response?.code;
|
|
1049
|
+
return typeof code === "string" ? code : "API_ERROR";
|
|
1050
|
+
}
|
|
1051
|
+
function asRecord(value) {
|
|
1052
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
1053
|
+
}
|
|
1043
1054
|
function isRetryableApiErrorResponse(status) {
|
|
1044
1055
|
return status === 408 || status === 425 || status >= 500 && status < 600;
|
|
1045
1056
|
}
|
|
@@ -1833,7 +1844,7 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
1833
1844
|
switch (normalized) {
|
|
1834
1845
|
case "queued":
|
|
1835
1846
|
case "pending":
|
|
1836
|
-
return "
|
|
1847
|
+
return "queued";
|
|
1837
1848
|
case "running":
|
|
1838
1849
|
case "started":
|
|
1839
1850
|
return "running";
|
|
@@ -1859,7 +1870,26 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
1859
1870
|
}
|
|
1860
1871
|
}
|
|
1861
1872
|
function isTerminalPlayRunLifecycleStatus(status) {
|
|
1862
|
-
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
1873
|
+
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
1874
|
+
normalizePlayRunLifecycleStatus(status)
|
|
1875
|
+
);
|
|
1876
|
+
}
|
|
1877
|
+
function decodePlayRunPublicStatus(value) {
|
|
1878
|
+
const status = normalizePlayRunLifecycleStatus(value);
|
|
1879
|
+
switch (status) {
|
|
1880
|
+
case "queued":
|
|
1881
|
+
case "running":
|
|
1882
|
+
case "waiting":
|
|
1883
|
+
case "completed":
|
|
1884
|
+
case "failed":
|
|
1885
|
+
case "cancelled":
|
|
1886
|
+
return status;
|
|
1887
|
+
case "terminated":
|
|
1888
|
+
case "timed_out":
|
|
1889
|
+
return "cancelled";
|
|
1890
|
+
case "unknown":
|
|
1891
|
+
return null;
|
|
1892
|
+
}
|
|
1863
1893
|
}
|
|
1864
1894
|
|
|
1865
1895
|
// ../shared_libs/play-runtime/run-snapshot-stream.ts
|
|
@@ -2800,7 +2830,13 @@ function isPlayRunPackage(value) {
|
|
|
2800
2830
|
function normalizePlayStatus(raw) {
|
|
2801
2831
|
const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
|
|
2802
2832
|
const packageRun = runPackage?.run;
|
|
2803
|
-
const
|
|
2833
|
+
const rawStatus = typeof raw.status === "string" ? raw.status : typeof packageRun?.status === "string" ? packageRun.status : null;
|
|
2834
|
+
const status = decodePlayRunPublicStatus(rawStatus);
|
|
2835
|
+
if (!status) {
|
|
2836
|
+
throw new Error(
|
|
2837
|
+
`Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`
|
|
2838
|
+
);
|
|
2839
|
+
}
|
|
2804
2840
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : packageRun?.id ?? "";
|
|
2805
2841
|
return {
|
|
2806
2842
|
...raw,
|
package/dist/index.mjs
CHANGED
|
@@ -367,7 +367,7 @@ var SDK_RELEASE = {
|
|
|
367
367
|
// 0.1.253 makes play-page browser opening opt-in and retires --no-open.
|
|
368
368
|
// 0.1.254 removes the internal operations tree from the published SDK CLI.
|
|
369
369
|
// Operators use the checkout-local deepline-admin binary instead.
|
|
370
|
-
version: "0.1.
|
|
370
|
+
version: "0.1.300",
|
|
371
371
|
contracts: {
|
|
372
372
|
api: {
|
|
373
373
|
name: "sdk-http-api",
|
|
@@ -712,7 +712,7 @@ var HttpClient = class {
|
|
|
712
712
|
* @param path - API path (e.g. `"/api/v2/tools"`)
|
|
713
713
|
* @param options - HTTP method, body, headers, and timeout
|
|
714
714
|
* @returns Parsed JSON response body
|
|
715
|
-
* @throws {@link AuthError} on HTTP 401/403 (immediate, no retry)
|
|
715
|
+
* @throws {@link AuthError} on Deepline-auth HTTP 401/403 (immediate, no retry)
|
|
716
716
|
* @throws {@link RateLimitError} on HTTP 429 after all retries exhausted
|
|
717
717
|
* @throws {@link DeeplineError} on other API errors or connection failures
|
|
718
718
|
*/
|
|
@@ -751,9 +751,6 @@ var HttpClient = class {
|
|
|
751
751
|
signal: controller.signal
|
|
752
752
|
});
|
|
753
753
|
clearTimeout(timeoutId);
|
|
754
|
-
if (response.status === 401 || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
755
|
-
throw new AuthError();
|
|
756
|
-
}
|
|
757
754
|
if (response.status === 429) {
|
|
758
755
|
const retryAfter = parseRetryAfter(response);
|
|
759
756
|
lastError = new RateLimitError(retryAfter);
|
|
@@ -764,11 +761,9 @@ var HttpClient = class {
|
|
|
764
761
|
throw lastError;
|
|
765
762
|
}
|
|
766
763
|
const body = await response.text();
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
} catch {
|
|
771
|
-
parsed = body;
|
|
764
|
+
const parsed = parseResponseBody(body);
|
|
765
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403 && !options?.forbiddenAsApiError) {
|
|
766
|
+
throw new AuthError();
|
|
772
767
|
}
|
|
773
768
|
if (!response.ok) {
|
|
774
769
|
const retryableApiError = options?.retryApiErrors === true && isRetryableApiErrorResponse(response.status);
|
|
@@ -795,7 +790,7 @@ var HttpClient = class {
|
|
|
795
790
|
}
|
|
796
791
|
const errorValue = typeof parsed === "object" && parsed && "error" in parsed ? parsed.error : void 0;
|
|
797
792
|
const msg = typeof errorValue === "string" ? errorValue : errorValue && typeof errorValue === "object" && "message" in errorValue && typeof errorValue.message === "string" ? errorValue.message : typeof parsed === "object" && parsed && "message" in parsed && typeof parsed.message === "string" ? parsed.message : `HTTP ${response.status}`;
|
|
798
|
-
const apiErrorCode =
|
|
793
|
+
const apiErrorCode = apiErrorCodeFromResponse(parsed);
|
|
799
794
|
lastError = new DeeplineError(msg, response.status, apiErrorCode, {
|
|
800
795
|
response: parsed
|
|
801
796
|
});
|
|
@@ -869,11 +864,12 @@ var HttpClient = class {
|
|
|
869
864
|
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0,
|
|
870
865
|
signal: options?.signal
|
|
871
866
|
});
|
|
872
|
-
if (response.status === 401 || response.status === 403) {
|
|
873
|
-
throw new AuthError();
|
|
874
|
-
}
|
|
875
867
|
if (!response.ok) {
|
|
876
868
|
const body = await response.text();
|
|
869
|
+
const parsed = parseResponseBody(body);
|
|
870
|
+
if (response.status === 401 && !isProviderOriginatedHttpError(parsed) || response.status === 403) {
|
|
871
|
+
throw new AuthError();
|
|
872
|
+
}
|
|
877
873
|
const htmlError = detectHtmlErrorBody(
|
|
878
874
|
body,
|
|
879
875
|
response.headers.get("content-type")
|
|
@@ -890,11 +886,10 @@ var HttpClient = class {
|
|
|
890
886
|
}
|
|
891
887
|
);
|
|
892
888
|
}
|
|
893
|
-
const parsed = parseResponseBody(body);
|
|
894
889
|
throw new DeeplineError(
|
|
895
890
|
apiErrorMessage(parsed, response.status),
|
|
896
891
|
response.status,
|
|
897
|
-
|
|
892
|
+
apiErrorCodeFromResponse(parsed),
|
|
898
893
|
{ response: parsed }
|
|
899
894
|
);
|
|
900
895
|
}
|
|
@@ -969,6 +964,22 @@ function parseResponseBody(body) {
|
|
|
969
964
|
return body;
|
|
970
965
|
}
|
|
971
966
|
}
|
|
967
|
+
function isProviderOriginatedHttpError(parsed) {
|
|
968
|
+
const response = asRecord(parsed);
|
|
969
|
+
const error = asRecord(response?.error);
|
|
970
|
+
const failureOrigin = error?.failure_origin ?? response?.failure_origin;
|
|
971
|
+
const code = error?.code ?? response?.code;
|
|
972
|
+
return failureOrigin === "provider" || code === "UPSTREAM_BLOCKED";
|
|
973
|
+
}
|
|
974
|
+
function apiErrorCodeFromResponse(parsed) {
|
|
975
|
+
const response = asRecord(parsed);
|
|
976
|
+
const error = asRecord(response?.error);
|
|
977
|
+
const code = error?.code ?? response?.code;
|
|
978
|
+
return typeof code === "string" ? code : "API_ERROR";
|
|
979
|
+
}
|
|
980
|
+
function asRecord(value) {
|
|
981
|
+
return typeof value === "object" && value !== null ? value : null;
|
|
982
|
+
}
|
|
972
983
|
function isRetryableApiErrorResponse(status) {
|
|
973
984
|
return status === 408 || status === 425 || status >= 500 && status < 600;
|
|
974
985
|
}
|
|
@@ -1762,7 +1773,7 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
1762
1773
|
switch (normalized) {
|
|
1763
1774
|
case "queued":
|
|
1764
1775
|
case "pending":
|
|
1765
|
-
return "
|
|
1776
|
+
return "queued";
|
|
1766
1777
|
case "running":
|
|
1767
1778
|
case "started":
|
|
1768
1779
|
return "running";
|
|
@@ -1788,7 +1799,26 @@ function normalizePlayRunLifecycleStatus(value) {
|
|
|
1788
1799
|
}
|
|
1789
1800
|
}
|
|
1790
1801
|
function isTerminalPlayRunLifecycleStatus(status) {
|
|
1791
|
-
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
1802
|
+
return TERMINAL_PLAY_RUN_STATUSES.has(
|
|
1803
|
+
normalizePlayRunLifecycleStatus(status)
|
|
1804
|
+
);
|
|
1805
|
+
}
|
|
1806
|
+
function decodePlayRunPublicStatus(value) {
|
|
1807
|
+
const status = normalizePlayRunLifecycleStatus(value);
|
|
1808
|
+
switch (status) {
|
|
1809
|
+
case "queued":
|
|
1810
|
+
case "running":
|
|
1811
|
+
case "waiting":
|
|
1812
|
+
case "completed":
|
|
1813
|
+
case "failed":
|
|
1814
|
+
case "cancelled":
|
|
1815
|
+
return status;
|
|
1816
|
+
case "terminated":
|
|
1817
|
+
case "timed_out":
|
|
1818
|
+
return "cancelled";
|
|
1819
|
+
case "unknown":
|
|
1820
|
+
return null;
|
|
1821
|
+
}
|
|
1792
1822
|
}
|
|
1793
1823
|
|
|
1794
1824
|
// ../shared_libs/play-runtime/run-snapshot-stream.ts
|
|
@@ -2729,7 +2759,13 @@ function isPlayRunPackage(value) {
|
|
|
2729
2759
|
function normalizePlayStatus(raw) {
|
|
2730
2760
|
const runPackage = isPlayRunPackage(raw) ? raw : isPlayRunPackage(raw.package) ? raw.package : null;
|
|
2731
2761
|
const packageRun = runPackage?.run;
|
|
2732
|
-
const
|
|
2762
|
+
const rawStatus = typeof raw.status === "string" ? raw.status : typeof packageRun?.status === "string" ? packageRun.status : null;
|
|
2763
|
+
const status = decodePlayRunPublicStatus(rawStatus);
|
|
2764
|
+
if (!status) {
|
|
2765
|
+
throw new Error(
|
|
2766
|
+
`Invalid play run lifecycle status in API response: ${JSON.stringify(rawStatus)}.`
|
|
2767
|
+
);
|
|
2768
|
+
}
|
|
2733
2769
|
const runId = typeof raw.runId === "string" ? raw.runId : typeof raw.workflowId === "string" ? raw.workflowId : packageRun?.id ?? "";
|
|
2734
2770
|
return {
|
|
2735
2771
|
...raw,
|