deepline 0.1.22 → 0.1.24

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/index.d.mts CHANGED
@@ -1399,7 +1399,7 @@ declare class DeeplineClient {
1399
1399
  }>;
1400
1400
  }
1401
1401
 
1402
- declare const SDK_VERSION = "0.1.22";
1402
+ declare const SDK_VERSION = "0.1.24";
1403
1403
  declare const SDK_API_CONTRACT = "2026-05-runs-v2";
1404
1404
 
1405
1405
  /**
package/dist/index.d.ts CHANGED
@@ -1399,7 +1399,7 @@ declare class DeeplineClient {
1399
1399
  }>;
1400
1400
  }
1401
1401
 
1402
- declare const SDK_VERSION = "0.1.22";
1402
+ declare const SDK_VERSION = "0.1.24";
1403
1403
  declare const SDK_API_CONTRACT = "2026-05-runs-v2";
1404
1404
 
1405
1405
  /**
package/dist/index.js CHANGED
@@ -241,7 +241,7 @@ function resolveConfig(options) {
241
241
  }
242
242
 
243
243
  // src/version.ts
244
- var SDK_VERSION = "0.1.22";
244
+ var SDK_VERSION = "0.1.24";
245
245
  var SDK_API_CONTRACT = "2026-05-runs-v2";
246
246
 
247
247
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -529,6 +529,19 @@ function sleep(ms) {
529
529
  // src/client.ts
530
530
  var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
531
531
  var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
532
+ var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
533
+ function sleep2(ms) {
534
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
535
+ }
536
+ function isTransientCompileManifestError(error) {
537
+ if (error instanceof DeeplineError && typeof error.statusCode === "number") {
538
+ return error.statusCode === 408 || error.statusCode === 425 || error.statusCode === 499 || error.statusCode >= 500 && error.statusCode < 600;
539
+ }
540
+ const message = error instanceof Error ? error.message : String(error);
541
+ return /fetch failed|connection (?:closed|reset|terminated)|socket hang up|econnreset|etimedout|eai_again|abort/i.test(
542
+ message
543
+ );
544
+ }
532
545
  function isRecord(value) {
533
546
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
534
547
  }
@@ -934,8 +947,22 @@ var DeeplineClient = class {
934
947
  });
935
948
  }
936
949
  async compilePlayManifest(input) {
937
- const response = await this.http.post("/api/v2/plays/compile-manifest", input);
938
- return response.compilerManifest;
950
+ const retryDelays = COMPILE_MANIFEST_RETRY_DELAYS_MS.slice(
951
+ 0,
952
+ Math.max(0, this.config.maxRetries)
953
+ );
954
+ for (let attempt = 0; ; attempt += 1) {
955
+ try {
956
+ const response = await this.http.post("/api/v2/plays/compile-manifest", input);
957
+ return response.compilerManifest;
958
+ } catch (error) {
959
+ const delayMs = retryDelays[attempt];
960
+ if (delayMs === void 0 || !isTransientCompileManifestError(error)) {
961
+ throw error;
962
+ }
963
+ await sleep2(delayMs);
964
+ }
965
+ }
939
966
  }
940
967
  /**
941
968
  * Check a bundled play artifact against the server's current play compiler.
package/dist/index.mjs CHANGED
@@ -195,7 +195,7 @@ function resolveConfig(options) {
195
195
  }
196
196
 
197
197
  // src/version.ts
198
- var SDK_VERSION = "0.1.22";
198
+ var SDK_VERSION = "0.1.24";
199
199
  var SDK_API_CONTRACT = "2026-05-runs-v2";
200
200
 
201
201
  // ../shared_libs/play-runtime/coordinator-headers.ts
@@ -483,6 +483,19 @@ function sleep(ms) {
483
483
  // src/client.ts
484
484
  var TERMINAL_PLAY_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
485
485
  var INCLUDE_TOOL_METADATA_HEADER = "x-deepline-include-tool-metadata";
486
+ var COMPILE_MANIFEST_RETRY_DELAYS_MS = [250, 1e3];
487
+ function sleep2(ms) {
488
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
489
+ }
490
+ function isTransientCompileManifestError(error) {
491
+ if (error instanceof DeeplineError && typeof error.statusCode === "number") {
492
+ return error.statusCode === 408 || error.statusCode === 425 || error.statusCode === 499 || error.statusCode >= 500 && error.statusCode < 600;
493
+ }
494
+ const message = error instanceof Error ? error.message : String(error);
495
+ return /fetch failed|connection (?:closed|reset|terminated)|socket hang up|econnreset|etimedout|eai_again|abort/i.test(
496
+ message
497
+ );
498
+ }
486
499
  function isRecord(value) {
487
500
  return Boolean(value && typeof value === "object" && !Array.isArray(value));
488
501
  }
@@ -888,8 +901,22 @@ var DeeplineClient = class {
888
901
  });
889
902
  }
890
903
  async compilePlayManifest(input) {
891
- const response = await this.http.post("/api/v2/plays/compile-manifest", input);
892
- return response.compilerManifest;
904
+ const retryDelays = COMPILE_MANIFEST_RETRY_DELAYS_MS.slice(
905
+ 0,
906
+ Math.max(0, this.config.maxRetries)
907
+ );
908
+ for (let attempt = 0; ; attempt += 1) {
909
+ try {
910
+ const response = await this.http.post("/api/v2/plays/compile-manifest", input);
911
+ return response.compilerManifest;
912
+ } catch (error) {
913
+ const delayMs = retryDelays[attempt];
914
+ if (delayMs === void 0 || !isTransientCompileManifestError(error)) {
915
+ throw error;
916
+ }
917
+ await sleep2(delayMs);
918
+ }
919
+ }
893
920
  }
894
921
  /**
895
922
  * Check a bundled play artifact against the server's current play compiler.
@@ -33,6 +33,7 @@ import {
33
33
  COORDINATOR_INTERNAL_TOKEN_HEADER,
34
34
  COORDINATOR_RUN_SCOPE_HEADER,
35
35
  } from '../../../shared_libs/play-runtime/coordinator-headers';
36
+ import { sanitizeLiveLogLines } from './runtime/live-progress';
36
37
 
37
38
  export { DynamicWorkflowBinding };
38
39
 
@@ -125,6 +126,8 @@ type CoordinatorTerminalState = {
125
126
  totalRows?: unknown;
126
127
  durationMs?: unknown;
127
128
  playName?: string | null;
129
+ liveLogs?: string[] | null;
130
+ liveNodeProgress?: unknown;
128
131
  completedAt?: number;
129
132
  };
130
133
 
@@ -154,6 +157,7 @@ type CoordinatorRunEvent =
154
157
  activeNodeId?: string | null;
155
158
  activeArtifactTableNamespace?: string | null;
156
159
  updatedAt?: number | null;
160
+ liveNodeProgress?: unknown;
157
161
  }
158
162
  | {
159
163
  seq?: number;
@@ -166,6 +170,8 @@ type CoordinatorRunEvent =
166
170
  totalRows?: unknown;
167
171
  durationMs?: unknown;
168
172
  playName?: string | null;
173
+ liveLogs?: string[] | null;
174
+ liveNodeProgress?: unknown;
169
175
  };
170
176
 
171
177
  type InlineWorkerRunResponse = {
@@ -229,12 +235,7 @@ interface CoordinatorEnv {
229
235
  HARNESS?: import('../../play-harness-worker/src/rpc-types').PlayHarnessRpc;
230
236
  }
231
237
 
232
- const WORKFLOW_READ_ONLY_ACTIONS = new Set([
233
- '',
234
- 'result',
235
- 'status',
236
- 'tail',
237
- ]);
238
+ const WORKFLOW_READ_ONLY_ACTIONS = new Set(['', 'result', 'status', 'tail']);
238
239
 
239
240
  function authorizeCoordinatorControlRequest(input: {
240
241
  request: Request;
@@ -411,11 +412,14 @@ async function appendCoordinatorRunEvent(
411
412
  event: CoordinatorRunEvent,
412
413
  ): Promise<void> {
413
414
  const stub = env.PLAY_DEDUP.get(env.PLAY_DEDUP.idFromName(event.runId));
414
- const response = await stub.fetch('https://deepline.dedup.internal/event-add', {
415
- method: 'POST',
416
- headers: { 'content-type': 'application/json' },
417
- body: JSON.stringify(event),
418
- });
415
+ const response = await stub.fetch(
416
+ 'https://deepline.dedup.internal/event-add',
417
+ {
418
+ method: 'POST',
419
+ headers: { 'content-type': 'application/json' },
420
+ body: JSON.stringify(event),
421
+ },
422
+ );
419
423
  if (!response.ok) {
420
424
  throw new Error(`coordinator event append failed ${response.status}`);
421
425
  }
@@ -455,7 +459,8 @@ async function listCoordinatorRunEvents(input: {
455
459
  typeof event.ts === 'number',
456
460
  )
457
461
  : [],
458
- latestSeq: typeof body.latestSeq === 'number' ? body.latestSeq : input.afterSeq,
462
+ latestSeq:
463
+ typeof body.latestSeq === 'number' ? body.latestSeq : input.afterSeq,
459
464
  };
460
465
  }
461
466
 
@@ -546,7 +551,9 @@ function buildDynamicWorkflowMetadata(
546
551
  };
547
552
  }
548
553
 
549
- function buildDispatcherEnvelope(params: PlayWorkflowParams): DispatcherEnvelope {
554
+ function buildDispatcherEnvelope(
555
+ params: PlayWorkflowParams,
556
+ ): DispatcherEnvelope {
550
557
  // Mirrors @cloudflare/dynamic-workflows' envelope. We need to send the
551
558
  // dispatcher payload via Workflow sendEvent for prewarmed instances; the
552
559
  // public wrapper only applies this envelope to create() params.
@@ -739,7 +746,9 @@ type WorkflowPoolListEntry = {
739
746
  expiresAt: number;
740
747
  };
741
748
 
742
- async function workflowPoolCount(env: CoordinatorEnv): Promise<WorkflowPoolCounts> {
749
+ async function workflowPoolCount(
750
+ env: CoordinatorEnv,
751
+ ): Promise<WorkflowPoolCounts> {
743
752
  const body = await callWorkflowPool<{
744
753
  available?: unknown;
745
754
  warming?: unknown;
@@ -810,17 +819,13 @@ async function markWorkflowPoolIdReady(
810
819
  env: CoordinatorEnv,
811
820
  poolId: string,
812
821
  ): Promise<boolean> {
813
- const body = await callWorkflowPool<{ ready?: unknown }>(
814
- env,
815
- '/pool-ready',
816
- {
817
- method: 'POST',
818
- body: JSON.stringify({
819
- poolId,
820
- version: WORKFLOW_POOL_PROTOCOL_VERSION,
821
- }),
822
- },
823
- );
822
+ const body = await callWorkflowPool<{ ready?: unknown }>(env, '/pool-ready', {
823
+ method: 'POST',
824
+ body: JSON.stringify({
825
+ poolId,
826
+ version: WORKFLOW_POOL_PROTOCOL_VERSION,
827
+ }),
828
+ });
824
829
  return body.ready === true;
825
830
  }
826
831
 
@@ -948,7 +953,9 @@ async function waitForWorkflowPoolReadySignal(input: {
948
953
  polls += 1;
949
954
  const [entry, status] = await Promise.all([
950
955
  listWorkflowPoolEntries(input.env)
951
- .then((entries) => entries.find((candidate) => candidate.id === input.poolId))
956
+ .then((entries) =>
957
+ entries.find((candidate) => candidate.id === input.poolId),
958
+ )
952
959
  .catch(() => undefined),
953
960
  input.instance.status().catch(() => null),
954
961
  ]);
@@ -1206,7 +1213,8 @@ async function submitViaPooledWorkflow(input: {
1206
1213
  if (!pooledInstanceId) {
1207
1214
  // A pool miss must not block the user path. Refilling is handled by the
1208
1215
  // caller's waitUntil after submit, so fall through to cold create now.
1209
- const counts = missCounts ?? (await workflowPoolCount(input.env).catch(() => null));
1216
+ const counts =
1217
+ missCounts ?? (await workflowPoolCount(input.env).catch(() => null));
1210
1218
  input.recordSubmitTiming({
1211
1219
  phase: 'coordinator.workflow_pool_refill_on_miss',
1212
1220
  ms: 0,
@@ -1404,7 +1412,9 @@ async function mintChildWorkflowExecutorToken(input: {
1404
1412
  }
1405
1413
  const executorToken = parsed.executorToken;
1406
1414
  if (typeof executorToken !== 'string' || !executorToken.trim()) {
1407
- throw new Error('Origin child executor token response was missing executorToken.');
1415
+ throw new Error(
1416
+ 'Origin child executor token response was missing executorToken.',
1417
+ );
1408
1418
  }
1409
1419
  return executorToken;
1410
1420
  }
@@ -1447,10 +1457,15 @@ function normalizeRuntimeBaseUrl(value: unknown): string | null {
1447
1457
  return parsed.toString().replace(/\/$/, '');
1448
1458
  }
1449
1459
 
1450
- function resolveRuntimeBaseUrl(env: CoordinatorEnv, body: Record<string, unknown>): string {
1451
- return normalizeRuntimeBaseUrl(body.callbackBaseUrl) ??
1460
+ function resolveRuntimeBaseUrl(
1461
+ env: CoordinatorEnv,
1462
+ body: Record<string, unknown>,
1463
+ ): string {
1464
+ return (
1465
+ normalizeRuntimeBaseUrl(body.callbackBaseUrl) ??
1452
1466
  normalizeRuntimeBaseUrl(body.baseUrl) ??
1453
- env.DEEPLINE_API_BASE_URL.replace(/\/$/, '');
1467
+ env.DEEPLINE_API_BASE_URL.replace(/\/$/, '')
1468
+ );
1454
1469
  }
1455
1470
 
1456
1471
  function validateChildSubmitBody(input: {
@@ -1603,7 +1618,9 @@ function buildChildWorkflowParams(input: {
1603
1618
  };
1604
1619
  }
1605
1620
 
1606
- function runRequestFromPlayWorkflowParams(params: PlayWorkflowParams): Record<string, unknown> {
1621
+ function runRequestFromPlayWorkflowParams(
1622
+ params: PlayWorkflowParams,
1623
+ ): Record<string, unknown> {
1607
1624
  return {
1608
1625
  runId: params.runId,
1609
1626
  callbackUrl: params.baseUrl,
@@ -1616,7 +1633,8 @@ function runRequestFromPlayWorkflowParams(params: PlayWorkflowParams): Record<st
1616
1633
  runtimeInput: params.input,
1617
1634
  inlineCsv: params.inlineCsv ?? null,
1618
1635
  inputR2Keys:
1619
- params.inputFile?.r2Key && (params.inputFile.name || params.inputFile.path)
1636
+ params.inputFile?.r2Key &&
1637
+ (params.inputFile.name || params.inputFile.path)
1620
1638
  ? {
1621
1639
  [String(params.inputFile.name ?? params.inputFile.path)]:
1622
1640
  params.inputFile.r2Key,
@@ -1720,13 +1738,8 @@ async function executeChildInline(input: {
1720
1738
  if (!validated.ok) {
1721
1739
  throw new Error(String(validated.error.message ?? 'Invalid child submit.'));
1722
1740
  }
1723
- const {
1724
- manifest,
1725
- governance,
1726
- childPlayName,
1727
- orgId,
1728
- parentExecutorToken,
1729
- } = validated;
1741
+ const { manifest, governance, childPlayName, orgId, parentExecutorToken } =
1742
+ validated;
1730
1743
  const childRunId = buildChildRunId(childPlayName);
1731
1744
  const timings: CoordinatorTiming[] = [];
1732
1745
  const trace = (
@@ -1801,9 +1814,7 @@ async function executeChildInline(input: {
1801
1814
  artifactStorageKey: manifest.artifactStorageKey,
1802
1815
  artifactHash: manifest.artifactHash,
1803
1816
  dynamicWorkerCode:
1804
- typeof manifest.bundledCode === 'string'
1805
- ? manifest.bundledCode
1806
- : null,
1817
+ typeof manifest.bundledCode === 'string' ? manifest.bundledCode : null,
1807
1818
  packagedFiles: null,
1808
1819
  });
1809
1820
  trace('coordinator.inline_child_loader_get', loaderStartedAt);
@@ -2027,9 +2038,7 @@ export class RuntimeApi extends WorkerEntrypoint<CoordinatorEnv, undefined> {
2027
2038
  type: 'progress',
2028
2039
  status,
2029
2040
  ts: Date.now(),
2030
- logs: Array.isArray(body.liveLogs)
2031
- ? body.liveLogs.filter((line): line is string => typeof line === 'string')
2032
- : undefined,
2041
+ logs: sanitizeLiveLogLines(body.liveLogs) ?? undefined,
2033
2042
  activeNodeId:
2034
2043
  typeof body.activeNodeId === 'string' ? body.activeNodeId : null,
2035
2044
  activeArtifactTableNamespace:
@@ -2040,6 +2049,8 @@ export class RuntimeApi extends WorkerEntrypoint<CoordinatorEnv, undefined> {
2040
2049
  typeof body.lastCheckpointAt === 'number'
2041
2050
  ? body.lastCheckpointAt
2042
2051
  : null,
2052
+ liveNodeProgress:
2053
+ body.liveNodeProgress !== undefined ? body.liveNodeProgress : undefined,
2043
2054
  });
2044
2055
  }
2045
2056
  }
@@ -2110,7 +2121,10 @@ export class CoordinatorControl extends WorkerEntrypoint<
2110
2121
  await appendCoordinatorPerfTrace(this.env, payload);
2111
2122
  }
2112
2123
 
2113
- async recordRunEvent(runId: string, event: CoordinatorRunEvent): Promise<void> {
2124
+ async recordRunEvent(
2125
+ runId: string,
2126
+ event: CoordinatorRunEvent,
2127
+ ): Promise<void> {
2114
2128
  if (!runId || event.runId !== runId) {
2115
2129
  throw new Error('Run event runId mismatch.');
2116
2130
  }
@@ -2280,9 +2294,9 @@ export class DynamicWorkflow extends WorkflowEntrypoint<
2280
2294
  totalRows: output?.totalRows ?? output?.outputRows ?? null,
2281
2295
  durationMs: output?.durationMs ?? null,
2282
2296
  playName:
2283
- typeof output?.playName === 'string'
2284
- ? output.playName
2285
- : null,
2297
+ typeof output?.playName === 'string' ? output.playName : null,
2298
+ liveLogs: sanitizeLiveLogLines(output?.liveLogs),
2299
+ liveNodeProgress: output?.liveNodeProgress ?? null,
2286
2300
  });
2287
2301
  trace({
2288
2302
  runId: runIdForTrace,
@@ -2407,8 +2421,12 @@ const coordinatorEntrypoint = {
2407
2421
  return new Response('unauthorized', { status: 401 });
2408
2422
  }
2409
2423
  const startedAt = Date.now();
2410
- const minAvailableRaw = Number(url.searchParams.get('minAvailable') ?? '');
2411
- const waitTimeoutMsRaw = Number(url.searchParams.get('waitTimeoutMs') ?? '');
2424
+ const minAvailableRaw = Number(
2425
+ url.searchParams.get('minAvailable') ?? '',
2426
+ );
2427
+ const waitTimeoutMsRaw = Number(
2428
+ url.searchParams.get('waitTimeoutMs') ?? '',
2429
+ );
2412
2430
  const result = await refillWorkflowPool(env, {
2413
2431
  waitReady: url.searchParams.get('waitReady') === '1',
2414
2432
  minAvailable:
@@ -3017,6 +3035,9 @@ async function handleWorkflowRoute(input: {
3017
3035
  error: terminalEvent.error ?? null,
3018
3036
  totalRows: terminalEvent.totalRows ?? null,
3019
3037
  durationMs: terminalEvent.durationMs ?? null,
3038
+ completedAt: terminalEvent.ts,
3039
+ liveLogs: sanitizeLiveLogLines(terminalEvent.liveLogs),
3040
+ liveNodeProgress: terminalEvent.liveNodeProgress ?? null,
3020
3041
  events: eventResult?.events ?? [],
3021
3042
  latestSeq: eventResult?.latestSeq ?? afterSeq,
3022
3043
  wait: null,
@@ -3039,8 +3060,7 @@ async function handleWorkflowRoute(input: {
3039
3060
  coordinatorObserve: {
3040
3061
  ms: Date.now() - statusStartedAt,
3041
3062
  waitMs,
3042
- workflowStatus:
3043
- eventResult?.events.length ? 'event' : 'event-timeout',
3063
+ workflowStatus: eventResult?.events.length ? 'event' : 'event-timeout',
3044
3064
  statusPolls: 0,
3045
3065
  instanceId: null,
3046
3066
  },
@@ -3126,27 +3146,31 @@ async function handleWorkflowRoute(input: {
3126
3146
  status: mapWorkflowStatus(await instance.status()),
3127
3147
  });
3128
3148
  }
3129
- if (
3130
- action === 'result' || action === 'status' || action === ''
3131
- ) {
3149
+ if (action === 'result' || action === 'status' || action === '') {
3132
3150
  const includeTrace =
3133
3151
  new URL(request.url).searchParams.get('trace') === '1';
3134
3152
  const statusStartedAt = Date.now();
3135
- const terminalState = await readCoordinatorTerminalState(env, runId).catch(
3136
- () => null,
3137
- );
3153
+ const terminalState = await readCoordinatorTerminalState(
3154
+ env,
3155
+ runId,
3156
+ ).catch(() => null);
3138
3157
  if (terminalState) {
3139
3158
  const coordinatorTrace = includeTrace
3140
3159
  ? await listCoordinatorPerfTrace(env, runId).catch(() => [])
3141
3160
  : [];
3142
3161
  return Response.json({
3143
3162
  runId,
3144
- ...(terminalState.playName ? { playName: terminalState.playName } : {}),
3163
+ ...(terminalState.playName
3164
+ ? { playName: terminalState.playName }
3165
+ : {}),
3145
3166
  status: terminalState.status,
3146
3167
  result: terminalState.result ?? null,
3147
3168
  error: terminalState.error ?? null,
3148
3169
  totalRows: terminalState.totalRows ?? null,
3149
3170
  durationMs: terminalState.durationMs ?? null,
3171
+ completedAt: terminalState.completedAt ?? null,
3172
+ liveLogs: sanitizeLiveLogLines(terminalState.liveLogs),
3173
+ liveNodeProgress: terminalState.liveNodeProgress ?? null,
3150
3174
  wait: null,
3151
3175
  coordinatorObserve: {
3152
3176
  ms: Date.now() - statusStartedAt,
@@ -3228,8 +3252,7 @@ function stableHash(value: string): string {
3228
3252
  return (hash >>> 0).toString(36);
3229
3253
  }
3230
3254
 
3231
- const DYNAMIC_PLAY_WORKER_HARNESS_VERSION =
3232
- 'h6-runtime-api-coordinator-deploy-scoped';
3255
+ const DYNAMIC_PLAY_WORKER_HARNESS_VERSION = 'h7-skip-high-volume-tool-traces';
3233
3256
  const DYNAMIC_WORKER_BUNDLED_CODE_CACHE_MAX_ENTRIES = 64;
3234
3257
  const dynamicWorkerBundledCodeCache = new Map<string, string>();
3235
3258
 
@@ -3614,8 +3637,7 @@ async function handleStagedFilePut(
3614
3637
  if (rawKey) {
3615
3638
  const key = rawKey;
3616
3639
  const contentType =
3617
- url.searchParams.get('contentType')?.trim() ||
3618
- 'application/octet-stream';
3640
+ url.searchParams.get('contentType')?.trim() || 'application/octet-stream';
3619
3641
  const expectedBytes = Number(url.searchParams.get('bytes') ?? 'NaN');
3620
3642
  if (!isAllowedStagedFileStorageKey(key)) {
3621
3643
  return Response.json(
@@ -3674,14 +3696,12 @@ async function handleStagedFilePut(
3674
3696
  timingsMs: { read: readMs, put: putMs },
3675
3697
  });
3676
3698
  }
3677
- const body = (await request.json().catch(() => null)) as
3678
- | {
3679
- key?: unknown;
3680
- contentBase64?: unknown;
3681
- contentType?: unknown;
3682
- bytes?: unknown;
3683
- }
3684
- | null;
3699
+ const body = (await request.json().catch(() => null)) as {
3700
+ key?: unknown;
3701
+ contentBase64?: unknown;
3702
+ contentType?: unknown;
3703
+ bytes?: unknown;
3704
+ } | null;
3685
3705
  const key = typeof body?.key === 'string' ? body.key.trim() : '';
3686
3706
  const contentBase64 =
3687
3707
  typeof body?.contentBase64 === 'string' ? body.contentBase64 : '';
@@ -3691,10 +3711,7 @@ async function handleStagedFilePut(
3691
3711
  : 'application/octet-stream';
3692
3712
  const expectedBytes = typeof body?.bytes === 'number' ? body.bytes : NaN;
3693
3713
  if (!isAllowedStagedFileStorageKey(key)) {
3694
- return Response.json(
3695
- { error: 'invalid staged file key' },
3696
- { status: 400 },
3697
- );
3714
+ return Response.json({ error: 'invalid staged file key' }, { status: 400 });
3698
3715
  }
3699
3716
  if (
3700
3717
  !contentBase64 ||
@@ -4003,10 +4020,7 @@ function makeCoordinatorControlBinding():
4003
4020
  runId: string,
4004
4021
  payload: CoordinatorPerfTracePayload,
4005
4022
  ): Promise<void>;
4006
- recordRunEvent(
4007
- runId: string,
4008
- event: CoordinatorRunEvent,
4009
- ): Promise<void>;
4023
+ recordRunEvent(runId: string, event: CoordinatorRunEvent): Promise<void>;
4010
4024
  };
4011
4025
  };
4012
4026
  const ctor = exports.CoordinatorControl;
@@ -4064,6 +4078,8 @@ function mapWorkflowResult(
4064
4078
  error,
4065
4079
  totalRows: output?.totalRows ?? output?.outputRows ?? null,
4066
4080
  durationMs: output?.durationMs ?? null,
4081
+ liveLogs: sanitizeLiveLogLines(output?.liveLogs),
4082
+ liveNodeProgress: output?.liveNodeProgress ?? null,
4067
4083
  wait:
4068
4084
  mapped === 'sleeping'
4069
4085
  ? {
@@ -16,6 +16,8 @@
16
16
  * Latency: ~5ms per request (DO storage is sub-ms; HTTP add ~3-5ms).
17
17
  */
