deepline 0.3.476 → 0.3.478
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-core.ts +5 -4
- package/dist/bundling-sources/sdk/src/http-core.ts +84 -3
- package/dist/bundling-sources/sdk/src/http.ts +2 -0
- package/dist/bundling-sources/sdk/src/play.ts +8 -2
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -0
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +33 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +10 -2
- package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts +77 -1
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/governor/rate-state-backend.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +11 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +77 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +83 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/sandbox-compute-usage.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +215 -22
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +42 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +13 -12
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +5 -2
- package/dist/bundling-sources/shared_libs/plays/sandbox-runtime-limits.ts +37 -12
- package/dist/bundling-sources/shared_libs/product-notifications/billing-sales.ts +1 -0
- package/dist/bundling-sources/shared_libs/product-notifications/catalog.ts +29 -0
- package/dist/bundling-sources/shared_libs/product-notifications/events.ts +15 -0
- package/dist/cli/{auth-A22724UX.mjs → auth-SA4DJCSO.mjs} +5 -5
- package/dist/cli/auth-U5SNVC5F.js +41 -0
- package/dist/cli/{billing-T5Q6OO6M.js → billing-462SAHWX.js} +107 -87
- package/dist/cli/{billing-IIBEZ6J7.mjs → billing-Z4D35MV5.mjs} +34 -14
- package/dist/cli/{chunk-NPNQCPFP.mjs → chunk-2FTUPGTN.mjs} +2 -2
- package/dist/cli/{chunk-2WEPQSA2.mjs → chunk-2JS5DNVX.mjs} +5 -5
- package/dist/cli/{chunk-L45IECBZ.js → chunk-2MSKG4ER.js} +7 -6
- package/dist/cli/{chunk-JU2KBLOR.mjs → chunk-3LTLQAU4.mjs} +4 -4
- package/dist/cli/{chunk-ZV4OWYLZ.mjs → chunk-3V7INABZ.mjs} +2 -2
- package/dist/cli/{chunk-VPAVNEDQ.mjs → chunk-4C3TMIF3.mjs} +4 -4
- package/dist/cli/{chunk-H3GOAZHV.mjs → chunk-4RJRGQ5Y.mjs} +2 -2
- package/dist/cli/{chunk-AS3VECCY.js → chunk-4RV7U3RP.js} +7 -7
- package/dist/cli/{chunk-UHTJWDYB.mjs → chunk-645RNF2Y.mjs} +1 -1
- package/dist/cli/{chunk-TEJSRJNH.js → chunk-6EEMW7YP.js} +8 -8
- package/dist/cli/{chunk-ZOXV6WFI.mjs → chunk-75DAGCEX.mjs} +1 -1
- package/dist/cli/{chunk-NTJDZURV.mjs → chunk-7HTWT3Z4.mjs} +2 -2
- package/dist/cli/chunk-7I4B6V2S.mjs +127 -0
- package/dist/cli/{chunk-MZSLFWOT.js → chunk-7UFFWPQ2.js} +13 -9
- package/dist/cli/{chunk-5FBCMLJW.js → chunk-A5LPDB6N.js} +6 -6
- package/dist/cli/{chunk-4YWYLHED.mjs → chunk-ABBP5ZCI.mjs} +3 -3
- package/dist/cli/{chunk-IC3BZJR7.js → chunk-AQYSZYNE.js} +8 -8
- package/dist/cli/{chunk-WTPRRKZA.js → chunk-AYW242XF.js} +37 -37
- package/dist/cli/{chunk-CFSCHLNQ.mjs → chunk-BLAZVZVD.mjs} +23 -5
- package/dist/cli/{chunk-KGLIDLJ2.js → chunk-D2LKEQKI.js} +5 -5
- package/dist/cli/{chunk-4WMIMSSI.mjs → chunk-F2SJYUBW.mjs} +5 -5
- package/dist/cli/{chunk-KCP6XNRR.mjs → chunk-F44O4PEP.mjs} +1 -1
- package/dist/cli/{chunk-EBWYNNTJ.js → chunk-HMUBLAT4.js} +5 -5
- package/dist/cli/{chunk-UYA7LJGC.mjs → chunk-IL5AF6AR.mjs} +4 -2
- package/dist/cli/{chunk-B7PEXXRW.js → chunk-IWYWZXCA.js} +53 -53
- package/dist/cli/{chunk-PGNLD6L6.js → chunk-J3ZYRN5L.js} +10 -10
- package/dist/cli/{chunk-VKBZLV2K.mjs → chunk-JH775FF6.mjs} +1 -1
- package/dist/cli/{chunk-5AEEINTU.js → chunk-KBBZXWXF.js} +63 -11
- package/dist/cli/{chunk-FVPT44IJ.mjs → chunk-M5USVQ33.mjs} +55 -3
- package/dist/cli/{chunk-2YHDNHRR.mjs → chunk-N573OK4W.mjs} +4 -4
- package/dist/cli/{chunk-WFVEMDQL.js → chunk-OKAZHDYN.js} +4 -2
- package/dist/cli/{chunk-J4FCTFQS.mjs → chunk-PHBOI24Y.mjs} +10 -10
- package/dist/cli/{chunk-D7EQ4PI5.mjs → chunk-PLJV6SX4.mjs} +1 -1
- package/dist/cli/{chunk-YQOWMQEW.mjs → chunk-PPHHPAQV.mjs} +1 -1
- package/dist/cli/{chunk-CBVCCXIY.js → chunk-PZHRNSMU.js} +21 -21
- package/dist/cli/{chunk-LJFIUT5R.mjs → chunk-QB3Q73LP.mjs} +2 -2
- package/dist/cli/{chunk-ULKGYVYP.js → chunk-QVZNUQAP.js} +2 -2
- package/dist/cli/{chunk-A6BETJ2A.js → chunk-S3BKOCVB.js} +1 -1
- package/dist/cli/{chunk-F5PYBZ2H.mjs → chunk-S7UEKKOX.mjs} +2 -1
- package/dist/cli/{chunk-W3BHZUPL.js → chunk-SCHE5QRN.js} +3 -3
- package/dist/cli/{chunk-YEJDFZJP.js → chunk-SXY4DOVA.js} +16 -16
- package/dist/cli/{chunk-LZCYDU6Q.mjs → chunk-TLF3KGWG.mjs} +2 -2
- package/dist/cli/{chunk-5PYSYW63.js → chunk-TQWI7LJX.js} +26 -26
- package/dist/cli/{chunk-7HAUVMRF.js → chunk-TW3TTKW5.js} +3 -3
- package/dist/cli/{chunk-FK7SBMSZ.js → chunk-UXQVSDFP.js} +3 -3
- package/dist/cli/{chunk-HSANVBVL.js → chunk-V7I65ME7.js} +2 -2
- package/dist/cli/{chunk-6YZYCKWD.js → chunk-VE25VUTE.js} +70 -52
- package/dist/cli/{chunk-VLYUFZUT.js → chunk-XFY3JOP2.js} +9 -9
- package/dist/cli/{chunk-MYYOCJZ2.js → chunk-XOORR6P3.js} +93 -93
- package/dist/cli/chunk-YGCKMI5P.js +127 -0
- package/dist/cli/{chunk-3A7TDUZV.mjs → chunk-ZBSUXXZS.mjs} +13 -9
- package/dist/cli/{chunk-NREO7TT4.mjs → chunk-ZSU3C4ST.mjs} +2 -2
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-GPVCETS2.mjs → csv-3SNWBO5F.mjs} +4 -4
- package/dist/cli/{csv-FXOQ2PBE.js → csv-LAYTDYIF.js} +13 -13
- package/dist/cli/{db-F5UJTBGP.mjs → db-72JKGQSK.mjs} +6 -6
- package/dist/cli/{db-LXYV4GPZ.js → db-OOUOSURL.js} +27 -27
- package/dist/cli/describe-7HYV44MO.js +48 -0
- package/dist/cli/{describe-GYWCI7I6.mjs → describe-KDPNOEUJ.mjs} +17 -17
- package/dist/cli/describe-core.d.mts +3 -3
- package/dist/cli/describe-core.d.ts +3 -3
- package/dist/cli/{executions-6NL2YW76.mjs → executions-O6JS3UKX.mjs} +6 -6
- package/dist/cli/{executions-6SJKTY2L.js → executions-RJNMGJEE.js} +8 -8
- package/dist/cli/{feedback-E3HULSQD.js → feedback-FXB6NV3Y.js} +8 -8
- package/dist/cli/{feedback-7AMQCNTB.mjs → feedback-T3JH3CWC.mjs} +4 -4
- package/dist/cli/git-5LTKPXGN.js +25 -0
- package/dist/cli/{git-74IS2EFH.mjs → git-6KAQSH5J.mjs} +5 -5
- package/dist/cli/index.js +161 -142
- package/dist/cli/index.mjs +65 -46
- package/dist/cli/{legacy-noops-52FFRTRZ.mjs → legacy-noops-7HDGEGTK.mjs} +5 -5
- package/dist/cli/{legacy-noops-ALWUQPKS.js → legacy-noops-PAOGRKUK.js} +8 -8
- package/dist/cli/{monitors-Z4ADOGTY.js → monitors-KQFI7TVJ.js} +91 -91
- package/dist/cli/{monitors-VTJIWWW2.mjs → monitors-LE2AYK3Z.mjs} +7 -7
- package/dist/cli/{org-2BTEKDF5.js → org-J6XFHDJE.js} +72 -72
- package/dist/cli/{org-7GU6H7JL.mjs → org-Z4DMJ72I.mjs} +6 -6
- package/dist/cli/{pages-I6PFQGEU.mjs → pages-5LYS6Y4I.mjs} +6 -6
- package/dist/cli/{pages-MG36E7RY.js → pages-FIXBZQJG.js} +17 -17
- package/dist/cli/{play-VN52S3RV.js → play-D7WPXADH.js} +604 -680
- package/dist/cli/{play-7KFSLJX2.mjs → play-GILXXIN7.mjs} +45 -121
- package/dist/cli/{providers-W5XLII66.js → providers-KN7YACT6.js} +9 -9
- package/dist/cli/{providers-D46JDEL2.mjs → providers-OQWL4Q4W.mjs} +6 -6
- package/dist/cli/{quickstart-4GTXBZHY.mjs → quickstart-2LRIORFM.mjs} +4 -4
- package/dist/cli/{quickstart-TIZAC63S.js → quickstart-M2OBP3W3.js} +6 -6
- package/dist/cli/{run-FOVEMYYX.js → run-6YZZO7VM.js} +36 -36
- package/dist/cli/{run-LE3D4LVU.mjs → run-GYRBKQZT.mjs} +22 -22
- package/dist/cli/search-OVKWA4AV.js +32 -0
- package/dist/cli/{search-6YL6WJMQ.mjs → search-VUPK6BNU.mjs} +7 -7
- package/dist/cli/{secrets-CSTTTMZH.js → secrets-RE3UMZB7.js} +15 -15
- package/dist/cli/{secrets-D66U6RTT.mjs → secrets-ULRGU7NM.mjs} +6 -6
- package/dist/cli/{sessions-XIO3OUER.mjs → sessions-2ZZVJ3P2.mjs} +5 -5
- package/dist/cli/{sessions-45M2NRAA.js → sessions-T4UMHNDW.js} +6 -6
- package/dist/cli/{settings-N42CVKSK.js → settings-BRV6AYFM.js} +78 -78
- package/dist/cli/{settings-R33X2D5T.mjs → settings-PDY4TJU6.mjs} +11 -11
- package/dist/cli/{setup-CBBC4FQP.mjs → setup-CXL6C5Z5.mjs} +9 -9
- package/dist/cli/{setup-HREDVNF2.js → setup-JONYJYBK.js} +44 -44
- package/dist/cli/{skills-4X6WS2PT.mjs → skills-TOMVQD5O.mjs} +7 -7
- package/dist/cli/skills-UK5AK35I.js +33 -0
- package/dist/cli/{tools-YR46YFR2.mjs → tools-B2LJK4MM.mjs} +16 -16
- package/dist/cli/tools-HH6E5G7J.js +55 -0
- package/dist/cli/{update-5CYAZX5X.mjs → update-CD6T2REC.mjs} +9 -9
- package/dist/cli/update-EGXT3EIJ.js +33 -0
- package/dist/cli/{workflow-M7AA722W.js → workflow-PZML43E2.js} +17 -17
- package/dist/cli/{workflow-NKQ3CWPK.mjs → workflow-ZAOBP6I7.mjs} +7 -7
- package/dist/{client-AjmfA5nR.d.mts → client-B1s1yJdT.d.mts} +1 -1
- package/dist/{client-DMyY-QL8.d.ts → client-DqUseRzd.d.ts} +1 -1
- package/dist/{client-core-C705vFyV.d.ts → client-core-Bd7tP9Uz.d.ts} +45 -6
- package/dist/{client-core-CpBbvLEX.d.mts → client-core-BijQEQ70.d.mts} +45 -6
- package/dist/{compiler-manifest-hqIAukR0.d.mts → compiler-manifest-B1m5tRzz.d.mts} +23 -17
- package/dist/{compiler-manifest-hqIAukR0.d.ts → compiler-manifest-B1m5tRzz.d.ts} +23 -17
- package/dist/{errors-CRO2qQ6k.d.ts → errors-3g71OMXy.d.ts} +1 -1
- package/dist/{errors-DIHVetNY.d.mts → errors-QiC6am-q.d.mts} +1 -1
- package/dist/{index-DVZ_X4Gb.d.mts → index-Biz5toO4.d.mts} +1 -1
- package/dist/{index-B8DVoeYt.d.ts → index-CIBiwzhK.d.ts} +1 -1
- package/dist/index.d.mts +15 -9
- package/dist/index.d.ts +15 -9
- package/dist/index.js +9 -9
- package/dist/index.mjs +6 -6
- package/dist/install-integrity.json +112 -110
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +2 -1
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/dist/server.d.mts +4 -4
- package/dist/server.d.ts +4 -4
- package/dist/server.js +5 -5
- package/dist/server.mjs +3 -3
- package/package.json +1 -1
- package/dist/cli/auth-2ZY57Q7W.js +0 -41
- package/dist/cli/describe-IB7SUIUT.js +0 -48
- package/dist/cli/git-A2QIIMW5.js +0 -25
- package/dist/cli/search-HN6SVDQU.js +0 -32
- package/dist/cli/skills-QZ6HZX2T.js +0 -33
- package/dist/cli/tools-KFIH7UWB.js +0 -55
- package/dist/cli/update-VZLEJLWJ.js +0 -33
|
@@ -12,6 +12,7 @@ import type {
|
|
|
12
12
|
PlaySettingsPatch,
|
|
13
13
|
PlaySettingsPathsPage,
|
|
14
14
|
} from '../../shared_libs/plays/settings-contract';
|
|
15
|
+
import type { PlaySandboxRuntimeDeclaration } from '../../shared_libs/plays/sandbox-runtime-limits';
|
|
15
16
|
import type {
|
|
16
17
|
PlayTriggerConfigUpdate,
|
|
17
18
|
PlayTriggerConfigUpdateResult,
|
|
@@ -2419,6 +2420,8 @@ export type BillingRecentUsageEntry = {
|
|
|
2419
2420
|
export type BillingUsageOptions = {
|
|
2420
2421
|
/** Return the one exact call identified by `executeTool().job_id`. */
|
|
2421
2422
|
requestId?: string;
|
|
2423
|
+
/** Return only the workspace identity and recent activity page. */
|
|
2424
|
+
recentOnly?: boolean;
|
|
2422
2425
|
/** Bound the recent-call page. Ignored for an exact requestId lookup. */
|
|
2423
2426
|
limit?: number;
|
|
2424
2427
|
offset?: number;
|
|
@@ -2555,10 +2558,7 @@ export type BillingNamespace = {
|
|
|
2555
2558
|
|
|
2556
2559
|
export type BillingQuoteRequest = {
|
|
2557
2560
|
quantity: number;
|
|
2558
|
-
sandbox_runtime:
|
|
2559
|
-
timeout?: string;
|
|
2560
|
-
size?: 'standard' | 'large' | 'xlarge';
|
|
2561
|
-
};
|
|
2561
|
+
sandbox_runtime: PlaySandboxRuntimeDeclaration;
|
|
2562
2562
|
};
|
|
2563
2563
|
|
|
2564
2564
|
export type BillingQuoteResult = {
|
|
@@ -6466,6 +6466,7 @@ export class DeeplineClient {
|
|
|
6466
6466
|
}
|
|
6467
6467
|
params.set('request_id', requestId);
|
|
6468
6468
|
} else {
|
|
6469
|
+
if (options.recentOnly) params.set('recent_only', 'true');
|
|
6469
6470
|
if (options.limit !== undefined) {
|
|
6470
6471
|
params.set('recent_limit', String(options.limit));
|
|
6471
6472
|
}
|
|
@@ -218,14 +218,95 @@ function mapNetworkError(
|
|
|
218
218
|
code: 'NETWORK_ABORTED',
|
|
219
219
|
};
|
|
220
220
|
}
|
|
221
|
+
const causeCode = networkCauseCode(error);
|
|
221
222
|
return {
|
|
222
|
-
message: error
|
|
223
|
-
? `Unable to connect to ${baseUrl}. ${error.message}`
|
|
224
|
-
: `Unable to connect to ${baseUrl}. Is the computer able to access the url?`,
|
|
223
|
+
message: connectionFailureMessage(baseUrl, error),
|
|
225
224
|
code: 'NETWORK_ERROR',
|
|
225
|
+
...(causeCode ? { details: { causeCode } } : {}),
|
|
226
226
|
};
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
const BLOCKED_EGRESS_CAUSE_CODES = new Set([
|
|
230
|
+
'EPERM',
|
|
231
|
+
'EACCES',
|
|
232
|
+
'ENOTFOUND',
|
|
233
|
+
'EAI_AGAIN',
|
|
234
|
+
'ENETUNREACH',
|
|
235
|
+
'EHOSTUNREACH',
|
|
236
|
+
'ETIMEDOUT',
|
|
237
|
+
'UND_ERR_CONNECT_TIMEOUT',
|
|
238
|
+
]);
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* The first system error code in a transport failure's cause chain. Node's
|
|
242
|
+
* fetch reports only "fetch failed"; the reason (ENOTFOUND, ECONNREFUSED,
|
|
243
|
+
* EPERM, ...) is on `cause`, or on `errors` when every address was tried.
|
|
244
|
+
*/
|
|
245
|
+
export function networkCauseCode(error: unknown): string | undefined {
|
|
246
|
+
const seen = new Set<unknown>();
|
|
247
|
+
const queue: unknown[] = [error];
|
|
248
|
+
while (queue.length > 0) {
|
|
249
|
+
const current = queue.shift();
|
|
250
|
+
if (!current || typeof current !== 'object' || seen.has(current)) continue;
|
|
251
|
+
seen.add(current);
|
|
252
|
+
const record = current as Record<string, unknown>;
|
|
253
|
+
if (
|
|
254
|
+
typeof record.code === 'string' &&
|
|
255
|
+
/^[A-Z][A-Z0-9_]+$/.test(record.code)
|
|
256
|
+
)
|
|
257
|
+
return record.code;
|
|
258
|
+
queue.push(record.cause);
|
|
259
|
+
if (Array.isArray(record.errors)) queue.push(...record.errors);
|
|
260
|
+
}
|
|
261
|
+
return undefined;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
function isLoopbackHost(hostname: string): boolean {
|
|
265
|
+
return (
|
|
266
|
+
hostname === 'localhost' ||
|
|
267
|
+
hostname === '[::1]' ||
|
|
268
|
+
hostname.startsWith('127.') ||
|
|
269
|
+
hostname.endsWith('.localhost')
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* One line naming the host, the transport error, its underlying cause code,
|
|
275
|
+
* and — when the cause is how blocked egress presents — what to check.
|
|
276
|
+
*/
|
|
277
|
+
export function connectionFailureMessage(
|
|
278
|
+
baseUrl: string,
|
|
279
|
+
error: Error | null,
|
|
280
|
+
): string {
|
|
281
|
+
if (!error?.message) {
|
|
282
|
+
return `Unable to connect to ${baseUrl}. Is the computer able to access the url?`;
|
|
283
|
+
}
|
|
284
|
+
const causeCode = networkCauseCode(error);
|
|
285
|
+
let hostname = '';
|
|
286
|
+
try {
|
|
287
|
+
hostname = new URL(baseUrl).hostname;
|
|
288
|
+
} catch {
|
|
289
|
+
// An unparseable base URL still reports the transport failure.
|
|
290
|
+
}
|
|
291
|
+
const blocked =
|
|
292
|
+
hostname !== '' &&
|
|
293
|
+
!isLoopbackHost(hostname) &&
|
|
294
|
+
causeCode !== undefined &&
|
|
295
|
+
(BLOCKED_EGRESS_CAUSE_CODES.has(causeCode) || causeCode === 'ECONNREFUSED');
|
|
296
|
+
// Without a code, the cause's own message is still more than "fetch failed".
|
|
297
|
+
const causeMessage =
|
|
298
|
+
error.cause instanceof Error ? error.cause.message.slice(0, 200) : '';
|
|
299
|
+
const cause = causeCode ?? causeMessage;
|
|
300
|
+
return [
|
|
301
|
+
`Unable to connect to ${baseUrl}. ${error.message}${cause && !error.message.includes(cause) ? ` (${cause})` : ''}.`,
|
|
302
|
+
...(blocked
|
|
303
|
+
? [
|
|
304
|
+
`A sandbox, firewall, or proxy may be blocking ${hostname}; allow outbound HTTPS to it and retry.`,
|
|
305
|
+
]
|
|
306
|
+
: []),
|
|
307
|
+
].join(' ');
|
|
308
|
+
}
|
|
309
|
+
|
|
229
310
|
function describeRequestTarget(path: string): string {
|
|
230
311
|
const toolExecuteMatch = path.match(
|
|
231
312
|
/^\/api\/v2\/integrations\/([^/?#]+)\/execute(?:[/?#]|$)/,
|
|
@@ -3,6 +3,8 @@ import { HttpClient as HttpClientCore } from './http-core';
|
|
|
3
3
|
import { readSdkSkillsLocalVersion } from './skills-version';
|
|
4
4
|
import type { ResolvedConfig } from './types';
|
|
5
5
|
|
|
6
|
+
export { connectionFailureMessage, networkCauseCode } from './http-core';
|
|
7
|
+
|
|
6
8
|
export class HttpClient extends HttpClientCore {
|
|
7
9
|
constructor(config: ResolvedConfig) {
|
|
8
10
|
super(config, readSdkSkillsLocalVersion);
|
|
@@ -185,8 +185,14 @@ export type PlayFetchResponse = PlayAuthoringFetchResponse;
|
|
|
185
185
|
* The changed row is delivered as the listener event's `after` in the play function's input.
|
|
186
186
|
*
|
|
187
187
|
* The default Play runtime is 30 minutes with the `standard` 1 GiB / 1 CPU
|
|
188
|
-
* profile.
|
|
189
|
-
*
|
|
188
|
+
* profile. Set `runtime.size` to `standard` or `1gb` (1 GiB / 1 CPU),
|
|
189
|
+
* `large` or `4gb` (4 GiB / 2 CPU), or `xlarge` or `8gb` (8 GiB / 4 CPU).
|
|
190
|
+
* Each alias selects the same resource profile and compute price.
|
|
191
|
+
*
|
|
192
|
+
* ```ts
|
|
193
|
+
* export const config = { runtime: { size: '4gb' } };
|
|
194
|
+
* ```
|
|
195
|
+
*
|
|
190
196
|
* Compute pricing follows the workspace plan; use `deepline billing quote`
|
|
191
197
|
* for the session ceiling.
|
|
192
198
|
* Set `runtime.timeout` for longer bounded runs; duration values are whole
|
|
@@ -205,7 +205,7 @@ export const SDK_RELEASE = {
|
|
|
205
205
|
// getters keep their established compatibility behavior.
|
|
206
206
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
207
207
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
208
|
-
version: '0.3.
|
|
208
|
+
version: '0.3.478',
|
|
209
209
|
updateSummary: {
|
|
210
210
|
introducedIn: '0.3.90',
|
|
211
211
|
summary:
|
|
@@ -255,6 +255,24 @@
|
|
|
255
255
|
"failureAlert": "github_workflow_run",
|
|
256
256
|
"domainReportRequired": true
|
|
257
257
|
},
|
|
258
|
+
{
|
|
259
|
+
"id": "github.prebuilt-benchmarks",
|
|
260
|
+
"name": "Prebuilt benchmarks",
|
|
261
|
+
"scheduler": "github_actions",
|
|
262
|
+
"cadence": "0 14 * * 1",
|
|
263
|
+
"timezone": "UTC",
|
|
264
|
+
"source": ".github/workflows/prebuilt-benchmarks.yml",
|
|
265
|
+
"locator": "schedule:",
|
|
266
|
+
"owner": "evals",
|
|
267
|
+
"criticality": "reporting",
|
|
268
|
+
"purpose": "Run each prebuilt play on its fixed labeled sample in a disposable Production workspace with the published CLI and publish found, exact, recall, precision and settled credits.",
|
|
269
|
+
"successDefinition": "Every benchmark exports its rows, scores them, settles within its credit cap, and the summary uploads; the disposable workspace is deleted.",
|
|
270
|
+
"failureDefinition": "Workspace bootstrap, dataset load, a play run, export, scoring, a credit-cap overrun, or workspace deletion fails.",
|
|
271
|
+
"startGraceMs": 600000,
|
|
272
|
+
"runTimeoutMs": 7200000,
|
|
273
|
+
"failureAlert": "github_workflow_run",
|
|
274
|
+
"domainReportRequired": true
|
|
275
|
+
},
|
|
258
276
|
{
|
|
259
277
|
"id": "github.fly-pr-preview-cleanup",
|
|
260
278
|
"name": "Reconcile Fly PR Preview Capacity",
|
|
@@ -2281,6 +2281,39 @@ export async function releaseRateStateViaAppRuntime(
|
|
|
2281
2281
|
});
|
|
2282
2282
|
}
|
|
2283
2283
|
|
|
2284
|
+
/** Persist the final success batch without acquiring another provider permit. */
|
|
2285
|
+
export async function flushRateStateFeedbackViaAppRuntime(
|
|
2286
|
+
context: WorkerRuntimeApiContext,
|
|
2287
|
+
input: PlayRunnerRateStateReleaseInput,
|
|
2288
|
+
signal: AbortSignal,
|
|
2289
|
+
): Promise<void> {
|
|
2290
|
+
const batch = input.concurrencyObservationBatch;
|
|
2291
|
+
if (!batch)
|
|
2292
|
+
throw new Error('Rate-state feedback is missing its batch identity.');
|
|
2293
|
+
const result = await postAppRuntimeApi<{
|
|
2294
|
+
acknowledgedObservationBatch?: typeof batch;
|
|
2295
|
+
}>(
|
|
2296
|
+
{
|
|
2297
|
+
...context,
|
|
2298
|
+
connectionRetryBudgetMs: 0,
|
|
2299
|
+
signal: context.signal
|
|
2300
|
+
? AbortSignal.any([context.signal, signal])
|
|
2301
|
+
: signal,
|
|
2302
|
+
},
|
|
2303
|
+
{ action: 'rate_state_release', ...input },
|
|
2304
|
+
);
|
|
2305
|
+
const acknowledged = result.acknowledgedObservationBatch;
|
|
2306
|
+
if (
|
|
2307
|
+
acknowledged?.observerId !== batch.observerId ||
|
|
2308
|
+
acknowledged.laneId !== batch.laneId ||
|
|
2309
|
+
acknowledged.sequence !== batch.sequence
|
|
2310
|
+
) {
|
|
2311
|
+
throw new Error(
|
|
2312
|
+
'Rate-state receiver did not acknowledge the success batch.',
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2284
2317
|
export async function penalizeRateStateViaAppRuntime(
|
|
2285
2318
|
context: WorkerRuntimeApiContext,
|
|
2286
2319
|
input: PlayRunnerRateStatePenalizeInput,
|
|
@@ -19656,11 +19656,19 @@ export class PlayContextImpl implements ScalarPlayAuthoringRuntimeContext {
|
|
|
19656
19656
|
statusCode: 504,
|
|
19657
19657
|
},
|
|
19658
19658
|
));
|
|
19659
|
+
// The gateway admits a recovery key only under the executor token's
|
|
19660
|
+
// run, which is the root run even inside an inline child. Root runs
|
|
19661
|
+
// keep their original key (executor run == logical run); an inline
|
|
19662
|
+
// child keeps its own logical identity inside the invocation key.
|
|
19663
|
+
const asyncRecoveryScope = this.currentExecutionScope;
|
|
19659
19664
|
const asyncRecoveryKey = (attempt: number) =>
|
|
19660
19665
|
asyncRecoveryInvocationKey
|
|
19661
19666
|
? buildRuntimeExecutionRecoveryKey({
|
|
19662
|
-
parentRunId:
|
|
19663
|
-
invocationKey:
|
|
19667
|
+
parentRunId: asyncRecoveryScope.placement.executorRunId,
|
|
19668
|
+
invocationKey:
|
|
19669
|
+
asyncRecoveryScope.placement.kind === 'inline_child'
|
|
19670
|
+
? `${asyncRecoveryInvocationKey}:inline-child:${asyncRecoveryScope.logical.runId}:attempt:${attempt}`
|
|
19671
|
+
: `${asyncRecoveryInvocationKey}:attempt:${attempt}`,
|
|
19664
19672
|
})
|
|
19665
19673
|
: null;
|
|
19666
19674
|
// This is deliberately a claim about only the immediately preceding
|
package/dist/bundling-sources/shared_libs/play-runtime/governor/app-runtime-rate-state-backend.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
acquireRateStateViaAppRuntime,
|
|
3
3
|
AppRuntimeApiTransportError,
|
|
4
4
|
capacityShedRetryAfterMs,
|
|
5
|
+
flushRateStateFeedbackViaAppRuntime,
|
|
5
6
|
penalizeRateStateViaAppRuntime,
|
|
6
7
|
releaseRateStateViaAppRuntime,
|
|
7
8
|
RateStateValidationUnavailableError,
|
|
@@ -54,6 +55,7 @@ export const RATE_ACQUIRE_MAX_WAIT_MS = 300_000;
|
|
|
54
55
|
*/
|
|
55
56
|
export const PROVIDER_ADMISSION_WAIT_BUDGET_MS = 120_000;
|
|
56
57
|
const PROVIDER_NO_PROGRESS_WARNING_MS = 180_000;
|
|
58
|
+
const SUCCESS_FEEDBACK_DRAIN_TIMEOUT_MS = 10_000;
|
|
57
59
|
|
|
58
60
|
/**
|
|
59
61
|
* Permits leased per app-runtime round trip for the direct Node substrate.
|
|
@@ -77,6 +79,10 @@ export interface AppRuntimeRatePort {
|
|
|
77
79
|
penalize(
|
|
78
80
|
input: Parameters<typeof penalizeRateStateViaAppRuntime>[1],
|
|
79
81
|
): ReturnType<typeof penalizeRateStateViaAppRuntime>;
|
|
82
|
+
flushFeedback?(
|
|
83
|
+
input: Parameters<typeof flushRateStateFeedbackViaAppRuntime>[1],
|
|
84
|
+
signal: AbortSignal,
|
|
85
|
+
): Promise<void>;
|
|
80
86
|
validate?(
|
|
81
87
|
input: Parameters<typeof validateRateStateViaAppRuntime>[1],
|
|
82
88
|
): ReturnType<typeof validateRateStateViaAppRuntime>;
|
|
@@ -87,6 +93,8 @@ function contextRatePort(context: WorkerRuntimeApiContext): AppRuntimeRatePort {
|
|
|
87
93
|
acquire: (input) => acquireRateStateViaAppRuntime(context, input),
|
|
88
94
|
release: (input) => releaseRateStateViaAppRuntime(context, input),
|
|
89
95
|
penalize: (input) => penalizeRateStateViaAppRuntime(context, input),
|
|
96
|
+
flushFeedback: (input, signal) =>
|
|
97
|
+
flushRateStateFeedbackViaAppRuntime(context, input, signal),
|
|
90
98
|
validate: (input) => validateRateStateViaAppRuntime(context, input),
|
|
91
99
|
};
|
|
92
100
|
}
|
|
@@ -296,6 +304,16 @@ export class AppRuntimeRateStateBackend implements RateStateBackend {
|
|
|
296
304
|
private readonly effectiveRps = new Map<string, number>();
|
|
297
305
|
private readonly pendingSuccesses = new Map<string, number>();
|
|
298
306
|
private readonly successFeedbackFlights = new Map<string, SuccessFeedback>();
|
|
307
|
+
private readonly successFeedbackScopes = new Map<
|
|
308
|
+
string,
|
|
309
|
+
{
|
|
310
|
+
bucketId: string;
|
|
311
|
+
rateScopeToken?: string | null;
|
|
312
|
+
rules: readonly PacingRule[];
|
|
313
|
+
}
|
|
314
|
+
>();
|
|
315
|
+
private readonly successFeedbackSupported = new Set<string>();
|
|
316
|
+
private successFeedbackDrain: Promise<void> | null = null;
|
|
299
317
|
/**
|
|
300
318
|
* Completion samples travel with the next lease refill. This keeps the
|
|
301
319
|
* Gradient2 checkpoint current without adding one gateway request per row.
|
|
@@ -1072,7 +1090,22 @@ export class AppRuntimeRateStateBackend implements RateStateBackend {
|
|
|
1072
1090
|
: rawResponse.waitMs,
|
|
1073
1091
|
}
|
|
1074
1092
|
: rawResponse;
|
|
1075
|
-
|
|
1093
|
+
const acknowledged = response.acknowledgedObservationBatch;
|
|
1094
|
+
const submitted = feedback.concurrencyObservationBatch;
|
|
1095
|
+
if (
|
|
1096
|
+
acknowledged === undefined ||
|
|
1097
|
+
(submitted &&
|
|
1098
|
+
acknowledged?.observerId === submitted.observerId &&
|
|
1099
|
+
acknowledged.laneId === submitted.laneId &&
|
|
1100
|
+
acknowledged.sequence === submitted.sequence)
|
|
1101
|
+
) {
|
|
1102
|
+
this.acknowledgeSuccessFeedback(successKey, feedback);
|
|
1103
|
+
}
|
|
1104
|
+
if (response.successFeedbackSupported === true) {
|
|
1105
|
+
this.successFeedbackSupported.add(bucketId);
|
|
1106
|
+
} else {
|
|
1107
|
+
this.successFeedbackSupported.delete(bucketId);
|
|
1108
|
+
}
|
|
1076
1109
|
this.recordCooldown(bucketId, response);
|
|
1077
1110
|
if (response.scopeValidationSupported === true)
|
|
1078
1111
|
this.validationScopes.add(bucketId);
|
|
@@ -1559,11 +1592,17 @@ export class AppRuntimeRateStateBackend implements RateStateBackend {
|
|
|
1559
1592
|
|
|
1560
1593
|
observeSuccess(input: {
|
|
1561
1594
|
bucketId: string;
|
|
1595
|
+
rateScopeToken?: string | null;
|
|
1562
1596
|
rules: readonly PacingRule[];
|
|
1563
1597
|
latencyMs?: number | null;
|
|
1564
1598
|
}): void {
|
|
1565
1599
|
this.providerStalls.delete(input.bucketId);
|
|
1566
1600
|
const key = pendingSuccessKey(input.bucketId, input.rules);
|
|
1601
|
+
this.successFeedbackScopes.set(key, {
|
|
1602
|
+
bucketId: input.bucketId,
|
|
1603
|
+
rateScopeToken: input.rateScopeToken,
|
|
1604
|
+
rules: input.rules,
|
|
1605
|
+
});
|
|
1567
1606
|
this.pendingSuccesses.set(
|
|
1568
1607
|
key,
|
|
1569
1608
|
Math.min(1_000_000, (this.pendingSuccesses.get(key) ?? 0) + 1),
|
|
@@ -1593,6 +1632,43 @@ export class AppRuntimeRateStateBackend implements RateStateBackend {
|
|
|
1593
1632
|
this.pendingConcurrencyObservations.set(key, pending);
|
|
1594
1633
|
}
|
|
1595
1634
|
|
|
1635
|
+
async flushSuccessFeedback(): Promise<void> {
|
|
1636
|
+
if (!this.port.flushFeedback) return;
|
|
1637
|
+
if (this.successFeedbackDrain) return await this.successFeedbackDrain;
|
|
1638
|
+
const signal = AbortSignal.timeout(SUCCESS_FEEDBACK_DRAIN_TIMEOUT_MS);
|
|
1639
|
+
const drain = async () => {
|
|
1640
|
+
for (const [key, scope] of this.successFeedbackScopes) {
|
|
1641
|
+
// Older receivers retain their existing piggyback behavior. An explicit
|
|
1642
|
+
// capability and matching batch acknowledgement protect rolling deploys.
|
|
1643
|
+
if (!this.successFeedbackSupported.has(scope.bucketId)) continue;
|
|
1644
|
+
for (;;) {
|
|
1645
|
+
if (signal.aborted) throw abortReason(signal);
|
|
1646
|
+
const feedback = this.snapshotSuccessFeedback(key);
|
|
1647
|
+
if (!feedback.concurrencyObservationBatch) break;
|
|
1648
|
+
await this.port.flushFeedback!(
|
|
1649
|
+
{
|
|
1650
|
+
...scope,
|
|
1651
|
+
rules: [...scope.rules],
|
|
1652
|
+
leaseIds: [],
|
|
1653
|
+
...feedback,
|
|
1654
|
+
schedulerSchema: this.schedulerSchema,
|
|
1655
|
+
},
|
|
1656
|
+
signal,
|
|
1657
|
+
);
|
|
1658
|
+
// A lost response leaves this exact frozen payload available to retry.
|
|
1659
|
+
this.acknowledgeSuccessFeedback(key, feedback);
|
|
1660
|
+
}
|
|
1661
|
+
this.successFeedbackScopes.delete(key);
|
|
1662
|
+
}
|
|
1663
|
+
};
|
|
1664
|
+
this.successFeedbackDrain = drain();
|
|
1665
|
+
try {
|
|
1666
|
+
await this.successFeedbackDrain;
|
|
1667
|
+
} finally {
|
|
1668
|
+
this.successFeedbackDrain = null;
|
|
1669
|
+
}
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1596
1672
|
private newPendingConcurrencyObservations(
|
|
1597
1673
|
key: string,
|
|
1598
1674
|
observations: Array<{ kind: 'success'; latencyMs: number }> = [],
|
|
@@ -197,6 +197,9 @@ export interface RateStateBackend {
|
|
|
197
197
|
/** Provider residence measured at the HTTP boundary. */
|
|
198
198
|
latencyMs?: number | null;
|
|
199
199
|
}): void;
|
|
200
|
+
|
|
201
|
+
/** Bounded final feedback write after the invocation's provider work settles. */
|
|
202
|
+
flushSuccessFeedback?(): Promise<void>;
|
|
200
203
|
}
|
|
201
204
|
|
|
202
205
|
const NOOP_PERMIT: PacingPermit = {
|
|
@@ -90,6 +90,13 @@ export type PlayRunnerRateStateAcquireResult = {
|
|
|
90
90
|
scopeValidationSupported?: boolean;
|
|
91
91
|
/** This gateway rechecks signed provider permits on integration execute. */
|
|
92
92
|
dispatchValidationSupported?: boolean;
|
|
93
|
+
/** This receiver acknowledges replay-safe success batches on release. */
|
|
94
|
+
successFeedbackSupported?: boolean;
|
|
95
|
+
/**
|
|
96
|
+
* Exact committed feedback identity; null leaves the batch pending for replay.
|
|
97
|
+
* Absent preserves implicit acknowledgement from older receivers.
|
|
98
|
+
*/
|
|
99
|
+
acknowledgedObservationBatch?: PlayRunnerRateStateConcurrencyObservationBatch | null;
|
|
93
100
|
/**
|
|
94
101
|
* Gateway clock used to produce `scheduledAtMs`. Runners translate the
|
|
95
102
|
* schedule into relative delays so cross-machine clock skew cannot compress
|
|
@@ -138,6 +145,10 @@ export type PlayRunnerRateStateReleaseInput = {
|
|
|
138
145
|
leaseIds: string[];
|
|
139
146
|
/** Idempotently refund rate reservations that never reached provider fetch. */
|
|
140
147
|
refundReservationIds?: string[];
|
|
148
|
+
/** Flush confirmed outcomes without reserving another provider permit. */
|
|
149
|
+
observedSuccesses?: number;
|
|
150
|
+
concurrencyObservations?: PlayRunnerRateStateConcurrencyObservation[];
|
|
151
|
+
concurrencyObservationBatch?: PlayRunnerRateStateConcurrencyObservationBatch;
|
|
141
152
|
schedulerSchema?: string | null;
|
|
142
153
|
};
|
|
143
154
|
|
|
@@ -3788,6 +3788,19 @@ async function run(
|
|
|
3788
3788
|
} finally {
|
|
3789
3789
|
clearInterval(workCounterTimer);
|
|
3790
3790
|
emitWorkCounters();
|
|
3791
|
+
try {
|
|
3792
|
+
await rateStateBackend.rateState?.flushSuccessFeedback?.();
|
|
3793
|
+
} catch (feedbackError) {
|
|
3794
|
+
// Feedback is advisory: preserve the Play's result or original failure.
|
|
3795
|
+
emitWorkerLog(
|
|
3796
|
+
`[warn] runtime.provider_success_feedback_flush_failed: ${
|
|
3797
|
+
feedbackError instanceof Error
|
|
3798
|
+
? feedbackError.message
|
|
3799
|
+
: String(feedbackError)
|
|
3800
|
+
}`,
|
|
3801
|
+
options,
|
|
3802
|
+
);
|
|
3803
|
+
}
|
|
3791
3804
|
}
|
|
3792
3805
|
}
|
|
3793
3806
|
|
|
@@ -83,6 +83,23 @@ export type StagedDaytonaPayload = {
|
|
|
83
83
|
startupDiagnosticPath: string;
|
|
84
84
|
};
|
|
85
85
|
|
|
86
|
+
/** No payload or customer command has been sent when this is raised. */
|
|
87
|
+
export class DaytonaNodeUnavailableError extends Error {
|
|
88
|
+
constructor(
|
|
89
|
+
readonly diagnostic: {
|
|
90
|
+
reason: 'command_failed' | 'empty_output';
|
|
91
|
+
exitCode: number | null;
|
|
92
|
+
attempts: number;
|
|
93
|
+
responseBytes: number;
|
|
94
|
+
},
|
|
95
|
+
) {
|
|
96
|
+
super(
|
|
97
|
+
`Daytona Node executable was not ready before payload staging (${diagnostic.reason}, exit ${diagnostic.exitCode ?? 'unknown'}).`,
|
|
98
|
+
);
|
|
99
|
+
this.name = 'DaytonaNodeUnavailableError';
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
86
103
|
export type RemoteRunnerPayloadSandbox = {
|
|
87
104
|
id: string;
|
|
88
105
|
/** Daytona target (region) the sandbox runs in, when the provider reports it. */
|
|
@@ -129,10 +146,11 @@ function nodeMaterializePayloadCommand(input: {
|
|
|
129
146
|
artifactCodePath: string;
|
|
130
147
|
artifactSourceMapPath: string;
|
|
131
148
|
crashPusherPath: string;
|
|
149
|
+
nodeBinaryPath?: string;
|
|
132
150
|
}): string {
|
|
133
151
|
const script = buildDaytonaPayloadMaterializerSource();
|
|
134
152
|
return [
|
|
135
|
-
'node',
|
|
153
|
+
input.nodeBinaryPath ? shellQuote(input.nodeBinaryPath) : 'node',
|
|
136
154
|
'-e',
|
|
137
155
|
shellQuote(script),
|
|
138
156
|
shellQuote(input.envelopePath),
|
|
@@ -583,6 +601,8 @@ export function withRunnerSandboxProvider(
|
|
|
583
601
|
export async function stageRunnerPayload(input: {
|
|
584
602
|
sandbox: RemoteRunnerPayloadSandbox;
|
|
585
603
|
bundlePromise: Promise<string>;
|
|
604
|
+
/** A provider-resolved executable, independent of detached-shell PATH. */
|
|
605
|
+
nodeBinaryPath?: string;
|
|
586
606
|
config: PlayRunnerExecutionConfig;
|
|
587
607
|
/** Provider-selected burst ceiling; the stored profile remains a reservation. */
|
|
588
608
|
memoryLimitMiB?: number;
|
|
@@ -736,8 +756,11 @@ export async function stageRunnerPayload(input: {
|
|
|
736
756
|
typeof sandboxTarget === 'string' && sandboxTarget.trim()
|
|
737
757
|
? `DEEPLINE_SANDBOX_TARGET=${shellQuote(sandboxTarget.trim())} `
|
|
738
758
|
: '';
|
|
759
|
+
const nodeCommand = input.nodeBinaryPath
|
|
760
|
+
? shellQuote(input.nodeBinaryPath)
|
|
761
|
+
: 'node';
|
|
739
762
|
const watchedRunnerCommand = [
|
|
740
|
-
|
|
763
|
+
nodeCommand,
|
|
741
764
|
'-e',
|
|
742
765
|
shellQuote(
|
|
743
766
|
buildDaytonaRuntimeWatchdogSource(
|
|
@@ -766,6 +789,7 @@ export async function stageRunnerPayload(input: {
|
|
|
766
789
|
artifactCodePath,
|
|
767
790
|
artifactSourceMapPath,
|
|
768
791
|
crashPusherPath,
|
|
792
|
+
nodeBinaryPath: input.nodeBinaryPath,
|
|
769
793
|
})} && DEEPLINE_PLAY_RUNNER_RUNTIME_STARTED_PATH=${shellQuote(runtimeStartedPath)} DEEPLINE_PLAY_RUNNER_RUNTIME_COMPLETED_PATH=${shellQuote(runtimeCompletedPath)} DEEPLINE_PLAY_RUNNER_PROGRESS_EVENT_PATH=${shellQuote(progressEventPath)} DEEPLINE_PLAY_RUNNER_STARTUP_DIAGNOSTIC_PATH=${shellQuote(startupDiagnosticPath)} DEEPLINE_PLAY_RUNNER_STDOUT_EVENT_MODE=compact UV_THREADPOOL_SIZE=${PLAY_RUNNER_UV_THREADPOOL_SIZE} ${runtimeReliabilityEnv}${runnerTraceEnv}${sandboxTargetEnv}${watchedRunnerCommand}`;
|
|
770
794
|
// Crash-containment epilogue: runs UNCONDITIONALLY after the runner exits and
|
|
771
795
|
// pushes an unacknowledged parsed (or synthesized) terminal so the parked
|
|
@@ -775,7 +799,7 @@ export async function stageRunnerPayload(input: {
|
|
|
775
799
|
// Its own retry diagnostics are kept in a separate log: appending them to
|
|
776
800
|
// `outputPath` after a near-gateway-sized result could hide that result from
|
|
777
801
|
// a later bounded-tail recovery read.
|
|
778
|
-
const command = `rm -f ${shellQuote(outputPath)} ${shellQuote(crashPusherLogPath)} ${shellQuote(exitCodePath)} ${shellQuote(oomKillBaselinePath)} ${shellQuote(runnerPidPath)} ${shellQuote(runtimeStartedPath)} ${shellQuote(runtimeCompletedPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(terminationDiagnosticPath)} ${shellQuote(memoryLedgerPath)} ${shellQuote(`${memoryLedgerPath}.tmp`)} ${shellQuote(memoryPressurePath)} ${shellQuote(progressEventPath)} ${shellQuote(`${progressEventPath}.*`)} ${shellQuote(startupDiagnosticPath)}; ( awk '$1 == "oom_kill" { print $2 }' /sys/fs/cgroup/memory.events 2>/dev/null || true ) > ${shellQuote(oomKillBaselinePath)}; ( ${runnerCommand} ) > ${shellQuote(outputPath)} 2>&1; code=$?; printf '%s' "$code" > ${shellQuote(exitCodePath)}; ${runtimeReliabilityEnv}
|
|
802
|
+
const command = `rm -f ${shellQuote(outputPath)} ${shellQuote(crashPusherLogPath)} ${shellQuote(exitCodePath)} ${shellQuote(oomKillBaselinePath)} ${shellQuote(runnerPidPath)} ${shellQuote(runtimeStartedPath)} ${shellQuote(runtimeCompletedPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(terminationDiagnosticPath)} ${shellQuote(memoryLedgerPath)} ${shellQuote(`${memoryLedgerPath}.tmp`)} ${shellQuote(memoryPressurePath)} ${shellQuote(progressEventPath)} ${shellQuote(`${progressEventPath}.*`)} ${shellQuote(startupDiagnosticPath)}; ( awk '$1 == "oom_kill" { print $2 }' /sys/fs/cgroup/memory.events 2>/dev/null || true ) > ${shellQuote(oomKillBaselinePath)}; ( ${runnerCommand} ) > ${shellQuote(outputPath)} 2>&1; code=$?; printf '%s' "$code" > ${shellQuote(exitCodePath)}; ${runtimeReliabilityEnv}${nodeCommand} ${shellQuote(crashPusherPath)} ${shellQuote(configPath)} "$code" ${shellQuote(outputPath)} ${shellQuote(runtimeLimitMarkerPath)} ${shellQuote(oomKillBaselinePath)} /sys/fs/cgroup/memory.events ${shellQuote(terminationDiagnosticPath)} ${shellQuote(runtimeCompletedPath)} > ${shellQuote(crashPusherLogPath)} 2>&1 || true; printf 'deepline runner output captured: %s\\n' ${shellQuote(outputPath)}; exit "$code"`;
|
|
779
803
|
|
|
780
804
|
return {
|
|
781
805
|
workDir: input.workDir,
|
|
@@ -793,12 +817,61 @@ export async function stageRunnerPayload(input: {
|
|
|
793
817
|
}
|
|
794
818
|
|
|
795
819
|
export async function stageDaytonaRunnerPayload(
|
|
796
|
-
input: Omit<
|
|
820
|
+
input: Omit<
|
|
821
|
+
Parameters<typeof stageRunnerPayload>[0],
|
|
822
|
+
'sandbox' | 'nodeBinaryPath'
|
|
823
|
+
> & {
|
|
797
824
|
sandbox: DaytonaSandbox;
|
|
798
825
|
},
|
|
799
826
|
): Promise<StagedDaytonaPayload> {
|
|
827
|
+
// Toolbox commands and detached sessions need not share PATH. Bind the
|
|
828
|
+
// provider's actual Node executable before constructing either launcher.
|
|
829
|
+
const nodeStartedAt = Date.now();
|
|
830
|
+
// A started sandbox may still be bringing its toolbox/runtime online. Retry
|
|
831
|
+
// only an unsuccessful or empty readiness read on this same sandbox before
|
|
832
|
+
// handing the pre-code failure back to the existing startup recovery owner.
|
|
833
|
+
const retryDelaysMs = [0, 150, 350] as const;
|
|
834
|
+
let node!: Awaited<ReturnType<DaytonaSandbox['process']['executeCommand']>>;
|
|
835
|
+
for (const [attempt, delayMs] of retryDelaysMs.entries()) {
|
|
836
|
+
if (delayMs) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
837
|
+
node = await input.sandbox.process.executeCommand(
|
|
838
|
+
'node -p process.execPath',
|
|
839
|
+
input.workDir,
|
|
840
|
+
{},
|
|
841
|
+
5,
|
|
842
|
+
);
|
|
843
|
+
if (node.exitCode === 0 && node.result.trim() !== '') break;
|
|
844
|
+
const diagnostic = {
|
|
845
|
+
reason: node.exitCode === 0 ? 'empty_output' : 'command_failed',
|
|
846
|
+
exitCode:
|
|
847
|
+
typeof node.exitCode === 'number' && Number.isInteger(node.exitCode)
|
|
848
|
+
? node.exitCode
|
|
849
|
+
: null,
|
|
850
|
+
attempts: attempt + 1,
|
|
851
|
+
responseBytes: Buffer.byteLength(node.result),
|
|
852
|
+
} satisfies DaytonaNodeUnavailableError['diagnostic'];
|
|
853
|
+
input.emitStage('runtime:node_unavailable', diagnostic);
|
|
854
|
+
if (attempt === retryDelaysMs.length - 1) {
|
|
855
|
+
throw new DaytonaNodeUnavailableError(diagnostic);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
const nodeBinaryPath = node.result.trim();
|
|
859
|
+
if (
|
|
860
|
+
node.exitCode !== 0 ||
|
|
861
|
+
!nodeBinaryPath.startsWith('/') ||
|
|
862
|
+
/[\r\n\0]/.test(nodeBinaryPath) ||
|
|
863
|
+
nodeBinaryPath.length > 4_096
|
|
864
|
+
) {
|
|
865
|
+
throw new Error(
|
|
866
|
+
'Daytona did not confirm an absolute Node executable path for this sandbox.',
|
|
867
|
+
);
|
|
868
|
+
}
|
|
869
|
+
input.emitStage('runtime:node_resolved', {
|
|
870
|
+
elapsedMs: Date.now() - nodeStartedAt,
|
|
871
|
+
});
|
|
800
872
|
return await stageRunnerPayload({
|
|
801
873
|
...input,
|
|
874
|
+
nodeBinaryPath,
|
|
802
875
|
sandbox: {
|
|
803
876
|
id: input.sandbox.id,
|
|
804
877
|
target:
|