deepline 0.1.219 → 0.1.221
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/compat.ts +1 -1
- package/dist/bundling-sources/sdk/src/release.ts +5 -3
- package/dist/bundling-sources/sdk/src/types.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +76 -3
- package/dist/bundling-sources/shared_libs/play-runtime/secret-redaction.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +62 -3
- package/dist/cli/index.js +231 -42
- package/dist/cli/index.mjs +231 -42
- package/dist/index.d.mts +21 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +6 -4
- package/dist/index.mjs +6 -4
- package/dist/viewer/viewer.css +11 -0
- package/dist/viewer/viewer.js +44 -2
- package/package.json +1 -1
|
@@ -26,7 +26,7 @@ export type SdkCompatibilityResponse = {
|
|
|
26
26
|
auto_update?: {
|
|
27
27
|
should_auto_update: boolean;
|
|
28
28
|
required: boolean;
|
|
29
|
-
reason: 'required' | 'patch_lag' | 'rollback_forced' | null;
|
|
29
|
+
reason: 'required' | 'deprecated' | 'patch_lag' | 'rollback_forced' | null;
|
|
30
30
|
patch_lag: number | null;
|
|
31
31
|
patch_lag_threshold: number;
|
|
32
32
|
update_command: string;
|
|
@@ -106,12 +106,14 @@ export const SDK_RELEASE = {
|
|
|
106
106
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
107
107
|
// fields shipped in 0.1.153.
|
|
108
108
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
109
|
-
|
|
109
|
+
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
110
|
+
// automatically without blocking their current command.
|
|
111
|
+
version: '0.1.221',
|
|
110
112
|
apiContract: '2026-06-dataset-handle-results-hard-cutover',
|
|
111
113
|
supportPolicy: {
|
|
112
|
-
latest: '0.1.
|
|
114
|
+
latest: '0.1.221',
|
|
113
115
|
minimumSupported: '0.1.53',
|
|
114
|
-
deprecatedBelow: '0.1.
|
|
116
|
+
deprecatedBelow: '0.1.219',
|
|
115
117
|
commandMinimumSupported: [
|
|
116
118
|
{
|
|
117
119
|
command: 'enrich',
|
|
@@ -997,6 +997,27 @@ export interface PlayCheckResult {
|
|
|
997
997
|
summary?: string;
|
|
998
998
|
artifactHash?: string | null;
|
|
999
999
|
graphHash?: string | null;
|
|
1000
|
+
/** SHA-256 of the exact source bytes checked by Deepline. */
|
|
1001
|
+
sourceHash?: string | null;
|
|
1002
|
+
/** Enforceable byte budgets measured during cloud preflight. */
|
|
1003
|
+
limits?: {
|
|
1004
|
+
revisionStorage: {
|
|
1005
|
+
usedBytes: number;
|
|
1006
|
+
limitBytes: number;
|
|
1007
|
+
withinLimit: boolean;
|
|
1008
|
+
breakdown: {
|
|
1009
|
+
sourceCodeBytes: number;
|
|
1010
|
+
staticPipelineBytes: number;
|
|
1011
|
+
bindingsBytes: number;
|
|
1012
|
+
descriptionBytes: number;
|
|
1013
|
+
};
|
|
1014
|
+
};
|
|
1015
|
+
bundle: {
|
|
1016
|
+
usedBytes: number;
|
|
1017
|
+
limitBytes: number;
|
|
1018
|
+
withinLimit: boolean;
|
|
1019
|
+
};
|
|
1020
|
+
};
|
|
1000
1021
|
}
|
|
1001
1022
|
|
|
1002
1023
|
/** Severity of a {@link PlayCheckIssue}. `error` fails the check; `warning` does not. */
|
|
@@ -8741,6 +8741,7 @@ export class PlayContextImpl {
|
|
|
8741
8741
|
const httpFailureAttempt = httpFailureAttempts.next({
|
|
8742
8742
|
toolId,
|
|
8743
8743
|
status: response.status,
|
|
8744
|
+
bodyText: text,
|
|
8744
8745
|
transientHttpRetrySafe: retrySafeTransientHttp,
|
|
8745
8746
|
});
|
|
8746
8747
|
const failure = classifyToolExecuteHttpFailure({
|
|
@@ -57,6 +57,13 @@ const DAYTONA_INFRASTRUCTURE_RETRY_PATTERN =
|
|
|
57
57
|
/\b(?:Request failed with status code (?:408|429|500|502|503|504)|ECONNRESET|ECONNREFUSED|ETIMEDOUT|UND_ERR_CONNECT_TIMEOUT|fetch failed|socket hang up|Daytona sandbox create failed across|Daytona sandbox create did not complete)\b/i;
|
|
58
58
|
|
|
59
59
|
type DaytonaExecution = { exitCode: number | null; result: string };
|
|
60
|
+
type DaytonaLookupFailure = {
|
|
61
|
+
errorName: string;
|
|
62
|
+
errorCode: string | null;
|
|
63
|
+
httpStatus: number | null;
|
|
64
|
+
requestId: string | null;
|
|
65
|
+
detail: string;
|
|
66
|
+
};
|
|
60
67
|
type DaytonaUploadAttemptTiming = {
|
|
61
68
|
attempt: number;
|
|
62
69
|
sandboxId: string;
|
|
@@ -98,6 +105,72 @@ export const daytonaSdkClientFactory = {
|
|
|
98
105
|
},
|
|
99
106
|
};
|
|
100
107
|
|
|
108
|
+
function stringProperty(value: unknown, key: string): string | null {
|
|
109
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
110
|
+
const candidate = (value as Record<string, unknown>)[key];
|
|
111
|
+
return typeof candidate === 'string' && candidate.trim()
|
|
112
|
+
? candidate.trim()
|
|
113
|
+
: null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function numberProperty(value: unknown, key: string): number | null {
|
|
117
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
|
118
|
+
const candidate = (value as Record<string, unknown>)[key];
|
|
119
|
+
return typeof candidate === 'number' && Number.isFinite(candidate)
|
|
120
|
+
? candidate
|
|
121
|
+
: null;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function redactDaytonaErrorDetail(value: string): string {
|
|
125
|
+
return value
|
|
126
|
+
.replace(
|
|
127
|
+
/authorization\s*[=:]\s*bearer\s+[^\s,;]+/gi,
|
|
128
|
+
'Authorization=Bearer [redacted]',
|
|
129
|
+
)
|
|
130
|
+
.replace(
|
|
131
|
+
/(authorization\s*[=:]\s*)(?!bearer\s+\[redacted\])[^\s,;]+/gi,
|
|
132
|
+
'$1[redacted]',
|
|
133
|
+
)
|
|
134
|
+
.replace(/(bearer\s+)[^\s,;]+/gi, '$1[redacted]')
|
|
135
|
+
.replace(
|
|
136
|
+
/((?:api[_-]?key|token)\s*[=:]\s*)[^\s,;]+/gi,
|
|
137
|
+
'$1[redacted]',
|
|
138
|
+
)
|
|
139
|
+
.replace(/\s+/g, ' ')
|
|
140
|
+
.trim()
|
|
141
|
+
.slice(0, 1_000);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Preserve the actionable shape of a Daytona control-plane failure without
|
|
146
|
+
* copying credentials or an arbitrarily large upstream response into logs.
|
|
147
|
+
*/
|
|
148
|
+
export function describeDaytonaLookupFailure(
|
|
149
|
+
error: unknown,
|
|
150
|
+
): DaytonaLookupFailure {
|
|
151
|
+
const record = error && typeof error === 'object' ? error : null;
|
|
152
|
+
const response = record ? (record as Record<string, unknown>).response : null;
|
|
153
|
+
const headers =
|
|
154
|
+
response && typeof response === 'object'
|
|
155
|
+
? (response as Record<string, unknown>).headers
|
|
156
|
+
: null;
|
|
157
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
158
|
+
return {
|
|
159
|
+
errorName: error instanceof Error ? error.name || 'Error' : 'NonErrorThrow',
|
|
160
|
+
errorCode: stringProperty(record, 'code'),
|
|
161
|
+
httpStatus:
|
|
162
|
+
numberProperty(record, 'status') ??
|
|
163
|
+
numberProperty(record, 'statusCode') ??
|
|
164
|
+
numberProperty(response, 'status'),
|
|
165
|
+
requestId:
|
|
166
|
+
stringProperty(record, 'requestId') ??
|
|
167
|
+
stringProperty(record, 'request_id') ??
|
|
168
|
+
stringProperty(headers, 'x-request-id') ??
|
|
169
|
+
stringProperty(headers, 'x-daytona-request-id'),
|
|
170
|
+
detail: redactDaytonaErrorDetail(message),
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
|
|
101
174
|
/**
|
|
102
175
|
* Best-effort deletion of an orphaned Daytona sandbox by id (push-execution B4).
|
|
103
176
|
*
|
|
@@ -189,16 +262,16 @@ export async function inspectDetachedDaytonaRunner(input: {
|
|
|
189
262
|
: { stage: 'result_missing', detail: null },
|
|
190
263
|
};
|
|
191
264
|
} catch (error) {
|
|
192
|
-
const
|
|
265
|
+
const failure = describeDaytonaLookupFailure(error);
|
|
193
266
|
console.warn('[play-runner.daytona.detached_inspect_failed]', {
|
|
194
267
|
sandboxId: input.sandboxId,
|
|
195
268
|
cmdId: input.cmdId,
|
|
196
|
-
|
|
269
|
+
failure,
|
|
197
270
|
});
|
|
198
271
|
return {
|
|
199
272
|
exitCode: null,
|
|
200
273
|
result: null,
|
|
201
|
-
diagnosis: { stage: 'sandbox_lookup_failed', detail },
|
|
274
|
+
diagnosis: { stage: 'sandbox_lookup_failed', detail: failure.detail },
|
|
202
275
|
};
|
|
203
276
|
}
|
|
204
277
|
}
|
|
@@ -10,7 +10,7 @@ const PRIVATE_KEY_RE =
|
|
|
10
10
|
// example `absurd-key-rotation-check`) and need an assignment context before
|
|
11
11
|
// they are sensitive; HIGH_ENTROPY_ASSIGNMENT_RE handles that case below.
|
|
12
12
|
const COMMON_SECRET_RE =
|
|
13
|
-
/\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]
|
|
13
|
+
/\b(?:(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9_./+=:-]{12,}|(?:pat|ghp|github_pat)_[A-Za-z0-9_./+=:-]{12,}|xox[baprs]-[A-Za-z0-9_./+=:-]{12,})\b/gi;
|
|
14
14
|
const GENERIC_PREFIXED_SECRET_RE =
|
|
15
15
|
/\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
|
|
16
16
|
const URL_SECRET_VALUE_RE =
|
|
@@ -5,6 +5,14 @@ import {
|
|
|
5
5
|
} from './tool-http-errors';
|
|
6
6
|
|
|
7
7
|
export const TOOL_EXECUTE_TRANSIENT_HTTP_MAX_ATTEMPTS = 2;
|
|
8
|
+
// A provider may need to finish the original request before it can replay the
|
|
9
|
+
// result for this key. With no Retry-After signal, these two polls give the
|
|
10
|
+
// original request ten seconds to finish without repeatedly hammering it.
|
|
11
|
+
export const TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_RETRY_DELAYS_MS = [
|
|
12
|
+
5_000, 5_000,
|
|
13
|
+
] as const;
|
|
14
|
+
export const TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_MAX_ATTEMPTS =
|
|
15
|
+
TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_RETRY_DELAYS_MS.length + 1;
|
|
8
16
|
export const TOOL_EXECUTE_RATE_LIMIT_MAX_ATTEMPTS = 8;
|
|
9
17
|
export const TOOL_EXECUTE_BARE_RATE_LIMIT_MAX_ATTEMPTS = 2;
|
|
10
18
|
export const TOOL_EXECUTE_TRANSPORT_MAX_ATTEMPTS = 3;
|
|
@@ -13,6 +21,13 @@ export const TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS = 1_000;
|
|
|
13
21
|
export const TOOL_EXECUTE_RETRY_DELAY_MAX_MS = 5_000;
|
|
14
22
|
export const TOOL_EXECUTE_BARE_RATE_LIMIT_BACKPRESSURE_MS = 60_000;
|
|
15
23
|
export const TOOL_EXECUTE_AUTH_SCOPE_CHANGED_CODE = 'AUTH_SCOPE_CHANGED';
|
|
24
|
+
/**
|
|
25
|
+
* A provider/action-local outcome contract emits this only when a provider has
|
|
26
|
+
* explicitly said that the same idempotency key is still executing. It is not
|
|
27
|
+
* a generic HTTP 409 policy.
|
|
28
|
+
*/
|
|
29
|
+
export const TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_CODE =
|
|
30
|
+
'UPSTREAM_IDEMPOTENCY_IN_PROGRESS';
|
|
16
31
|
|
|
17
32
|
export class ToolExecuteAuthScopeChangedError extends Error {
|
|
18
33
|
readonly code = TOOL_EXECUTE_AUTH_SCOPE_CHANGED_CODE;
|
|
@@ -29,6 +44,7 @@ export type ToolExecuteHttpRetryDecision = {
|
|
|
29
44
|
attemptCap: number;
|
|
30
45
|
reason:
|
|
31
46
|
| 'rate_limit'
|
|
47
|
+
| 'idempotency_in_progress'
|
|
32
48
|
| 'retry_safe_transient_5xx'
|
|
33
49
|
| 'unsafe_transient_5xx'
|
|
34
50
|
| 'hard_billing_error'
|
|
@@ -49,6 +65,7 @@ export type ToolExecuteHttpFailureAttemptTracker = {
|
|
|
49
65
|
next(input: {
|
|
50
66
|
toolId: string;
|
|
51
67
|
status: number;
|
|
68
|
+
bodyText?: string;
|
|
52
69
|
transientHttpRetrySafe?: boolean;
|
|
53
70
|
}): number;
|
|
54
71
|
};
|
|
@@ -65,6 +82,29 @@ function parseJsonObject(text: string): Record<string, unknown> | null {
|
|
|
65
82
|
}
|
|
66
83
|
}
|
|
67
84
|
|
|
85
|
+
function isIdempotencyInProgressResponse(input: {
|
|
86
|
+
status: number;
|
|
87
|
+
bodyText: string;
|
|
88
|
+
}): boolean {
|
|
89
|
+
if (input.status !== 409) return false;
|
|
90
|
+
const body = parseJsonObject(input.bodyText);
|
|
91
|
+
return (
|
|
92
|
+
body?.code === TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_CODE &&
|
|
93
|
+
body.error_category === 'idempotency_in_progress'
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function idempotencyInProgressRetryDelayMs(attempt: number): number {
|
|
98
|
+
return (
|
|
99
|
+
TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_RETRY_DELAYS_MS[
|
|
100
|
+
Math.min(
|
|
101
|
+
Math.max(0, attempt - 1),
|
|
102
|
+
TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_RETRY_DELAYS_MS.length - 1,
|
|
103
|
+
)
|
|
104
|
+
] ?? TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
68
108
|
export function parseToolExecuteAuthScopeChangedError(input: {
|
|
69
109
|
status: number;
|
|
70
110
|
bodyText: string;
|
|
@@ -84,6 +124,7 @@ export function parseToolExecuteAuthScopeChangedError(input: {
|
|
|
84
124
|
|
|
85
125
|
function decideToolExecuteHttpRetry(input: {
|
|
86
126
|
status: number;
|
|
127
|
+
idempotencyInProgress?: boolean;
|
|
87
128
|
hardBillingFailure?: boolean;
|
|
88
129
|
hasRetryAfterHeader?: boolean;
|
|
89
130
|
transientHttpRetrySafe?: boolean;
|
|
@@ -110,6 +151,13 @@ function decideToolExecuteHttpRetry(input: {
|
|
|
110
151
|
reason: 'rate_limit',
|
|
111
152
|
};
|
|
112
153
|
}
|
|
154
|
+
if (input.idempotencyInProgress) {
|
|
155
|
+
return {
|
|
156
|
+
retryable: true,
|
|
157
|
+
attemptCap: TOOL_EXECUTE_IDEMPOTENCY_IN_PROGRESS_MAX_ATTEMPTS,
|
|
158
|
+
reason: 'idempotency_in_progress',
|
|
159
|
+
};
|
|
160
|
+
}
|
|
113
161
|
if (input.status >= 500 && input.status < 600) {
|
|
114
162
|
if (!input.transientHttpRetrySafe) {
|
|
115
163
|
return {
|
|
@@ -137,6 +185,7 @@ export function createToolExecuteHttpFailureAttemptTracker(): ToolExecuteHttpFai
|
|
|
137
185
|
number
|
|
138
186
|
> = {
|
|
139
187
|
rate_limit: 0,
|
|
188
|
+
idempotency_in_progress: 0,
|
|
140
189
|
retry_safe_transient_5xx: 0,
|
|
141
190
|
unsafe_transient_5xx: 0,
|
|
142
191
|
hard_billing_error: 0,
|
|
@@ -147,6 +196,10 @@ export function createToolExecuteHttpFailureAttemptTracker(): ToolExecuteHttpFai
|
|
|
147
196
|
next(input) {
|
|
148
197
|
const decision = decideToolExecuteHttpRetry({
|
|
149
198
|
status: input.status,
|
|
199
|
+
idempotencyInProgress: isIdempotencyInProgressResponse({
|
|
200
|
+
status: input.status,
|
|
201
|
+
bodyText: input.bodyText ?? '',
|
|
202
|
+
}),
|
|
150
203
|
hasRetryAfterHeader: true,
|
|
151
204
|
transientHttpRetrySafe: input.transientHttpRetrySafe === true,
|
|
152
205
|
});
|
|
@@ -186,8 +239,10 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
186
239
|
const hasRetryAfterHeader =
|
|
187
240
|
typeof input.retryAfterHeader === 'string' &&
|
|
188
241
|
input.retryAfterHeader.trim().length > 0;
|
|
242
|
+
const idempotencyInProgress = isIdempotencyInProgressResponse(input);
|
|
189
243
|
const initialRetryDecision = decideToolExecuteHttpRetry({
|
|
190
244
|
status: input.status,
|
|
245
|
+
idempotencyInProgress,
|
|
191
246
|
hasRetryAfterHeader,
|
|
192
247
|
transientHttpRetrySafe,
|
|
193
248
|
});
|
|
@@ -208,6 +263,7 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
208
263
|
const hardBillingFailure = isHardBillingToolHttpError(error);
|
|
209
264
|
const retryDecision = decideToolExecuteHttpRetry({
|
|
210
265
|
status: input.status,
|
|
266
|
+
idempotencyInProgress,
|
|
211
267
|
hardBillingFailure,
|
|
212
268
|
hasRetryAfterHeader,
|
|
213
269
|
transientHttpRetrySafe,
|
|
@@ -238,9 +294,12 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
238
294
|
TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS * input.attempt,
|
|
239
295
|
),
|
|
240
296
|
)
|
|
241
|
-
:
|
|
242
|
-
|
|
243
|
-
|
|
297
|
+
: retryDecision.reason === 'idempotency_in_progress' &&
|
|
298
|
+
!hasRetryAfterHeader
|
|
299
|
+
? idempotencyInProgressRetryDelayMs(input.attempt)
|
|
300
|
+
: retryAfterMs > 0
|
|
301
|
+
? Math.min(TOOL_EXECUTE_RETRY_DELAY_MAX_MS, retryAfterMs)
|
|
302
|
+
: TOOL_EXECUTE_RETRY_DELAY_FALLBACK_MS;
|
|
244
303
|
return {
|
|
245
304
|
...retryDecision,
|
|
246
305
|
error,
|
package/dist/cli/index.js
CHANGED
|
@@ -623,12 +623,14 @@ var SDK_RELEASE = {
|
|
|
623
623
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
624
624
|
// fields shipped in 0.1.153.
|
|
625
625
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
626
|
-
|
|
626
|
+
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
627
|
+
// automatically without blocking their current command.
|
|
628
|
+
version: "0.1.221",
|
|
627
629
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
628
630
|
supportPolicy: {
|
|
629
|
-
latest: "0.1.
|
|
631
|
+
latest: "0.1.221",
|
|
630
632
|
minimumSupported: "0.1.53",
|
|
631
|
-
deprecatedBelow: "0.1.
|
|
633
|
+
deprecatedBelow: "0.1.219",
|
|
632
634
|
commandMinimumSupported: [
|
|
633
635
|
{
|
|
634
636
|
command: "enrich",
|
|
@@ -1364,7 +1366,7 @@ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
|
|
|
1364
1366
|
var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
|
|
1365
1367
|
var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
1366
1368
|
var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
|
|
1367
|
-
var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]
|
|
1369
|
+
var COMMON_SECRET_RE = /\b(?:(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9_./+=:-]{12,}|(?:pat|ghp|github_pat)_[A-Za-z0-9_./+=:-]{12,}|xox[baprs]-[A-Za-z0-9_./+=:-]{12,})\b/gi;
|
|
1368
1370
|
var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
|
|
1369
1371
|
var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
|
|
1370
1372
|
var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
|
|
@@ -14646,6 +14648,73 @@ function parsePlayCheckOptions(args) {
|
|
|
14646
14648
|
const jsonOutput = argsWantJson(args);
|
|
14647
14649
|
return { target, jsonOutput };
|
|
14648
14650
|
}
|
|
14651
|
+
function parsePlayPublishOptions(args) {
|
|
14652
|
+
const target = args[0];
|
|
14653
|
+
if (!target) {
|
|
14654
|
+
throw new Error(
|
|
14655
|
+
"Usage: deepline plays publish <play-file.ts|play-name> [--expected-artifact <hash>] [--dry-run] [--latest|--revision-id <id>] [--json]"
|
|
14656
|
+
);
|
|
14657
|
+
}
|
|
14658
|
+
let revisionId;
|
|
14659
|
+
let useLatest = false;
|
|
14660
|
+
let expectedArtifactHash;
|
|
14661
|
+
let dryRun = false;
|
|
14662
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
14663
|
+
const arg = args[index];
|
|
14664
|
+
if (arg === "--revision-id") {
|
|
14665
|
+
revisionId = args[++index];
|
|
14666
|
+
if (!revisionId) throw new Error("--revision-id requires a revision id.");
|
|
14667
|
+
continue;
|
|
14668
|
+
}
|
|
14669
|
+
if (arg === "--latest") {
|
|
14670
|
+
useLatest = true;
|
|
14671
|
+
continue;
|
|
14672
|
+
}
|
|
14673
|
+
if (arg === "--expected-artifact") {
|
|
14674
|
+
expectedArtifactHash = args[++index];
|
|
14675
|
+
if (!expectedArtifactHash) {
|
|
14676
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
14677
|
+
}
|
|
14678
|
+
continue;
|
|
14679
|
+
}
|
|
14680
|
+
if (arg.startsWith("--expected-artifact=")) {
|
|
14681
|
+
expectedArtifactHash = arg.slice("--expected-artifact=".length);
|
|
14682
|
+
if (!expectedArtifactHash) {
|
|
14683
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
14684
|
+
}
|
|
14685
|
+
continue;
|
|
14686
|
+
}
|
|
14687
|
+
if (arg === "--dry-run") {
|
|
14688
|
+
dryRun = true;
|
|
14689
|
+
continue;
|
|
14690
|
+
}
|
|
14691
|
+
if (arg === "--json") continue;
|
|
14692
|
+
throw new Error(`Unknown plays publish option: ${arg}`);
|
|
14693
|
+
}
|
|
14694
|
+
if (revisionId && useLatest) {
|
|
14695
|
+
throw new Error("Choose only one live target: --latest or --revision-id.");
|
|
14696
|
+
}
|
|
14697
|
+
return {
|
|
14698
|
+
target,
|
|
14699
|
+
revisionId,
|
|
14700
|
+
useLatest,
|
|
14701
|
+
expectedArtifactHash,
|
|
14702
|
+
dryRun,
|
|
14703
|
+
jsonOutput: argsWantJson(args)
|
|
14704
|
+
};
|
|
14705
|
+
}
|
|
14706
|
+
function formatByteBudget(usedBytes, limitBytes) {
|
|
14707
|
+
return `${usedBytes.toLocaleString()} B / ${limitBytes.toLocaleString()} B`;
|
|
14708
|
+
}
|
|
14709
|
+
function printPlayCheckLimits(limits) {
|
|
14710
|
+
if (!limits) return;
|
|
14711
|
+
console.log(
|
|
14712
|
+
` revision storage: ${formatByteBudget(limits.revisionStorage.usedBytes, limits.revisionStorage.limitBytes)}`
|
|
14713
|
+
);
|
|
14714
|
+
console.log(
|
|
14715
|
+
` bundle: ${formatByteBudget(limits.bundle.usedBytes, limits.bundle.limitBytes)}`
|
|
14716
|
+
);
|
|
14717
|
+
}
|
|
14649
14718
|
function shouldUseLocalOnlyPlayCheck() {
|
|
14650
14719
|
const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
|
|
14651
14720
|
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
@@ -14958,7 +15027,11 @@ async function handlePlayCheck(args) {
|
|
|
14958
15027
|
);
|
|
14959
15028
|
} else {
|
|
14960
15029
|
console.log(`\u2713 ${playName} passed local play check`);
|
|
15030
|
+
console.log(` source: ${graph.root.artifact.sourceHash.slice(0, 12)}`);
|
|
14961
15031
|
console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
|
|
15032
|
+
console.log(
|
|
15033
|
+
` publish: deepline plays publish ${shellQuote2(options.target)} --expected-artifact ${result2.artifactHash}`
|
|
15034
|
+
);
|
|
14962
15035
|
printToolGetterHints(result2.toolGetterHints);
|
|
14963
15036
|
}
|
|
14964
15037
|
return 0;
|
|
@@ -15000,6 +15073,15 @@ async function handlePlayCheck(args) {
|
|
|
15000
15073
|
if (enrichedResult.artifactHash) {
|
|
15001
15074
|
console.log(` artifact: ${enrichedResult.artifactHash.slice(0, 12)}`);
|
|
15002
15075
|
}
|
|
15076
|
+
if (enrichedResult.sourceHash) {
|
|
15077
|
+
console.log(` source: ${enrichedResult.sourceHash.slice(0, 12)}`);
|
|
15078
|
+
}
|
|
15079
|
+
printPlayCheckLimits(enrichedResult.limits);
|
|
15080
|
+
if (enrichedResult.artifactHash) {
|
|
15081
|
+
console.log(
|
|
15082
|
+
` publish: deepline plays publish ${shellQuote2(options.target)} --expected-artifact ${enrichedResult.artifactHash}`
|
|
15083
|
+
);
|
|
15084
|
+
}
|
|
15003
15085
|
printPlayTriggers(enrichedResult.triggers);
|
|
15004
15086
|
printRecognizedSummary(enrichedResult.recognized);
|
|
15005
15087
|
printPlayCheckIssues(enrichedResult.issues, (line) => console.log(line));
|
|
@@ -16356,28 +16438,15 @@ async function handlePlayDescribe(args) {
|
|
|
16356
16438
|
return 0;
|
|
16357
16439
|
}
|
|
16358
16440
|
async function handlePlayPublish(args) {
|
|
16359
|
-
|
|
16360
|
-
|
|
16361
|
-
|
|
16362
|
-
|
|
16363
|
-
);
|
|
16364
|
-
return
|
|
16365
|
-
}
|
|
16366
|
-
let revisionId;
|
|
16367
|
-
let useLatest = false;
|
|
16368
|
-
for (let index = 1; index < args.length; index += 1) {
|
|
16369
|
-
const arg = args[index];
|
|
16370
|
-
if (arg === "--revision-id" && args[index + 1]) {
|
|
16371
|
-
revisionId = args[++index];
|
|
16372
|
-
}
|
|
16373
|
-
if (arg === "--latest") {
|
|
16374
|
-
useLatest = true;
|
|
16375
|
-
}
|
|
16376
|
-
}
|
|
16377
|
-
if (revisionId && useLatest) {
|
|
16378
|
-
console.error("Choose only one live target: --latest or --revision-id.");
|
|
16379
|
-
return 1;
|
|
16441
|
+
let options;
|
|
16442
|
+
try {
|
|
16443
|
+
options = parsePlayPublishOptions(args);
|
|
16444
|
+
} catch (error) {
|
|
16445
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16446
|
+
return 2;
|
|
16380
16447
|
}
|
|
16448
|
+
const { target: playName, useLatest } = options;
|
|
16449
|
+
let revisionId = options.revisionId;
|
|
16381
16450
|
const client2 = new DeeplineClient();
|
|
16382
16451
|
if (isFileTarget(playName)) {
|
|
16383
16452
|
if (revisionId || useLatest) {
|
|
@@ -16394,6 +16463,66 @@ async function handlePlayPublish(args) {
|
|
|
16394
16463
|
() => collectBundledPlayGraph((0, import_node_path11.resolve)(playName))
|
|
16395
16464
|
);
|
|
16396
16465
|
assertBundledPlayGraphDescriptions(graph);
|
|
16466
|
+
} catch (error) {
|
|
16467
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16468
|
+
return 1;
|
|
16469
|
+
}
|
|
16470
|
+
const rootPlayName = graph.root.playName ?? extractPlayName(graph.root.sourceCode, graph.root.filePath);
|
|
16471
|
+
const artifactHash = graph.root.artifact.artifactHash;
|
|
16472
|
+
if (options.expectedArtifactHash && options.expectedArtifactHash !== artifactHash) {
|
|
16473
|
+
const result3 = {
|
|
16474
|
+
ok: false,
|
|
16475
|
+
code: "PLAY_ARTIFACT_HASH_MISMATCH",
|
|
16476
|
+
message: "Refusing to publish: the local file no longer produces the artifact checked earlier.",
|
|
16477
|
+
expectedArtifactHash: options.expectedArtifactHash,
|
|
16478
|
+
currentArtifactHash: artifactHash,
|
|
16479
|
+
next: `deepline plays check ${shellQuote2(playName)}`
|
|
16480
|
+
};
|
|
16481
|
+
if (options.jsonOutput) {
|
|
16482
|
+
process.stdout.write(`${JSON.stringify(result3)}
|
|
16483
|
+
`);
|
|
16484
|
+
} else {
|
|
16485
|
+
console.error(result3.message);
|
|
16486
|
+
console.error(` checked artifact: ${result3.expectedArtifactHash}`);
|
|
16487
|
+
console.error(` current artifact: ${result3.currentArtifactHash}`);
|
|
16488
|
+
console.error(` run: ${result3.next}`);
|
|
16489
|
+
}
|
|
16490
|
+
return 7;
|
|
16491
|
+
}
|
|
16492
|
+
const dryRun = {
|
|
16493
|
+
ok: true,
|
|
16494
|
+
dryRun: true,
|
|
16495
|
+
name: rootPlayName,
|
|
16496
|
+
sourcePath: graph.root.filePath,
|
|
16497
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
16498
|
+
artifactHash,
|
|
16499
|
+
graphHash: graph.root.artifact.graphHash,
|
|
16500
|
+
importedPlayCount: Math.max(0, graph.nodes.size - 1),
|
|
16501
|
+
plannedMutation: "register revision and promote it live",
|
|
16502
|
+
expectedArtifactHash: options.expectedArtifactHash ?? null
|
|
16503
|
+
};
|
|
16504
|
+
if (options.dryRun) {
|
|
16505
|
+
if (options.jsonOutput) {
|
|
16506
|
+
process.stdout.write(`${JSON.stringify(dryRun)}
|
|
16507
|
+
`);
|
|
16508
|
+
} else {
|
|
16509
|
+
console.log(`Dry run: ${rootPlayName}`);
|
|
16510
|
+
console.log(` source: ${dryRun.sourceHash}`);
|
|
16511
|
+
console.log(` artifact: ${dryRun.artifactHash}`);
|
|
16512
|
+
console.log(` would: ${dryRun.plannedMutation}`);
|
|
16513
|
+
}
|
|
16514
|
+
return 0;
|
|
16515
|
+
}
|
|
16516
|
+
let previousLive = null;
|
|
16517
|
+
try {
|
|
16518
|
+
previousLive = (await client2.getPlay(rootPlayName)).play.liveRevision ?? null;
|
|
16519
|
+
} catch (error) {
|
|
16520
|
+
if (!(error instanceof DeeplineError) || error.statusCode !== 404) {
|
|
16521
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16522
|
+
return 5;
|
|
16523
|
+
}
|
|
16524
|
+
}
|
|
16525
|
+
try {
|
|
16397
16526
|
await traceCliSpan(
|
|
16398
16527
|
"cli.play_publish_compile_manifests",
|
|
16399
16528
|
{ targetKind: "file", nodeCount: graph.nodes.size },
|
|
@@ -16408,13 +16537,12 @@ async function handlePlayPublish(args) {
|
|
|
16408
16537
|
console.error(error instanceof Error ? error.message : String(error));
|
|
16409
16538
|
return 1;
|
|
16410
16539
|
}
|
|
16411
|
-
const rootPlayName = graph.root.playName ?? extractPlayName(graph.root.sourceCode, graph.root.filePath);
|
|
16412
16540
|
const published = await traceCliSpan(
|
|
16413
16541
|
"cli.play_publish_register_root",
|
|
16414
16542
|
{
|
|
16415
16543
|
targetKind: "file",
|
|
16416
16544
|
playName: rootPlayName,
|
|
16417
|
-
artifactHash
|
|
16545
|
+
artifactHash
|
|
16418
16546
|
},
|
|
16419
16547
|
() => client2.registerPlayArtifact({
|
|
16420
16548
|
name: rootPlayName,
|
|
@@ -16426,17 +16554,63 @@ async function handlePlayPublish(args) {
|
|
|
16426
16554
|
publish: true
|
|
16427
16555
|
})
|
|
16428
16556
|
);
|
|
16429
|
-
|
|
16430
|
-
|
|
16431
|
-
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
|
|
16435
|
-
|
|
16436
|
-
|
|
16437
|
-
|
|
16438
|
-
|
|
16439
|
-
|
|
16557
|
+
const result2 = {
|
|
16558
|
+
success: true,
|
|
16559
|
+
name: rootPlayName,
|
|
16560
|
+
sourcePath: graph.root.filePath,
|
|
16561
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
16562
|
+
artifactHash,
|
|
16563
|
+
liveVersion: published.version ?? null,
|
|
16564
|
+
revisionId: published.revisionId ?? null,
|
|
16565
|
+
previousLiveVersion: previousLive?.version ?? null,
|
|
16566
|
+
previousArtifactHash: previousLive?.artifactHash ?? null,
|
|
16567
|
+
sourceBytes: {
|
|
16568
|
+
before: previousLive?.sourceCode ? Buffer.byteLength(previousLive.sourceCode, "utf8") : null,
|
|
16569
|
+
after: Buffer.byteLength(graph.root.sourceCode, "utf8")
|
|
16570
|
+
},
|
|
16571
|
+
triggerMetadata: published.triggerMetadata ?? null,
|
|
16572
|
+
triggerBindings: published.triggerBindings ?? []
|
|
16573
|
+
};
|
|
16574
|
+
if (options.jsonOutput) {
|
|
16575
|
+
process.stdout.write(`${JSON.stringify(result2)}
|
|
16576
|
+
`);
|
|
16577
|
+
} else {
|
|
16578
|
+
console.log(
|
|
16579
|
+
`\u2713 Published ${rootPlayName} as v${result2.liveVersion ?? "?"}`
|
|
16580
|
+
);
|
|
16581
|
+
console.log(` source: ${result2.sourceHash.slice(0, 12)}`);
|
|
16582
|
+
console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
|
|
16583
|
+
if (result2.previousLiveVersion !== null) {
|
|
16584
|
+
console.log(
|
|
16585
|
+
` previous live: v${result2.previousLiveVersion} (${result2.previousArtifactHash?.slice(0, 12) ?? "unknown artifact"})`
|
|
16586
|
+
);
|
|
16587
|
+
}
|
|
16588
|
+
if (result2.sourceBytes.before !== null) {
|
|
16589
|
+
console.log(
|
|
16590
|
+
` source bytes: ${result2.sourceBytes.before.toLocaleString()} \u2192 ${result2.sourceBytes.after.toLocaleString()}`
|
|
16591
|
+
);
|
|
16592
|
+
}
|
|
16593
|
+
console.log(
|
|
16594
|
+
` revisions: deepline plays versions --name ${rootPlayName}`
|
|
16595
|
+
);
|
|
16596
|
+
}
|
|
16597
|
+
return 0;
|
|
16598
|
+
}
|
|
16599
|
+
if (options.expectedArtifactHash) {
|
|
16600
|
+
console.error("--expected-artifact only applies to a local play file.");
|
|
16601
|
+
return 2;
|
|
16602
|
+
}
|
|
16603
|
+
if (options.dryRun) {
|
|
16604
|
+
const result2 = {
|
|
16605
|
+
ok: true,
|
|
16606
|
+
dryRun: true,
|
|
16607
|
+
name: playName,
|
|
16608
|
+
plannedMutation: "promote a saved revision live",
|
|
16609
|
+
revisionId: revisionId ?? null,
|
|
16610
|
+
latest: useLatest
|
|
16611
|
+
};
|
|
16612
|
+
process.stdout.write(`${JSON.stringify(result2)}
|
|
16613
|
+
`);
|
|
16440
16614
|
return 0;
|
|
16441
16615
|
}
|
|
16442
16616
|
const resolvedName = parseReferencedPlayTarget2(playName).playName;
|
|
@@ -16800,7 +16974,9 @@ Notes:
|
|
|
16800
16974
|
Mutates cloud state. For a saved play, --latest or --revision-id promotes an
|
|
16801
16975
|
existing saved revision live.
|
|
16802
16976
|
Local .play.ts publishing bundles the file, validates it, saves a revision,
|
|
16803
|
-
and promotes that revision live.
|
|
16977
|
+
and promotes that revision live. Use --expected-artifact with the hash from
|
|
16978
|
+
plays check to refuse publishing bytes that changed after validation.
|
|
16979
|
+
--dry-run bundles only and prints the exact artifact that would be published.
|
|
16804
16980
|
Running a local file with plays run does not publish it.
|
|
16805
16981
|
|
|
16806
16982
|
Examples:
|
|
@@ -16808,27 +16984,40 @@ Examples:
|
|
|
16808
16984
|
deepline plays set-live my-play --revision-id <revision-id> --json
|
|
16809
16985
|
deepline plays set-live my.play.ts --json
|
|
16810
16986
|
deepline plays publish my.play.ts --json
|
|
16987
|
+
deepline plays check my.play.ts
|
|
16988
|
+
deepline plays publish my.play.ts --expected-artifact <artifact-hash>
|
|
16989
|
+
deepline plays publish my.play.ts --dry-run --json
|
|
16811
16990
|
`
|
|
16812
16991
|
);
|
|
16813
16992
|
addPublishHelp(
|
|
16814
16993
|
play.command("publish <target>").description(
|
|
16815
16994
|
"Promote a saved play revision or publish a local play file."
|
|
16816
16995
|
)
|
|
16817
|
-
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
16996
|
+
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
16997
|
+
"--expected-artifact <hash>",
|
|
16998
|
+
"Require the local file to produce this checked artifact hash"
|
|
16999
|
+
).option("--dry-run", "Bundle and show the planned publish without mutation").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
16818
17000
|
process.exitCode = await handlePlayPublish([
|
|
16819
17001
|
target,
|
|
16820
17002
|
...options.latest ? ["--latest"] : [],
|
|
16821
17003
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
17004
|
+
...options.expectedArtifact ? ["--expected-artifact", options.expectedArtifact] : [],
|
|
17005
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
16822
17006
|
...options.json ? ["--json"] : []
|
|
16823
17007
|
]);
|
|
16824
17008
|
});
|
|
16825
17009
|
addPublishHelp(
|
|
16826
17010
|
play.command("set-live <target>").description("Promote a saved revision or publish a local play file.")
|
|
16827
|
-
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17011
|
+
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17012
|
+
"--expected-artifact <hash>",
|
|
17013
|
+
"Require the local file to produce this checked artifact hash"
|
|
17014
|
+
).option("--dry-run", "Bundle and show the planned publish without mutation").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
16828
17015
|
process.exitCode = await handlePlayPublish([
|
|
16829
17016
|
target,
|
|
16830
17017
|
...options.latest ? ["--latest"] : [],
|
|
16831
17018
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
17019
|
+
...options.expectedArtifact ? ["--expected-artifact", options.expectedArtifact] : [],
|
|
17020
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
16832
17021
|
...options.json ? ["--json"] : []
|
|
16833
17022
|
]);
|
|
16834
17023
|
});
|
|
@@ -28940,7 +29129,7 @@ async function maybeAutoUpdateAndRelaunch(response) {
|
|
|
28940
29129
|
if (plan.kind === "source") {
|
|
28941
29130
|
return false;
|
|
28942
29131
|
}
|
|
28943
|
-
const label = autoUpdate.reason === "rollback_forced" ? "has a server rollback pending and needs the latest rollback-aware CLI" : autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
29132
|
+
const label = autoUpdate.reason === "rollback_forced" ? "has a server rollback pending and needs the latest rollback-aware CLI" : autoUpdate.reason === "deprecated" ? "is deprecated and will update automatically" : autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
28944
29133
|
process.stderr.write(
|
|
28945
29134
|
`Deepline SDK/CLI ${label}; running ${plan.manualCommand}
|
|
28946
29135
|
`
|
package/dist/cli/index.mjs
CHANGED
|
@@ -608,12 +608,14 @@ var SDK_RELEASE = {
|
|
|
608
608
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
609
609
|
// fields shipped in 0.1.153.
|
|
610
610
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
611
|
-
|
|
611
|
+
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
612
|
+
// automatically without blocking their current command.
|
|
613
|
+
version: "0.1.221",
|
|
612
614
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
613
615
|
supportPolicy: {
|
|
614
|
-
latest: "0.1.
|
|
616
|
+
latest: "0.1.221",
|
|
615
617
|
minimumSupported: "0.1.53",
|
|
616
|
-
deprecatedBelow: "0.1.
|
|
618
|
+
deprecatedBelow: "0.1.219",
|
|
617
619
|
commandMinimumSupported: [
|
|
618
620
|
{
|
|
619
621
|
command: "enrich",
|
|
@@ -1349,7 +1351,7 @@ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
|
|
|
1349
1351
|
var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
|
|
1350
1352
|
var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
1351
1353
|
var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
|
|
1352
|
-
var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]
|
|
1354
|
+
var COMMON_SECRET_RE = /\b(?:(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9_./+=:-]{12,}|(?:pat|ghp|github_pat)_[A-Za-z0-9_./+=:-]{12,}|xox[baprs]-[A-Za-z0-9_./+=:-]{12,})\b/gi;
|
|
1353
1355
|
var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
|
|
1354
1356
|
var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
|
|
1355
1357
|
var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
|
|
@@ -14675,6 +14677,73 @@ function parsePlayCheckOptions(args) {
|
|
|
14675
14677
|
const jsonOutput = argsWantJson(args);
|
|
14676
14678
|
return { target, jsonOutput };
|
|
14677
14679
|
}
|
|
14680
|
+
function parsePlayPublishOptions(args) {
|
|
14681
|
+
const target = args[0];
|
|
14682
|
+
if (!target) {
|
|
14683
|
+
throw new Error(
|
|
14684
|
+
"Usage: deepline plays publish <play-file.ts|play-name> [--expected-artifact <hash>] [--dry-run] [--latest|--revision-id <id>] [--json]"
|
|
14685
|
+
);
|
|
14686
|
+
}
|
|
14687
|
+
let revisionId;
|
|
14688
|
+
let useLatest = false;
|
|
14689
|
+
let expectedArtifactHash;
|
|
14690
|
+
let dryRun = false;
|
|
14691
|
+
for (let index = 1; index < args.length; index += 1) {
|
|
14692
|
+
const arg = args[index];
|
|
14693
|
+
if (arg === "--revision-id") {
|
|
14694
|
+
revisionId = args[++index];
|
|
14695
|
+
if (!revisionId) throw new Error("--revision-id requires a revision id.");
|
|
14696
|
+
continue;
|
|
14697
|
+
}
|
|
14698
|
+
if (arg === "--latest") {
|
|
14699
|
+
useLatest = true;
|
|
14700
|
+
continue;
|
|
14701
|
+
}
|
|
14702
|
+
if (arg === "--expected-artifact") {
|
|
14703
|
+
expectedArtifactHash = args[++index];
|
|
14704
|
+
if (!expectedArtifactHash) {
|
|
14705
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
14706
|
+
}
|
|
14707
|
+
continue;
|
|
14708
|
+
}
|
|
14709
|
+
if (arg.startsWith("--expected-artifact=")) {
|
|
14710
|
+
expectedArtifactHash = arg.slice("--expected-artifact=".length);
|
|
14711
|
+
if (!expectedArtifactHash) {
|
|
14712
|
+
throw new Error("--expected-artifact requires an artifact hash.");
|
|
14713
|
+
}
|
|
14714
|
+
continue;
|
|
14715
|
+
}
|
|
14716
|
+
if (arg === "--dry-run") {
|
|
14717
|
+
dryRun = true;
|
|
14718
|
+
continue;
|
|
14719
|
+
}
|
|
14720
|
+
if (arg === "--json") continue;
|
|
14721
|
+
throw new Error(`Unknown plays publish option: ${arg}`);
|
|
14722
|
+
}
|
|
14723
|
+
if (revisionId && useLatest) {
|
|
14724
|
+
throw new Error("Choose only one live target: --latest or --revision-id.");
|
|
14725
|
+
}
|
|
14726
|
+
return {
|
|
14727
|
+
target,
|
|
14728
|
+
revisionId,
|
|
14729
|
+
useLatest,
|
|
14730
|
+
expectedArtifactHash,
|
|
14731
|
+
dryRun,
|
|
14732
|
+
jsonOutput: argsWantJson(args)
|
|
14733
|
+
};
|
|
14734
|
+
}
|
|
14735
|
+
function formatByteBudget(usedBytes, limitBytes) {
|
|
14736
|
+
return `${usedBytes.toLocaleString()} B / ${limitBytes.toLocaleString()} B`;
|
|
14737
|
+
}
|
|
14738
|
+
function printPlayCheckLimits(limits) {
|
|
14739
|
+
if (!limits) return;
|
|
14740
|
+
console.log(
|
|
14741
|
+
` revision storage: ${formatByteBudget(limits.revisionStorage.usedBytes, limits.revisionStorage.limitBytes)}`
|
|
14742
|
+
);
|
|
14743
|
+
console.log(
|
|
14744
|
+
` bundle: ${formatByteBudget(limits.bundle.usedBytes, limits.bundle.limitBytes)}`
|
|
14745
|
+
);
|
|
14746
|
+
}
|
|
14678
14747
|
function shouldUseLocalOnlyPlayCheck() {
|
|
14679
14748
|
const value = process.env.DEEPLINE_PLAY_CHECK_LOCAL_ONLY?.trim().toLowerCase();
|
|
14680
14749
|
return value === "1" || value === "true" || value === "yes" || value === "on";
|
|
@@ -14987,7 +15056,11 @@ async function handlePlayCheck(args) {
|
|
|
14987
15056
|
);
|
|
14988
15057
|
} else {
|
|
14989
15058
|
console.log(`\u2713 ${playName} passed local play check`);
|
|
15059
|
+
console.log(` source: ${graph.root.artifact.sourceHash.slice(0, 12)}`);
|
|
14990
15060
|
console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
|
|
15061
|
+
console.log(
|
|
15062
|
+
` publish: deepline plays publish ${shellQuote2(options.target)} --expected-artifact ${result2.artifactHash}`
|
|
15063
|
+
);
|
|
14991
15064
|
printToolGetterHints(result2.toolGetterHints);
|
|
14992
15065
|
}
|
|
14993
15066
|
return 0;
|
|
@@ -15029,6 +15102,15 @@ async function handlePlayCheck(args) {
|
|
|
15029
15102
|
if (enrichedResult.artifactHash) {
|
|
15030
15103
|
console.log(` artifact: ${enrichedResult.artifactHash.slice(0, 12)}`);
|
|
15031
15104
|
}
|
|
15105
|
+
if (enrichedResult.sourceHash) {
|
|
15106
|
+
console.log(` source: ${enrichedResult.sourceHash.slice(0, 12)}`);
|
|
15107
|
+
}
|
|
15108
|
+
printPlayCheckLimits(enrichedResult.limits);
|
|
15109
|
+
if (enrichedResult.artifactHash) {
|
|
15110
|
+
console.log(
|
|
15111
|
+
` publish: deepline plays publish ${shellQuote2(options.target)} --expected-artifact ${enrichedResult.artifactHash}`
|
|
15112
|
+
);
|
|
15113
|
+
}
|
|
15032
15114
|
printPlayTriggers(enrichedResult.triggers);
|
|
15033
15115
|
printRecognizedSummary(enrichedResult.recognized);
|
|
15034
15116
|
printPlayCheckIssues(enrichedResult.issues, (line) => console.log(line));
|
|
@@ -16385,28 +16467,15 @@ async function handlePlayDescribe(args) {
|
|
|
16385
16467
|
return 0;
|
|
16386
16468
|
}
|
|
16387
16469
|
async function handlePlayPublish(args) {
|
|
16388
|
-
|
|
16389
|
-
|
|
16390
|
-
|
|
16391
|
-
|
|
16392
|
-
);
|
|
16393
|
-
return
|
|
16394
|
-
}
|
|
16395
|
-
let revisionId;
|
|
16396
|
-
let useLatest = false;
|
|
16397
|
-
for (let index = 1; index < args.length; index += 1) {
|
|
16398
|
-
const arg = args[index];
|
|
16399
|
-
if (arg === "--revision-id" && args[index + 1]) {
|
|
16400
|
-
revisionId = args[++index];
|
|
16401
|
-
}
|
|
16402
|
-
if (arg === "--latest") {
|
|
16403
|
-
useLatest = true;
|
|
16404
|
-
}
|
|
16405
|
-
}
|
|
16406
|
-
if (revisionId && useLatest) {
|
|
16407
|
-
console.error("Choose only one live target: --latest or --revision-id.");
|
|
16408
|
-
return 1;
|
|
16470
|
+
let options;
|
|
16471
|
+
try {
|
|
16472
|
+
options = parsePlayPublishOptions(args);
|
|
16473
|
+
} catch (error) {
|
|
16474
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16475
|
+
return 2;
|
|
16409
16476
|
}
|
|
16477
|
+
const { target: playName, useLatest } = options;
|
|
16478
|
+
let revisionId = options.revisionId;
|
|
16410
16479
|
const client2 = new DeeplineClient();
|
|
16411
16480
|
if (isFileTarget(playName)) {
|
|
16412
16481
|
if (revisionId || useLatest) {
|
|
@@ -16423,6 +16492,66 @@ async function handlePlayPublish(args) {
|
|
|
16423
16492
|
() => collectBundledPlayGraph(resolve8(playName))
|
|
16424
16493
|
);
|
|
16425
16494
|
assertBundledPlayGraphDescriptions(graph);
|
|
16495
|
+
} catch (error) {
|
|
16496
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16497
|
+
return 1;
|
|
16498
|
+
}
|
|
16499
|
+
const rootPlayName = graph.root.playName ?? extractPlayName(graph.root.sourceCode, graph.root.filePath);
|
|
16500
|
+
const artifactHash = graph.root.artifact.artifactHash;
|
|
16501
|
+
if (options.expectedArtifactHash && options.expectedArtifactHash !== artifactHash) {
|
|
16502
|
+
const result3 = {
|
|
16503
|
+
ok: false,
|
|
16504
|
+
code: "PLAY_ARTIFACT_HASH_MISMATCH",
|
|
16505
|
+
message: "Refusing to publish: the local file no longer produces the artifact checked earlier.",
|
|
16506
|
+
expectedArtifactHash: options.expectedArtifactHash,
|
|
16507
|
+
currentArtifactHash: artifactHash,
|
|
16508
|
+
next: `deepline plays check ${shellQuote2(playName)}`
|
|
16509
|
+
};
|
|
16510
|
+
if (options.jsonOutput) {
|
|
16511
|
+
process.stdout.write(`${JSON.stringify(result3)}
|
|
16512
|
+
`);
|
|
16513
|
+
} else {
|
|
16514
|
+
console.error(result3.message);
|
|
16515
|
+
console.error(` checked artifact: ${result3.expectedArtifactHash}`);
|
|
16516
|
+
console.error(` current artifact: ${result3.currentArtifactHash}`);
|
|
16517
|
+
console.error(` run: ${result3.next}`);
|
|
16518
|
+
}
|
|
16519
|
+
return 7;
|
|
16520
|
+
}
|
|
16521
|
+
const dryRun = {
|
|
16522
|
+
ok: true,
|
|
16523
|
+
dryRun: true,
|
|
16524
|
+
name: rootPlayName,
|
|
16525
|
+
sourcePath: graph.root.filePath,
|
|
16526
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
16527
|
+
artifactHash,
|
|
16528
|
+
graphHash: graph.root.artifact.graphHash,
|
|
16529
|
+
importedPlayCount: Math.max(0, graph.nodes.size - 1),
|
|
16530
|
+
plannedMutation: "register revision and promote it live",
|
|
16531
|
+
expectedArtifactHash: options.expectedArtifactHash ?? null
|
|
16532
|
+
};
|
|
16533
|
+
if (options.dryRun) {
|
|
16534
|
+
if (options.jsonOutput) {
|
|
16535
|
+
process.stdout.write(`${JSON.stringify(dryRun)}
|
|
16536
|
+
`);
|
|
16537
|
+
} else {
|
|
16538
|
+
console.log(`Dry run: ${rootPlayName}`);
|
|
16539
|
+
console.log(` source: ${dryRun.sourceHash}`);
|
|
16540
|
+
console.log(` artifact: ${dryRun.artifactHash}`);
|
|
16541
|
+
console.log(` would: ${dryRun.plannedMutation}`);
|
|
16542
|
+
}
|
|
16543
|
+
return 0;
|
|
16544
|
+
}
|
|
16545
|
+
let previousLive = null;
|
|
16546
|
+
try {
|
|
16547
|
+
previousLive = (await client2.getPlay(rootPlayName)).play.liveRevision ?? null;
|
|
16548
|
+
} catch (error) {
|
|
16549
|
+
if (!(error instanceof DeeplineError) || error.statusCode !== 404) {
|
|
16550
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16551
|
+
return 5;
|
|
16552
|
+
}
|
|
16553
|
+
}
|
|
16554
|
+
try {
|
|
16426
16555
|
await traceCliSpan(
|
|
16427
16556
|
"cli.play_publish_compile_manifests",
|
|
16428
16557
|
{ targetKind: "file", nodeCount: graph.nodes.size },
|
|
@@ -16437,13 +16566,12 @@ async function handlePlayPublish(args) {
|
|
|
16437
16566
|
console.error(error instanceof Error ? error.message : String(error));
|
|
16438
16567
|
return 1;
|
|
16439
16568
|
}
|
|
16440
|
-
const rootPlayName = graph.root.playName ?? extractPlayName(graph.root.sourceCode, graph.root.filePath);
|
|
16441
16569
|
const published = await traceCliSpan(
|
|
16442
16570
|
"cli.play_publish_register_root",
|
|
16443
16571
|
{
|
|
16444
16572
|
targetKind: "file",
|
|
16445
16573
|
playName: rootPlayName,
|
|
16446
|
-
artifactHash
|
|
16574
|
+
artifactHash
|
|
16447
16575
|
},
|
|
16448
16576
|
() => client2.registerPlayArtifact({
|
|
16449
16577
|
name: rootPlayName,
|
|
@@ -16455,17 +16583,63 @@ async function handlePlayPublish(args) {
|
|
|
16455
16583
|
publish: true
|
|
16456
16584
|
})
|
|
16457
16585
|
);
|
|
16458
|
-
|
|
16459
|
-
|
|
16460
|
-
|
|
16461
|
-
|
|
16462
|
-
|
|
16463
|
-
|
|
16464
|
-
|
|
16465
|
-
|
|
16466
|
-
|
|
16467
|
-
|
|
16468
|
-
|
|
16586
|
+
const result2 = {
|
|
16587
|
+
success: true,
|
|
16588
|
+
name: rootPlayName,
|
|
16589
|
+
sourcePath: graph.root.filePath,
|
|
16590
|
+
sourceHash: graph.root.artifact.sourceHash,
|
|
16591
|
+
artifactHash,
|
|
16592
|
+
liveVersion: published.version ?? null,
|
|
16593
|
+
revisionId: published.revisionId ?? null,
|
|
16594
|
+
previousLiveVersion: previousLive?.version ?? null,
|
|
16595
|
+
previousArtifactHash: previousLive?.artifactHash ?? null,
|
|
16596
|
+
sourceBytes: {
|
|
16597
|
+
before: previousLive?.sourceCode ? Buffer.byteLength(previousLive.sourceCode, "utf8") : null,
|
|
16598
|
+
after: Buffer.byteLength(graph.root.sourceCode, "utf8")
|
|
16599
|
+
},
|
|
16600
|
+
triggerMetadata: published.triggerMetadata ?? null,
|
|
16601
|
+
triggerBindings: published.triggerBindings ?? []
|
|
16602
|
+
};
|
|
16603
|
+
if (options.jsonOutput) {
|
|
16604
|
+
process.stdout.write(`${JSON.stringify(result2)}
|
|
16605
|
+
`);
|
|
16606
|
+
} else {
|
|
16607
|
+
console.log(
|
|
16608
|
+
`\u2713 Published ${rootPlayName} as v${result2.liveVersion ?? "?"}`
|
|
16609
|
+
);
|
|
16610
|
+
console.log(` source: ${result2.sourceHash.slice(0, 12)}`);
|
|
16611
|
+
console.log(` artifact: ${result2.artifactHash.slice(0, 12)}`);
|
|
16612
|
+
if (result2.previousLiveVersion !== null) {
|
|
16613
|
+
console.log(
|
|
16614
|
+
` previous live: v${result2.previousLiveVersion} (${result2.previousArtifactHash?.slice(0, 12) ?? "unknown artifact"})`
|
|
16615
|
+
);
|
|
16616
|
+
}
|
|
16617
|
+
if (result2.sourceBytes.before !== null) {
|
|
16618
|
+
console.log(
|
|
16619
|
+
` source bytes: ${result2.sourceBytes.before.toLocaleString()} \u2192 ${result2.sourceBytes.after.toLocaleString()}`
|
|
16620
|
+
);
|
|
16621
|
+
}
|
|
16622
|
+
console.log(
|
|
16623
|
+
` revisions: deepline plays versions --name ${rootPlayName}`
|
|
16624
|
+
);
|
|
16625
|
+
}
|
|
16626
|
+
return 0;
|
|
16627
|
+
}
|
|
16628
|
+
if (options.expectedArtifactHash) {
|
|
16629
|
+
console.error("--expected-artifact only applies to a local play file.");
|
|
16630
|
+
return 2;
|
|
16631
|
+
}
|
|
16632
|
+
if (options.dryRun) {
|
|
16633
|
+
const result2 = {
|
|
16634
|
+
ok: true,
|
|
16635
|
+
dryRun: true,
|
|
16636
|
+
name: playName,
|
|
16637
|
+
plannedMutation: "promote a saved revision live",
|
|
16638
|
+
revisionId: revisionId ?? null,
|
|
16639
|
+
latest: useLatest
|
|
16640
|
+
};
|
|
16641
|
+
process.stdout.write(`${JSON.stringify(result2)}
|
|
16642
|
+
`);
|
|
16469
16643
|
return 0;
|
|
16470
16644
|
}
|
|
16471
16645
|
const resolvedName = parseReferencedPlayTarget2(playName).playName;
|
|
@@ -16829,7 +17003,9 @@ Notes:
|
|
|
16829
17003
|
Mutates cloud state. For a saved play, --latest or --revision-id promotes an
|
|
16830
17004
|
existing saved revision live.
|
|
16831
17005
|
Local .play.ts publishing bundles the file, validates it, saves a revision,
|
|
16832
|
-
and promotes that revision live.
|
|
17006
|
+
and promotes that revision live. Use --expected-artifact with the hash from
|
|
17007
|
+
plays check to refuse publishing bytes that changed after validation.
|
|
17008
|
+
--dry-run bundles only and prints the exact artifact that would be published.
|
|
16833
17009
|
Running a local file with plays run does not publish it.
|
|
16834
17010
|
|
|
16835
17011
|
Examples:
|
|
@@ -16837,27 +17013,40 @@ Examples:
|
|
|
16837
17013
|
deepline plays set-live my-play --revision-id <revision-id> --json
|
|
16838
17014
|
deepline plays set-live my.play.ts --json
|
|
16839
17015
|
deepline plays publish my.play.ts --json
|
|
17016
|
+
deepline plays check my.play.ts
|
|
17017
|
+
deepline plays publish my.play.ts --expected-artifact <artifact-hash>
|
|
17018
|
+
deepline plays publish my.play.ts --dry-run --json
|
|
16840
17019
|
`
|
|
16841
17020
|
);
|
|
16842
17021
|
addPublishHelp(
|
|
16843
17022
|
play.command("publish <target>").description(
|
|
16844
17023
|
"Promote a saved play revision or publish a local play file."
|
|
16845
17024
|
)
|
|
16846
|
-
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17025
|
+
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17026
|
+
"--expected-artifact <hash>",
|
|
17027
|
+
"Require the local file to produce this checked artifact hash"
|
|
17028
|
+
).option("--dry-run", "Bundle and show the planned publish without mutation").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
16847
17029
|
process.exitCode = await handlePlayPublish([
|
|
16848
17030
|
target,
|
|
16849
17031
|
...options.latest ? ["--latest"] : [],
|
|
16850
17032
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
17033
|
+
...options.expectedArtifact ? ["--expected-artifact", options.expectedArtifact] : [],
|
|
17034
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
16851
17035
|
...options.json ? ["--json"] : []
|
|
16852
17036
|
]);
|
|
16853
17037
|
});
|
|
16854
17038
|
addPublishHelp(
|
|
16855
17039
|
play.command("set-live <target>").description("Promote a saved revision or publish a local play file.")
|
|
16856
|
-
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17040
|
+
).option("--latest", "Promote the newest saved revision").option("--revision-id <id>", "Revision to promote").option(
|
|
17041
|
+
"--expected-artifact <hash>",
|
|
17042
|
+
"Require the local file to produce this checked artifact hash"
|
|
17043
|
+
).option("--dry-run", "Bundle and show the planned publish without mutation").option("--json", "Emit JSON output. Also automatic when stdout is piped").action(async (target, options) => {
|
|
16857
17044
|
process.exitCode = await handlePlayPublish([
|
|
16858
17045
|
target,
|
|
16859
17046
|
...options.latest ? ["--latest"] : [],
|
|
16860
17047
|
...options.revisionId ? ["--revision-id", options.revisionId] : [],
|
|
17048
|
+
...options.expectedArtifact ? ["--expected-artifact", options.expectedArtifact] : [],
|
|
17049
|
+
...options.dryRun ? ["--dry-run"] : [],
|
|
16861
17050
|
...options.json ? ["--json"] : []
|
|
16862
17051
|
]);
|
|
16863
17052
|
});
|
|
@@ -28997,7 +29186,7 @@ async function maybeAutoUpdateAndRelaunch(response) {
|
|
|
28997
29186
|
if (plan.kind === "source") {
|
|
28998
29187
|
return false;
|
|
28999
29188
|
}
|
|
29000
|
-
const label = autoUpdate.reason === "rollback_forced" ? "has a server rollback pending and needs the latest rollback-aware CLI" : autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
29189
|
+
const label = autoUpdate.reason === "rollback_forced" ? "has a server rollback pending and needs the latest rollback-aware CLI" : autoUpdate.reason === "deprecated" ? "is deprecated and will update automatically" : autoUpdate.required ? "requires an update" : "is more than the supported auto-update lag behind";
|
|
29001
29190
|
process.stderr.write(
|
|
29002
29191
|
`Deepline SDK/CLI ${label}; running ${plan.manualCommand}
|
|
29003
29192
|
`
|
package/dist/index.d.mts
CHANGED
|
@@ -945,6 +945,27 @@ interface PlayCheckResult {
|
|
|
945
945
|
summary?: string;
|
|
946
946
|
artifactHash?: string | null;
|
|
947
947
|
graphHash?: string | null;
|
|
948
|
+
/** SHA-256 of the exact source bytes checked by Deepline. */
|
|
949
|
+
sourceHash?: string | null;
|
|
950
|
+
/** Enforceable byte budgets measured during cloud preflight. */
|
|
951
|
+
limits?: {
|
|
952
|
+
revisionStorage: {
|
|
953
|
+
usedBytes: number;
|
|
954
|
+
limitBytes: number;
|
|
955
|
+
withinLimit: boolean;
|
|
956
|
+
breakdown: {
|
|
957
|
+
sourceCodeBytes: number;
|
|
958
|
+
staticPipelineBytes: number;
|
|
959
|
+
bindingsBytes: number;
|
|
960
|
+
descriptionBytes: number;
|
|
961
|
+
};
|
|
962
|
+
};
|
|
963
|
+
bundle: {
|
|
964
|
+
usedBytes: number;
|
|
965
|
+
limitBytes: number;
|
|
966
|
+
withinLimit: boolean;
|
|
967
|
+
};
|
|
968
|
+
};
|
|
948
969
|
}
|
|
949
970
|
/** Severity of a {@link PlayCheckIssue}. `error` fails the check; `warning` does not. */
|
|
950
971
|
type PlayCheckIssueSeverity = 'error' | 'warning';
|
package/dist/index.d.ts
CHANGED
|
@@ -945,6 +945,27 @@ interface PlayCheckResult {
|
|
|
945
945
|
summary?: string;
|
|
946
946
|
artifactHash?: string | null;
|
|
947
947
|
graphHash?: string | null;
|
|
948
|
+
/** SHA-256 of the exact source bytes checked by Deepline. */
|
|
949
|
+
sourceHash?: string | null;
|
|
950
|
+
/** Enforceable byte budgets measured during cloud preflight. */
|
|
951
|
+
limits?: {
|
|
952
|
+
revisionStorage: {
|
|
953
|
+
usedBytes: number;
|
|
954
|
+
limitBytes: number;
|
|
955
|
+
withinLimit: boolean;
|
|
956
|
+
breakdown: {
|
|
957
|
+
sourceCodeBytes: number;
|
|
958
|
+
staticPipelineBytes: number;
|
|
959
|
+
bindingsBytes: number;
|
|
960
|
+
descriptionBytes: number;
|
|
961
|
+
};
|
|
962
|
+
};
|
|
963
|
+
bundle: {
|
|
964
|
+
usedBytes: number;
|
|
965
|
+
limitBytes: number;
|
|
966
|
+
withinLimit: boolean;
|
|
967
|
+
};
|
|
968
|
+
};
|
|
948
969
|
}
|
|
949
970
|
/** Severity of a {@link PlayCheckIssue}. `error` fails the check; `warning` does not. */
|
|
950
971
|
type PlayCheckIssueSeverity = 'error' | 'warning';
|
package/dist/index.js
CHANGED
|
@@ -422,12 +422,14 @@ var SDK_RELEASE = {
|
|
|
422
422
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
423
423
|
// fields shipped in 0.1.153.
|
|
424
424
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
425
|
-
|
|
425
|
+
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
426
|
+
// automatically without blocking their current command.
|
|
427
|
+
version: "0.1.221",
|
|
426
428
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
427
429
|
supportPolicy: {
|
|
428
|
-
latest: "0.1.
|
|
430
|
+
latest: "0.1.221",
|
|
429
431
|
minimumSupported: "0.1.53",
|
|
430
|
-
deprecatedBelow: "0.1.
|
|
432
|
+
deprecatedBelow: "0.1.219",
|
|
431
433
|
commandMinimumSupported: [
|
|
432
434
|
{
|
|
433
435
|
command: "enrich",
|
|
@@ -1163,7 +1165,7 @@ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
|
|
|
1163
1165
|
var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
|
|
1164
1166
|
var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
1165
1167
|
var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
|
|
1166
|
-
var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]
|
|
1168
|
+
var COMMON_SECRET_RE = /\b(?:(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9_./+=:-]{12,}|(?:pat|ghp|github_pat)_[A-Za-z0-9_./+=:-]{12,}|xox[baprs]-[A-Za-z0-9_./+=:-]{12,})\b/gi;
|
|
1167
1169
|
var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
|
|
1168
1170
|
var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
|
|
1169
1171
|
var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
|
package/dist/index.mjs
CHANGED
|
@@ -352,12 +352,14 @@ var SDK_RELEASE = {
|
|
|
352
352
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
353
353
|
// fields shipped in 0.1.153.
|
|
354
354
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
355
|
-
|
|
355
|
+
// 0.1.220 deprecates SDK CLI versions below 0.1.219 and updates them
|
|
356
|
+
// automatically without blocking their current command.
|
|
357
|
+
version: "0.1.221",
|
|
356
358
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
357
359
|
supportPolicy: {
|
|
358
|
-
latest: "0.1.
|
|
360
|
+
latest: "0.1.221",
|
|
359
361
|
minimumSupported: "0.1.53",
|
|
360
|
-
deprecatedBelow: "0.1.
|
|
362
|
+
deprecatedBelow: "0.1.219",
|
|
361
363
|
commandMinimumSupported: [
|
|
362
364
|
{
|
|
363
365
|
command: "enrich",
|
|
@@ -1093,7 +1095,7 @@ var SECRET_REDACTION_PLACEHOLDER = "[REDACTED_SECRET]";
|
|
|
1093
1095
|
var BEARER_TOKEN_RE = /\bBearer\s+[A-Za-z0-9._~+/=-]{12,}\b/g;
|
|
1094
1096
|
var JWT_RE = /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g;
|
|
1095
1097
|
var PRIVATE_KEY_RE = /-----BEGIN [A-Z0-9 ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z0-9 ]*PRIVATE KEY-----/g;
|
|
1096
|
-
var COMMON_SECRET_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox[baprs]
|
|
1098
|
+
var COMMON_SECRET_RE = /\b(?:(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9_./+=:-]{12,}|(?:pat|ghp|github_pat)_[A-Za-z0-9_./+=:-]{12,}|xox[baprs]-[A-Za-z0-9_./+=:-]{12,})\b/gi;
|
|
1097
1099
|
var GENERIC_PREFIXED_SECRET_RE = /\b(?:key|token|secret|api[_-]?key)_[A-Za-z0-9_./+=:-]{12,}\b/gi;
|
|
1098
1100
|
var URL_SECRET_VALUE_RE = /\b(?:sk|pk|rk|pat|ghp|github_pat|xox)[A-Za-z0-9_./+=:-]{12,}\b/i;
|
|
1099
1101
|
var GENERIC_SECRET_ASSIGNMENT_RE = /\b(?:api[_-]?key|token|secret|password)\b\s*[:=]\s*["']?[^"',\s]{12,}["']?/gi;
|
package/dist/viewer/viewer.css
CHANGED
|
@@ -353,6 +353,17 @@ body {
|
|
|
353
353
|
border: 1px solid var(--red);
|
|
354
354
|
background: rgba(248,81,73,0.06);
|
|
355
355
|
}
|
|
356
|
+
.tool-detail-toggle {
|
|
357
|
+
margin-top: 8px;
|
|
358
|
+
background: var(--bg-tertiary);
|
|
359
|
+
border: 1px solid var(--border);
|
|
360
|
+
border-radius: 4px;
|
|
361
|
+
color: var(--blue);
|
|
362
|
+
cursor: pointer;
|
|
363
|
+
font-size: 12px;
|
|
364
|
+
padding: 4px 8px;
|
|
365
|
+
}
|
|
366
|
+
.tool-detail-toggle:hover { border-color: var(--blue); }
|
|
356
367
|
|
|
357
368
|
/* Result card */
|
|
358
369
|
.result-card {
|
package/dist/viewer/viewer.js
CHANGED
|
@@ -1334,7 +1334,7 @@ function renderTimeline(timeline) {
|
|
|
1334
1334
|
<div class="tool-detail" id="detail-${i}">
|
|
1335
1335
|
<div class="tool-detail-section">
|
|
1336
1336
|
<div class="label">Input</div>
|
|
1337
|
-
|
|
1337
|
+
${formatToolInputHtml(e.tool, e.input, i)}
|
|
1338
1338
|
</div>
|
|
1339
1339
|
${e.result_content != null ? `<div class="tool-detail-section">
|
|
1340
1340
|
<div class="label">Result</div>
|
|
@@ -1347,8 +1347,17 @@ function renderTimeline(timeline) {
|
|
|
1347
1347
|
return html;
|
|
1348
1348
|
}
|
|
1349
1349
|
|
|
1350
|
+
function isShellCommandTool(tool) {
|
|
1351
|
+
const normalized = String(tool || '').toLowerCase().replace(/[^a-z]/g, '');
|
|
1352
|
+
return ['bash', 'exec', 'execcommand', 'runcommand', 'shell'].includes(normalized);
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
function shellCommand(input) {
|
|
1356
|
+
return input.command || input.cmd || input.CommandLine || null;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1350
1359
|
function formatInput(tool, input) {
|
|
1351
|
-
if (tool
|
|
1360
|
+
if (isShellCommandTool(tool)) return shellCommand(input) || JSON.stringify(input, null, 2);
|
|
1352
1361
|
if (tool === 'Write') {
|
|
1353
1362
|
let s = 'file: ' + (input.file_path || input.path || '') + '\n\n';
|
|
1354
1363
|
if (input.content != null) s += '--- content ---\n' + String(input.content);
|
|
@@ -1364,6 +1373,39 @@ function formatInput(tool, input) {
|
|
|
1364
1373
|
return JSON.stringify(input, null, 2);
|
|
1365
1374
|
}
|
|
1366
1375
|
|
|
1376
|
+
function isLongShellCommand(command) {
|
|
1377
|
+
return command.length > 600 || command.split('\n').length > 10;
|
|
1378
|
+
}
|
|
1379
|
+
|
|
1380
|
+
function shellCommandPreview(command) {
|
|
1381
|
+
const lines = command.split('\n');
|
|
1382
|
+
let preview = lines.slice(0, 10).join('\n');
|
|
1383
|
+
if (preview.length > 600) preview = preview.slice(0, 600);
|
|
1384
|
+
return preview + '\n...[full command hidden]';
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
function formatToolInputHtml(tool, input, entryIndex) {
|
|
1388
|
+
const formatted = formatInput(tool, input);
|
|
1389
|
+
if (!isShellCommandTool(tool) || !isLongShellCommand(formatted)) {
|
|
1390
|
+
return `<pre>${esc(formatted)}</pre>`;
|
|
1391
|
+
}
|
|
1392
|
+
const previewId = `command-preview-${entryIndex}`;
|
|
1393
|
+
const fullId = `command-full-${entryIndex}`;
|
|
1394
|
+
return `<pre id="${previewId}">${esc(shellCommandPreview(formatted))}</pre>
|
|
1395
|
+
<button class="tool-detail-toggle" onclick="toggleCommandInput('${previewId}', '${fullId}', this)">Show full command</button>
|
|
1396
|
+
<pre id="${fullId}" hidden>${esc(formatted)}</pre>`;
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
function toggleCommandInput(previewId, fullId, toggle) {
|
|
1400
|
+
const preview = document.getElementById(previewId);
|
|
1401
|
+
const full = document.getElementById(fullId);
|
|
1402
|
+
if (!preview || !full) return;
|
|
1403
|
+
const showFull = full.hidden;
|
|
1404
|
+
full.hidden = !showFull;
|
|
1405
|
+
preview.hidden = showFull;
|
|
1406
|
+
toggle.textContent = showFull ? 'Show less' : 'Show full command';
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1367
1409
|
function toggleReasoning(id, toggle) {
|
|
1368
1410
|
const el = document.getElementById(id);
|
|
1369
1411
|
const collapsed = el.classList.toggle('collapsed');
|