deepline 0.3.477 → 0.3.479
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/integration-contracts/billing-entitlements.ts +11 -0
- package/dist/bundling-sources/shared_libs/observability/scheduled-jobs.json +18 -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 +11 -1
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +5 -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/scheduler-backends/postgres-rate-state.ts +60 -27
- 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 +3 -1
- 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/bundling-sources/shared_libs/product-notifications/slack-delivery.ts +57 -5
- package/dist/bundling-sources/shared_libs/product-notifications/slack-transport.ts +19 -0
- package/dist/cli/{auth-XVXRRWIQ.mjs → auth-D7DYB57R.mjs} +5 -5
- package/dist/cli/auth-MZDFNRPG.js +41 -0
- package/dist/cli/{billing-2H7GFJDT.js → billing-DHGSNM6E.js} +107 -87
- package/dist/cli/{billing-EOPUJ4JI.mjs → billing-DT4JT4QN.mjs} +34 -14
- package/dist/cli/{chunk-CH4VMDB5.js → chunk-27GSBTWD.js} +70 -52
- package/dist/cli/{chunk-PQQNMMWM.mjs → chunk-27PXHD2P.mjs} +1 -1
- package/dist/cli/{chunk-ACDXGOXE.js → chunk-33O2JGHE.js} +63 -11
- package/dist/cli/{chunk-255O6APS.js → chunk-3GIM7XRH.js} +2 -2
- package/dist/cli/{chunk-6IJJCRE5.mjs → chunk-3PHOAUU4.mjs} +23 -5
- package/dist/cli/{chunk-NC52JG66.js → chunk-3SGA53DX.js} +3 -3
- package/dist/cli/{chunk-RHIFH3GD.mjs → chunk-6C3QY5JS.mjs} +1 -1
- package/dist/cli/{chunk-NJMYX2TP.mjs → chunk-6QIXWFPO.mjs} +3 -3
- package/dist/cli/chunk-7I4B6V2S.mjs +127 -0
- package/dist/cli/{chunk-MZSLFWOT.js → chunk-7UFFWPQ2.js} +13 -9
- package/dist/cli/{chunk-RGNMMDSJ.js → chunk-AFHFZU5V.js} +37 -37
- package/dist/cli/{chunk-KWQNNPMH.js → chunk-AKVNUNL7.js} +3 -3
- package/dist/cli/{chunk-LXKGZKTL.js → chunk-CK2Q6AWR.js} +26 -26
- package/dist/cli/{chunk-DFKHXZQ7.mjs → chunk-D6MLXRMQ.mjs} +10 -10
- package/dist/cli/{chunk-7CILZKLE.js → chunk-EMVWC5LP.js} +5 -5
- package/dist/cli/{chunk-75NLWBYQ.js → chunk-FBEXJVQL.js} +93 -93
- package/dist/cli/{chunk-JS4UO6G4.mjs → chunk-FKEZ5DIJ.mjs} +2 -1
- package/dist/cli/{chunk-ZDPL5AIK.js → chunk-FV7WGK5X.js} +5 -5
- package/dist/cli/{chunk-E2CUSH56.js → chunk-G6V34EQ5.js} +16 -16
- package/dist/cli/{chunk-DS3DZUES.mjs → chunk-GICSDK72.mjs} +2 -2
- package/dist/cli/{chunk-C2V2HQDW.mjs → chunk-GONL4EFT.mjs} +2 -2
- package/dist/cli/{chunk-6KKDIISC.js → chunk-GQCH6Y7W.js} +1 -1
- package/dist/cli/{chunk-3UKKM6OS.js → chunk-GSULE54L.js} +7 -6
- package/dist/cli/{chunk-2YNLW43I.mjs → chunk-GZ43YXHT.mjs} +2 -2
- package/dist/cli/{chunk-UYA7LJGC.mjs → chunk-IL5AF6AR.mjs} +4 -2
- package/dist/cli/{chunk-R5FNCFEK.js → chunk-J5VDE42G.js} +3 -3
- package/dist/cli/{chunk-KMXBZIKO.mjs → chunk-JFGOMQW6.mjs} +2 -2
- package/dist/cli/{chunk-C46DWB56.mjs → chunk-JKUFOP7M.mjs} +1 -1
- package/dist/cli/{chunk-23EEVP5W.js → chunk-JMCTNS6S.js} +6 -6
- package/dist/cli/{chunk-ISEUOYCB.mjs → chunk-JNFNNJ75.mjs} +4 -4
- package/dist/cli/{chunk-C2AN2HTB.mjs → chunk-K5RRY7DJ.mjs} +4 -4
- package/dist/cli/{chunk-M2UL4ZS5.js → chunk-LXYDN5FE.js} +7 -7
- package/dist/cli/{chunk-3W6E3WVU.js → chunk-N4M6CO5H.js} +9 -9
- package/dist/cli/{chunk-RLCAECZH.mjs → chunk-N7E25EU2.mjs} +5 -5
- package/dist/cli/{chunk-YZA5UJXM.mjs → chunk-O5BUFQ2P.mjs} +1 -1
- package/dist/cli/{chunk-WFVEMDQL.js → chunk-OKAZHDYN.js} +4 -2
- package/dist/cli/{chunk-4RAENEAX.js → chunk-OVFCPV24.js} +53 -53
- package/dist/cli/{chunk-NO7ZC2GV.mjs → chunk-PUOKABQF.mjs} +5 -5
- package/dist/cli/{chunk-SG2SZQ4K.mjs → chunk-RJVUILW4.mjs} +2 -2
- package/dist/cli/{chunk-SVU2VR6Q.mjs → chunk-TZCHXF4R.mjs} +2 -2
- package/dist/cli/{chunk-XQLYPHYW.mjs → chunk-UOYA35OT.mjs} +1 -1
- package/dist/cli/{chunk-THMGJOR4.js → chunk-VKBLXJCK.js} +8 -8
- package/dist/cli/{chunk-UBNS6GSV.js → chunk-VRZXGJXH.js} +21 -21
- package/dist/cli/{chunk-DMWHEYZM.js → chunk-W4HIOBQQ.js} +2 -2
- package/dist/cli/{chunk-347EE4YE.js → chunk-W6N2S5N7.js} +8 -8
- package/dist/cli/{chunk-WRHLAAGN.mjs → chunk-XBYW5EHY.mjs} +1 -1
- package/dist/cli/{chunk-LJYTYNQZ.mjs → chunk-XDFARN7U.mjs} +55 -3
- package/dist/cli/{chunk-2QT6KN54.js → chunk-Y2MVDYV6.js} +10 -10
- package/dist/cli/{chunk-QODW5ILA.mjs → chunk-YC2QBF2W.mjs} +2 -2
- package/dist/cli/chunk-YGCKMI5P.js +127 -0
- package/dist/cli/{chunk-3A7TDUZV.mjs → chunk-ZBSUXXZS.mjs} +13 -9
- package/dist/cli/{chunk-2GZFIWSA.mjs → chunk-ZJRVHQSZ.mjs} +4 -4
- package/dist/cli/command-docs.js +2 -2
- package/dist/cli/command-docs.mjs +1 -1
- package/dist/cli/{csv-ECB7TYR2.js → csv-DQWOZ2BL.js} +13 -13
- package/dist/cli/{csv-IDRPTSSC.mjs → csv-JXFOD7DJ.mjs} +4 -4
- package/dist/cli/{db-FOBZD44N.mjs → db-NOGMZAQE.mjs} +6 -6
- package/dist/cli/{db-S74XZZ77.js → db-Q2OAAXRX.js} +27 -27
- package/dist/cli/describe-THHHNUEA.js +48 -0
- package/dist/cli/{describe-KMTPPI2J.mjs → describe-VKZTZLX6.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-ZE3JMNA4.js → executions-B3GDZ4GQ.js} +8 -8
- package/dist/cli/{executions-4JAIVE2E.mjs → executions-XU3JMNI3.mjs} +6 -6
- package/dist/cli/{feedback-W6VA47A3.js → feedback-5IW3ZKRP.js} +8 -8
- package/dist/cli/{feedback-EUX5PDBA.mjs → feedback-R5UQXINE.mjs} +4 -4
- package/dist/cli/{git-UOVG4PLH.mjs → git-7B4H7VEL.mjs} +5 -5
- package/dist/cli/git-BX27JAW4.js +25 -0
- package/dist/cli/index.js +161 -142
- package/dist/cli/index.mjs +65 -46
- package/dist/cli/{legacy-noops-3H35EH5Y.js → legacy-noops-AVT6T5QI.js} +8 -8
- package/dist/cli/{legacy-noops-ZBWUNFWV.mjs → legacy-noops-KY7JAALE.mjs} +5 -5
- package/dist/cli/{monitors-AYSGSUAK.mjs → monitors-G7L7AFXR.mjs} +7 -7
- package/dist/cli/{monitors-PI3KPLR2.js → monitors-GZB6CWK2.js} +91 -91
- package/dist/cli/{org-2BIG7U4V.mjs → org-QDUBOQTH.mjs} +6 -6
- package/dist/cli/{org-MVS3Y6BK.js → org-ZHHKAPCE.js} +72 -72
- package/dist/cli/{pages-VB6FOVDE.js → pages-5P3SPMN5.js} +17 -17
- package/dist/cli/{pages-4TRRL24G.mjs → pages-Q4WGQCST.mjs} +6 -6
- package/dist/cli/{play-BLT6IT2O.js → play-IRLKESZB.js} +585 -678
- package/dist/cli/{play-JR3VUOZM.mjs → play-WRSHD4RE.mjs} +26 -119
- package/dist/cli/{providers-547DPK4S.mjs → providers-7CQUHS57.mjs} +6 -6
- package/dist/cli/{providers-BBXIAGW4.js → providers-LKEYLN6D.js} +9 -9
- package/dist/cli/{quickstart-NTLXD7HS.mjs → quickstart-I6NYGMEE.mjs} +4 -4
- package/dist/cli/{quickstart-RNPI5B6J.js → quickstart-KS45M5SR.js} +6 -6
- package/dist/cli/{run-QZ4SFECD.mjs → run-AZETCL7R.mjs} +22 -22
- package/dist/cli/{run-BCCEXBOG.js → run-BLMOBNAN.js} +36 -36
- package/dist/cli/{search-PYNELH4C.mjs → search-EEKEP67Y.mjs} +7 -7
- package/dist/cli/search-PEQXXY2B.js +32 -0
- package/dist/cli/{secrets-O5WGREQ7.mjs → secrets-HAULG2EW.mjs} +6 -6
- package/dist/cli/{secrets-VD35LMYJ.js → secrets-M6NU3TD2.js} +15 -15
- package/dist/cli/{sessions-2TL6Z5J5.mjs → sessions-5MB4XKOK.mjs} +5 -5
- package/dist/cli/{sessions-NGGIBYXF.js → sessions-DSR5AHIA.js} +6 -6
- package/dist/cli/{settings-ERFNZRHO.js → settings-6US327NQ.js} +78 -78
- package/dist/cli/{settings-6KM74AJT.mjs → settings-JUQP4HYQ.mjs} +11 -11
- package/dist/cli/{setup-6X7EJ6RG.js → setup-5ZRSEQUD.js} +44 -44
- package/dist/cli/{setup-Y3BN6XRS.mjs → setup-JRH4UC47.mjs} +9 -9
- package/dist/cli/{skills-OUBQASHI.mjs → skills-HFOZ5WDH.mjs} +7 -7
- package/dist/cli/skills-P67KCVDR.js +33 -0
- package/dist/cli/{tools-EELZ5FF5.mjs → tools-CJEBZNPB.mjs} +16 -16
- package/dist/cli/tools-PDBEAI22.js +55 -0
- package/dist/cli/update-G6DI3BQW.js +33 -0
- package/dist/cli/{update-TX7SW32Y.mjs → update-VQJEPAAK.mjs} +9 -9
- package/dist/cli/{workflow-PUNQG7LG.mjs → workflow-EYWE3T75.mjs} +7 -7
- package/dist/cli/{workflow-5AI2BJA7.js → workflow-NKPDRZOP.js} +17 -17
- package/dist/{client-AjmfA5nR.d.mts → client-B9N1bcGc.d.mts} +1 -1
- package/dist/{client-DMyY-QL8.d.ts → client-Btw075Hq.d.ts} +1 -1
- package/dist/{client-core-C705vFyV.d.ts → client-core-DvGWlwtX.d.ts} +45 -6
- package/dist/{client-core-CpBbvLEX.d.mts → client-core-TulbIeRB.d.mts} +45 -6
- package/dist/{compiler-manifest-hqIAukR0.d.mts → compiler-manifest-gkO9ZkVg.d.mts} +37 -17
- package/dist/{compiler-manifest-hqIAukR0.d.ts → compiler-manifest-gkO9ZkVg.d.ts} +37 -17
- package/dist/{errors-CRO2qQ6k.d.ts → errors-Cc92LKH-.d.ts} +1 -1
- package/dist/{errors-DIHVetNY.d.mts → errors-CeCCOKSA.d.mts} +1 -1
- package/dist/{index-B8DVoeYt.d.ts → index-DJQKdV76.d.ts} +1 -1
- package/dist/{index-DVZ_X4Gb.d.mts → index-DsqWJL3Q.d.mts} +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-QITP34OX.js +0 -41
- package/dist/cli/describe-PI7HCT7K.js +0 -48
- package/dist/cli/git-NDOGCQZY.js +0 -25
- package/dist/cli/search-YHEICYQL.js +0 -32
- package/dist/cli/skills-F7MPYC4P.js +0 -33
- package/dist/cli/tools-MCWDAK53.js +0 -55
- package/dist/cli/update-G5BRJOVT.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.479',
|
|
209
209
|
updateSummary: {
|
|
210
210
|
introducedIn: '0.3.90',
|
|
211
211
|
summary:
|
|
@@ -87,4 +87,15 @@ export type IncludedCompute = {
|
|
|
87
87
|
included_credits_used?: number;
|
|
88
88
|
minutes_used: number;
|
|
89
89
|
days: Array<{ day: string; minutes: number }>;
|
|
90
|
+
/** Same settled sessions and allowance period for every value. */
|
|
91
|
+
opt_in_comparison?: {
|
|
92
|
+
minutes_used: number;
|
|
93
|
+
/** Standard-equivalent usage at the opt-in rate, before the allowance. */
|
|
94
|
+
allowance_minutes_used: number;
|
|
95
|
+
paid_credits: number;
|
|
96
|
+
opt_in_credits: number;
|
|
97
|
+
has_plan_rate_charges: boolean;
|
|
98
|
+
};
|
|
99
|
+
/** Play compute charges for the same period on Growth and Team, for Pay As You Go workspaces. */
|
|
100
|
+
plan_cost_comparison?: { growth_credits: number; team_credits: number };
|
|
90
101
|
};
|
|
@@ -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",
|
|
@@ -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
|
@@ -1090,7 +1090,17 @@ export class AppRuntimeRateStateBackend implements RateStateBackend {
|
|
|
1090
1090
|
: rawResponse.waitMs,
|
|
1091
1091
|
}
|
|
1092
1092
|
: rawResponse;
|
|
1093
|
-
|
|
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
|
+
}
|
|
1094
1104
|
if (response.successFeedbackSupported === true) {
|
|
1095
1105
|
this.successFeedbackSupported.add(bucketId);
|
|
1096
1106
|
} else {
|
|
@@ -92,6 +92,11 @@ export type PlayRunnerRateStateAcquireResult = {
|
|
|
92
92
|
dispatchValidationSupported?: boolean;
|
|
93
93
|
/** This receiver acknowledges replay-safe success batches on release. */
|
|
94
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;
|
|
95
100
|
/**
|
|
96
101
|
* Gateway clock used to produce `scheduledAtMs`. Runners translate the
|
|
97
102
|
* schedule into relative delays so cross-machine clock skew cannot compress
|
|
@@ -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:
|
|
@@ -29,6 +29,18 @@ export type DetachedDaytonaStartupDiagnostic = {
|
|
|
29
29
|
errorCode?: string;
|
|
30
30
|
transportAttemptId?: string;
|
|
31
31
|
} | null;
|
|
32
|
+
/** Fixed summaries only: raw runner output can contain customer secrets. */
|
|
33
|
+
launcherFailure?: {
|
|
34
|
+
reason:
|
|
35
|
+
| 'node_not_found'
|
|
36
|
+
| 'node_loader_failed'
|
|
37
|
+
| 'permission_denied'
|
|
38
|
+
| 'argument_list_too_long'
|
|
39
|
+
| 'exec_format_error'
|
|
40
|
+
| 'unknown_exit_127'
|
|
41
|
+
| 'output_unavailable';
|
|
42
|
+
nodeCheckExitCode: number;
|
|
43
|
+
};
|
|
32
44
|
errors: string[];
|
|
33
45
|
};
|
|
34
46
|
|
|
@@ -124,6 +136,7 @@ function summarizeProcesses(value: unknown): {
|
|
|
124
136
|
* Process names are reduced to a Node count before logging; runner logs,
|
|
125
137
|
* output, and arbitrary process names are deliberately excluded because no
|
|
126
138
|
* heuristic redactor can guarantee removal of arbitrary customer secrets.
|
|
139
|
+
* Exit-127 shell failures are classified inside the sandbox into fixed enums.
|
|
127
140
|
*/
|
|
128
141
|
export async function inspectDetachedDaytonaStartup(input: {
|
|
129
142
|
sandbox: DaytonaSandbox;
|
|
@@ -131,6 +144,7 @@ export async function inspectDetachedDaytonaStartup(input: {
|
|
|
131
144
|
cmdId: string;
|
|
132
145
|
exitCodePath: string;
|
|
133
146
|
startupDiagnosticPath?: string;
|
|
147
|
+
outputPath?: string;
|
|
134
148
|
}): Promise<DetachedDaytonaStartupDiagnostic> {
|
|
135
149
|
const errors: string[] = [];
|
|
136
150
|
const diagnostic: DetachedDaytonaStartupDiagnostic = {
|
|
@@ -189,6 +203,70 @@ export async function inspectDetachedDaytonaStartup(input: {
|
|
|
189
203
|
.catch(() => errors.push('process_snapshot_failed')),
|
|
190
204
|
]);
|
|
191
205
|
|
|
206
|
+
if (
|
|
207
|
+
input.outputPath &&
|
|
208
|
+
diagnostic.exitCodeFile === 127 &&
|
|
209
|
+
!diagnostic.runnerStartup
|
|
210
|
+
) {
|
|
211
|
+
// The failed shell is retired immediately after this inspection. Classify
|
|
212
|
+
// its bounded output inside the sandbox, returning only known enum values
|
|
213
|
+
// and an exit code. Never ship arbitrary output through a heuristic redactor.
|
|
214
|
+
const quotedPath = "'" + input.outputPath.replace(/'/g, "'\\''") + "'";
|
|
215
|
+
try {
|
|
216
|
+
const result = await input.sandbox.process.executeCommand(
|
|
217
|
+
`
|
|
218
|
+
if [ -r ${quotedPath} ]; then
|
|
219
|
+
startup_tail="$(tail -c 4096 -- ${quotedPath} 2>/dev/null)"
|
|
220
|
+
case "$startup_tail" in
|
|
221
|
+
*"error while loading shared libraries"*) startup_reason=node_loader_failed ;;
|
|
222
|
+
*"not found: node"*|*node*"not found"*|*node*"No such file"*) startup_reason=node_not_found ;;
|
|
223
|
+
*"Permission denied"*) startup_reason=permission_denied ;;
|
|
224
|
+
*"Argument list too long"*) startup_reason=argument_list_too_long ;;
|
|
225
|
+
*"Exec format error"*) startup_reason=exec_format_error ;;
|
|
226
|
+
*) startup_reason=unknown_exit_127 ;;
|
|
227
|
+
esac
|
|
228
|
+
else
|
|
229
|
+
startup_reason=output_unavailable
|
|
230
|
+
fi
|
|
231
|
+
node --version >/dev/null 2>&1
|
|
232
|
+
startup_node_code=$?
|
|
233
|
+
printf '{"reason":"%s","nodeCheckExitCode":%s}\\n' "$startup_reason" "$startup_node_code"
|
|
234
|
+
`,
|
|
235
|
+
undefined,
|
|
236
|
+
{},
|
|
237
|
+
5,
|
|
238
|
+
);
|
|
239
|
+
const value = JSON.parse(result.result) as Record<string, unknown>;
|
|
240
|
+
const reasons = [
|
|
241
|
+
'node_not_found',
|
|
242
|
+
'node_loader_failed',
|
|
243
|
+
'permission_denied',
|
|
244
|
+
'argument_list_too_long',
|
|
245
|
+
'exec_format_error',
|
|
246
|
+
'unknown_exit_127',
|
|
247
|
+
'output_unavailable',
|
|
248
|
+
];
|
|
249
|
+
if (
|
|
250
|
+
typeof value.reason !== 'string' ||
|
|
251
|
+
!reasons.includes(value.reason) ||
|
|
252
|
+
typeof value.nodeCheckExitCode !== 'number' ||
|
|
253
|
+
!Number.isInteger(value.nodeCheckExitCode) ||
|
|
254
|
+
value.nodeCheckExitCode < 0 ||
|
|
255
|
+
value.nodeCheckExitCode > 255
|
|
256
|
+
) {
|
|
257
|
+
errors.push('launcher_diagnostic_invalid');
|
|
258
|
+
} else {
|
|
259
|
+
diagnostic.launcherFailure = {
|
|
260
|
+
reason: value.reason as NonNullable<
|
|
261
|
+
DetachedDaytonaStartupDiagnostic['launcherFailure']
|
|
262
|
+
>['reason'],
|
|
263
|
+
nodeCheckExitCode: value.nodeCheckExitCode,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
} catch {
|
|
267
|
+
errors.push('launcher_diagnostic_unavailable');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
192
270
|
return diagnostic;
|
|
193
271
|
}
|
|
194
272
|
|
|
@@ -225,6 +303,7 @@ export type DetachedDaytonaRunnerSupervisor = {
|
|
|
225
303
|
command: string;
|
|
226
304
|
exitCodePath: string;
|
|
227
305
|
startupDiagnosticPath?: string;
|
|
306
|
+
outputPath?: string;
|
|
228
307
|
}): Promise<Extract<DetachedDaytonaRunnerState, { phase: 'ready' }>>;
|
|
229
308
|
};
|
|
230
309
|
|
|
@@ -394,7 +473,7 @@ export function prepareDetachedDaytonaRunner(input: {
|
|
|
394
473
|
let started = false;
|
|
395
474
|
|
|
396
475
|
return {
|
|
397
|
-
async start({ command, exitCodePath, startupDiagnosticPath }) {
|
|
476
|
+
async start({ command, exitCodePath, startupDiagnosticPath, outputPath }) {
|
|
398
477
|
if (started) {
|
|
399
478
|
throw new Error(
|
|
400
479
|
`Detached Daytona runner session ${input.sessionId} was already started.`,
|
|
@@ -435,6 +514,7 @@ export function prepareDetachedDaytonaRunner(input: {
|
|
|
435
514
|
cmdId: state.cmdId,
|
|
436
515
|
exitCodePath,
|
|
437
516
|
startupDiagnosticPath,
|
|
517
|
+
outputPath,
|
|
438
518
|
readiness: input.readiness,
|
|
439
519
|
baselineHeartbeatAt: state.baselineHeartbeatAt,
|
|
440
520
|
runControl: input.runControl,
|
|
@@ -461,6 +541,7 @@ export async function confirmDetachedDaytonaRunnerReady(input: {
|
|
|
461
541
|
cmdId: string;
|
|
462
542
|
exitCodePath: string;
|
|
463
543
|
startupDiagnosticPath?: string;
|
|
544
|
+
outputPath?: string;
|
|
464
545
|
readiness: DetachedRunnerReadinessPort;
|
|
465
546
|
baselineHeartbeatAt: string | null;
|
|
466
547
|
runControl?: <T>(
|
|
@@ -517,6 +598,7 @@ export async function confirmDetachedDaytonaRunnerReady(input: {
|
|
|
517
598
|
cmdId: input.cmdId,
|
|
518
599
|
exitCodePath: input.exitCodePath,
|
|
519
600
|
startupDiagnosticPath: input.startupDiagnosticPath,
|
|
601
|
+
outputPath: input.outputPath,
|
|
520
602
|
});
|
|
521
603
|
const diagnostic = await (input.runControl
|
|
522
604
|
? input.runControl(inspect)
|
|
@@ -67,6 +67,7 @@ import {
|
|
|
67
67
|
recoveryForRunnerStartupNotLive,
|
|
68
68
|
} from '../../play-run-recovery-policy';
|
|
69
69
|
import {
|
|
70
|
+
DaytonaNodeUnavailableError,
|
|
70
71
|
stageDaytonaRunnerPayload,
|
|
71
72
|
withRunnerSandboxProvider,
|
|
72
73
|
} from './daytona-payload-transport';
|
|
@@ -1506,6 +1507,7 @@ const DAYTONA_UNANSWERED_REQUEST_CODES: ReadonlySet<string> = new Set([
|
|
|
1506
1507
|
* loud too, because its input may be too large for any sandbox.
|
|
1507
1508
|
*/
|
|
1508
1509
|
function isFailedDaytonaRunnerStart(error: unknown): boolean {
|
|
1510
|
+
if (error instanceof DaytonaNodeUnavailableError) return true;
|
|
1509
1511
|
if (error instanceof DaytonaControlTimeoutError) return true;
|
|
1510
1512
|
if (!isDaytonaProviderError(error)) return false;
|
|
1511
1513
|
const status = daytonaErrorStatusForLog(error);
|
|
@@ -1536,6 +1538,9 @@ function startFailureForLog(error: unknown) {
|
|
|
1536
1538
|
errorName: error instanceof Error ? error.name : null,
|
|
1537
1539
|
providerStatus: daytonaErrorStatusForLog(error),
|
|
1538
1540
|
providerCode: daytonaErrorCodeForLog(error),
|
|
1541
|
+
...(error instanceof DaytonaNodeUnavailableError
|
|
1542
|
+
? { nodeReadiness: error.diagnostic }
|
|
1543
|
+
: {}),
|
|
1539
1544
|
...(diagnostic
|
|
1540
1545
|
? {
|
|
1541
1546
|
// Retain the already-sanitized evidence before sandbox retirement.
|
|
@@ -1563,6 +1568,7 @@ function startFailureForLog(error: unknown) {
|
|
|
1563
1568
|
transportAttemptId: startup.transportAttemptId,
|
|
1564
1569
|
}
|
|
1565
1570
|
: null,
|
|
1571
|
+
launcherFailure: diagnostic.launcherFailure,
|
|
1566
1572
|
inspectionErrorCount: diagnostic.errors.length,
|
|
1567
1573
|
},
|
|
1568
1574
|
}
|
|
@@ -2092,6 +2098,7 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
|
|
|
2092
2098
|
command: stagedPayload.command,
|
|
2093
2099
|
exitCodePath: stagedPayload.exitCodePath,
|
|
2094
2100
|
startupDiagnosticPath: stagedPayload.startupDiagnosticPath,
|
|
2101
|
+
outputPath: stagedPayload.outputPath,
|
|
2095
2102
|
});
|
|
2096
2103
|
} catch (error) {
|
|
2097
2104
|
if (
|