deepline 0.1.191 → 0.1.193
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/apps/play-runner-workers/src/child-play-await.ts +3 -18
- package/dist/bundling-sources/apps/play-runner-workers/src/coordinator-entry.ts +158 -14
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +35 -39
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime-api-retry.ts +23 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry-state.ts +7 -2
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry.ts +10 -3
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/child-run-id.ts +8 -3
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-failure.ts +14 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +8 -1
- package/dist/bundling-sources/shared_libs/play-runtime/tool-execute-retry-policy.ts +1 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-http-errors.ts +2 -2
- package/dist/cli/index.js +29 -3
- package/dist/cli/index.mjs +29 -3
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* is a coordinator-side safety net for missed signals.
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { isRetryableWorkerRuntimeApiError } from './runtime-api-retry';
|
|
16
|
+
|
|
15
17
|
export type WorkflowStepLike = {
|
|
16
18
|
waitForEvent: (
|
|
17
19
|
name: string,
|
|
@@ -77,12 +79,6 @@ const CHILD_TERMINAL_DURABLE_VERIFY_GRACE_MS = 5_000;
|
|
|
77
79
|
const CHILD_TERMINAL_DURABLE_VERIFY_POLL_MS = 250;
|
|
78
80
|
const CHILD_TERMINAL_DURABLE_VERIFY_READ_TIMEOUT_MS = 3_000;
|
|
79
81
|
const CHILD_TERMINAL_DURABLE_VERIFY_MIN_READ_TIMEOUT_MS = 2_000;
|
|
80
|
-
const CHILD_TERMINAL_PERMANENT_RUNTIME_API_STATUS_RE =
|
|
81
|
-
/runtime API (400|401|403|404):/i;
|
|
82
|
-
const CHILD_TERMINAL_RETRYABLE_RUNTIME_API_STATUS_RE =
|
|
83
|
-
/runtime API (408|429|500|502|503|504|530):/i;
|
|
84
|
-
const CHILD_TERMINAL_RETRYABLE_ERROR_RE =
|
|
85
|
-
/timed out|timeout|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT/i;
|
|
86
82
|
|
|
87
83
|
export interface AwaitChildTerminalInput {
|
|
88
84
|
parentRunId: string;
|
|
@@ -140,17 +136,6 @@ function terminalPayloadFromState(
|
|
|
140
136
|
return isRecord(state?.data) ? state.data : null;
|
|
141
137
|
}
|
|
142
138
|
|
|
143
|
-
function isRetryableChildTerminalSnapshotError(error: unknown): boolean {
|
|
144
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
145
|
-
if (CHILD_TERMINAL_PERMANENT_RUNTIME_API_STATUS_RE.test(message)) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
return (
|
|
149
|
-
CHILD_TERMINAL_RETRYABLE_RUNTIME_API_STATUS_RE.test(message) ||
|
|
150
|
-
CHILD_TERMINAL_RETRYABLE_ERROR_RE.test(message)
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
139
|
function sleep(ms: number): Promise<void> {
|
|
155
140
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
156
141
|
}
|
|
@@ -259,7 +244,7 @@ async function readVerifiedChildTerminalPayload(input: {
|
|
|
259
244
|
if (payload) return { payload, lastState, lastError };
|
|
260
245
|
} catch (error) {
|
|
261
246
|
lastError = error;
|
|
262
|
-
if (!
|
|
247
|
+
if (!isRetryableWorkerRuntimeApiError(error)) {
|
|
263
248
|
throw error;
|
|
264
249
|
}
|
|
265
250
|
}
|
|
@@ -23,7 +23,10 @@ import {
|
|
|
23
23
|
} from '@cloudflare/dynamic-workflows';
|
|
24
24
|
import type { ExecutionPlan } from '../../../shared_libs/play-runtime/execution-plan';
|
|
25
25
|
import { buildChildRunId as buildSharedChildRunId } from '../../../shared_libs/play-runtime/child-run-id';
|
|
26
|
-
import type {
|
|
26
|
+
import type {
|
|
27
|
+
PlayCallGovernanceSnapshot,
|
|
28
|
+
PlayRunInputPayload,
|
|
29
|
+
} from '../../../shared_libs/play-runtime/scheduler-backend';
|
|
27
30
|
import type { RuntimeTestPolicyOverrides } from '../../../shared_libs/play-runtime/test-runtime-seams';
|
|
28
31
|
import { DYNAMIC_PLAY_WORKER_ARTIFACT_VERSION } from '../../../shared_libs/play-runtime/dynamic-worker-version';
|
|
29
32
|
import {
|
|
@@ -96,7 +99,7 @@ export type PlayWorkflowParams = {
|
|
|
96
99
|
artifactStorageKey: string;
|
|
97
100
|
artifactHash: string;
|
|
98
101
|
graphHash: string;
|
|
99
|
-
input:
|
|
102
|
+
input: PlayRunInputPayload;
|
|
100
103
|
force?: boolean;
|
|
101
104
|
runAttempt?: number;
|
|
102
105
|
inputFile?: {
|
|
@@ -131,6 +134,8 @@ export type PlayWorkflowParams = {
|
|
|
131
134
|
dynamicWorkerCode?: string | null;
|
|
132
135
|
executorToken: string;
|
|
133
136
|
baseUrl: string;
|
|
137
|
+
runtimeApiBaseUrl?: string | null;
|
|
138
|
+
callbackUrl?: string | null;
|
|
134
139
|
integrationMode?: 'live' | 'eval_stub' | 'fixture' | null;
|
|
135
140
|
orgId: string;
|
|
136
141
|
userEmail: string;
|
|
@@ -402,6 +407,15 @@ function recordCoordinatorPerfTrace(event: CoordinatorPerfTraceInput): void {
|
|
|
402
407
|
logCoordinatorPerfTrace(payload);
|
|
403
408
|
}
|
|
404
409
|
|
|
410
|
+
function safeOrigin(value: string | null | undefined): string | null {
|
|
411
|
+
if (!value?.trim()) return null;
|
|
412
|
+
try {
|
|
413
|
+
return new URL(value).origin;
|
|
414
|
+
} catch {
|
|
415
|
+
return '<invalid>';
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
405
419
|
async function appendCoordinatorPerfTrace(
|
|
406
420
|
env: CoordinatorEnv,
|
|
407
421
|
payload: CoordinatorPerfTracePayload,
|
|
@@ -1330,9 +1344,23 @@ async function markWorkflowRuntimeFailure(input: {
|
|
|
1330
1344
|
const backoffMs = [200, 500, 1500];
|
|
1331
1345
|
let lastError: unknown = null;
|
|
1332
1346
|
for (let attempt = 0; attempt <= backoffMs.length; attempt += 1) {
|
|
1347
|
+
const requestId = crypto.randomUUID();
|
|
1333
1348
|
try {
|
|
1349
|
+
headers.set('x-deepline-request-id', requestId);
|
|
1334
1350
|
const response = await fetch(url, { method: 'POST', headers, body });
|
|
1335
|
-
if (response.ok)
|
|
1351
|
+
if (response.ok) {
|
|
1352
|
+
if (attempt > 0) {
|
|
1353
|
+
console.info('[coordinator.runtime_api.retry]', {
|
|
1354
|
+
action: 'append_run_events',
|
|
1355
|
+
status: 'ok',
|
|
1356
|
+
attempt,
|
|
1357
|
+
runId,
|
|
1358
|
+
requestId,
|
|
1359
|
+
baseOrigin: safeOrigin(baseUrl),
|
|
1360
|
+
});
|
|
1361
|
+
}
|
|
1362
|
+
return;
|
|
1363
|
+
}
|
|
1336
1364
|
lastError = new Error(
|
|
1337
1365
|
`runtime API responded ${response.status}: ${(await response.text().catch(() => '')).slice(0, 400)}`,
|
|
1338
1366
|
);
|
|
@@ -1348,6 +1376,19 @@ async function markWorkflowRuntimeFailure(input: {
|
|
|
1348
1376
|
lastError = error;
|
|
1349
1377
|
}
|
|
1350
1378
|
if (attempt < backoffMs.length) {
|
|
1379
|
+
console.warn('[coordinator.runtime_api.retry]', {
|
|
1380
|
+
action: 'append_run_events',
|
|
1381
|
+
status: 'retry',
|
|
1382
|
+
attempt: attempt + 1,
|
|
1383
|
+
retryDelayMs: backoffMs[attempt],
|
|
1384
|
+
runId,
|
|
1385
|
+
requestId,
|
|
1386
|
+
baseOrigin: safeOrigin(baseUrl),
|
|
1387
|
+
error:
|
|
1388
|
+
lastError instanceof Error
|
|
1389
|
+
? lastError.message.slice(0, 300)
|
|
1390
|
+
: String(lastError).slice(0, 300),
|
|
1391
|
+
});
|
|
1351
1392
|
await new Promise((resolve) => setTimeout(resolve, backoffMs[attempt]));
|
|
1352
1393
|
}
|
|
1353
1394
|
}
|
|
@@ -2203,6 +2244,26 @@ async function callRuntimeApiFromCoordinator(input: {
|
|
|
2203
2244
|
});
|
|
2204
2245
|
|
|
2205
2246
|
const fetchStartedAt = Date.now();
|
|
2247
|
+
const requestId = crypto.randomUUID();
|
|
2248
|
+
const action =
|
|
2249
|
+
body && typeof body === 'object' && !Array.isArray(body)
|
|
2250
|
+
? String((body as { action?: unknown }).action ?? 'unknown')
|
|
2251
|
+
: 'unknown';
|
|
2252
|
+
const runId =
|
|
2253
|
+
body && typeof body === 'object' && !Array.isArray(body)
|
|
2254
|
+
? String(
|
|
2255
|
+
(body as { runId?: unknown; playId?: unknown }).runId ??
|
|
2256
|
+
(body as { runId?: unknown; playId?: unknown }).playId ??
|
|
2257
|
+
'',
|
|
2258
|
+
) || null
|
|
2259
|
+
: null;
|
|
2260
|
+
console.info('[coordinator.runtime_api.breadcrumb]', {
|
|
2261
|
+
phase: 'request',
|
|
2262
|
+
action,
|
|
2263
|
+
runId,
|
|
2264
|
+
requestId,
|
|
2265
|
+
baseOrigin: safeOrigin(input.baseUrl),
|
|
2266
|
+
});
|
|
2206
2267
|
const response = await input.env.HARNESS.runtimeApiCall({
|
|
2207
2268
|
contract: PLAY_RUNTIME_CONTRACT,
|
|
2208
2269
|
executorToken: input.executorToken,
|
|
@@ -2210,11 +2271,20 @@ async function callRuntimeApiFromCoordinator(input: {
|
|
|
2210
2271
|
path: PLAY_RUNTIME_API_COMPAT_PATH,
|
|
2211
2272
|
body,
|
|
2212
2273
|
headers: {
|
|
2213
|
-
'x-deepline-request-id':
|
|
2274
|
+
'x-deepline-request-id': requestId,
|
|
2214
2275
|
[PLAY_RUNTIME_CONTRACT_HEADER]: String(PLAY_RUNTIME_CONTRACT),
|
|
2215
2276
|
},
|
|
2216
2277
|
});
|
|
2217
2278
|
recordTiming('coordinator.runtime_api.fetch', fetchStartedAt);
|
|
2279
|
+
console.info('[coordinator.runtime_api.breadcrumb]', {
|
|
2280
|
+
phase: 'response',
|
|
2281
|
+
action,
|
|
2282
|
+
runId,
|
|
2283
|
+
requestId,
|
|
2284
|
+
status: response.status,
|
|
2285
|
+
ms: Date.now() - fetchStartedAt,
|
|
2286
|
+
baseOrigin: safeOrigin(input.baseUrl),
|
|
2287
|
+
});
|
|
2218
2288
|
|
|
2219
2289
|
const bodyStartedAt = Date.now();
|
|
2220
2290
|
const responseBody = response.body;
|
|
@@ -2329,7 +2399,7 @@ function buildChildRunId(input: {
|
|
|
2329
2399
|
? governance.parentPlayName
|
|
2330
2400
|
: null,
|
|
2331
2401
|
key: typeof governance?.key === 'string' ? governance.key : null,
|
|
2332
|
-
input: isRecord(body.input) ? body.input : {},
|
|
2402
|
+
input: isRecord(body.input) || Array.isArray(body.input) ? body.input : {},
|
|
2333
2403
|
graphHash: isRecord(body.manifest)
|
|
2334
2404
|
? typeof body.manifest.graphHash === 'string'
|
|
2335
2405
|
? body.manifest.graphHash
|
|
@@ -2361,12 +2431,82 @@ function normalizeRuntimeBaseUrl(value: unknown): string | null {
|
|
|
2361
2431
|
return parsed.toString().replace(/\/$/, '');
|
|
2362
2432
|
}
|
|
2363
2433
|
|
|
2364
|
-
|
|
2434
|
+
const DEEPLINE_PRODUCTION_APP_HOST = 'code.deepline.com';
|
|
2435
|
+
const DEEPLINE_VERCEL_DEPLOYMENT_HOST_RE =
|
|
2436
|
+
/^deepline-api(?:-[a-z0-9-]+)?-aero-team-0f650658\.vercel\.app$/i;
|
|
2437
|
+
const DEEPLINE_VERCEL_PROJECT_HOST_RE =
|
|
2438
|
+
/^deepline-[a-z0-9]+-aero-team-0f650658\.vercel\.app$/i;
|
|
2439
|
+
const DEEPLINE_WORKERS_DEV_SUBDOMAINS = new Set(['chirag-d94']);
|
|
2440
|
+
|
|
2441
|
+
function isDeeplineCoordinatorWorkerHost(hostname: string): boolean {
|
|
2442
|
+
const labels = hostname.toLowerCase().split('.');
|
|
2443
|
+
return (
|
|
2444
|
+
labels.length === 4 &&
|
|
2445
|
+
labels[0]?.startsWith('deepline-play-coordinator-') &&
|
|
2446
|
+
labels[2] === 'workers' &&
|
|
2447
|
+
labels[3] === 'dev' &&
|
|
2448
|
+
DEEPLINE_WORKERS_DEV_SUBDOMAINS.has(labels[1] ?? '')
|
|
2449
|
+
);
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
function shouldCanonicalizeRuntimeApiBaseUrl(input: {
|
|
2453
|
+
configuredBaseUrl: URL;
|
|
2454
|
+
overrideBaseUrl: URL;
|
|
2455
|
+
}): boolean {
|
|
2456
|
+
if (input.overrideBaseUrl.host === input.configuredBaseUrl.host) {
|
|
2457
|
+
return false;
|
|
2458
|
+
}
|
|
2459
|
+
const configuredHostname = input.configuredBaseUrl.hostname.toLowerCase();
|
|
2460
|
+
const overrideHostname = input.overrideBaseUrl.hostname.toLowerCase();
|
|
2461
|
+
if (isDeeplineCoordinatorWorkerHost(overrideHostname)) {
|
|
2462
|
+
return true;
|
|
2463
|
+
}
|
|
2464
|
+
const overrideIsDeeplineVercelHost =
|
|
2465
|
+
DEEPLINE_VERCEL_DEPLOYMENT_HOST_RE.test(overrideHostname) ||
|
|
2466
|
+
DEEPLINE_VERCEL_PROJECT_HOST_RE.test(overrideHostname);
|
|
2467
|
+
if (!overrideIsDeeplineVercelHost) {
|
|
2468
|
+
return false;
|
|
2469
|
+
}
|
|
2470
|
+
const configuredIsDeeplineVercelHost =
|
|
2471
|
+
DEEPLINE_VERCEL_DEPLOYMENT_HOST_RE.test(configuredHostname) ||
|
|
2472
|
+
DEEPLINE_VERCEL_PROJECT_HOST_RE.test(configuredHostname);
|
|
2473
|
+
return (
|
|
2474
|
+
configuredHostname === DEEPLINE_PRODUCTION_APP_HOST ||
|
|
2475
|
+
!configuredIsDeeplineVercelHost
|
|
2476
|
+
);
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
function resolveRuntimeApiBaseUrl(
|
|
2480
|
+
env: CoordinatorEnv,
|
|
2481
|
+
body: Record<string, unknown>,
|
|
2482
|
+
): string {
|
|
2483
|
+
const configuredBaseUrl =
|
|
2484
|
+
normalizeRuntimeBaseUrl(env.DEEPLINE_API_BASE_URL) ??
|
|
2485
|
+
env.DEEPLINE_API_BASE_URL.replace(/\/$/, '');
|
|
2486
|
+
const overrideBaseUrl =
|
|
2487
|
+
normalizeRuntimeBaseUrl(body.runtimeApiBaseUrl) ??
|
|
2488
|
+
normalizeRuntimeBaseUrl(body.baseUrl);
|
|
2489
|
+
if (!overrideBaseUrl) {
|
|
2490
|
+
return configuredBaseUrl;
|
|
2491
|
+
}
|
|
2492
|
+
if (
|
|
2493
|
+
shouldCanonicalizeRuntimeApiBaseUrl({
|
|
2494
|
+
configuredBaseUrl: new URL(configuredBaseUrl),
|
|
2495
|
+
overrideBaseUrl: new URL(overrideBaseUrl),
|
|
2496
|
+
})
|
|
2497
|
+
) {
|
|
2498
|
+
return configuredBaseUrl;
|
|
2499
|
+
}
|
|
2500
|
+
return overrideBaseUrl;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
function resolveWorkflowCallbackBaseUrl(
|
|
2365
2504
|
env: CoordinatorEnv,
|
|
2366
2505
|
body: Record<string, unknown>,
|
|
2367
2506
|
): string {
|
|
2368
2507
|
return (
|
|
2369
2508
|
normalizeRuntimeBaseUrl(body.callbackBaseUrl) ??
|
|
2509
|
+
normalizeRuntimeBaseUrl(body.callbackUrl) ??
|
|
2370
2510
|
normalizeRuntimeBaseUrl(body.baseUrl) ??
|
|
2371
2511
|
env.DEEPLINE_API_BASE_URL.replace(/\/$/, '')
|
|
2372
2512
|
);
|
|
@@ -2388,7 +2528,8 @@ function validateChildSubmitBody(input: {
|
|
|
2388
2528
|
const { parentRunId, body } = input;
|
|
2389
2529
|
const manifest = body.manifest as PlayRuntimeManifest | undefined;
|
|
2390
2530
|
const governance = body.internalRunPlay as
|
|
2391
|
-
|
|
2531
|
+
| PlayCallGovernanceSnapshot
|
|
2532
|
+
| undefined;
|
|
2392
2533
|
const childPlayName =
|
|
2393
2534
|
typeof body.name === 'string' && body.name.trim()
|
|
2394
2535
|
? body.name.trim()
|
|
@@ -2480,7 +2621,8 @@ function buildChildWorkflowParams(input: {
|
|
|
2480
2621
|
dynamicWorkerCode,
|
|
2481
2622
|
preloadedDbSessions,
|
|
2482
2623
|
} = input;
|
|
2483
|
-
const baseUrl =
|
|
2624
|
+
const baseUrl = resolveRuntimeApiBaseUrl(env, body);
|
|
2625
|
+
const callbackUrl = resolveWorkflowCallbackBaseUrl(env, body);
|
|
2484
2626
|
return {
|
|
2485
2627
|
runId: childRunId,
|
|
2486
2628
|
playId: childRunId,
|
|
@@ -2488,7 +2630,7 @@ function buildChildWorkflowParams(input: {
|
|
|
2488
2630
|
artifactStorageKey: manifest.artifactStorageKey,
|
|
2489
2631
|
artifactHash: manifest.artifactHash,
|
|
2490
2632
|
graphHash: manifest.graphHash,
|
|
2491
|
-
input: isRecord(body.input) ? body.input : {},
|
|
2633
|
+
input: isRecord(body.input) || Array.isArray(body.input) ? body.input : {},
|
|
2492
2634
|
contractSnapshot: {
|
|
2493
2635
|
source: 'published',
|
|
2494
2636
|
revisionVersion: null,
|
|
@@ -2517,7 +2659,9 @@ function buildChildWorkflowParams(input: {
|
|
|
2517
2659
|
preloadedDbSessions,
|
|
2518
2660
|
dynamicWorkerCode,
|
|
2519
2661
|
executorToken: childToken,
|
|
2520
|
-
baseUrl,
|
|
2662
|
+
baseUrl: callbackUrl,
|
|
2663
|
+
runtimeApiBaseUrl: baseUrl,
|
|
2664
|
+
callbackUrl,
|
|
2521
2665
|
integrationMode: normalizeIntegrationMode(body.integrationMode),
|
|
2522
2666
|
force: body.force === true || body.forceToolRefresh === true,
|
|
2523
2667
|
forceToolRefresh: body.forceToolRefresh === true,
|
|
@@ -2545,9 +2689,9 @@ function runRequestFromPlayWorkflowParams(
|
|
|
2545
2689
|
params.inputFile?.r2Key ?? params.inputFile?.storageKey ?? null;
|
|
2546
2690
|
return {
|
|
2547
2691
|
runId: params.runId,
|
|
2548
|
-
callbackUrl: params.baseUrl,
|
|
2692
|
+
callbackUrl: params.callbackUrl ?? params.baseUrl,
|
|
2549
2693
|
executorToken: params.executorToken,
|
|
2550
|
-
baseUrl: params.baseUrl,
|
|
2694
|
+
baseUrl: params.runtimeApiBaseUrl ?? params.baseUrl,
|
|
2551
2695
|
integrationMode: normalizeIntegrationMode(params.integrationMode),
|
|
2552
2696
|
orgId: params.orgId,
|
|
2553
2697
|
playName: params.playName,
|
|
@@ -2742,7 +2886,7 @@ async function executeChildInline(input: {
|
|
|
2742
2886
|
input.body.parentPlayName.trim()
|
|
2743
2887
|
? input.body.parentPlayName.trim()
|
|
2744
2888
|
: governance.parentPlayName;
|
|
2745
|
-
const baseUrl =
|
|
2889
|
+
const baseUrl = resolveRuntimeApiBaseUrl(input.env, input.body);
|
|
2746
2890
|
const { childToken, preloadedDbSessions, prepareTimings, transportTimings } =
|
|
2747
2891
|
await prepareInlineChildRunWithRuntime({
|
|
2748
2892
|
env: input.env,
|
|
@@ -3072,7 +3216,7 @@ async function submitChildWorkflowThroughCoordinator(input: {
|
|
|
3072
3216
|
parentRunId: input.parentRunId,
|
|
3073
3217
|
body: input.body,
|
|
3074
3218
|
});
|
|
3075
|
-
const baseUrl =
|
|
3219
|
+
const baseUrl = resolveRuntimeApiBaseUrl(input.env, input.body);
|
|
3076
3220
|
|
|
3077
3221
|
const tokenStartedAt = Date.now();
|
|
3078
3222
|
const childToken = await mintChildWorkflowExecutorToken({
|
|
@@ -65,6 +65,7 @@ import {
|
|
|
65
65
|
type WorkflowStepLike,
|
|
66
66
|
} from './child-play-await';
|
|
67
67
|
import { submitChildPlayThroughCoordinator } from './child-play-submit';
|
|
68
|
+
import { isRetryableWorkerRuntimeApiError } from './runtime-api-retry';
|
|
68
69
|
import {
|
|
69
70
|
attachToolResultListDataset,
|
|
70
71
|
createToolExecuteResult,
|
|
@@ -307,6 +308,7 @@ import {
|
|
|
307
308
|
type PreviousCell,
|
|
308
309
|
} from '../../../shared_libs/play-runtime/cell-staleness';
|
|
309
310
|
import type { PlayRowUpdate } from '../../../shared_libs/play-runtime/ctx-types';
|
|
311
|
+
import type { PlayRunInputPayload } from '../../../shared_libs/play-runtime/scheduler-backend';
|
|
310
312
|
|
|
311
313
|
// The play's default export. The bundler injects this — see bundle-play-file.ts.
|
|
312
314
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -323,7 +325,7 @@ type RunRequest = {
|
|
|
323
325
|
playName: string;
|
|
324
326
|
graphHash?: string | null;
|
|
325
327
|
userEmail: string | null;
|
|
326
|
-
runtimeInput:
|
|
328
|
+
runtimeInput: PlayRunInputPayload;
|
|
327
329
|
/** Start a fresh run graph and recompute runtime-sheet rows. */
|
|
328
330
|
force?: boolean;
|
|
329
331
|
/** Explicit durable tool receipt refresh that can re-execute completed provider calls. */
|
|
@@ -648,8 +650,15 @@ type WorkerEnv = {
|
|
|
648
650
|
|
|
649
651
|
let cachedRuntimeApiBinding: WorkerEnv['RUNTIME_API'] | null = null;
|
|
650
652
|
let cachedRuntimeApiVercelBypassToken: string | null = null;
|
|
653
|
+
|
|
654
|
+
function runtimeApiBindingFromEnv(
|
|
655
|
+
env: WorkerEnv,
|
|
656
|
+
): WorkerEnv['RUNTIME_API'] | null {
|
|
657
|
+
return env.RUNTIME_API ?? env.HARNESS ?? null;
|
|
658
|
+
}
|
|
659
|
+
|
|
651
660
|
function captureRuntimeApiBinding(env: WorkerEnv): void {
|
|
652
|
-
cachedRuntimeApiBinding = env
|
|
661
|
+
cachedRuntimeApiBinding = runtimeApiBindingFromEnv(env);
|
|
653
662
|
cachedRuntimeApiVercelBypassToken =
|
|
654
663
|
typeof env.VERCEL_PROTECTION_BYPASS_TOKEN === 'string' &&
|
|
655
664
|
env.VERCEL_PROTECTION_BYPASS_TOKEN.trim()
|
|
@@ -831,7 +840,9 @@ async function fetchRuntimeApi(
|
|
|
831
840
|
signal: controller.signal,
|
|
832
841
|
};
|
|
833
842
|
if (!cachedRuntimeApiBinding) {
|
|
834
|
-
throw new Error(
|
|
843
|
+
throw new Error(
|
|
844
|
+
'[play-harness] RUNTIME_API/HARNESS service binding is required',
|
|
845
|
+
);
|
|
835
846
|
}
|
|
836
847
|
if (abortSignal?.aborted) {
|
|
837
848
|
throw abortError();
|
|
@@ -1360,7 +1371,7 @@ async function postRuntimeApi<T>(
|
|
|
1360
1371
|
lastError = error;
|
|
1361
1372
|
if (
|
|
1362
1373
|
attempt >= RUNTIME_API_RETRY_DELAYS_MS.length ||
|
|
1363
|
-
!
|
|
1374
|
+
!isRetryableWorkerRuntimeApiError(error)
|
|
1364
1375
|
) {
|
|
1365
1376
|
throw error;
|
|
1366
1377
|
}
|
|
@@ -1386,13 +1397,6 @@ async function postRuntimeApi<T>(
|
|
|
1386
1397
|
throw lastError instanceof Error ? lastError : new Error(String(lastError));
|
|
1387
1398
|
}
|
|
1388
1399
|
|
|
1389
|
-
function isRetryableRuntimeApiError(error: unknown): boolean {
|
|
1390
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
1391
|
-
return /timed out|timeout|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT/i.test(
|
|
1392
|
-
message,
|
|
1393
|
-
);
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
1400
|
function isRetryableRuntimePersistenceError(error: unknown): boolean {
|
|
1397
1401
|
const message = error instanceof Error ? error.message : String(error);
|
|
1398
1402
|
return /deadlock detected|Runtime Postgres connection timed out|could not serialize access|tuple concurrently updated/i.test(
|
|
@@ -1401,21 +1405,17 @@ function isRetryableRuntimePersistenceError(error: unknown): boolean {
|
|
|
1401
1405
|
}
|
|
1402
1406
|
|
|
1403
1407
|
function isRetryableRuntimeApiResponse(status: number, body: string): boolean {
|
|
1404
|
-
|
|
1408
|
+
return (
|
|
1405
1409
|
status === 408 ||
|
|
1406
1410
|
status === 429 ||
|
|
1407
|
-
status
|
|
1408
|
-
status ===
|
|
1409
|
-
status ===
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
status === 500 &&
|
|
1416
|
-
/timeout exceeded when trying to connect|timed out|fetch failed|ECONNRESET|UND_ERR_CONNECT_TIMEOUT/i.test(
|
|
1417
|
-
body,
|
|
1418
|
-
)
|
|
1411
|
+
(status >= 502 && status <= 504) ||
|
|
1412
|
+
status === 530 ||
|
|
1413
|
+
(status === 404 &&
|
|
1414
|
+
/DEPLOYMENT_NOT_FOUND|DeploymentNotFound|deployment .*not found|requested deployment .*exist/i.test(
|
|
1415
|
+
body,
|
|
1416
|
+
)) ||
|
|
1417
|
+
(status === 500 &&
|
|
1418
|
+
isRetryableWorkerRuntimeApiError(`runtime API ${status}: ${body}`))
|
|
1419
1419
|
);
|
|
1420
1420
|
}
|
|
1421
1421
|
|
|
@@ -2076,7 +2076,7 @@ async function callToolDirect(
|
|
|
2076
2076
|
);
|
|
2077
2077
|
if (
|
|
2078
2078
|
transportAttempt >= TOOL_EXECUTE_TRANSPORT_MAX_ATTEMPTS ||
|
|
2079
|
-
!
|
|
2079
|
+
!isRetryableWorkerRuntimeApiError(error)
|
|
2080
2080
|
) {
|
|
2081
2081
|
throw lastError;
|
|
2082
2082
|
}
|
|
@@ -2360,7 +2360,10 @@ function isRuntimeReceiptPersistenceError(error: unknown): boolean {
|
|
|
2360
2360
|
}
|
|
2361
2361
|
|
|
2362
2362
|
function isRunFatalWorkerRowError(error: unknown): boolean {
|
|
2363
|
+
const failure = normalizePlayRunFailure(error);
|
|
2363
2364
|
return (
|
|
2365
|
+
failure.code === 'PLATFORM_DEPLOY_INTERRUPTED' ||
|
|
2366
|
+
failure.code === 'PLATFORM_WORKER_SUBREQUEST_INTERRUPTED' ||
|
|
2364
2367
|
isCoordinatorProgressAuthorizationError(error) ||
|
|
2365
2368
|
isRowIsolationExemptError(error) ||
|
|
2366
2369
|
isRuntimeReceiptPersistenceError(error) ||
|
|
@@ -6891,7 +6894,7 @@ function createMinimalWorkerCtx(
|
|
|
6891
6894
|
childIdempotencyKey: receiptKey,
|
|
6892
6895
|
input: isRecord(input) ? input : {},
|
|
6893
6896
|
orgId: req.orgId,
|
|
6894
|
-
|
|
6897
|
+
callbackUrl: req.callbackUrl,
|
|
6895
6898
|
baseUrl: req.baseUrl,
|
|
6896
6899
|
integrationMode: req.integrationMode ?? null,
|
|
6897
6900
|
parentExecutorToken: req.executorToken,
|
|
@@ -7381,10 +7384,7 @@ async function handleRun(request: Request, env: WorkerEnv): Promise<Response> {
|
|
|
7381
7384
|
await probeHarnessOnce(env, runPrefix);
|
|
7382
7385
|
const ctx = createMinimalWorkerCtx(req, emit, env);
|
|
7383
7386
|
const result = await (
|
|
7384
|
-
playFn as (
|
|
7385
|
-
ctx: unknown,
|
|
7386
|
-
input: Record<string, unknown>,
|
|
7387
|
-
) => Promise<unknown>
|
|
7387
|
+
playFn as (ctx: unknown, input: PlayRunInputPayload) => Promise<unknown>
|
|
7388
7388
|
)(ctx, req.runtimeInput);
|
|
7389
7389
|
emit({
|
|
7390
7390
|
type: 'result',
|
|
@@ -7913,10 +7913,7 @@ async function executeRunRequest(
|
|
|
7913
7913
|
try {
|
|
7914
7914
|
const playStartedAt = nowMs();
|
|
7915
7915
|
const result = await (
|
|
7916
|
-
playFn as (
|
|
7917
|
-
ctx: unknown,
|
|
7918
|
-
input: Record<string, unknown>,
|
|
7919
|
-
) => Promise<unknown>
|
|
7916
|
+
playFn as (ctx: unknown, input: PlayRunInputPayload) => Promise<unknown>
|
|
7920
7917
|
)(ctx, req.runtimeInput);
|
|
7921
7918
|
recordRunnerPerfTrace({
|
|
7922
7919
|
req,
|
|
@@ -8305,9 +8302,9 @@ function runRequestFromWorkflowParams(
|
|
|
8305
8302
|
: null;
|
|
8306
8303
|
return {
|
|
8307
8304
|
runId: String(params.runId ?? ''),
|
|
8308
|
-
callbackUrl: String(params.baseUrl ?? ''),
|
|
8305
|
+
callbackUrl: String(params.callbackUrl ?? params.baseUrl ?? ''),
|
|
8309
8306
|
executorToken: String(params.executorToken ?? ''),
|
|
8310
|
-
baseUrl: String(params.baseUrl ?? ''),
|
|
8307
|
+
baseUrl: String(params.runtimeApiBaseUrl ?? params.baseUrl ?? ''),
|
|
8311
8308
|
integrationMode: normalizeIntegrationMode(params.integrationMode),
|
|
8312
8309
|
orgId: String(params.orgId ?? ''),
|
|
8313
8310
|
playName: String(params.playName ?? ''),
|
|
@@ -8315,9 +8312,8 @@ function runRequestFromWorkflowParams(
|
|
|
8315
8312
|
force: params.force === true,
|
|
8316
8313
|
forceToolRefresh: params.forceToolRefresh === true,
|
|
8317
8314
|
runAttempt: normalizeWorkerRunAttempt(params.runAttempt),
|
|
8318
|
-
runtimeInput:
|
|
8319
|
-
|
|
8320
|
-
: {},
|
|
8315
|
+
runtimeInput:
|
|
8316
|
+
isRecord(params.input) || Array.isArray(params.input) ? params.input : {},
|
|
8321
8317
|
inlineCsv: isInlineCsv(params.inlineCsv) ? params.inlineCsv : null,
|
|
8322
8318
|
inputFiles:
|
|
8323
8319
|
inputFile && inputStorageKey
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const PERMANENT_RUNTIME_API_STATUS_RE = /runtime API 40[0134]:/i;
|
|
2
|
+
const RETRYABLE_RUNTIME_API_ERROR_RE =
|
|
3
|
+
/runtime API (408|429|500|50[2-4]|530):|time(?:d out|out)|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT|DeploymentNotFound|DEPLOYMENT_NOT_FOUND|requested deployment .*exist|The deployment could not be found on Vercel|Authentication infrastructure/i;
|
|
4
|
+
|
|
5
|
+
function isVercelDeploymentMissingRuntimeApi404(message: string): boolean {
|
|
6
|
+
return (
|
|
7
|
+
/runtime API 404:/i.test(message) &&
|
|
8
|
+
/DeploymentNotFound|DEPLOYMENT_NOT_FOUND|requested deployment .*exist|The deployment could not be found on Vercel/i.test(
|
|
9
|
+
message,
|
|
10
|
+
)
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function isRetryableWorkerRuntimeApiError(error: unknown): boolean {
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16
|
+
if (
|
|
17
|
+
PERMANENT_RUNTIME_API_STATUS_RE.test(message) &&
|
|
18
|
+
!isVercelDeploymentMissingRuntimeApi404(message)
|
|
19
|
+
) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return RETRYABLE_RUNTIME_API_ERROR_RE.test(message);
|
|
23
|
+
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { ExecutionPlan } from '../../../shared_libs/play-runtime/execution-plan';
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
PlayCallGovernanceSnapshot,
|
|
4
|
+
PlayRunInputPayload,
|
|
5
|
+
} from '../../../shared_libs/play-runtime/scheduler-backend';
|
|
3
6
|
import type { PreloadedRuntimeDbSession } from '../../../shared_libs/play-runtime/db-session';
|
|
4
7
|
import type {
|
|
5
8
|
PlayRuntimeManifest,
|
|
@@ -33,7 +36,7 @@ export type WorkflowRetryPlayParams = {
|
|
|
33
36
|
artifactStorageKey: string;
|
|
34
37
|
artifactHash: string;
|
|
35
38
|
graphHash: string;
|
|
36
|
-
input:
|
|
39
|
+
input: PlayRunInputPayload;
|
|
37
40
|
inputFile?: {
|
|
38
41
|
name?: string;
|
|
39
42
|
r2Key?: string;
|
|
@@ -65,6 +68,8 @@ export type WorkflowRetryPlayParams = {
|
|
|
65
68
|
dynamicWorkerCode?: string | null;
|
|
66
69
|
executorToken: string;
|
|
67
70
|
baseUrl: string;
|
|
71
|
+
runtimeApiBaseUrl?: string | null;
|
|
72
|
+
callbackUrl?: string | null;
|
|
68
73
|
orgId: string;
|
|
69
74
|
userEmail: string;
|
|
70
75
|
userId?: string | null;
|
|
@@ -24,14 +24,19 @@ export function decideWorkflowPlatformRetry(input: {
|
|
|
24
24
|
return { action: 'fail', reason: null, message: null };
|
|
25
25
|
}
|
|
26
26
|
const failure = normalizePlayRunFailure(input.error);
|
|
27
|
-
const retryablePlatformReset =
|
|
27
|
+
const retryablePlatformReset =
|
|
28
|
+
failure.code === 'PLATFORM_DEPLOY_INTERRUPTED' ||
|
|
29
|
+
failure.code === 'PLATFORM_WORKER_SUBREQUEST_INTERRUPTED';
|
|
28
30
|
if (
|
|
29
31
|
retryablePlatformReset &&
|
|
30
32
|
input.retryAttempts < PLATFORM_DEPLOY_WORKFLOW_RETRY_LIMIT
|
|
31
33
|
) {
|
|
32
34
|
return {
|
|
33
35
|
action: 'retry',
|
|
34
|
-
reason:
|
|
36
|
+
reason:
|
|
37
|
+
failure.code === 'PLATFORM_WORKER_SUBREQUEST_INTERRUPTED'
|
|
38
|
+
? 'cloudflare_worker_subrequest_limit'
|
|
39
|
+
: 'cloudflare_durable_object_reset',
|
|
35
40
|
nextAttempt: input.retryAttempts + 1,
|
|
36
41
|
message: failure.message,
|
|
37
42
|
};
|
|
@@ -39,7 +44,9 @@ export function decideWorkflowPlatformRetry(input: {
|
|
|
39
44
|
return {
|
|
40
45
|
action: 'fail',
|
|
41
46
|
reason: retryablePlatformReset
|
|
42
|
-
? '
|
|
47
|
+
? failure.code === 'PLATFORM_WORKER_SUBREQUEST_INTERRUPTED'
|
|
48
|
+
? 'cloudflare_worker_subrequest_limit_retry_exhausted'
|
|
49
|
+
: 'cloudflare_durable_object_reset_retry_exhausted'
|
|
43
50
|
: null,
|
|
44
51
|
message: failure.message,
|
|
45
52
|
};
|
|
@@ -105,10 +105,10 @@ export const SDK_RELEASE = {
|
|
|
105
105
|
// 0.1.154 removes the short-lived generated enrich StepOptions recompute
|
|
106
106
|
// fields shipped in 0.1.153.
|
|
107
107
|
// 0.1.175 ships loud `deepline enrich` empty-waterfall reporting.
|
|
108
|
-
version: '0.1.
|
|
108
|
+
version: '0.1.193',
|
|
109
109
|
apiContract: '2026-06-dataset-handle-results-hard-cutover',
|
|
110
110
|
supportPolicy: {
|
|
111
|
-
latest: '0.1.
|
|
111
|
+
latest: '0.1.193',
|
|
112
112
|
minimumSupported: '0.1.53',
|
|
113
113
|
deprecatedBelow: '0.1.53',
|
|
114
114
|
commandMinimumSupported: [
|
|
@@ -49,7 +49,7 @@ export interface ChildRunIdInputs {
|
|
|
49
49
|
*/
|
|
50
50
|
runPlaySemanticKey?: string | null;
|
|
51
51
|
/** Child input payload (semantic-fallback input). */
|
|
52
|
-
input?:
|
|
52
|
+
input?: unknown;
|
|
53
53
|
/**
|
|
54
54
|
* Compiled child graph hash. Only present on workers_edge; `null` in-process.
|
|
55
55
|
*/
|
|
@@ -89,11 +89,16 @@ export function buildChildRunId(inputs: ChildRunIdInputs): string {
|
|
|
89
89
|
stableStringify({
|
|
90
90
|
parentRunId: inputs.parentRunId,
|
|
91
91
|
parentPlayName:
|
|
92
|
-
typeof inputs.parentPlayName === 'string'
|
|
92
|
+
typeof inputs.parentPlayName === 'string'
|
|
93
|
+
? inputs.parentPlayName
|
|
94
|
+
: null,
|
|
93
95
|
childPlayName: inputs.childPlayName,
|
|
94
96
|
key: typeof inputs.key === 'string' ? inputs.key : null,
|
|
95
97
|
...(runPlaySemanticKey ? { runPlaySemanticKey } : {}),
|
|
96
|
-
input:
|
|
98
|
+
input:
|
|
99
|
+
isRecord(inputs.input) || Array.isArray(inputs.input)
|
|
100
|
+
? inputs.input
|
|
101
|
+
: {},
|
|
97
102
|
graphHash: typeof inputs.graphHash === 'string' ? inputs.graphHash : null,
|
|
98
103
|
});
|
|
99
104
|
const digest = sha256Hex(semanticKey).slice(0, 24);
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
isPlayExecutionSuspendedError,
|
|
12
12
|
isPlayRowExecutionSuspendedError,
|
|
13
13
|
} from './suspension';
|
|
14
|
+
import { getToolHttpErrorReceiptFailureKind } from './tool-http-errors';
|
|
14
15
|
import type { WorkReceiptFailureKind } from './work-receipts';
|
|
15
16
|
import {
|
|
16
17
|
PLAY_RUNTIME_WORK_RECEIPT_LEASE_TTL_MS,
|
|
@@ -48,6 +49,8 @@ function isInFlightRuntimeReceipt(
|
|
|
48
49
|
export function runtimeReceiptFailureKindForError(
|
|
49
50
|
error: unknown,
|
|
50
51
|
): WorkReceiptFailureKind {
|
|
52
|
+
const toolFailureKind = getToolHttpErrorReceiptFailureKind(error);
|
|
53
|
+
if (toolFailureKind) return toolFailureKind;
|
|
51
54
|
return isPlayExecutionSuspendedError(error) ||
|
|
52
55
|
isPlayRowExecutionSuspendedError(error)
|
|
53
56
|
? 'repairable'
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
const CLOUDFLARE_DURABLE_OBJECT_RESET_RE =
|
|
2
|
-
/Durable Object.*(?:code was updated|storage caused object)/;
|
|
2
|
+
/Durable Object.*(?:code (?:was|has been) updated|storage caused object)/;
|
|
3
|
+
const CLOUDFLARE_WORKER_SUBREQUEST_LIMIT_RE =
|
|
4
|
+
/Too many subrequests by single Worker invocation/i;
|
|
3
5
|
|
|
4
6
|
export const PLATFORM_DEPLOY_INTERRUPTED_MESSAGE =
|
|
5
7
|
'Run interrupted by a platform deploy. Deepline retries this automatically when possible; if this error is still visible, re-run the same command.';
|
|
8
|
+
export const PLATFORM_WORKER_SUBREQUEST_INTERRUPTED_MESSAGE =
|
|
9
|
+
'Worker subrequest limit hit. Deepline retries automatically; if still visible, re-run.';
|
|
6
10
|
|
|
7
11
|
export const INTERNAL_RUNTIME_STORAGE_ERROR_MESSAGE =
|
|
8
12
|
'Internal play runtime storage failed. Please retry the run; if this keeps happening, contact Deepline support with the run ID.';
|
|
@@ -64,6 +68,15 @@ export function normalizePlayRunFailure(error: unknown): PlayRunFailureDetails {
|
|
|
64
68
|
cause,
|
|
65
69
|
};
|
|
66
70
|
}
|
|
71
|
+
if (CLOUDFLARE_WORKER_SUBREQUEST_LIMIT_RE.test(cause)) {
|
|
72
|
+
return {
|
|
73
|
+
code: 'PLATFORM_WORKER_SUBREQUEST_INTERRUPTED',
|
|
74
|
+
phase: 'runtime',
|
|
75
|
+
message: PLATFORM_WORKER_SUBREQUEST_INTERRUPTED_MESSAGE,
|
|
76
|
+
retryable: true,
|
|
77
|
+
cause,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
67
80
|
const playDepthBudgetMatch = cause.match(
|
|
68
81
|
/Play execution playDepth budget exceeded \((\d+)\/(\d+)\)\./,
|
|
69
82
|
);
|
|
@@ -36,6 +36,8 @@ export const PLAY_SCHEDULER_BACKENDS = {
|
|
|
36
36
|
export type PlaySchedulerBackendId =
|
|
37
37
|
(typeof PLAY_SCHEDULER_BACKENDS)[keyof typeof PLAY_SCHEDULER_BACKENDS];
|
|
38
38
|
|
|
39
|
+
export type PlayRunInputPayload = Record<string, unknown> | unknown[];
|
|
40
|
+
|
|
39
41
|
export type PlayCallGovernanceSnapshot = {
|
|
40
42
|
rootRunId: string;
|
|
41
43
|
parentRunId: string;
|
|
@@ -83,7 +85,7 @@ export type PlaySchedulerSubmitInput = {
|
|
|
83
85
|
runtimeArtifact?: unknown;
|
|
84
86
|
artifactHash: string;
|
|
85
87
|
graphHash: string;
|
|
86
|
-
input:
|
|
88
|
+
input: PlayRunInputPayload;
|
|
87
89
|
/** Start a fresh run graph and recompute runtime-sheet rows. */
|
|
88
90
|
force?: boolean;
|
|
89
91
|
/** Explicit cache bypass for completed ctx.tools.execute receipts. */
|
|
@@ -128,6 +130,11 @@ export type PlaySchedulerSubmitInput = {
|
|
|
128
130
|
/** Optional immutable Worker module source for local Dynamic Worker loading. */
|
|
129
131
|
dynamicWorkerCode?: string | null;
|
|
130
132
|
executorToken: string;
|
|
133
|
+
/**
|
|
134
|
+
* Public app origin used by Workers to call Deepline runtime API routes.
|
|
135
|
+
* When omitted, legacy schedulers fall back to baseUrl.
|
|
136
|
+
*/
|
|
137
|
+
runtimeApiBaseUrl?: string | null;
|
|
131
138
|
baseUrl: string;
|
|
132
139
|
/** Optional per-run provider execution mode. Defaults to server policy when omitted. */
|
|
133
140
|
integrationMode?: 'live' | 'eval_stub' | 'fixture';
|
|
@@ -204,9 +204,7 @@ export function classifyToolExecuteHttpFailure(input: {
|
|
|
204
204
|
});
|
|
205
205
|
const shouldRetry =
|
|
206
206
|
retryDecision.retryable && input.attempt < retryDecision.attemptCap;
|
|
207
|
-
error.receiptFailureKind =
|
|
208
|
-
? 'repairable'
|
|
209
|
-
: 'terminal';
|
|
207
|
+
if (retryDecision.retryable) error.receiptFailureKind = 'repairable';
|
|
210
208
|
const retryAfterMs = parseToolExecuteRetryAfterMs(
|
|
211
209
|
input.retryAfterHeader,
|
|
212
210
|
input.nowMs,
|
|
@@ -4,13 +4,13 @@ export class ToolHttpError extends Error {
|
|
|
4
4
|
readonly billing: Record<string, unknown> | null;
|
|
5
5
|
/** HTTP status of the failed tool-execute response (e.g. 429, 502). */
|
|
6
6
|
readonly status: number;
|
|
7
|
-
receiptFailureKind: WorkReceiptFailureKind
|
|
7
|
+
receiptFailureKind: WorkReceiptFailureKind;
|
|
8
8
|
|
|
9
9
|
constructor(
|
|
10
10
|
message: string,
|
|
11
11
|
billing: Record<string, unknown> | null,
|
|
12
12
|
status: number,
|
|
13
|
-
receiptFailureKind: WorkReceiptFailureKind
|
|
13
|
+
receiptFailureKind: WorkReceiptFailureKind = 'terminal',
|
|
14
14
|
) {
|
|
15
15
|
super(message);
|
|
16
16
|
this.name = 'ToolHttpError';
|
package/dist/cli/index.js
CHANGED
|
@@ -623,10 +623,10 @@ 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
|
-
version: "0.1.
|
|
626
|
+
version: "0.1.193",
|
|
627
627
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
628
628
|
supportPolicy: {
|
|
629
|
-
latest: "0.1.
|
|
629
|
+
latest: "0.1.193",
|
|
630
630
|
minimumSupported: "0.1.53",
|
|
631
631
|
deprecatedBelow: "0.1.53",
|
|
632
632
|
commandMinimumSupported: [
|
|
@@ -19385,6 +19385,30 @@ function coalesceExportableSheetRows(rows, sourceRowStart = 0) {
|
|
|
19385
19385
|
bySourceRowIndex.set(rowIndex, next);
|
|
19386
19386
|
mergedRows.push(next);
|
|
19387
19387
|
}
|
|
19388
|
+
if (bySourceRowIndex.size > 0) {
|
|
19389
|
+
mergedRows.sort((left, right) => {
|
|
19390
|
+
const leftIndex = sourceRowIndexFromEnrichRow(
|
|
19391
|
+
left,
|
|
19392
|
+
sourceRowStart,
|
|
19393
|
+
Number.MAX_SAFE_INTEGER
|
|
19394
|
+
);
|
|
19395
|
+
const rightIndex = sourceRowIndexFromEnrichRow(
|
|
19396
|
+
right,
|
|
19397
|
+
sourceRowStart,
|
|
19398
|
+
Number.MAX_SAFE_INTEGER
|
|
19399
|
+
);
|
|
19400
|
+
if (leftIndex !== null && rightIndex !== null) {
|
|
19401
|
+
return leftIndex - rightIndex;
|
|
19402
|
+
}
|
|
19403
|
+
if (leftIndex !== null) {
|
|
19404
|
+
return -1;
|
|
19405
|
+
}
|
|
19406
|
+
if (rightIndex !== null) {
|
|
19407
|
+
return 1;
|
|
19408
|
+
}
|
|
19409
|
+
return 0;
|
|
19410
|
+
});
|
|
19411
|
+
}
|
|
19388
19412
|
return mergedRows;
|
|
19389
19413
|
}
|
|
19390
19414
|
function sourceRowIndexFromEnrichRow(row, start, end) {
|
|
@@ -21227,7 +21251,9 @@ function registerEnrichCommand(program) {
|
|
|
21227
21251
|
...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
|
|
21228
21252
|
});
|
|
21229
21253
|
if (chunk.exportResult) {
|
|
21230
|
-
currentChunkCommittedExportResult = await commitInPlaceOutput(
|
|
21254
|
+
currentChunkCommittedExportResult = await commitInPlaceOutput(
|
|
21255
|
+
chunk.exportResult
|
|
21256
|
+
);
|
|
21231
21257
|
finalExportResult = currentChunkCommittedExportResult;
|
|
21232
21258
|
}
|
|
21233
21259
|
const reportedExportResult = currentChunkCommittedExportResult ?? finalExportResult;
|
package/dist/cli/index.mjs
CHANGED
|
@@ -608,10 +608,10 @@ 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
|
-
version: "0.1.
|
|
611
|
+
version: "0.1.193",
|
|
612
612
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
613
613
|
supportPolicy: {
|
|
614
|
-
latest: "0.1.
|
|
614
|
+
latest: "0.1.193",
|
|
615
615
|
minimumSupported: "0.1.53",
|
|
616
616
|
deprecatedBelow: "0.1.53",
|
|
617
617
|
commandMinimumSupported: [
|
|
@@ -19414,6 +19414,30 @@ function coalesceExportableSheetRows(rows, sourceRowStart = 0) {
|
|
|
19414
19414
|
bySourceRowIndex.set(rowIndex, next);
|
|
19415
19415
|
mergedRows.push(next);
|
|
19416
19416
|
}
|
|
19417
|
+
if (bySourceRowIndex.size > 0) {
|
|
19418
|
+
mergedRows.sort((left, right) => {
|
|
19419
|
+
const leftIndex = sourceRowIndexFromEnrichRow(
|
|
19420
|
+
left,
|
|
19421
|
+
sourceRowStart,
|
|
19422
|
+
Number.MAX_SAFE_INTEGER
|
|
19423
|
+
);
|
|
19424
|
+
const rightIndex = sourceRowIndexFromEnrichRow(
|
|
19425
|
+
right,
|
|
19426
|
+
sourceRowStart,
|
|
19427
|
+
Number.MAX_SAFE_INTEGER
|
|
19428
|
+
);
|
|
19429
|
+
if (leftIndex !== null && rightIndex !== null) {
|
|
19430
|
+
return leftIndex - rightIndex;
|
|
19431
|
+
}
|
|
19432
|
+
if (leftIndex !== null) {
|
|
19433
|
+
return -1;
|
|
19434
|
+
}
|
|
19435
|
+
if (rightIndex !== null) {
|
|
19436
|
+
return 1;
|
|
19437
|
+
}
|
|
19438
|
+
return 0;
|
|
19439
|
+
});
|
|
19440
|
+
}
|
|
19417
19441
|
return mergedRows;
|
|
19418
19442
|
}
|
|
19419
19443
|
function sourceRowIndexFromEnrichRow(row, start, end) {
|
|
@@ -21256,7 +21280,9 @@ function registerEnrichCommand(program) {
|
|
|
21256
21280
|
...finalExportResult ? { rowSetComplete: !finalExportResult.partial } : {}
|
|
21257
21281
|
});
|
|
21258
21282
|
if (chunk.exportResult) {
|
|
21259
|
-
currentChunkCommittedExportResult = await commitInPlaceOutput(
|
|
21283
|
+
currentChunkCommittedExportResult = await commitInPlaceOutput(
|
|
21284
|
+
chunk.exportResult
|
|
21285
|
+
);
|
|
21260
21286
|
finalExportResult = currentChunkCommittedExportResult;
|
|
21261
21287
|
}
|
|
21262
21288
|
const reportedExportResult = currentChunkCommittedExportResult ?? finalExportResult;
|
package/dist/index.js
CHANGED
|
@@ -422,10 +422,10 @@ 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
|
-
version: "0.1.
|
|
425
|
+
version: "0.1.193",
|
|
426
426
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
427
427
|
supportPolicy: {
|
|
428
|
-
latest: "0.1.
|
|
428
|
+
latest: "0.1.193",
|
|
429
429
|
minimumSupported: "0.1.53",
|
|
430
430
|
deprecatedBelow: "0.1.53",
|
|
431
431
|
commandMinimumSupported: [
|
package/dist/index.mjs
CHANGED
|
@@ -352,10 +352,10 @@ 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
|
-
version: "0.1.
|
|
355
|
+
version: "0.1.193",
|
|
356
356
|
apiContract: "2026-06-dataset-handle-results-hard-cutover",
|
|
357
357
|
supportPolicy: {
|
|
358
|
-
latest: "0.1.
|
|
358
|
+
latest: "0.1.193",
|
|
359
359
|
minimumSupported: "0.1.53",
|
|
360
360
|
deprecatedBelow: "0.1.53",
|
|
361
361
|
commandMinimumSupported: [
|