@workflow/world-testing 5.0.0-beta.46 → 5.0.0-beta.48

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.
@@ -370,6 +370,8 @@ var init_error_codes = __esm({
370
370
  MAX_EVENTS_EXCEEDED: "MAX_EVENTS_EXCEEDED",
371
371
  /** Workflow replay exceeded the maximum allowed duration */
372
372
  REPLAY_TIMEOUT: "REPLAY_TIMEOUT",
373
+ /** Workflow stream infrastructure failed while reading or writing data */
374
+ STREAM_ERROR: "STREAM_ERROR",
373
375
  /** World response violated the SDK contract and cannot be retried safely */
374
376
  WORLD_CONTRACT_ERROR: "WORLD_CONTRACT_ERROR",
375
377
  /** Run was delivered to a deployment other than the one it is pinned to */
@@ -410,12 +412,13 @@ function buildFramedDetails(hint2, slug) {
410
412
  });
411
413
  return out;
412
414
  }
413
- var BASE_URL, ERROR_SLUGS, WorkflowError, WorkflowWorldError, WorkflowRunFailedError, WorkflowRunNotCompletedError, WorkflowRuntimeError, RuntimeDecryptionError, SerializationError, StepNotRegisteredError, WorkflowNotRegisteredError, WorkflowRunNotFoundError, HookConflictError, HookNotFoundError, EntityConflictError, RunExpiredError, StreamExpiredError, ThrottleError, WorkflowRunCancelledError, FatalError, RetryableError, FATAL_ERROR_KEY, RETRYABLE_ERROR_KEY, HOOK_CONFLICT_ERROR_KEY, RUNTIME_DECRYPTION_ERROR_KEY;
415
+ var BASE_URL, ERROR_SLUGS, WorkflowError, WorkflowWorldError, WorkflowRunFailedError, WorkflowRunNotCompletedError, WorkflowRuntimeError, RuntimeDecryptionError, SerializationError, StepNotRegisteredError, WorkflowNotRegisteredError, WorkflowRunNotFoundError, HookConflictError, HookNotFoundError, EntityConflictError, RunExpiredError, StreamError, StreamExpiredError, ThrottleError, WorkflowRunCancelledError, FatalError, RetryableError, FATAL_ERROR_KEY, RETRYABLE_ERROR_KEY, HOOK_CONFLICT_ERROR_KEY, RUNTIME_DECRYPTION_ERROR_KEY, STREAM_ERROR_KEY;
414
416
  var init_dist2 = __esm({
415
417
  "../errors/dist/index.js"() {
416
418
  "use strict";
417
419
  init_dist();
418
420
  init_error_codes();
421
+ init_error_codes();
419
422
  BASE_URL = "https://workflow-sdk.dev/err";
420
423
  __name(isError, "isError");
421
424
  __name(appendFramedDetails, "appendFramedDetails");
@@ -467,6 +470,12 @@ Caused by: ${options.cause.stack}`;
467
470
  url;
468
471
  /** Retry-After value in seconds, present on 429 and 425 responses */
469
472
  retryAfter;
473
+ /**
474
+ * The offending argument, present on client-side validation failures
475
+ * (`code: 'INVALID_ARGUMENT'`). Lets a caller correct the specific
476
+ * parameter without parsing the message.
477
+ */
478
+ field;
470
479
  constructor(message, options) {
471
480
  super(message, {
472
481
  cause: options?.cause
@@ -476,6 +485,7 @@ Caused by: ${options.cause.stack}`;
476
485
  this.code = options?.code;
477
486
  this.url = options?.url;
478
487
  this.retryAfter = options?.retryAfter;
488
+ this.field = options?.field;
479
489
  }
480
490
  static is(value) {
481
491
  return isError(value) && value.name === "WorkflowWorldError";
@@ -686,6 +696,23 @@ Caused by: ${options.cause.stack}`;
686
696
  return isError(value) && value.name === "RunExpiredError";
687
697
  }
688
698
  };
699
+ StreamError = class extends WorkflowWorldError {
700
+ static {
701
+ __name(this, "StreamError");
702
+ }
703
+ constructor(message, options) {
704
+ super(message, {
705
+ code: RUN_ERROR_CODES.STREAM_ERROR,
706
+ cause: options?.cause,
707
+ url: options?.url,
708
+ status: options?.status
709
+ });
710
+ this.name = "StreamError";
711
+ }
712
+ static is(value) {
713
+ return isError(value) && value.name === "StreamError";
714
+ }
715
+ };
689
716
  StreamExpiredError = class extends WorkflowWorldError {
690
717
  static {
691
718
  __name(this, "StreamExpiredError");
@@ -775,6 +802,7 @@ Caused by: ${options.cause.stack}`;
775
802
  RETRYABLE_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RetryableError");
776
803
  HOOK_CONFLICT_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookConflictError");
777
804
  RUNTIME_DECRYPTION_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RuntimeDecryptionError");
805
+ STREAM_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//StreamError");
778
806
  if (typeof globalThis !== "undefined") {
779
807
  if (!Object.hasOwn(globalThis, FATAL_ERROR_KEY)) {
780
808
  Object.defineProperty(globalThis, FATAL_ERROR_KEY, {
@@ -808,6 +836,14 @@ Caused by: ${options.cause.stack}`;
808
836
  configurable: false
809
837
  });
810
838
  }
839
+ if (!Object.hasOwn(globalThis, STREAM_ERROR_KEY)) {
840
+ Object.defineProperty(globalThis, STREAM_ERROR_KEY, {
841
+ value: StreamError,
842
+ writable: false,
843
+ enumerable: false,
844
+ configurable: false
845
+ });
846
+ }
811
847
  }
812
848
  }
813
849
  });
@@ -2804,6 +2840,7 @@ var RegisteredStepsKey, globalSymbols, registeredSteps, BUILTIN_RESPONSE_STEP_NA
2804
2840
  var init_private = __esm({
2805
2841
  "../core/dist/private.js"() {
2806
2842
  "use strict";
2843
+ init_dist2();
2807
2844
  init_global();
2808
2845
  RegisteredStepsKey = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps");
2809
2846
  globalSymbols = globalThis;
@@ -19108,7 +19145,7 @@ var init_runs = __esm({
19108
19145
  // Completed state - output can be v1 or v2 format
19109
19146
  WorkflowRunBaseSchema.extend({
19110
19147
  status: external_exports.literal("completed"),
19111
- output: SerializedDataSchema,
19148
+ output: SerializedDataSchema.optional(),
19112
19149
  error: external_exports.undefined().optional(),
19113
19150
  completedAt: external_exports.coerce.date()
19114
19151
  }),
@@ -19116,7 +19153,7 @@ var init_runs = __esm({
19116
19153
  WorkflowRunBaseSchema.extend({
19117
19154
  status: external_exports.literal("failed"),
19118
19155
  output: external_exports.undefined().optional(),
19119
- error: SerializedDataSchema,
19156
+ error: SerializedDataSchema.optional(),
19120
19157
  completedAt: external_exports.coerce.date()
19121
19158
  })
19122
19159
  ]);
@@ -19372,8 +19409,8 @@ var init_analytics = __esm({
19372
19409
  AnalyticsAttributeKeySchema = external_exports.object({
19373
19410
  key: external_exports.string(),
19374
19411
  runCount: external_exports.coerce.number(),
19375
- firstSeenAt: external_exports.coerce.date(),
19376
- lastSeenAt: external_exports.coerce.date()
19412
+ firstSeenAt: UTCDateSchema,
19413
+ lastSeenAt: UTCDateSchema
19377
19414
  });
19378
19415
  }
19379
19416
  });
@@ -19509,8 +19546,9 @@ var init_queue = __esm({
19509
19546
  /** Epoch ms immediately before the queue publish was requested. */
19510
19547
  queuePublishRequestedAtMs: external_exports.number(),
19511
19548
  /**
19512
- * Which `resumeHook()` dispatch path ran: `lazy` or `sequential` (`parallel`
19513
- * from producers predating lazy-only resume).
19549
+ * Which `resumeHook()` dispatch path ran. Current producers always report
19550
+ * `sequential` (durable write, then wake); older producers may report
19551
+ * `lazy` or `parallel`.
19514
19552
  */
19515
19553
  strategy: external_exports.string().optional(),
19516
19554
  /** Epoch ms the final consumer's queue handler was entered. */
@@ -19582,9 +19620,9 @@ var init_queue = __esm({
19582
19620
  /** Run creation data, only present on the first queue delivery from start() */
19583
19621
  runInput: RunInputSchema.optional(),
19584
19622
  /**
19585
- * Lazy hook resume data, only present when `resumeHook()` takes the parallel
19586
- * fast path. A consumer that understands this field idempotently ensures the
19587
- * `hook_received` event exists (keyed by `resumeId`) before replaying.
19623
+ * Legacy lazy hook resume data. A consumer that understands this field
19624
+ * idempotently ensures the `hook_received` event exists (keyed by `resumeId`)
19625
+ * before replaying.
19588
19626
  */
19589
19627
  hookInput: HookResumeInputSchema.optional(),
19590
19628
  /**
@@ -19596,7 +19634,7 @@ var init_queue = __esm({
19596
19634
  stepInput: StepDispatchInputSchema.optional(),
19597
19635
  /**
19598
19636
  * Hook-resume TTR timing. Present on both `resumeHook()` dispatch paths
19599
- * (unlike `hookInput`, which only rides the lazy path), and
19637
+ * (unlike legacy `hookInput`), and
19600
19638
  * forwarded onto a dispatched step message when the resuming invocation
19601
19639
  * hands the next durable step to another invocation. Purely observational.
19602
19640
  * See {@link HookResumeTimingSchema}.
@@ -19654,12 +19692,14 @@ var init_hooks = __esm({
19654
19692
  encryptionPublicKey: external_exports.string().optional(),
19655
19693
  // Feature marker: the version of the lazy-hook-resume consumer protocol the
19656
19694
  // run's creating deployment supports. Present (>= 1) means that deployment's
19657
- // `@workflow/core` re-ensures the `hook_received` event from the queue
19658
- // message's `hookInput` on replay, so `resumeHook()`'s lazy path is safe to
19659
- // use. Because a run is pinned to its creating deployment, this
19660
- // marker is a reliable per-run attestation, unlike inferring support from a
19661
- // version compare against a predicted release cutoff. Absent on runs created
19662
- // before the marker existed (fall back to the sequential path).
19695
+ // `@workflow/core` re-ensures the `hook_received` event from a queue
19696
+ // message's `hookInput` on replay. Current producers no longer send
19697
+ // `hookInput` (the durable write happens before the wake is published), so
19698
+ // they never read this marker; it remains stamped so OLDER producers, which
19699
+ // still gate their lazy path on it, keep working against new runs. Because a
19700
+ // run is pinned to its creating deployment, this marker is a reliable
19701
+ // per-run attestation, unlike inferring support from a version compare
19702
+ // against a predicted release cutoff.
19663
19703
  hookResumeInputVersion: external_exports.number().optional()
19664
19704
  });
19665
19705
  HOOK_RESUME_INPUT_VERSION = 1;
@@ -20438,6 +20478,18 @@ function getCommonReducers(_global = globalThis) {
20438
20478
  }
20439
20479
  return reduced;
20440
20480
  }, "RuntimeDecryptionError"),
20481
+ StreamError: /* @__PURE__ */ __name((value) => {
20482
+ const base = reduceNamedErrorSubclassBase("StreamError", value);
20483
+ if (!base) return false;
20484
+ const reduced = {
20485
+ ...base
20486
+ };
20487
+ const status = readProperty(value, "status");
20488
+ const url2 = readProperty(value, "url");
20489
+ if (typeof status === "number") reduced.status = status;
20490
+ if (typeof url2 === "string") reduced.url = url2;
20491
+ return reduced;
20492
+ }, "StreamError"),
20441
20493
  SyntaxError: makeErrorSubclassReducer("SyntaxError"),
20442
20494
  TypeError: makeErrorSubclassReducer("TypeError"),
20443
20495
  URIError: makeErrorSubclassReducer("URIError"),
@@ -20571,6 +20623,18 @@ function getCommonRevivers(global2 = globalThis) {
20571
20623
  if (value.stack !== void 0) error48.stack = value.stack;
20572
20624
  return error48;
20573
20625
  }, "RuntimeDecryptionError"),
20626
+ StreamError: /* @__PURE__ */ __name((value) => {
20627
+ const Ctor = global2[/* @__PURE__ */ Symbol.for("@workflow/errors//StreamError")] ?? StreamError;
20628
+ const error48 = new Ctor(value.message, {
20629
+ ..."cause" in value ? {
20630
+ cause: value.cause
20631
+ } : {},
20632
+ status: value.status,
20633
+ url: value.url
20634
+ });
20635
+ if (value.stack !== void 0) error48.stack = value.stack;
20636
+ return error48;
20637
+ }, "StreamError"),
20574
20638
  SyntaxError: makeErrorSubclassReviver(global2, "SyntaxError"),
20575
20639
  TypeError: makeErrorSubclassReviver(global2, "TypeError"),
20576
20640
  URIError: makeErrorSubclassReviver(global2, "URIError"),
@@ -21227,7 +21291,7 @@ function SemanticConvention(...names) {
21227
21291
  value
21228
21292
  ]));
21229
21293
  }
21230
- var WorkflowName, WorkflowOperation, WorkflowRunId, WorkflowRunStatus, WorkflowStartedAt, WorkflowEventsCount, WorkflowExecutionMode, WorkflowParkedEventsCount, WorkflowParkedEventId, WorkflowParkedEventType, WorkflowArgumentsCount, WorkflowResultType, WorkflowTracePropagated, WorkflowVm, QuickJSOutcome, QuickJSEventsPreloaded, QuickJSEventsFetchedCount, QuickJSEventsFetchedPages, QuickJSPendingOpsCount, QuickJSInlineSteps, WorkflowTraceMode, WorkflowTurbo, WorkflowErrorName, WorkflowErrorMessage, WorkflowErrorCode, WorkflowStepsCreated, WorkflowHooksCreated, WorkflowWaitsCreated, WorkflowStepsFailedSerialization, WorkflowOwnedRecoverySteps, WorkflowBackstopWakesArmed, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, HookToken, HookId, HookFound, HookResilientResume, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, ResumeTotalMs, ResumeProducerPrepMs, ResumeQueueDeliveryMs, ResumeSetupMs, ResumeReplayMs, ResumeStepDispatchMs, ResumeStepClaimMs, ResumeStepPrepareMs, ResumeTrigger, ResumeStrategy, ResumeSetupSource, ResumeStepExecution, WebhookHandlersTriggered, WorkflowSuspensionState, WorkflowSuspensionHookCount, WorkflowSuspensionStepCount, WorkflowSuspensionWaitCount, HttpRequestMethod, HttpRoute, UrlFull, ServerAddress, ServerPort, HttpResponseStatusCode, ErrorType, WorldParseFormat, WorkflowEventsPagesLoaded, QueueDeserializeTimeMs, QueueExecutionTimeMs, QueueSerializeTimeMs, SerializationOperation, SerializationCompressed, SerializationCodec, SerializationUncompressedBytes, SerializationStoredBytes, SerializationCompressionRatio, SerializationGuestCodeExecutions, SerializationGuestCodeDetails, PeerService, RpcSystem, RpcService, RpcMethod, ErrorRetryable, ErrorCategory;
21294
+ var WorkflowName, WorkflowOperation, WorkflowRunId, WorkflowRunStatus, WorkflowStartedAt, WorkflowEventsCount, WorkflowExecutionMode, WorkflowBundleCompileCacheHit, WorkflowReplayLoadSource, WorkflowParkedEventsCount, WorkflowParkedEventId, WorkflowParkedEventType, WorkflowArgumentsCount, WorkflowResultType, WorkflowTracePropagated, WorkflowVm, QuickJSOutcome, QuickJSEventsPreloaded, QuickJSEventsFetchedCount, QuickJSEventsFetchedPages, QuickJSPendingOpsCount, QuickJSInlineSteps, WorkflowTraceMode, WorkflowTurbo, WorkflowErrorName, WorkflowErrorMessage, WorkflowErrorCode, WorkflowStepsCreated, WorkflowHooksCreated, WorkflowWaitsCreated, WorkflowStepsFailedSerialization, WorkflowOwnedRecoverySteps, WorkflowBackstopWakesArmed, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, HookToken, HookId, HookFound, HookResilientResume, HookResumeCommitted, HookWakePublished, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, ResumeTotalMs, ResumeProducerPrepMs, ResumeQueueDeliveryMs, ResumeSetupMs, ResumeReplayMs, ResumeStepDispatchMs, ResumeStepClaimMs, ResumeStepPrepareMs, ResumeTrigger, ResumeStrategy, ResumeSetupSource, ResumeStepExecution, WebhookHandlersTriggered, WorkflowSuspensionState, WorkflowSuspensionHookCount, WorkflowSuspensionStepCount, WorkflowSuspensionWaitCount, HttpRequestMethod, HttpRoute, UrlFull, ServerAddress, ServerPort, HttpResponseStatusCode, ErrorType, WorldParseFormat, WorkflowEventsPagesLoaded, QueueDeserializeTimeMs, QueueExecutionTimeMs, QueueSerializeTimeMs, SerializationOperation, SerializationCompressed, SerializationCodec, SerializationUncompressedBytes, SerializationStoredBytes, SerializationCompressionRatio, SerializationGuestCodeExecutions, SerializationGuestCodeDetails, PeerService, RpcSystem, RpcService, RpcMethod, ErrorRetryable, ErrorCategory;
21231
21295
  var init_semantic_conventions = __esm({
21232
21296
  "../core/dist/telemetry/semantic-conventions.js"() {
21233
21297
  "use strict";
@@ -21239,6 +21303,8 @@ var init_semantic_conventions = __esm({
21239
21303
  WorkflowStartedAt = SemanticConvention("workflow.started_at");
21240
21304
  WorkflowEventsCount = SemanticConvention("workflow.events.count");
21241
21305
  WorkflowExecutionMode = SemanticConvention("workflow.execution.mode");
21306
+ WorkflowBundleCompileCacheHit = SemanticConvention("workflow.bundle.compile.cache_hit");
21307
+ WorkflowReplayLoadSource = SemanticConvention("workflow.replay.load.source");
21242
21308
  WorkflowParkedEventsCount = SemanticConvention("workflow.events.parked.count");
21243
21309
  WorkflowParkedEventId = SemanticConvention("workflow.events.parked.event_id");
21244
21310
  WorkflowParkedEventType = SemanticConvention("workflow.events.parked.event_type");
@@ -21303,6 +21369,8 @@ var init_semantic_conventions = __esm({
21303
21369
  HookId = SemanticConvention("workflow.hook.id");
21304
21370
  HookFound = SemanticConvention("workflow.hook.found");
21305
21371
  HookResilientResume = SemanticConvention("workflow.hook.resilient_resume");
21372
+ HookResumeCommitted = SemanticConvention("workflow.hook.resume_committed");
21373
+ HookWakePublished = SemanticConvention("workflow.hook.wake_published");
21306
21374
  HookResilientResumeMaterialized = SemanticConvention("workflow.hook.resilient_resume_materialized");
21307
21375
  HookResumeSetupSource = SemanticConvention("workflow.resume_setup_source");
21308
21376
  StepResilientDispatchRecovered = SemanticConvention("workflow.step.resilient_dispatch_recovered");
@@ -23405,6 +23473,16 @@ async function deserializeTraceCarrier(traceCarrier) {
23405
23473
  if (!otel) return;
23406
23474
  return otel.propagation.extract(otel.context.active(), traceCarrier);
23407
23475
  }
23476
+ function describeThrownValue(value) {
23477
+ try {
23478
+ if (typeof value === "object" && value !== null && "message" in value && typeof value.message === "string") {
23479
+ return value.message;
23480
+ }
23481
+ return String(value);
23482
+ } catch {
23483
+ return "Unknown error";
23484
+ }
23485
+ }
23408
23486
  function logOtelDiagnosticOnce(otel, tracer) {
23409
23487
  const debugEnabled = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
23410
23488
  if (otelDiagLogged || !debugEnabled) return;
@@ -23459,7 +23537,7 @@ async function trace(spanName, ...args) {
23459
23537
  } else {
23460
23538
  span.setStatus({
23461
23539
  code: otel.SpanStatusCode.ERROR,
23462
- message: e.message
23540
+ message: describeThrownValue(e)
23463
23541
  });
23464
23542
  }
23465
23543
  throw e;
@@ -23552,6 +23630,7 @@ var init_telemetry = __esm({
23552
23630
  });
23553
23631
  });
23554
23632
  otelDiagLogged = false;
23633
+ __name(describeThrownValue, "describeThrownValue");
23555
23634
  __name(logOtelDiagnosticOnce, "logOtelDiagnosticOnce");
23556
23635
  __name(trace, "trace");
23557
23636
  __name(recordElapsedSpan, "recordElapsedSpan");
@@ -25963,7 +26042,7 @@ var version2;
25963
26042
  var init_version = __esm({
25964
26043
  "../core/dist/version.js"() {
25965
26044
  "use strict";
25966
- version2 = "5.0.0-beta.46";
26045
+ version2 = "5.0.0-beta.48";
25967
26046
  }
25968
26047
  });
25969
26048
 
@@ -31094,7 +31173,6 @@ var resume_hook_exports = {};
31094
31173
  __export(resume_hook_exports, {
31095
31174
  getHookByToken: () => getHookByToken,
31096
31175
  resumeHook: () => resumeHook,
31097
- resumeHookDurable: () => resumeHookDurable,
31098
31176
  resumeWebhook: () => resumeWebhook
31099
31177
  });
31100
31178
  async function computeResumePayloadDigest(bytes) {
@@ -31106,6 +31184,38 @@ async function computeResumePayloadDigest(bytes) {
31106
31184
  }
31107
31185
  return hex3;
31108
31186
  }
31187
+ function isRetryableWakeError(error48, isDeploymentUnavailableError) {
31188
+ if (isDeploymentUnavailableError?.(error48)) return false;
31189
+ const status = error48 ?? {};
31190
+ const code2 = status.status ?? status.statusCode;
31191
+ if (typeof code2 === "number") {
31192
+ return code2 >= 500 || code2 === 408 || code2 === 429;
31193
+ }
31194
+ const name = error48?.name;
31195
+ return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
31196
+ }
31197
+ async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
31198
+ let lastError;
31199
+ for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
31200
+ try {
31201
+ await publish();
31202
+ return;
31203
+ } catch (error48) {
31204
+ lastError = error48;
31205
+ if (!isRetryableWakeError(error48, isDeploymentUnavailableError)) break;
31206
+ const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
31207
+ if (delayMs !== void 0) {
31208
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
31209
+ }
31210
+ }
31211
+ }
31212
+ if (HookNotFoundError.is(lastError)) {
31213
+ throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
31214
+ cause: lastError
31215
+ });
31216
+ }
31217
+ throw lastError;
31218
+ }
31109
31219
  function resumeContextFromRun(run2) {
31110
31220
  const coreVersion = run2.executionContext?.workflowCoreVersion;
31111
31221
  const traceCarrier = run2.executionContext?.traceCarrier;
@@ -31163,12 +31273,9 @@ async function getHookByToken(token) {
31163
31273
  return hook;
31164
31274
  }
31165
31275
  async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
31166
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), false);
31167
- }
31168
- async function resumeHookDurable(tokenOrHook, payload, encryptionKeyOverride) {
31169
- return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now(), true);
31276
+ return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
31170
31277
  }
31171
- async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, requireDurableWrite) {
31278
+ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
31172
31279
  return await waitedUntil(() => {
31173
31280
  return trace("hook.resume", async (span) => {
31174
31281
  const world = await getWorldLazy();
@@ -31205,11 +31312,15 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
31205
31312
  }
31206
31313
  const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
31207
31314
  const ops = [];
31315
+ const readbackOps = [];
31208
31316
  const v1Compat = isLegacySpecVersion(hook.specVersion);
31209
- const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression);
31210
- safeWaitUntil(Promise.all(ops), (err) => {
31317
+ const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
31318
+ await Promise.all(ops.map((op) => op.catch((error48) => {
31319
+ if (error48 !== void 0) throw error48;
31320
+ })));
31321
+ safeWaitUntil(Promise.all(readbackOps), (err) => {
31211
31322
  if (err === void 0) return;
31212
- runtimeLogger.warn("Background flush of hook payload ops failed", {
31323
+ runtimeLogger.warn("Background readback of hook payload failed", {
31213
31324
  workflowRunId: hook.runId,
31214
31325
  hookId: hook.hookId,
31215
31326
  error: err instanceof Error ? err.message : String(err)
@@ -31227,81 +31338,66 @@ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookF
31227
31338
  deploymentId: resumeContext.deploymentId,
31228
31339
  specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
31229
31340
  };
31230
- const lazyResumeDisabled = process.env.WORKFLOW_DISABLE_LAZY_HOOK_RESUME === "1";
31231
31341
  const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
31232
- const fallbackReason = requireDurableWrite ? (
31233
- // resolves (an ordering barrier), which only the eager write
31234
- // provides. Checked first so the span names the real reason
31235
- // rather than whichever gate happens to fail alongside it.
31236
- "durable_required"
31237
- ) : lazyResumeDisabled ? "disabled" : !backendDedupSupported ? "backend_unsupported" : (resumeContext.hookResumeInputVersion ?? 0) < HOOK_RESUME_INPUT_VERSION ? "consumer_unsupported" : v1Compat ? "legacy" : (resumeContext.runSpecVersion ?? 0) < SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT ? "non_cbor_transport" : !(dehydratedPayload instanceof Uint8Array) ? "non_bytes" : dehydratedPayload.byteLength > MAX_INLINE_RESUME_PAYLOAD_BYTES ? "oversized" : null;
31238
- const useLazyResume = fallbackReason === null;
31342
+ const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
31239
31343
  span?.setAttributes({
31240
- "workflow.hook.resume_strategy": useLazyResume ? "lazy" : "sequential",
31241
- ...fallbackReason ? {
31242
- "workflow.hook.resume_fallback_reason": fallbackReason
31243
- } : {}
31344
+ "workflow.hook.resume_strategy": "sequential"
31244
31345
  });
31245
- if (!useLazyResume) {
31246
- const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || EntityConflictError.is(err) || RunExpiredError.is(err), "isHookGoneError");
31247
- try {
31248
- await world.events.create(hook.runId, {
31249
- eventType: "hook_received",
31250
- specVersion: SPEC_VERSION_CURRENT,
31251
- correlationId: hook.hookId,
31252
- eventData: {
31253
- ...v1Compat ? {} : {
31254
- token: hook.token
31255
- },
31256
- payload: dehydratedPayload
31257
- }
31258
- }, {
31259
- v1Compat
31260
- });
31261
- } catch (err) {
31262
- if (isHookGoneError(err)) {
31263
- throw new HookNotFoundError(hook.token);
31264
- }
31265
- throw err;
31266
- }
31267
- const queuePublishRequestedAtMs2 = Date.now();
31268
- await world.queue(queueName, {
31269
- runId: hook.runId,
31270
- traceCarrier: resumeContext.traceCarrier ?? void 0,
31271
- hookResumeTiming: {
31272
- resumeRequestedAtMs,
31273
- queuePublishRequestedAtMs: queuePublishRequestedAtMs2,
31274
- strategy: "sequential"
31346
+ const resumeId = canClaimResume ? generateResumeId() : void 0;
31347
+ const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
31348
+ if (resumeId) {
31349
+ span?.setAttributes({
31350
+ "workflow.hook.resume_id": resumeId
31351
+ });
31352
+ }
31353
+ const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || RunExpiredError.is(err), "isHookGoneError");
31354
+ try {
31355
+ await world.events.create(hook.runId, {
31356
+ eventType: "hook_received",
31357
+ specVersion: SPEC_VERSION_CURRENT,
31358
+ correlationId: hook.hookId,
31359
+ eventData: {
31360
+ ...v1Compat ? {} : {
31361
+ token: hook.token
31362
+ },
31363
+ payload: dehydratedPayload
31275
31364
  }
31276
- }, queueOptions);
31277
- return hook;
31365
+ }, {
31366
+ v1Compat,
31367
+ ...resumeId && payloadDigest ? {
31368
+ resumeId,
31369
+ resumePayloadDigest: payloadDigest
31370
+ } : {}
31371
+ });
31372
+ } catch (err) {
31373
+ if (isHookGoneError(err)) {
31374
+ throw new HookNotFoundError(hook.token);
31375
+ }
31376
+ throw err;
31278
31377
  }
31279
- const resumeId = generateResumeId();
31280
- const payloadDigest = await computeResumePayloadDigest(dehydratedPayload);
31281
- span?.setAttributes({
31282
- "workflow.hook.resume_id": resumeId
31283
- });
31378
+ span?.setAttributes(HookResumeCommitted(true));
31284
31379
  const queuePublishRequestedAtMs = Date.now();
31285
- await world.queue(queueName, {
31380
+ await publishHookWakeWithRetry(() => world.queue(queueName, {
31286
31381
  runId: hook.runId,
31287
31382
  traceCarrier: resumeContext.traceCarrier ?? void 0,
31288
- hookInput: {
31289
- resumeId,
31290
- hookId: hook.hookId,
31291
- token: hook.token,
31292
- payload: dehydratedPayload,
31293
- payloadDigest,
31294
- // Deployment affinity for the consumer's cheap pre-write
31295
- // check: lets a misrouted delivery re-route before its
31296
- // hoisted hook_received write instead of after.
31297
- deploymentId: resumeContext.deploymentId
31298
- },
31299
31383
  hookResumeTiming: {
31300
31384
  resumeRequestedAtMs,
31301
31385
  queuePublishRequestedAtMs,
31302
- strategy: "lazy"
31386
+ strategy: "sequential"
31303
31387
  }
31304
- }, queueOptions);
31388
+ }, {
31389
+ ...queueOptions,
31390
+ // Dedup retried publishes whose response was lost: a
31391
+ // duplicate wake is harmless for correctness (deterministic
31392
+ // replay) but costs a full replay of the run, and the queue
31393
+ // accepts a repeated idempotency key by delivering only one
31394
+ // of the messages. Claim-less writes have no resumeId and
31395
+ // keep the previous behavior.
31396
+ ...resumeId ? {
31397
+ idempotencyKey: `hook-${resumeId}`
31398
+ } : {}
31399
+ }), world.isDeploymentUnavailableError?.bind(world));
31400
+ span?.setAttributes(HookWakePublished(true));
31305
31401
  return hook;
31306
31402
  } catch (err) {
31307
31403
  span?.setAttributes({
@@ -31338,7 +31434,7 @@ async function resumeWebhook(token, request) {
31338
31434
  status: 202
31339
31435
  });
31340
31436
  }
31341
- await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs, false);
31437
+ await resumeHookImpl(hook, request, encryptionKey, true, resumeRequestedAtMs);
31342
31438
  if (responseReadable) {
31343
31439
  const reader = responseReadable.getReader();
31344
31440
  const chunk = await reader.read();
@@ -31354,7 +31450,7 @@ async function resumeWebhook(token, request) {
31354
31450
  }
31355
31451
  return response;
31356
31452
  }
31357
- var generateResumeId, MAX_INLINE_RESUME_PAYLOAD_BYTES;
31453
+ var generateResumeId, HOOK_WAKE_RETRY_DELAYS_MS;
31358
31454
  var init_resume_hook = __esm({
31359
31455
  "../core/dist/runtime/resume-hook.js"() {
31360
31456
  "use strict";
@@ -31374,15 +31470,19 @@ var init_resume_hook = __esm({
31374
31470
  init_helpers();
31375
31471
  init_wait_until();
31376
31472
  generateResumeId = monotonicFactory();
31377
- MAX_INLINE_RESUME_PAYLOAD_BYTES = 128 * 1024;
31378
31473
  __name(computeResumePayloadDigest, "computeResumePayloadDigest");
31474
+ HOOK_WAKE_RETRY_DELAYS_MS = [
31475
+ 25,
31476
+ 100
31477
+ ];
31478
+ __name(isRetryableWakeError, "isRetryableWakeError");
31479
+ __name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
31379
31480
  __name(resumeContextFromRun, "resumeContextFromRun");
31380
31481
  __name(resolveHookResumeInfo, "resolveHookResumeInfo");
31381
31482
  __name(resolveHookEncryptionKey, "resolveHookEncryptionKey");
31382
31483
  __name(getHookByTokenWithKey, "getHookByTokenWithKey");
31383
31484
  __name(getHookByToken, "getHookByToken");
31384
31485
  __name(resumeHook, "resumeHook");
31385
- __name(resumeHookDurable, "resumeHookDurable");
31386
31486
  __name(resumeHookImpl, "resumeHookImpl");
31387
31487
  __name(resumeWebhook, "resumeWebhook");
31388
31488
  }
@@ -31650,6 +31750,18 @@ function recordReadTimeToFirstChunk(startEpochMs, runId, name, startIndex, conne
31650
31750
  });
31651
31751
  })();
31652
31752
  }
31753
+ function recordStreamReadKeyResolution(startEpochMs, runId, name, succeeded) {
31754
+ void (async () => {
31755
+ await recordElapsedSpan("workflow.stream.read.resolve_key", startEpochMs, {
31756
+ kind: await getSpanKind("CLIENT"),
31757
+ attributes: {
31758
+ "workflow.run.id": runId,
31759
+ "workflow.stream.name": name,
31760
+ "workflow.stream.read.key_succeeded": succeeded
31761
+ }
31762
+ });
31763
+ })();
31764
+ }
31653
31765
  function recordStreamReadComplete(startEpochMs, runId, name, chunkCount, byteCount, reconnects) {
31654
31766
  void (async () => {
31655
31767
  await recordElapsedSpan("workflow.stream.read.complete", startEpochMs, {
@@ -31668,26 +31780,46 @@ function recordStreamReadComplete(startEpochMs, runId, name, chunkCount, byteCou
31668
31780
  });
31669
31781
  })();
31670
31782
  }
31671
- function createReconnectingFramedStream(runId, name, startIndex) {
31783
+ function createReconnectingFramedStream(runId, name, startIndex, prefetchEncryptionKey = async () => void 0) {
31672
31784
  const reconnectSupported = startIndex === void 0 || startIndex >= 0;
31673
31785
  let currentStartIndex = startIndex ?? 0;
31674
31786
  let consumedFrames = 0;
31675
31787
  let reconnectCount = 0;
31676
31788
  let totalReconnectCount = 0;
31677
31789
  let reader;
31790
+ let canceled = false;
31791
+ let cancelReason;
31678
31792
  let buffer2 = new Uint8Array(0);
31679
31793
  let readStart;
31680
31794
  let connectMs;
31681
31795
  let firstChunkReported = false;
31682
31796
  let chunksDelivered = 0;
31683
31797
  let bytesDelivered = 0;
31798
+ let keyPrefetched = false;
31799
+ function prefetchKey() {
31800
+ if (keyPrefetched) return;
31801
+ keyPrefetched = true;
31802
+ const keyStart = Date.now();
31803
+ void prefetchEncryptionKey().then((key) => {
31804
+ if (key) recordStreamReadKeyResolution(keyStart, runId, name, true);
31805
+ }, () => recordStreamReadKeyResolution(keyStart, runId, name, false));
31806
+ }
31807
+ __name(prefetchKey, "prefetchKey");
31684
31808
  async function connect() {
31809
+ if (canceled) return false;
31685
31810
  const world = await getWorldLazy();
31811
+ if (canceled) return false;
31686
31812
  const effectiveStartIndex = reconnectSupported ? currentStartIndex + consumedFrames : startIndex;
31687
31813
  const connectStart = Date.now();
31688
31814
  const stream = await world.streams.get(runId, name, effectiveStartIndex);
31815
+ if (canceled) {
31816
+ await stream.cancel(cancelReason).catch(() => {
31817
+ });
31818
+ return false;
31819
+ }
31689
31820
  if (connectMs === void 0) connectMs = Date.now() - connectStart;
31690
31821
  reader = stream.getReader();
31822
+ return true;
31691
31823
  }
31692
31824
  __name(connect, "connect");
31693
31825
  async function isVerifiedComplete() {
@@ -31701,11 +31833,13 @@ function createReconnectingFramedStream(runId, name, startIndex) {
31701
31833
  }
31702
31834
  __name(isVerifiedComplete, "isVerifiedComplete");
31703
31835
  async function reconnect() {
31836
+ if (canceled) return false;
31704
31837
  if (reader) {
31705
31838
  await reader.cancel().catch(() => {
31706
31839
  });
31707
31840
  reader = void 0;
31708
31841
  }
31842
+ if (canceled) return false;
31709
31843
  currentStartIndex += consumedFrames;
31710
31844
  consumedFrames = 0;
31711
31845
  buffer2 = new Uint8Array(0);
@@ -31715,15 +31849,16 @@ function createReconnectingFramedStream(runId, name, startIndex) {
31715
31849
  reconnectCount++;
31716
31850
  totalReconnectCount++;
31717
31851
  if (reconnectCount > maxReconnects) {
31718
- throw new Error(`Stream "${name}" exceeded maximum reconnection attempts (${maxReconnects})`);
31852
+ throw new StreamError(`Stream "${name}" exceeded maximum reconnection attempts (${maxReconnects})`);
31719
31853
  }
31720
31854
  if (totalReconnectCount > maxTotalReconnects) {
31721
- throw new Error(`Stream "${name}" exceeded maximum total reconnection attempts (${maxTotalReconnects})`);
31855
+ throw new StreamError(`Stream "${name}" exceeded maximum total reconnection attempts (${maxTotalReconnects})`);
31722
31856
  }
31723
31857
  try {
31724
- await connect();
31725
- return;
31858
+ if (!await connect()) return false;
31859
+ return true;
31726
31860
  } catch (error48) {
31861
+ if (canceled) return false;
31727
31862
  if (StreamExpiredError.is(error48)) throw error48;
31728
31863
  }
31729
31864
  }
@@ -31731,12 +31866,15 @@ function createReconnectingFramedStream(runId, name, startIndex) {
31731
31866
  __name(reconnect, "reconnect");
31732
31867
  return new ReadableStream({
31733
31868
  pull: /* @__PURE__ */ __name(async (controller) => {
31869
+ if (canceled) return;
31734
31870
  if (readStart === void 0) readStart = Date.now();
31871
+ prefetchKey();
31735
31872
  for (; ; ) {
31736
31873
  if (!reader) {
31737
31874
  try {
31738
- await connect();
31875
+ if (!await connect()) return;
31739
31876
  } catch (err) {
31877
+ if (canceled) return;
31740
31878
  controller.error(err);
31741
31879
  return;
31742
31880
  }
@@ -31745,23 +31883,27 @@ function createReconnectingFramedStream(runId, name, startIndex) {
31745
31883
  try {
31746
31884
  result = await reader.read();
31747
31885
  } catch (err) {
31886
+ if (canceled) return;
31748
31887
  if (!reconnectSupported) {
31749
31888
  controller.error(err);
31750
31889
  return;
31751
31890
  }
31752
31891
  try {
31753
- await reconnect();
31892
+ if (!await reconnect()) return;
31754
31893
  } catch (reconnectErr) {
31755
31894
  controller.error(reconnectErr);
31756
31895
  return;
31757
31896
  }
31758
31897
  continue;
31759
31898
  }
31899
+ if (canceled) return;
31760
31900
  if (result.done || !result.value) {
31761
31901
  reader = void 0;
31762
- if (reconnectSupported && !await isVerifiedComplete()) {
31902
+ const verifiedComplete = !reconnectSupported || await isVerifiedComplete();
31903
+ if (canceled) return;
31904
+ if (!verifiedComplete) {
31763
31905
  try {
31764
- await reconnect();
31906
+ if (!await reconnect()) return;
31765
31907
  } catch (reconnectErr) {
31766
31908
  controller.error(reconnectErr);
31767
31909
  return;
@@ -31803,12 +31945,15 @@ function createReconnectingFramedStream(runId, name, startIndex) {
31803
31945
  }
31804
31946
  }
31805
31947
  }, "pull"),
31806
- cancel: /* @__PURE__ */ __name(async () => {
31807
- if (reader) {
31808
- await reader.cancel().catch((err) => {
31948
+ cancel: /* @__PURE__ */ __name(async (reason) => {
31949
+ canceled = true;
31950
+ cancelReason = reason;
31951
+ const currentReader = reader;
31952
+ reader = void 0;
31953
+ if (currentReader) {
31954
+ await currentReader.cancel(reason).catch((err) => {
31809
31955
  console.warn("Error closing ReadableStream reader:", err);
31810
31956
  });
31811
- reader = void 0;
31812
31957
  }
31813
31958
  }, "cancel")
31814
31959
  });
@@ -31945,7 +32090,7 @@ function attachAbortListenerOnce(signal, streamName, runId, cryptoKey, ops) {
31945
32090
  once: true
31946
32091
  });
31947
32092
  }
31948
- function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
32093
+ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier, readbackOps = ops) {
31949
32094
  return {
31950
32095
  ...getAllBaseReducers(global2),
31951
32096
  ReadableStream: /* @__PURE__ */ __name((value) => {
@@ -31966,7 +32111,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
31966
32111
  ops.push(value.pipeTo(writable));
31967
32112
  }
31968
32113
  } else {
31969
- ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
32114
+ ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier, readbackOps), cryptoKey)).pipeTo(writable));
31970
32115
  }
31971
32116
  const s = {
31972
32117
  name
@@ -31997,7 +32142,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
31997
32142
  const streamId = (global2[STABLE_ULID] || defaultUlid)();
31998
32143
  const name = `strm_${streamId}`;
31999
32144
  const readable = new WorkflowServerReadableStream(runId, name);
32000
- ops.push(readable.pipeTo(value));
32145
+ readbackOps.push(readable.pipeTo(value));
32001
32146
  return {
32002
32147
  name
32003
32148
  };
@@ -32096,7 +32241,7 @@ function getWorkflowReducers(global2 = globalThis) {
32096
32241
  }, "AbortSignal")
32097
32242
  };
32098
32243
  }
32099
- function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
32244
+ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier, readbackOps = ops) {
32100
32245
  return {
32101
32246
  ...getAllBaseReducers(global2),
32102
32247
  ReadableStream: /* @__PURE__ */ __name((value) => {
@@ -32122,7 +32267,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
32122
32267
  ops.push(value.pipeTo(writable));
32123
32268
  }
32124
32269
  } else {
32125
- ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
32270
+ ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier, readbackOps), cryptoKey)).pipeTo(writable));
32126
32271
  }
32127
32272
  }
32128
32273
  const s = {
@@ -32139,7 +32284,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
32139
32284
  if (!name) {
32140
32285
  const streamId = (global2[STABLE_ULID] || defaultUlid)();
32141
32286
  name = `strm_${streamId}`;
32142
- ops.push(new WorkflowServerReadableStream(runId, name).pipeThrough(getDeserializeStream(getStepRevivers(global2, ops, runId, cryptoKey), cryptoKey)).pipeTo(value));
32287
+ readbackOps.push(new WorkflowServerReadableStream(runId, name).pipeThrough(getDeserializeStream(getStepRevivers(global2, readbackOps, runId, cryptoKey), cryptoKey)).pipeTo(value));
32143
32288
  }
32144
32289
  const s = {
32145
32290
  name
@@ -32268,8 +32413,8 @@ function reviveAbortController(value, ops, runId) {
32268
32413
  if (value.hookToken) {
32269
32414
  const hookResume = (async () => {
32270
32415
  try {
32271
- const { resumeHookDurable: resumeHookDurable2 } = await Promise.resolve().then(() => (init_resume_hook(), resume_hook_exports));
32272
- await resumeHookDurable2(value.hookToken, {
32416
+ const { resumeHook: resumeHook2 } = await Promise.resolve().then(() => (init_resume_hook(), resume_hook_exports));
32417
+ await resumeHook2(value.hookToken, {
32273
32418
  aborted: true,
32274
32419
  reason
32275
32420
  });
@@ -32313,7 +32458,51 @@ async function getForwardedWritableEncryptionKey(runId, deploymentId, encryption
32313
32458
  "encrypt"
32314
32459
  ]) : void 0;
32315
32460
  }
32316
- function getExternalRevivers(global2 = globalThis, ops, runId, cryptoKey) {
32461
+ function getRunReadableStream(global2, ops, runId, name, startIndex, cryptoKey) {
32462
+ let reader;
32463
+ let lockState;
32464
+ let lockPollingStarted = false;
32465
+ let userReadable;
32466
+ userReadable = new ReadableStream(
32467
+ {
32468
+ async pull(controller) {
32469
+ try {
32470
+ if (!reader) {
32471
+ const stream = getExternalRevivers(global2, ops, runId, cryptoKey, {
32472
+ onReadableState: /* @__PURE__ */ __name((state) => {
32473
+ lockState = state;
32474
+ }, "onReadableState")
32475
+ }).ReadableStream({
32476
+ name,
32477
+ startIndex
32478
+ });
32479
+ reader = stream.getReader();
32480
+ if (lockState && !lockPollingStarted) {
32481
+ lockPollingStarted = true;
32482
+ pollReadableLock(userReadable, lockState);
32483
+ }
32484
+ }
32485
+ const result = await reader.read();
32486
+ if (result.done) controller.close();
32487
+ else controller.enqueue(result.value);
32488
+ } catch (error48) {
32489
+ controller.error(error48);
32490
+ }
32491
+ },
32492
+ async cancel(reason) {
32493
+ await reader?.cancel(reason).catch(() => {
32494
+ });
32495
+ }
32496
+ },
32497
+ // A positive default high-water mark would run pull at construction to
32498
+ // fill the queue, turning an unread Run.getReadable() into I/O.
32499
+ {
32500
+ highWaterMark: 0
32501
+ }
32502
+ );
32503
+ return userReadable;
32504
+ }
32505
+ function getExternalRevivers(global2 = globalThis, ops, runId, cryptoKey, options) {
32317
32506
  return {
32318
32507
  ...getCommonRevivers2(global2),
32319
32508
  // StepFunction should not be returned from workflows to clients
@@ -32361,16 +32550,23 @@ function getExternalRevivers(global2 = globalThis, ops, runId, cryptoKey) {
32361
32550
  const { readable: userReadable, writable } = value.framing === "framed-v1" ? getByteUnframingStream() : new global2.TransformStream();
32362
32551
  flushablePipe(readable, writable, state).catch(() => {
32363
32552
  });
32364
- pollReadableLock(userReadable, state);
32553
+ if (options?.onReadableState) options.onReadableState(state);
32554
+ else pollReadableLock(userReadable, state);
32365
32555
  return userReadable;
32366
32556
  } else {
32367
- const readable = createReconnectingFramedStream(runId, value.name, value.startIndex);
32368
- const transform2 = getDeserializeStream(getExternalRevivers(global2, ops, runId, cryptoKey), cryptoKey);
32557
+ let keyPromise;
32558
+ const resolveKey = /* @__PURE__ */ __name(() => {
32559
+ keyPromise ??= resolveEncryptionKey(cryptoKey);
32560
+ return keyPromise;
32561
+ }, "resolveKey");
32562
+ const readable = createReconnectingFramedStream(runId, value.name, value.startIndex, resolveKey);
32563
+ const transform2 = getDeserializeStream(getExternalRevivers(global2, ops, runId, resolveKey), resolveKey);
32369
32564
  const state = createFlushableState();
32370
32565
  ops.push(state.promise);
32371
32566
  flushablePipe(readable, transform2.writable, state).catch(() => {
32372
32567
  });
32373
- pollReadableLock(transform2.readable, state);
32568
+ if (options?.onReadableState) options.onReadableState(state);
32569
+ else pollReadableLock(transform2.readable, state);
32374
32570
  return transform2.readable;
32375
32571
  }
32376
32572
  }, "ReadableStream"),
@@ -32581,16 +32777,16 @@ function getStepRevivers(global2 = globalThis, ops, runId, cryptoKey, deployment
32581
32777
  AbortSignal: /* @__PURE__ */ __name((value) => reviveAbortSignal(value, ops, runId), "AbortSignal")
32582
32778
  };
32583
32779
  }
32584
- async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
32780
+ async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, readbackOps = ops) {
32585
32781
  if (v1Compat) {
32586
- const str = stringify(value, getExternalReducers(global2, ops, runId, key, framedByteStreams));
32782
+ const str = stringify(value, getExternalReducers(global2, ops, runId, key, framedByteStreams, void 0, readbackOps));
32587
32783
  return revive(str);
32588
32784
  }
32589
32785
  try {
32590
32786
  const compressionStats = {};
32591
32787
  const result = await serialize(value, key, {
32592
32788
  global: global2,
32593
- extraReducers: getStreamAndRequestReducers(getExternalReducers(global2, ops, runId, key, framedByteStreams)),
32789
+ extraReducers: getStreamAndRequestReducers(getExternalReducers(global2, ops, runId, key, framedByteStreams, void 0, readbackOps)),
32594
32790
  compression,
32595
32791
  compressionStats
32596
32792
  });
@@ -32660,16 +32856,16 @@ async function hydrateStepArguments(value, runId, key, ops = [], global2 = globa
32660
32856
  await recordCompression(compressionStats, "deserialize");
32661
32857
  return result;
32662
32858
  }
32663
- async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, runReadyBarrier) {
32859
+ async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, runReadyBarrier, readbackOps = ops) {
32664
32860
  if (v1Compat) {
32665
- const str = stringify(value, getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier));
32861
+ const str = stringify(value, getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier, readbackOps));
32666
32862
  return revive(str);
32667
32863
  }
32668
32864
  try {
32669
32865
  const compressionStats = {};
32670
32866
  const result = await serialize2(value, key, {
32671
32867
  global: global2,
32672
- extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier)),
32868
+ extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier, readbackOps)),
32673
32869
  compression,
32674
32870
  compressionStats
32675
32871
  });
@@ -32766,6 +32962,7 @@ var init_serialization2 = __esm({
32766
32962
  __name(getByteFramingStream, "getByteFramingStream");
32767
32963
  __name(getByteUnframingStream, "getByteUnframingStream");
32768
32964
  __name(recordReadTimeToFirstChunk, "recordReadTimeToFirstChunk");
32965
+ __name(recordStreamReadKeyResolution, "recordStreamReadKeyResolution");
32769
32966
  __name(recordStreamReadComplete, "recordStreamReadComplete");
32770
32967
  WorkflowServerReadableStream = class extends ReadableStream {
32771
32968
  static {
@@ -33080,6 +33277,7 @@ var init_serialization2 = __esm({
33080
33277
  __name(reviveAbortSignal, "reviveAbortSignal");
33081
33278
  __name(getCommonRevivers2, "getCommonRevivers");
33082
33279
  __name(getForwardedWritableEncryptionKey, "getForwardedWritableEncryptionKey");
33280
+ __name(getRunReadableStream, "getRunReadableStream");
33083
33281
  __name(getExternalRevivers, "getExternalRevivers");
33084
33282
  __name(getStepRevivers, "getStepRevivers");
33085
33283
  __name(dehydrateWorkflowArguments, "dehydrateWorkflowArguments");
@@ -33258,7 +33456,8 @@ var WORLD_CONTRACT_ERROR_CODES = /* @__PURE__ */ new Set([
33258
33456
  ]);
33259
33457
  var RETRYABLE_WORLD_ERROR_CODES = /* @__PURE__ */ new Set([
33260
33458
  "TRANSPORT",
33261
- "TIMEOUT"
33459
+ "TIMEOUT",
33460
+ RUN_ERROR_CODES.STREAM_ERROR
33262
33461
  ]);
33263
33462
  var RUNTIME_ERROR_CHECKS = [
33264
33463
  WorkflowRuntimeError.is,
@@ -33274,6 +33473,9 @@ function isRetryableWorldError(err) {
33274
33473
  if (ThrottleError.is(err)) {
33275
33474
  return true;
33276
33475
  }
33476
+ if (StreamError.is(err)) {
33477
+ return err.status === void 0 || err.status >= 500;
33478
+ }
33277
33479
  if (!WorkflowWorldError.is(err)) {
33278
33480
  return false;
33279
33481
  }
@@ -33460,9 +33662,9 @@ async function start(workflow, argsOrOptions, options) {
33460
33662
  },
33461
33663
  // Attest that the *consumer* deployment's runtime re-ensures a
33462
33664
  // `hook_received` event from a queue message's `hookInput` on replay.
33463
- // A resume of this run reads the marker (mirrored onto the hook's
33464
- // resumeContext by the server) to decide whether the parallel fast
33465
- // path is safe. For a cross-deployment start the consumer is the
33665
+ // An OLDER producer resuming this run reads the marker (mirrored onto
33666
+ // the hook's resumeContext by the server) to decide whether its lazy
33667
+ // fast path is safe. For a cross-deployment start the consumer is the
33466
33668
  // target deployment, so we stamp the *target's* value carried back on
33467
33669
  // the health-check probe, never the caller's. Omitted when we could
33468
33670
  // not attest the target (older target, timeout, or no probe channel),
@@ -33573,7 +33775,7 @@ __name(start, "start");
33573
33775
  value: "start",
33574
33776
  configurable: true
33575
33777
  });
33576
- })(start, "step//@workflow/core/runtime/start@5.0.0-beta.46//start");
33778
+ })(start, "step//@workflow/core/runtime/start@5.0.0-beta.48//start");
33577
33779
 
33578
33780
  // ../core/dist/runtime/runs.js
33579
33781
  async function wakeUpRun(world, runId, options) {
@@ -33757,9 +33959,9 @@ var Run = class _Run {
33757
33959
  return this.#encryptionKeyPromise;
33758
33960
  }
33759
33961
  /**
33760
- * Defer fetching the run and its encryption key until serialized stream data
33761
- * is actually read. An empty or metadata-only stream must not start an
33762
- * unobserved run lookup.
33962
+ * Defers fetching the run and its encryption key until a readable is first
33963
+ * consumed. The first pull prefetches it so an encrypted first frame can join
33964
+ * the lookup; this also applies to an empty consumed stream.
33763
33965
  * @internal
33764
33966
  */
33765
33967
  #getEncryptionKeyLazily() {
@@ -33870,10 +34072,7 @@ var Run = class _Run {
33870
34072
  const { ops = [], global: global2 = globalThis, startIndex, namespace } = options;
33871
34073
  const name = getWorkflowRunStreamId(this.runId, namespace);
33872
34074
  const encryptionKey = this.#getEncryptionKeyLazily();
33873
- const stream = getExternalRevivers(global2, ops, this.runId, encryptionKey).ReadableStream({
33874
- name,
33875
- startIndex
33876
- });
34075
+ const stream = getRunReadableStream(global2, ops, this.runId, name, startIndex, encryptionKey);
33877
34076
  const worldPromise = this.#lazyWorldPromise;
33878
34077
  const runId = this.runId;
33879
34078
  return Object.assign(stream, {
@@ -33972,7 +34171,7 @@ var Run = class _Run {
33972
34171
  value: "wakeUp",
33973
34172
  configurable: true
33974
34173
  });
33975
- })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#wakeUp");
34174
+ })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#wakeUp");
33976
34175
  (function(__wf_fn, __wf_id) {
33977
34176
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33978
34177
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33981,7 +34180,7 @@ var Run = class _Run {
33981
34180
  value: "cancel",
33982
34181
  configurable: true
33983
34182
  });
33984
- })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#cancel");
34183
+ })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#cancel");
33985
34184
  (function(__wf_fn, __wf_id) {
33986
34185
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33987
34186
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33990,7 +34189,7 @@ var Run = class _Run {
33990
34189
  value: "getReadable",
33991
34190
  configurable: true
33992
34191
  });
33993
- })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#getReadable");
34192
+ })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#getReadable");
33994
34193
  (function(__wf_fn, __wf_id) {
33995
34194
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
33996
34195
  __wf_reg.set(__wf_id, __wf_fn);
@@ -33999,7 +34198,7 @@ var Run = class _Run {
33999
34198
  value: "exists",
34000
34199
  configurable: true
34001
34200
  });
34002
- })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#exists");
34201
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#exists");
34003
34202
  (function(__wf_fn, __wf_id) {
34004
34203
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34005
34204
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34008,7 +34207,7 @@ var Run = class _Run {
34008
34207
  value: "status",
34009
34208
  configurable: true
34010
34209
  });
34011
- })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#status");
34210
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#status");
34012
34211
  (function(__wf_fn, __wf_id) {
34013
34212
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34014
34213
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34017,7 +34216,7 @@ var Run = class _Run {
34017
34216
  value: "returnValue",
34018
34217
  configurable: true
34019
34218
  });
34020
- })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#returnValue");
34219
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#returnValue");
34021
34220
  (function(__wf_fn, __wf_id) {
34022
34221
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34023
34222
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34026,7 +34225,7 @@ var Run = class _Run {
34026
34225
  value: "workflowName",
34027
34226
  configurable: true
34028
34227
  });
34029
- })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#workflowName");
34228
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#workflowName");
34030
34229
  (function(__wf_fn, __wf_id) {
34031
34230
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34032
34231
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34035,7 +34234,7 @@ var Run = class _Run {
34035
34234
  value: "createdAt",
34036
34235
  configurable: true
34037
34236
  });
34038
- })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#createdAt");
34237
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#createdAt");
34039
34238
  (function(__wf_fn, __wf_id) {
34040
34239
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34041
34240
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34044,7 +34243,7 @@ var Run = class _Run {
34044
34243
  value: "startedAt",
34045
34244
  configurable: true
34046
34245
  });
34047
- })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#startedAt");
34246
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#startedAt");
34048
34247
  (function(__wf_fn, __wf_id) {
34049
34248
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34050
34249
  __wf_reg.set(__wf_id, __wf_fn);
@@ -34053,7 +34252,7 @@ var Run = class _Run {
34053
34252
  value: "completedAt",
34054
34253
  configurable: true
34055
34254
  });
34056
- })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.46//Run#completedAt");
34255
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.48//Run#completedAt");
34057
34256
  (function(__wf_cls, __wf_id) {
34058
34257
  var __wf_sym = /* @__PURE__ */ Symbol.for("workflow-class-registry"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
34059
34258
  __wf_reg.set(__wf_id, __wf_cls);
@@ -34063,7 +34262,7 @@ var Run = class _Run {
34063
34262
  enumerable: false,
34064
34263
  configurable: false
34065
34264
  });
34066
- })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.46//Run");
34265
+ })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.48//Run");
34067
34266
 
34068
34267
  // ../workflow/dist/stdlib.js
34069
34268
  async function fetch2(...args) {