18
18
 
19
+ import { sanitizeLiveLogLines } from './runtime/live-progress';
20
+
19
21
  type DedupEntry =
20
22
  | { status: 'in_flight'; claimedBy: string; claimedAt: number }
21
23
  | { status: 'completed'; result: unknown; completedAt: number }
@@ -91,6 +93,8 @@ type CoordinatorTerminalState = {
91
93
  totalRows?: unknown;
92
94
  durationMs?: unknown;
93
95
  playName?: string | null;
96
+ liveLogs?: string[] | null;
97
+ liveNodeProgress?: unknown;
94
98
  completedAt: number;
95
99
  };
96
100
 
@@ -120,6 +124,7 @@ type CoordinatorRunEvent =
120
124
  activeNodeId?: string | null;
121
125
  activeArtifactTableNamespace?: string | null;
122
126
  updatedAt?: number | null;
127
+ liveNodeProgress?: unknown;
123
128
  }
124
129
  | {
125
130
  seq: number;
@@ -132,6 +137,8 @@ type CoordinatorRunEvent =
132
137
  totalRows?: unknown;
133
138
  durationMs?: unknown;
134
139
  playName?: string | null;
140
+ liveLogs?: string[] | null;
141
+ liveNodeProgress?: unknown;
135
142
  };
