deepline 0.1.12 → 0.1.20
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/README.md +14 -6
- package/dist/cli/index.js +1346 -717
- package/dist/cli/index.mjs +1342 -713
- package/dist/index.d.mts +199 -23
- package/dist/index.d.ts +199 -23
- package/dist/index.js +221 -14
- package/dist/index.mjs +221 -14
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +214 -77
- package/dist/repo/apps/play-runner-workers/src/dedup-do.ts +85 -60
- package/dist/repo/apps/play-runner-workers/src/entry.ts +385 -66
- package/dist/repo/sdk/src/client.ts +237 -0
- package/dist/repo/sdk/src/config.ts +125 -8
- package/dist/repo/sdk/src/http.ts +29 -5
- package/dist/repo/sdk/src/play.ts +19 -36
- package/dist/repo/sdk/src/plays/bundle-play-file.ts +22 -8
- package/dist/repo/sdk/src/plays/local-file-discovery.ts +207 -160
- package/dist/repo/sdk/src/types.ts +25 -0
- package/dist/repo/sdk/src/version.ts +2 -2
- package/dist/repo/shared_libs/play-runtime/tool-result.ts +237 -145
- package/dist/repo/shared_libs/plays/bundling/index.ts +206 -229
- package/dist/repo/shared_libs/plays/dataset.ts +28 -0
- package/dist/repo/shared_libs/plays/row-identity.ts +59 -4
- package/package.json +5 -4
- package/dist/cli/index.js.map +0 -1
- package/dist/cli/index.mjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/repo/apps/play-runner-workers/src/runtime/README.md +0 -21
- package/dist/repo/apps/play-runner-workers/src/runtime/batching.ts +0 -177
- package/dist/repo/apps/play-runner-workers/src/runtime/execution-plan.ts +0 -52
- package/dist/repo/apps/play-runner-workers/src/runtime/tool-batch.ts +0 -100
- package/dist/repo/sdk/src/cli/commands/auth.ts +0 -500
- package/dist/repo/sdk/src/cli/commands/billing.ts +0 -188
- package/dist/repo/sdk/src/cli/commands/csv.ts +0 -123
- package/dist/repo/sdk/src/cli/commands/db.ts +0 -119
- package/dist/repo/sdk/src/cli/commands/feedback.ts +0 -40
- package/dist/repo/sdk/src/cli/commands/org.ts +0 -117
- package/dist/repo/sdk/src/cli/commands/play.ts +0 -3441
- package/dist/repo/sdk/src/cli/commands/tools.ts +0 -687
- package/dist/repo/sdk/src/cli/dataset-stats.ts +0 -415
- package/dist/repo/sdk/src/cli/index.ts +0 -148
- package/dist/repo/sdk/src/cli/progress.ts +0 -149
- package/dist/repo/sdk/src/cli/skills-sync.ts +0 -141
- package/dist/repo/sdk/src/cli/trace.ts +0 -61
- package/dist/repo/sdk/src/cli/utils.ts +0 -145
- package/dist/repo/sdk/src/compat.ts +0 -77
- package/dist/repo/shared_libs/observability/node-tracing.ts +0 -129
- package/dist/repo/shared_libs/observability/tracing.ts +0 -98
- package/dist/repo/shared_libs/play-runtime/context.ts +0 -4242
- package/dist/repo/shared_libs/play-runtime/ctx-contract.ts +0 -250
- package/dist/repo/shared_libs/play-runtime/ctx-types.ts +0 -725
- package/dist/repo/shared_libs/play-runtime/dataset-id.ts +0 -10
- package/dist/repo/shared_libs/play-runtime/db-session-crypto.ts +0 -304
- package/dist/repo/shared_libs/play-runtime/db-session.ts +0 -462
- package/dist/repo/shared_libs/play-runtime/live-events.ts +0 -214
- package/dist/repo/shared_libs/play-runtime/live-state-contract.ts +0 -50
- package/dist/repo/shared_libs/play-runtime/map-execution-frame.ts +0 -114
- package/dist/repo/shared_libs/play-runtime/map-row-identity.ts +0 -158
- package/dist/repo/shared_libs/play-runtime/progress-emitter.ts +0 -172
- package/dist/repo/shared_libs/play-runtime/protocol.ts +0 -121
- package/dist/repo/shared_libs/play-runtime/public-play-contract.ts +0 -42
- package/dist/repo/shared_libs/play-runtime/result-normalization.ts +0 -33
- package/dist/repo/shared_libs/play-runtime/runtime-api.ts +0 -1873
- package/dist/repo/shared_libs/play-runtime/runtime-constraints.ts +0 -2
- package/dist/repo/shared_libs/play-runtime/runtime-pg-driver-neon-serverless.ts +0 -201
- package/dist/repo/shared_libs/play-runtime/runtime-pg-driver-pg.ts +0 -48
- package/dist/repo/shared_libs/play-runtime/runtime-pg-driver.ts +0 -84
- package/dist/repo/shared_libs/play-runtime/static-pipeline-types.ts +0 -147
- package/dist/repo/shared_libs/play-runtime/suspension.ts +0 -68
- package/dist/repo/shared_libs/play-runtime/tracing.ts +0 -31
- package/dist/repo/shared_libs/play-runtime/waterfall-replay.ts +0 -75
- package/dist/repo/shared_libs/play-runtime/worker-api-types.ts +0 -140
- package/dist/repo/shared_libs/plays/artifact-transport.ts +0 -14
- package/dist/repo/shared_libs/plays/artifact-types.ts +0 -49
- package/dist/repo/shared_libs/plays/compiler-manifest.ts +0 -186
- package/dist/repo/shared_libs/plays/definition.ts +0 -264
- package/dist/repo/shared_libs/plays/file-refs.ts +0 -11
- package/dist/repo/shared_libs/plays/rate-limit-scheduler.ts +0 -206
- package/dist/repo/shared_libs/plays/resolve-static-pipeline.ts +0 -164
- package/dist/repo/shared_libs/plays/runtime-validation.ts +0 -395
- package/dist/repo/shared_libs/temporal/constants.ts +0 -39
- package/dist/repo/shared_libs/temporal/preview-config.ts +0 -153
|
@@ -156,6 +156,7 @@ interface CoordinatorEnv {
|
|
|
156
156
|
DEEPLINE_API_BASE_URL: string;
|
|
157
157
|
DEEPLINE_INTERNAL_TOKEN?: string;
|
|
158
158
|
DEEPLINE_TAIL_LOG_TOKEN?: string;
|
|
159
|
+
DEEPLINE_COORDINATOR_DEPLOY_MARKER?: string;
|
|
159
160
|
VERCEL_PROTECTION_BYPASS_TOKEN?: string;
|
|
160
161
|
DEEPLINE_PLAY_PREVIEW_SLUG?: string;
|
|
161
162
|
/**
|
|
@@ -367,6 +368,9 @@ const WORKFLOW_POOL_TTL_MS = 8 * 60 * 1000;
|
|
|
367
368
|
const WORKFLOW_POOL_TARGET_SIZE = 2;
|
|
368
369
|
const WORKFLOW_POOL_READY_TIMEOUT_MS = 1_500;
|
|
369
370
|
const WORKFLOW_POOL_READY_POLL_MS = 250;
|
|
371
|
+
const WORKFLOW_POOL_REFILL_ON_MISS_TIMEOUT_MS = 2_500;
|
|
372
|
+
const WORKFLOW_POOL_REFILL_ON_MISS_MIN_AVAILABLE = 1;
|
|
373
|
+
const WORKFLOW_POOL_CONTROL_TIMEOUT_MS = 750;
|
|
370
374
|
|
|
371
375
|
function buildDynamicWorkflowMetadata(
|
|
372
376
|
params: PlayWorkflowParams,
|
|
@@ -467,26 +471,48 @@ function workflowPoolDurableObject(env: CoordinatorEnv): DurableObjectStub {
|
|
|
467
471
|
async function callWorkflowPool<T>(
|
|
468
472
|
env: CoordinatorEnv,
|
|
469
473
|
path: string,
|
|
470
|
-
init?: RequestInit,
|
|
474
|
+
init?: RequestInit & { timeoutMs?: number },
|
|
471
475
|
): Promise<T> {
|
|
472
|
-
const
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
...init,
|
|
476
|
-
headers: {
|
|
477
|
-
'content-type': 'application/json',
|
|
478
|
-
...(init?.headers ?? {}),
|
|
479
|
-
},
|
|
480
|
-
},
|
|
476
|
+
const timeoutMs = Math.max(
|
|
477
|
+
1,
|
|
478
|
+
Math.floor(init?.timeoutMs ?? WORKFLOW_POOL_CONTROL_TIMEOUT_MS),
|
|
481
479
|
);
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
480
|
+
const controller = new AbortController();
|
|
481
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
482
|
+
try {
|
|
483
|
+
const fetchInit: RequestInit = { ...(init ?? {}) };
|
|
484
|
+
delete (fetchInit as { timeoutMs?: number }).timeoutMs;
|
|
485
|
+
delete fetchInit.signal;
|
|
486
|
+
const response = await workflowPoolDurableObject(env).fetch(
|
|
487
|
+
`https://deepline.workflow-pool.internal${path}`,
|
|
488
|
+
{
|
|
489
|
+
...fetchInit,
|
|
490
|
+
signal: controller.signal,
|
|
491
|
+
headers: {
|
|
492
|
+
'content-type': 'application/json',
|
|
493
|
+
...(init?.headers ?? {}),
|
|
494
|
+
},
|
|
495
|
+
},
|
|
487
496
|
);
|
|
497
|
+
if (!response.ok) {
|
|
498
|
+
throw new Error(
|
|
499
|
+
`workflow pool ${path} failed ${response.status}: ${(
|
|
500
|
+
await response.text().catch(() => '')
|
|
501
|
+
).slice(0, 400)}`,
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
return (await response.json()) as T;
|
|
505
|
+
} catch (error) {
|
|
506
|
+
if (
|
|
507
|
+
error instanceof Error &&
|
|
508
|
+
(error.name === 'AbortError' || error.message.includes('aborted'))
|
|
509
|
+
) {
|
|
510
|
+
throw new Error(`workflow pool ${path} timed out after ${timeoutMs}ms`);
|
|
511
|
+
}
|
|
512
|
+
throw error;
|
|
513
|
+
} finally {
|
|
514
|
+
clearTimeout(timer);
|
|
488
515
|
}
|
|
489
|
-
return (await response.json()) as T;
|
|
490
516
|
}
|
|
491
517
|
|
|
492
518
|
type WorkflowPoolCounts = {
|
|
@@ -901,7 +927,11 @@ async function submitViaPooledWorkflow(input: {
|
|
|
901
927
|
return null;
|
|
902
928
|
}
|
|
903
929
|
const leaseStartedAt = Date.now();
|
|
904
|
-
|
|
930
|
+
let leaseError: string | null = null;
|
|
931
|
+
let pooledInstanceId = await leaseWorkflowPoolId(input.env).catch((error) => {
|
|
932
|
+
leaseError = error instanceof Error ? error.message : String(error);
|
|
933
|
+
return null;
|
|
934
|
+
});
|
|
905
935
|
const missCounts = pooledInstanceId
|
|
906
936
|
? null
|
|
907
937
|
: await workflowPoolCount(input.env).catch(() => null);
|
|
@@ -911,6 +941,7 @@ async function submitViaPooledWorkflow(input: {
|
|
|
911
941
|
graphHash: input.params.graphHash ?? null,
|
|
912
942
|
extra: {
|
|
913
943
|
pooled: Boolean(pooledInstanceId),
|
|
944
|
+
...(leaseError ? { error: leaseError } : {}),
|
|
914
945
|
...(missCounts
|
|
915
946
|
? {
|
|
916
947
|
availableAfterMiss: missCounts.available,
|
|
@@ -919,43 +950,79 @@ async function submitViaPooledWorkflow(input: {
|
|
|
919
950
|
: {}),
|
|
920
951
|
},
|
|
921
952
|
});
|
|
953
|
+
|
|
954
|
+
if (!pooledInstanceId) {
|
|
955
|
+
// A pool miss is often a timing gap rather than a true lack of warm
|
|
956
|
+
// capacity. Wait briefly for refill/promotion, then retry lease once
|
|
957
|
+
// before falling back to a cold workflow create.
|
|
958
|
+
const refillStartedAt = Date.now();
|
|
959
|
+
const refillResult = await refillWorkflowPool(input.env, {
|
|
960
|
+
waitReady: true,
|
|
961
|
+
minAvailable: WORKFLOW_POOL_REFILL_ON_MISS_MIN_AVAILABLE,
|
|
962
|
+
waitTimeoutMs: WORKFLOW_POOL_REFILL_ON_MISS_TIMEOUT_MS,
|
|
963
|
+
}).catch(() => null);
|
|
964
|
+
input.recordSubmitTiming({
|
|
965
|
+
phase: 'coordinator.workflow_pool_refill_on_miss',
|
|
966
|
+
ms: Date.now() - refillStartedAt,
|
|
967
|
+
graphHash: input.params.graphHash ?? null,
|
|
968
|
+
extra:
|
|
969
|
+
refillResult === null
|
|
970
|
+
? { ok: false }
|
|
971
|
+
: {
|
|
972
|
+
ok: true,
|
|
973
|
+
available: refillResult.available,
|
|
974
|
+
warming: refillResult.warming,
|
|
975
|
+
created: refillResult.created,
|
|
976
|
+
promoted: refillResult.promoted,
|
|
977
|
+
removed: refillResult.removed,
|
|
978
|
+
waitedMs: refillResult.waitedMs,
|
|
979
|
+
waitIterations: refillResult.waitIterations,
|
|
980
|
+
},
|
|
981
|
+
});
|
|
982
|
+
if (refillResult?.available) {
|
|
983
|
+
const retryStartedAt = Date.now();
|
|
984
|
+
let retryLeaseError: string | null = null;
|
|
985
|
+
pooledInstanceId = await leaseWorkflowPoolId(input.env).catch((error) => {
|
|
986
|
+
retryLeaseError = error instanceof Error ? error.message : String(error);
|
|
987
|
+
return null;
|
|
988
|
+
});
|
|
989
|
+
input.recordSubmitTiming({
|
|
990
|
+
phase: 'coordinator.workflow_pool_lease_retry',
|
|
991
|
+
ms: Date.now() - retryStartedAt,
|
|
992
|
+
graphHash: input.params.graphHash ?? null,
|
|
993
|
+
extra: {
|
|
994
|
+
pooled: Boolean(pooledInstanceId),
|
|
995
|
+
...(retryLeaseError ? { error: retryLeaseError } : {}),
|
|
996
|
+
},
|
|
997
|
+
});
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
|
|
922
1001
|
if (!pooledInstanceId) {
|
|
923
1002
|
return null;
|
|
924
1003
|
}
|
|
925
1004
|
|
|
926
1005
|
const instance = await input.env.PLAY_WORKFLOW.get(pooledInstanceId);
|
|
1006
|
+
const readyCheckStartedAt = Date.now();
|
|
1007
|
+
const status = await instance.status().catch(() => null);
|
|
1008
|
+
const statusName = workflowStatusName(status);
|
|
1009
|
+
input.recordSubmitTiming({
|
|
1010
|
+
phase: 'coordinator.workflow_pool_ready_check',
|
|
1011
|
+
ms: Date.now() - readyCheckStartedAt,
|
|
1012
|
+
graphHash: input.params.graphHash ?? null,
|
|
1013
|
+
extra: { instanceId: pooledInstanceId, status: statusName },
|
|
1014
|
+
});
|
|
1015
|
+
if (!workflowPoolStatusIsReady(statusName)) {
|
|
1016
|
+
await instance.terminate().catch(() => undefined);
|
|
1017
|
+
disposeRpcStub(instance);
|
|
1018
|
+
return null;
|
|
1019
|
+
}
|
|
1020
|
+
const sendStartedAt = Date.now();
|
|
927
1021
|
try {
|
|
928
|
-
const readyCheckStartedAt = Date.now();
|
|
929
|
-
const status = await instance.status().catch(() => null);
|
|
930
|
-
const statusName = workflowStatusName(status);
|
|
931
|
-
input.recordSubmitTiming({
|
|
932
|
-
phase: 'coordinator.workflow_pool_ready_check',
|
|
933
|
-
ms: Date.now() - readyCheckStartedAt,
|
|
934
|
-
graphHash: input.params.graphHash ?? null,
|
|
935
|
-
extra: { instanceId: pooledInstanceId, status: statusName },
|
|
936
|
-
});
|
|
937
|
-
if (!workflowPoolStatusIsReady(statusName)) {
|
|
938
|
-
await instance.terminate().catch(() => undefined);
|
|
939
|
-
disposeRpcStub(instance);
|
|
940
|
-
return null;
|
|
941
|
-
}
|
|
942
|
-
const sendStartedAt = Date.now();
|
|
943
1022
|
await instance.sendEvent({
|
|
944
1023
|
type: WORKFLOW_POOL_START_EVENT_TYPE,
|
|
945
1024
|
payload: buildDispatcherEnvelope(input.params),
|
|
946
1025
|
});
|
|
947
|
-
await mapRunToWorkflowInstance({
|
|
948
|
-
env: input.env,
|
|
949
|
-
runId: input.params.runId,
|
|
950
|
-
instanceId: pooledInstanceId,
|
|
951
|
-
});
|
|
952
|
-
input.recordSubmitTiming({
|
|
953
|
-
phase: 'coordinator.workflow_pool_send_event',
|
|
954
|
-
ms: Date.now() - sendStartedAt,
|
|
955
|
-
graphHash: input.params.graphHash ?? null,
|
|
956
|
-
extra: { instanceId: pooledInstanceId },
|
|
957
|
-
});
|
|
958
|
-
return instance;
|
|
959
1026
|
} catch (error) {
|
|
960
1027
|
disposeRpcStub(instance);
|
|
961
1028
|
console.warn('[coordinator.workflow_pool] sendEvent failed; falling back', {
|
|
@@ -965,6 +1032,27 @@ async function submitViaPooledWorkflow(input: {
|
|
|
965
1032
|
});
|
|
966
1033
|
return null;
|
|
967
1034
|
}
|
|
1035
|
+
try {
|
|
1036
|
+
await mapRunToWorkflowInstance({
|
|
1037
|
+
env: input.env,
|
|
1038
|
+
runId: input.params.runId,
|
|
1039
|
+
instanceId: pooledInstanceId,
|
|
1040
|
+
});
|
|
1041
|
+
} catch (error) {
|
|
1042
|
+
disposeRpcStub(instance);
|
|
1043
|
+
throw new Error(
|
|
1044
|
+
`workflow pool mapRunToWorkflowInstance failed after pooled workflow start for ${input.params.runId}: ${
|
|
1045
|
+
error instanceof Error ? error.message : String(error)
|
|
1046
|
+
}`,
|
|
1047
|
+
);
|
|
1048
|
+
}
|
|
1049
|
+
input.recordSubmitTiming({
|
|
1050
|
+
phase: 'coordinator.workflow_pool_send_event',
|
|
1051
|
+
ms: Date.now() - sendStartedAt,
|
|
1052
|
+
graphHash: input.params.graphHash ?? null,
|
|
1053
|
+
extra: { instanceId: pooledInstanceId },
|
|
1054
|
+
});
|
|
1055
|
+
return instance;
|
|
968
1056
|
}
|
|
969
1057
|
|
|
970
1058
|
function readWorkflowPayload(event: unknown): Record<string, unknown> | null {
|
|
@@ -1986,6 +2074,29 @@ const coordinatorEntrypoint = {
|
|
|
1986
2074
|
if (authError) return authError;
|
|
1987
2075
|
return await handleCoordinatorWarmup(request, env, ctx);
|
|
1988
2076
|
}
|
|
2077
|
+
if (url.pathname === '/tail-log-token/probe') {
|
|
2078
|
+
const authError = authorizeCoordinatorControlRequest({ request, env });
|
|
2079
|
+
if (authError) return authError;
|
|
2080
|
+
const expectedTailLogToken = env.DEEPLINE_TAIL_LOG_TOKEN?.trim();
|
|
2081
|
+
if (!expectedTailLogToken) {
|
|
2082
|
+
return Response.json(
|
|
2083
|
+
{ ok: false, error: 'tail log token is not configured' },
|
|
2084
|
+
{ status: 503 },
|
|
2085
|
+
);
|
|
2086
|
+
}
|
|
2087
|
+
const actualTailLogToken =
|
|
2088
|
+
request.headers.get('x-deepline-tail-log-token')?.trim() ?? '';
|
|
2089
|
+
if (actualTailLogToken !== expectedTailLogToken) {
|
|
2090
|
+
return Response.json(
|
|
2091
|
+
{ ok: false, error: 'tail log token mismatch' },
|
|
2092
|
+
{ status: 401 },
|
|
2093
|
+
);
|
|
2094
|
+
}
|
|
2095
|
+
return Response.json({
|
|
2096
|
+
ok: true,
|
|
2097
|
+
deployMarker: env.DEEPLINE_COORDINATOR_DEPLOY_MARKER ?? null,
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
1989
2100
|
if (url.pathname === '/workflow-pool/refill') {
|
|
1990
2101
|
const internalAuthError = authorizeCoordinatorControlRequest({
|
|
1991
2102
|
request,
|
|
@@ -2755,7 +2866,7 @@ function loadDynamicPlayWorkerSync(
|
|
|
2755
2866
|
}
|
|
2756
2867
|
const artifactIdentity =
|
|
2757
2868
|
metadata.artifactHash?.trim() || stableHash(artifactStorageKey);
|
|
2758
|
-
const workerCacheKey = `play:${graphHash}:${artifactIdentity}:harness=
|
|
2869
|
+
const workerCacheKey = `play:${graphHash}:${artifactIdentity}:harness=h5-runtime-api-coordinator`;
|
|
2759
2870
|
const runIdForTrace = metadata.runId ?? graphHash;
|
|
2760
2871
|
const loaderGetStartedAt = Date.now();
|
|
2761
2872
|
const stub = env.LOADER.get(workerCacheKey, async () => {
|
|
@@ -2781,10 +2892,15 @@ function loadDynamicPlayWorkerSync(
|
|
|
2781
2892
|
// which case the per-play stub throws a loud error on first use
|
|
2782
2893
|
// (no silent fallbacks — see harness-stub.ts → requireBinding).
|
|
2783
2894
|
HARNESS: env.HARNESS,
|
|
2895
|
+
VERCEL_PROTECTION_BYPASS_TOKEN: env.VERCEL_PROTECTION_BYPASS_TOKEN,
|
|
2784
2896
|
// In-process runtime API bridge used by the play harness for status,
|
|
2785
2897
|
// tool execution, DB session, and artifact callbacks. This avoids a
|
|
2786
|
-
// public fetch hop
|
|
2787
|
-
|
|
2898
|
+
// public fetch hop when Cloudflare exposes the RuntimeApi export.
|
|
2899
|
+
...makeRuntimeApiEnvBinding(),
|
|
2900
|
+
// In-process coordinator control bridge used by ctx.runPlay and
|
|
2901
|
+
// parent terminal signals. This keeps scalar child plays inline with
|
|
2902
|
+
// the parent instead of round-tripping through nested Workflow waits.
|
|
2903
|
+
...makeCoordinatorControlBinding(),
|
|
2788
2904
|
// NOTE: We intentionally do NOT pass `env.PLAYS_BUCKET` (an R2Bucket
|
|
2789
2905
|
// binding) through to the per-play Worker's env. Including a raw
|
|
2790
2906
|
// R2Bucket in the dynamically-loaded Worker's env makes Cloudflare
|
|
@@ -2836,7 +2952,7 @@ async function loadDynamicPlayWorker(
|
|
|
2836
2952
|
}
|
|
2837
2953
|
const artifactIdentity =
|
|
2838
2954
|
metadata.artifactHash?.trim() || stableHash(artifactStorageKey);
|
|
2839
|
-
const workerCacheKey = `play:${graphHash}:${artifactIdentity}:harness=
|
|
2955
|
+
const workerCacheKey = `play:${graphHash}:${artifactIdentity}:harness=h5-runtime-api-coordinator`;
|
|
2840
2956
|
const runIdForTrace = metadata.runId ?? graphHash;
|
|
2841
2957
|
const loaderGetStartedAt = Date.now();
|
|
2842
2958
|
const stub = env.LOADER.get(workerCacheKey, async () => {
|
|
@@ -2858,10 +2974,11 @@ async function loadDynamicPlayWorker(
|
|
|
2858
2974
|
// Mirror of the sync loader (above) — see that copy for the
|
|
2859
2975
|
// architectural rationale. The dynamic worker env is intentionally
|
|
2860
2976
|
// minimal; runtime callbacks use RUNTIME_API, file reads go through
|
|
2861
|
-
// HARNESS, and child workflow control uses the
|
|
2862
|
-
// run request.
|
|
2977
|
+
// HARNESS, and child workflow control uses the COORDINATOR binding.
|
|
2863
2978
|
HARNESS: env.HARNESS,
|
|
2864
|
-
|
|
2979
|
+
VERCEL_PROTECTION_BYPASS_TOKEN: env.VERCEL_PROTECTION_BYPASS_TOKEN,
|
|
2980
|
+
...makeRuntimeApiEnvBinding(),
|
|
2981
|
+
...makeCoordinatorControlBinding(),
|
|
2865
2982
|
},
|
|
2866
2983
|
};
|
|
2867
2984
|
});
|
|
@@ -3169,11 +3286,16 @@ async function handleCoordinatorWarmup(
|
|
|
3169
3286
|
* structured-cloneable. WorkerEntrypoint stubs ARE cloneable — same trick
|
|
3170
3287
|
* `makePlayAssetsBinding` already uses.
|
|
3171
3288
|
*
|
|
3172
|
-
* Falls back transparently
|
|
3173
|
-
*
|
|
3174
|
-
*
|
|
3289
|
+
* Falls back transparently when Cloudflare does not expose module exports in
|
|
3290
|
+
* the current execution path: if the binding is omitted from `env`, the play
|
|
3291
|
+
* worker uses its existing `fetch(req.baseUrl + path)` transport.
|
|
3175
3292
|
*/
|
|
3176
|
-
|
|
3293
|
+
let loggedMissingRuntimeApiExport = false;
|
|
3294
|
+
let loggedMissingCoordinatorControlExport = false;
|
|
3295
|
+
|
|
3296
|
+
function makeRuntimeApiEnvBinding():
|
|
3297
|
+
| { RUNTIME_API: { fetch(req: Request): Promise<Response> } }
|
|
3298
|
+
| Record<string, never> {
|
|
3177
3299
|
const exports = workersExports as unknown as {
|
|
3178
3300
|
RuntimeApi?: (init: { props: undefined }) => {
|
|
3179
3301
|
fetch(req: Request): Promise<Response>;
|
|
@@ -3181,27 +3303,35 @@ function makeRuntimeApiBinding(): { fetch(req: Request): Promise<Response> } {
|
|
|
3181
3303
|
};
|
|
3182
3304
|
const ctor = exports.RuntimeApi;
|
|
3183
3305
|
if (typeof ctor !== 'function') {
|
|
3184
|
-
|
|
3185
|
-
|
|
3186
|
-
|
|
3306
|
+
if (!loggedMissingRuntimeApiExport) {
|
|
3307
|
+
loggedMissingRuntimeApiExport = true;
|
|
3308
|
+
console.warn(
|
|
3309
|
+
'[coordinator] RuntimeApi is not registered on cloudflare:workers exports; using public runtime API transport.',
|
|
3310
|
+
);
|
|
3311
|
+
}
|
|
3312
|
+
return {};
|
|
3187
3313
|
}
|
|
3188
|
-
return ctor({ props: undefined });
|
|
3314
|
+
return { RUNTIME_API: ctor({ props: undefined }) };
|
|
3189
3315
|
}
|
|
3190
3316
|
|
|
3191
|
-
function makeCoordinatorControlBinding():
|
|
3192
|
-
|
|
3193
|
-
|
|
3194
|
-
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3317
|
+
function makeCoordinatorControlBinding():
|
|
3318
|
+
| {
|
|
3319
|
+
COORDINATOR: {
|
|
3320
|
+
submitChild(
|
|
3321
|
+
parentRunId: string,
|
|
3322
|
+
body: Record<string, unknown>,
|
|
3323
|
+
): Promise<{ workflowId?: string; runId?: string; error?: unknown }>;
|
|
3324
|
+
signal(
|
|
3325
|
+
runId: string,
|
|
3326
|
+
body: Record<string, unknown>,
|
|
3327
|
+
): Promise<Record<string, unknown>>;
|
|
3328
|
+
recordPerfTrace(
|
|
3329
|
+
runId: string,
|
|
3330
|
+
payload: CoordinatorPerfTracePayload,
|
|
3331
|
+
): Promise<void>;
|
|
3332
|
+
};
|
|
3333
|
+
}
|
|
3334
|
+
| Record<string, never> {
|
|
3205
3335
|
const exports = workersExports as unknown as {
|
|
3206
3336
|
CoordinatorControl?: (init: { props: undefined }) => {
|
|
3207
3337
|
submitChild(
|
|
@@ -3220,11 +3350,15 @@ function makeCoordinatorControlBinding(): {
|
|
|
3220
3350
|
};
|
|
3221
3351
|
const ctor = exports.CoordinatorControl;
|
|
3222
3352
|
if (typeof ctor !== 'function') {
|
|
3223
|
-
|
|
3224
|
-
|
|
3225
|
-
|
|
3353
|
+
if (!loggedMissingCoordinatorControlExport) {
|
|
3354
|
+
loggedMissingCoordinatorControlExport = true;
|
|
3355
|
+
console.warn(
|
|
3356
|
+
'[coordinator] CoordinatorControl is not registered on cloudflare:workers exports; using public coordinator transport.',
|
|
3357
|
+
);
|
|
3358
|
+
}
|
|
3359
|
+
return {};
|
|
3226
3360
|
}
|
|
3227
|
-
return ctor({ props: undefined });
|
|
3361
|
+
return { COORDINATOR: ctor({ props: undefined }) };
|
|
3228
3362
|
}
|
|
3229
3363
|
|
|
3230
3364
|
async function loadStoredPlayArtifactFromR2(
|
|
@@ -3261,6 +3395,9 @@ function mapWorkflowResult(
|
|
|
3261
3395
|
: null;
|
|
3262
3396
|
return {
|
|
3263
3397
|
runId,
|
|
3398
|
+
...(typeof output?.playName === 'string' && output.playName.trim()
|
|
3399
|
+
? { playName: output.playName.trim() }
|
|
3400
|
+
: {}),
|
|
3264
3401
|
status: mapped,
|
|
3265
3402
|
result: output?.result ?? status.output ?? null,
|
|
3266
3403
|
error,
|