136
143
 
137
144
  type OmitRunEventSequence<T> = T extends unknown ? Omit<T, 'seq'> : never;
@@ -851,7 +858,8 @@ export class PlayDedup implements DurableObject {
851
858
  state: startedAt !== null ? 'started' : 'claimed',
852
859
  blockedInstanceId: null,
853
860
  claimedAt:
854
- existing?.version === version && typeof existing.claimedAt === 'number'
861
+ existing?.version === version &&
862
+ typeof existing.claimedAt === 'number'
855
863
  ? existing.claimedAt
856
864
  : now,
857
865
  startedAt,
@@ -904,7 +912,8 @@ export class PlayDedup implements DurableObject {
904
912
  state: 'blocked',
905
913
  blockedInstanceId: instanceId,
906
914
  claimedAt:
907
- existing?.version === version && typeof existing.claimedAt === 'number'
915
+ existing?.version === version &&
916
+ typeof existing.claimedAt === 'number'
908
917
  ? existing.claimedAt
909
918
  : now,
910
919
  startedAt: null,
@@ -1056,6 +1065,8 @@ export class PlayDedup implements DurableObject {
1056
1065
  totalRows: body.totalRows,
1057
1066
  durationMs: body.durationMs,
1058
1067
  playName: typeof body.playName === 'string' ? body.playName : null,
1068
+ liveLogs: sanitizeLiveLogLines(body.liveLogs),
1069
+ liveNodeProgress: body.liveNodeProgress,
1059
1070
  completedAt:
1060
1071
  typeof body.completedAt === 'number' ? body.completedAt : Date.now(),
1061
1072
  };
@@ -1069,6 +1080,8 @@ export class PlayDedup implements DurableObject {
1069
1080
  totalRows: state.totalRows,
1070
1081
  durationMs: state.durationMs,
1071
1082
  playName: state.playName,
1083
+ liveLogs: state.liveLogs,
1084
+ liveNodeProgress: state.liveNodeProgress,
1072
1085
  ts: state.completedAt,
1073
1086
  });
1074
1087
  this.wakeRunEventWaiters(event);
@@ -1123,9 +1136,9 @@ export class PlayDedup implements DurableObject {
1123
1136
  }
1124
1137
 
1125
1138
  private async handleRunEventAdd(req: Request): Promise<Response> {
1126
- const body = (await req.json().catch(() => null)) as
1127
- | Partial<CoordinatorRunEvent>
1128
- | null;
1139
+ const body = (await req
1140
+ .json()
1141
+ .catch(() => null)) as Partial<CoordinatorRunEvent> | null;
1129
1142
  if (!body || typeof body.runId !== 'string') {
1130
1143
  return new Response('invalid run event', { status: 400 });
1131
1144
  }