@workflow/world-testing 5.0.0-beta.55 → 5.0.0-beta.57

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.
@@ -412,7 +412,7 @@ function buildFramedDetails(hint2, slug) {
412
412
  });
413
413
  return out;
414
414
  }
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;
415
+ var BASE_URL, ERROR_SLUGS, WorkflowError, WorkflowWorldError, WorkflowRunFailedError, WorkflowRunNotCompletedError, WorkflowRuntimeError, RuntimeDecryptionError, SerializationError, StepNotRegisteredError, WorkflowNotRegisteredError, WorkflowRunNotFoundError, HookConflictError, HookForceClaimedError, HookNotFoundError, EntityConflictError, RunExpiredError, StreamError, StreamExpiredError, ThrottleError, WorkflowRunCancelledError, FatalError, RetryableError, FATAL_ERROR_KEY, RETRYABLE_ERROR_KEY, HOOK_CONFLICT_ERROR_KEY, HOOK_FORCE_CLAIMED_ERROR_KEY, RUNTIME_DECRYPTION_ERROR_KEY, STREAM_ERROR_KEY;
416
416
  var init_dist2 = __esm({
417
417
  "../errors/dist/index.js"() {
418
418
  "use strict";
@@ -432,6 +432,7 @@ var init_dist2 = __esm({
432
432
  FETCH_IN_WORKFLOW_FUNCTION: "fetch-in-workflow",
433
433
  TIMEOUT_FUNCTIONS_IN_WORKFLOW: "timeout-in-workflow",
434
434
  HOOK_CONFLICT: "hook-conflict",
435
+ HOOK_FORCE_CLAIMED: "hook-force-claimed",
435
436
  CORRUPTED_EVENT_LOG: "corrupted-event-log",
436
437
  REPLAY_DIVERGENCE: "replay-divergence",
437
438
  STEP_NOT_REGISTERED: "step-not-registered",
@@ -495,6 +496,17 @@ Caused by: ${options.cause.stack}`;
495
496
  static {
496
497
  __name(this, "WorkflowRunFailedError");
497
498
  }
499
+ /**
500
+ * `failed` is terminal, and a run's terminal state is immutable. This error
501
+ * is only ever thrown after a *successful* read of such a run, so re-running
502
+ * the read returns the same record and throws the same error. Marking it
503
+ * non-retryable is what stops the step executor from spending a retry budget
504
+ * on that when the read happens inside a step — a parent awaiting a child's
505
+ * `returnValue` — and then replacing this error with its retry-exhaustion
506
+ * wrapper. A read that *fails* throws something else and stays retryable.
507
+ * See `FatalError.is()`.
508
+ */
509
+ fatal = true;
498
510
  runId;
499
511
  /**
500
512
  * The high-level error category (e.g. USER_ERROR, RUNTIME_ERROR) for the
@@ -658,6 +670,30 @@ Caused by: ${options.cause.stack}`;
658
670
  return isError(value) && value.name === "HookConflictError";
659
671
  }
660
672
  };
673
+ HookForceClaimedError = class extends WorkflowError {
674
+ static {
675
+ __name(this, "HookForceClaimedError");
676
+ }
677
+ token;
678
+ /** The run that took the token. */
679
+ claimedByRunId;
680
+ /** The hook (in `claimedByRunId`) the token now belongs to. */
681
+ claimedByHookId;
682
+ constructor(token, claimedByRunId, claimedByHookId) {
683
+ super(`Hook token "${token}" was force-claimed by another workflow (run "${claimedByRunId}")`, {
684
+ slug: ERROR_SLUGS.HOOK_FORCE_CLAIMED
685
+ });
686
+ this.name = "HookForceClaimedError";
687
+ this.token = token;
688
+ this.claimedByRunId = claimedByRunId;
689
+ if (claimedByHookId !== void 0) {
690
+ this.claimedByHookId = claimedByHookId;
691
+ }
692
+ }
693
+ static is(value) {
694
+ return isError(value) && value.name === "HookForceClaimedError";
695
+ }
696
+ };
661
697
  HookNotFoundError = class extends WorkflowError {
662
698
  static {
663
699
  __name(this, "HookNotFoundError");
@@ -761,6 +797,8 @@ Caused by: ${options.cause.stack}`;
761
797
  static {
762
798
  __name(this, "WorkflowRunCancelledError");
763
799
  }
800
+ /** Terminal and immutable, for the same reason as {@link WorkflowRunFailedError.fatal}. */
801
+ fatal = true;
764
802
  runId;
765
803
  constructor(runId) {
766
804
  super(`Workflow run "${runId}" cancelled`, {});
@@ -810,6 +848,7 @@ Caused by: ${options.cause.stack}`;
810
848
  FATAL_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//FatalError");
811
849
  RETRYABLE_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RetryableError");
812
850
  HOOK_CONFLICT_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookConflictError");
851
+ HOOK_FORCE_CLAIMED_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError");
813
852
  RUNTIME_DECRYPTION_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//RuntimeDecryptionError");
814
853
  STREAM_ERROR_KEY = /* @__PURE__ */ Symbol.for("@workflow/errors//StreamError");
815
854
  if (typeof globalThis !== "undefined") {
@@ -837,6 +876,14 @@ Caused by: ${options.cause.stack}`;
837
876
  configurable: false
838
877
  });
839
878
  }
879
+ if (!Object.hasOwn(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY)) {
880
+ Object.defineProperty(globalThis, HOOK_FORCE_CLAIMED_ERROR_KEY, {
881
+ value: HookForceClaimedError,
882
+ writable: false,
883
+ enumerable: false,
884
+ configurable: false
885
+ });
886
+ }
840
887
  if (!Object.hasOwn(globalThis, RUNTIME_DECRYPTION_ERROR_KEY)) {
841
888
  Object.defineProperty(globalThis, RUNTIME_DECRYPTION_ERROR_KEY, {
842
889
  value: RuntimeDecryptionError,
@@ -904,27 +951,6 @@ var init_env_config = __esm({
904
951
  }
905
952
  });
906
953
 
907
- // ../world/dist/spec-version.js
908
- function isLegacySpecVersion(v) {
909
- return v === void 0 || v === null || v <= SPEC_VERSION_LEGACY;
910
- }
911
- var SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_ATTRIBUTES, SPEC_VERSION_SUPPORTS_COMPRESSION, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY, SPEC_VERSION_SUPPORTS_SEALED_LOG, SPEC_VERSION_CURRENT, SPEC_VERSION_MAX_SUPPORTED;
912
- var init_spec_version = __esm({
913
- "../world/dist/spec-version.js"() {
914
- "use strict";
915
- init_env_config();
916
- SPEC_VERSION_LEGACY = 1;
917
- SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT = 3;
918
- SPEC_VERSION_SUPPORTS_ATTRIBUTES = 4;
919
- SPEC_VERSION_SUPPORTS_COMPRESSION = 5;
920
- SPEC_VERSION_SUPPORTS_SLOT_IDENTITY = 6;
921
- SPEC_VERSION_SUPPORTS_SEALED_LOG = 7;
922
- SPEC_VERSION_CURRENT = SPEC_VERSION_SUPPORTS_SEALED_LOG;
923
- SPEC_VERSION_MAX_SUPPORTED = SPEC_VERSION_SUPPORTS_SEALED_LOG;
924
- __name(isLegacySpecVersion, "isLegacySpecVersion");
925
- }
926
- });
927
-
928
954
  // ../core/dist/encryption.js
929
955
  async function importKey(raw, usages = [
930
956
  "encrypt",
@@ -24904,7 +24930,30 @@ var init_events = __esm({
24904
24930
  tokenRetentionUntil: external_exports.coerce.date().optional(),
24905
24931
  metadata: SerializedDataSchema.optional(),
24906
24932
  isWebhook: external_exports.boolean().optional(),
24907
- isSystem: external_exports.boolean().optional()
24933
+ isSystem: external_exports.boolean().optional(),
24934
+ /**
24935
+ * `createHook({ experimental_force: true })`: when the token belongs to
24936
+ * another live run, the World takes it over — journaling
24937
+ * `hook_disposed{forceClaimedBy}` in that run's log and re-pointing the
24938
+ * token — instead of answering `hook_conflict`. Requires the
24939
+ * `hookForceClaim` capability.
24940
+ */
24941
+ force: external_exports.boolean().optional(),
24942
+ /**
24943
+ * World-written on a forced creation that did take a token over: the
24944
+ * run and hook it was taken from, plus what a queue message to that run
24945
+ * needs (`workflowName`, `deploymentId`, `runSpecVersion`). Absent when
24946
+ * the token was free. The wake-targeting fields are in the LOG, not only
24947
+ * on the hook entity, so a replay can republish the victim's wake from
24948
+ * the row alone; see `publishForceClaimVictimWake` in @workflow/core.
24949
+ */
24950
+ forceClaimedFrom: external_exports.object({
24951
+ runId: external_exports.string(),
24952
+ hookId: external_exports.string(),
24953
+ workflowName: external_exports.string().optional(),
24954
+ deploymentId: external_exports.string().optional(),
24955
+ runSpecVersion: external_exports.number().optional()
24956
+ }).optional()
24908
24957
  })
24909
24958
  }));
24910
24959
  HookReceivedEventSchema = external_exports.compile(BaseEventSchema.extend({
@@ -24919,7 +24968,17 @@ var init_events = __esm({
24919
24968
  eventType: external_exports.literal("hook_disposed"),
24920
24969
  correlationId: external_exports.string(),
24921
24970
  eventData: external_exports.object({
24922
- token: external_exports.string().optional()
24971
+ token: external_exports.string().optional(),
24972
+ /**
24973
+ * World-written: this disposal was not the run's own. Another run
24974
+ * took the hook's token with `experimental_force`, and this names
24975
+ * it. The hook consumer rejects the hook's awaiters with
24976
+ * `HookForceClaimedError` when it reads this row.
24977
+ */
24978
+ forceClaimedBy: external_exports.object({
24979
+ runId: external_exports.string(),
24980
+ hookId: external_exports.string()
24981
+ }).optional()
24923
24982
  }).optional()
24924
24983
  }));
24925
24984
  HookConflictEventSchema = external_exports.compile(BaseEventSchema.extend({
@@ -24929,7 +24988,18 @@ var init_events = __esm({
24929
24988
  token: external_exports.string(),
24930
24989
  // TODO: Make this required once all persisted hook_conflict events and
24931
24990
  // remote World implementations always include the active hook owner's run ID.
24932
- conflictingRunId: external_exports.string().optional()
24991
+ conflictingRunId: external_exports.string().optional(),
24992
+ /**
24993
+ * Set when the creation asked for `force` and the World declined to take
24994
+ * the token over. `victim-spec-version`: the run holding the token was
24995
+ * started at a spec version below
24996
+ * `SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM`, so its runtime would not
24997
+ * understand the involuntary disposal — the forced hook gets the
24998
+ * ordinary `HookConflictError` it opted out of instead of stranding
24999
+ * that run. Absent on a conflict answered by a World that does not
25000
+ * implement forcing at all.
25001
+ */
25002
+ forceRefusedReason: external_exports.literal("victim-spec-version").optional()
24933
25003
  })
24934
25004
  }));
24935
25005
  NoopEventSchema = external_exports.compile(BaseEventSchema.extend({
@@ -25790,7 +25860,7 @@ var init_queue = __esm({
25790
25860
  });
25791
25861
 
25792
25862
  // ../world/dist/hooks.js
25793
- var HookResumeContextSchema, HOOK_RESUME_INPUT_VERSION, HOOK_RESUME_DEDUP_VERSION, HookResumeCapabilitiesSchema, HookSchema;
25863
+ var HookResumeContextSchema, HOOK_RESUME_INPUT_VERSION, HOOK_RESUME_DEDUP_VERSION, HookResumeCapabilitiesSchema, HookClaimedFromSchema, HookSchema;
25794
25864
  var init_hooks = __esm({
25795
25865
  "../world/dist/hooks.js"() {
25796
25866
  "use strict";
@@ -25831,6 +25901,13 @@ var init_hooks = __esm({
25831
25901
  // is engaged.
25832
25902
  hookResumeDedupVersion: external_exports.number()
25833
25903
  }));
25904
+ HookClaimedFromSchema = external_exports.compile(external_exports.object({
25905
+ runId: external_exports.string(),
25906
+ hookId: external_exports.string(),
25907
+ workflowName: external_exports.string().optional(),
25908
+ deploymentId: external_exports.string().optional(),
25909
+ runSpecVersion: external_exports.number().optional()
25910
+ }));
25834
25911
  HookSchema = external_exports.compile(external_exports.object({
25835
25912
  runId: external_exports.string(),
25836
25913
  hookId: external_exports.string(),
@@ -25858,7 +25935,12 @@ var init_hooks = __esm({
25858
25935
  // `resumeHook()` gates its lazy path on this being present and
25859
25936
  // current. Absent against an older/rolled-back server or when the kill switch
25860
25937
  // is active.
25861
- resumeCapabilities: HookResumeCapabilitiesSchema.optional()
25938
+ resumeCapabilities: HookResumeCapabilitiesSchema.optional(),
25939
+ // Set when this hook took its token from another run
25940
+ // (`experimental_force`). The wake-targeting fields are the victim run's,
25941
+ // so the claimer's runtime can publish the victim's wake without reading
25942
+ // a run it may not be able to reach; see `HookClaimedFromSchema`.
25943
+ claimedFrom: HookClaimedFromSchema.optional()
25862
25944
  }));
25863
25945
  }
25864
25946
  });
@@ -25919,6 +26001,28 @@ var init_slot_identity = __esm({
25919
26001
  }
25920
26002
  });
25921
26003
 
26004
+ // ../world/dist/spec-version.js
26005
+ function isLegacySpecVersion(v) {
26006
+ return v === void 0 || v === null || v <= SPEC_VERSION_LEGACY;
26007
+ }
26008
+ var SPEC_VERSION_LEGACY, SPEC_VERSION_SUPPORTS_EVENT_SOURCING, SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT, SPEC_VERSION_SUPPORTS_ATTRIBUTES, SPEC_VERSION_SUPPORTS_COMPRESSION, SPEC_VERSION_SUPPORTS_SLOT_IDENTITY, SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM, SPEC_VERSION_CURRENT, SPEC_VERSION_MAX_SUPPORTED;
26009
+ var init_spec_version = __esm({
26010
+ "../world/dist/spec-version.js"() {
26011
+ "use strict";
26012
+ init_env_config();
26013
+ SPEC_VERSION_LEGACY = 1;
26014
+ SPEC_VERSION_SUPPORTS_EVENT_SOURCING = 2;
26015
+ SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT = 3;
26016
+ SPEC_VERSION_SUPPORTS_ATTRIBUTES = 4;
26017
+ SPEC_VERSION_SUPPORTS_COMPRESSION = 5;
26018
+ SPEC_VERSION_SUPPORTS_SLOT_IDENTITY = 6;
26019
+ SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM = 8;
26020
+ SPEC_VERSION_CURRENT = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM;
26021
+ SPEC_VERSION_MAX_SUPPORTED = SPEC_VERSION_SUPPORTS_HOOK_FORCE_CLAIM;
26022
+ __name(isLegacySpecVersion, "isLegacySpecVersion");
26023
+ }
26024
+ });
26025
+
25922
26026
  // ../world/dist/ulid.js
25923
26027
  var UlidSchema, workflowRunIdSchema, DEFAULT_TIMESTAMP_THRESHOLD_PAST_MS, DEFAULT_TIMESTAMP_THRESHOLD_FUTURE_MS;
25924
26028
  var init_ulid = __esm({
@@ -26549,6 +26653,20 @@ function getCommonReducers(_global = globalThis) {
26549
26653
  }
26550
26654
  return reduced;
26551
26655
  }, "HookConflictError"),
26656
+ HookForceClaimedError: /* @__PURE__ */ __name((value) => {
26657
+ const base = reduceNamedErrorSubclassBase("HookForceClaimedError", value);
26658
+ if (!base) return false;
26659
+ const reduced = {
26660
+ ...base,
26661
+ token: readProperty(value, "token"),
26662
+ claimedByRunId: readProperty(value, "claimedByRunId")
26663
+ };
26664
+ const claimedByHookId = readProperty(value, "claimedByHookId");
26665
+ if (claimedByHookId !== void 0) {
26666
+ reduced.claimedByHookId = claimedByHookId;
26667
+ }
26668
+ return reduced;
26669
+ }, "HookForceClaimedError"),
26552
26670
  RangeError: makeErrorSubclassReducer("RangeError"),
26553
26671
  ReferenceError: makeErrorSubclassReducer("ReferenceError"),
26554
26672
  // RetryableError carries an extra `retryAfter` Date that we serialize as
@@ -26723,6 +26841,15 @@ function getCommonRevivers(global2 = globalThis) {
26723
26841
  }
26724
26842
  return error61;
26725
26843
  }, "HookConflictError"),
26844
+ HookForceClaimedError: /* @__PURE__ */ __name((value) => {
26845
+ const Ctor = global2[/* @__PURE__ */ Symbol.for("@workflow/errors//HookForceClaimedError")] ?? HookForceClaimedError;
26846
+ const error61 = new Ctor(value.token, value.claimedByRunId, value.claimedByHookId);
26847
+ if (value.stack !== void 0) error61.stack = value.stack;
26848
+ if ("cause" in value) {
26849
+ error61.cause = value.cause;
26850
+ }
26851
+ return error61;
26852
+ }, "HookForceClaimedError"),
26726
26853
  RangeError: makeErrorSubclassReviver(global2, "RangeError"),
26727
26854
  ReferenceError: makeErrorSubclassReviver(global2, "ReferenceError"),
26728
26855
  RetryableError: /* @__PURE__ */ __name((value) => {
@@ -27427,7 +27554,7 @@ function SemanticConvention(...names) {
27427
27554
  value
27428
27555
  ]));
27429
27556
  }
27430
- 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, WorkflowDispatchRepublishSkipped, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepStartStrategy, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, MessagingBatchMessageCount, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, HookToken, HookId, HookFound, HookResilientResume, HookResumeCommitted, HookWakePublished, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, StepDispatchPrologue, 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;
27557
+ 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, WorkflowDispatchRepublishSkipped, WorkflowRouteType, WorkflowRouteHandlerCached, WorkflowRouteInvocationCount, WorkflowRouteEntrypointAgeMs, WorkflowRouteModuleBodyInitMs, FaasInstance, StepName, StepId, StepAttempt, StepStatus, StepMaxRetries, StepTracePropagated, StepTtfsMs, StepStsoMs, StepRsfsMs, StepFinalSchedulingReplayMs, StepLatencyOptimizations, StepStartStrategy, StepSkipped, StepSkipReason, StepArgumentsCount, StepResultType, StepErrorName, StepErrorMessage, StepFatalError, StepRetryExhausted, StepRetryTimeoutSeconds, StepRetryWillRetry, MessagingSystem, MessagingDestinationName, MessagingMessageId, MessagingOperationType, MessagingBatchMessageCount, QueueOverheadMs, DeploymentId, WorkflowRunPinnedDeploymentId, WorkflowDeploymentMismatchRetryCount, WorkflowDeploymentMismatchRecovered, WorkflowRunSpecVersion, WorkflowRunSpecVersionSource, WorkflowCapabilityProbeLatencyMs, WorkflowCapabilityProbeCached, WorkflowCapabilityProbeError, HookToken, HookId, HookFound, HookResilientResume, HookResumeCommitted, HookWakePublished, HookResilientResumeMaterialized, HookResumeSetupSource, StepResilientDispatchRecovered, StepResilientDispatchMaterialized, StepDispatchPrologue, 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;
27431
27558
  var init_semantic_conventions = __esm({
27432
27559
  "../core/dist/telemetry/semantic-conventions.js"() {
27433
27560
  "use strict";
@@ -27504,6 +27631,11 @@ var init_semantic_conventions = __esm({
27504
27631
  WorkflowRunPinnedDeploymentId = SemanticConvention("workflow.deployment.pinned_id");
27505
27632
  WorkflowDeploymentMismatchRetryCount = SemanticConvention("workflow.deployment_mismatch.retry_count");
27506
27633
  WorkflowDeploymentMismatchRecovered = SemanticConvention("workflow.deployment_mismatch.recovered");
27634
+ WorkflowRunSpecVersion = SemanticConvention("workflow.run.spec_version");
27635
+ WorkflowRunSpecVersionSource = SemanticConvention("workflow.run.spec_version_source");
27636
+ WorkflowCapabilityProbeLatencyMs = SemanticConvention("workflow.capability_probe.latency_ms");
27637
+ WorkflowCapabilityProbeCached = SemanticConvention("workflow.capability_probe.cached");
27638
+ WorkflowCapabilityProbeError = SemanticConvention("workflow.capability_probe.error");
27507
27639
  HookToken = SemanticConvention("workflow.hook.token");
27508
27640
  HookId = SemanticConvention("workflow.hook.id");
27509
27641
  HookFound = SemanticConvention("workflow.hook.found");
@@ -32182,7 +32314,7 @@ var version2;
32182
32314
  var init_version = __esm({
32183
32315
  "../core/dist/version.js"() {
32184
32316
  "use strict";
32185
- version2 = "5.0.0-beta.55";
32317
+ version2 = "5.0.0-beta.57";
32186
32318
  }
32187
32319
  });
32188
32320
 
@@ -32250,7 +32382,8 @@ function parseHealthCheckResponse(chunks) {
32250
32382
  } catch {
32251
32383
  if (responseText.length > 0) {
32252
32384
  return {
32253
- healthy: true
32385
+ healthy: true,
32386
+ format: "text"
32254
32387
  };
32255
32388
  }
32256
32389
  return null;
@@ -32260,7 +32393,8 @@ function parseHealthCheckResponse(chunks) {
32260
32393
  }
32261
32394
  const r = response;
32262
32395
  const parsed = {
32263
- healthy: r.healthy
32396
+ healthy: r.healthy,
32397
+ format: "json"
32264
32398
  };
32265
32399
  if (typeof r.specVersion === "number") {
32266
32400
  parsed.specVersion = r.specVersion;
@@ -32361,6 +32495,57 @@ var init_helpers = __esm({
32361
32495
  }
32362
32496
  });
32363
32497
 
32498
+ // ../core/dist/runtime/hook-wake.js
32499
+ function isRetryableWakeError(error61, isDeploymentUnavailableError) {
32500
+ if (isDeploymentUnavailableError?.(error61)) return false;
32501
+ const status = error61 ?? {};
32502
+ const code2 = status.status ?? status.statusCode;
32503
+ if (typeof code2 === "number") {
32504
+ return code2 >= 500 || code2 === 408 || code2 === 429;
32505
+ }
32506
+ const name = error61?.name;
32507
+ return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
32508
+ }
32509
+ async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
32510
+ let lastError;
32511
+ for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
32512
+ try {
32513
+ await publish();
32514
+ return;
32515
+ } catch (error61) {
32516
+ lastError = error61;
32517
+ if (!isRetryableWakeError(error61, isDeploymentUnavailableError)) break;
32518
+ const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
32519
+ if (delayMs !== void 0) {
32520
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
32521
+ }
32522
+ }
32523
+ }
32524
+ if (HookNotFoundError.is(lastError)) {
32525
+ throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
32526
+ cause: lastError
32527
+ });
32528
+ }
32529
+ throw lastError;
32530
+ }
32531
+ var HOOK_WAKE_RETRY_DELAYS_MS, FORCE_CLAIM_WAKE_REPUBLISH_WINDOW_MS;
32532
+ var init_hook_wake = __esm({
32533
+ "../core/dist/runtime/hook-wake.js"() {
32534
+ "use strict";
32535
+ init_dist2();
32536
+ init_dist4();
32537
+ init_logger();
32538
+ init_helpers();
32539
+ HOOK_WAKE_RETRY_DELAYS_MS = [
32540
+ 25,
32541
+ 100
32542
+ ];
32543
+ __name(isRetryableWakeError, "isRetryableWakeError");
32544
+ __name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
32545
+ FORCE_CLAIM_WAKE_REPUBLISH_WINDOW_MS = 24 * 60 * 60 * 1e3;
32546
+ }
32547
+ });
32548
+
32364
32549
  // ../core/dist/runtime/invocations.js
32365
32550
  var HookInvocationSchema, HookInvocationResultSchema;
32366
32551
  var init_invocations = __esm({
@@ -32393,6 +32578,18 @@ var init_invocations = __esm({
32393
32578
  }
32394
32579
  });
32395
32580
 
32581
+ // ../core/dist/runtime/run-spec-version.js
32582
+ function specVersionForRunWrite(runSpecVersion, whenUnknown = SPEC_VERSION_CURRENT) {
32583
+ return Math.min(SPEC_VERSION_CURRENT, runSpecVersion ?? whenUnknown);
32584
+ }
32585
+ var init_run_spec_version = __esm({
32586
+ "../core/dist/runtime/run-spec-version.js"() {
32587
+ "use strict";
32588
+ init_spec_version();
32589
+ __name(specVersionForRunWrite, "specVersionForRunWrite");
32590
+ }
32591
+ });
32592
+
32396
32593
  // ../../node_modules/.pnpm/@vercel+functions@3.8.0_@aws-sdk+credential-provider-web-identity@3.972.49_ws@8.20.0/node_modules/@vercel/functions/headers.js
32397
32594
  var require_headers = __commonJS({
32398
32595
  "../../node_modules/.pnpm/@vercel+functions@3.8.0_@aws-sdk+credential-provider-web-identity@3.972.49_ws@8.20.0/node_modules/@vercel/functions/headers.js"(exports, module) {
@@ -37356,38 +37553,6 @@ async function computeResumePayloadDigest(bytes) {
37356
37553
  }
37357
37554
  return hex3;
37358
37555
  }
37359
- function isRetryableWakeError(error61, isDeploymentUnavailableError) {
37360
- if (isDeploymentUnavailableError?.(error61)) return false;
37361
- const status = error61 ?? {};
37362
- const code2 = status.status ?? status.statusCode;
37363
- if (typeof code2 === "number") {
37364
- return code2 >= 500 || code2 === 408 || code2 === 429;
37365
- }
37366
- const name = error61?.name;
37367
- return name !== "BadRequestError" && name !== "UnauthorizedError" && name !== "ForbiddenError";
37368
- }
37369
- async function publishHookWakeWithRetry(publish, isDeploymentUnavailableError) {
37370
- let lastError;
37371
- for (let attempt = 0; attempt <= HOOK_WAKE_RETRY_DELAYS_MS.length; attempt++) {
37372
- try {
37373
- await publish();
37374
- return;
37375
- } catch (error61) {
37376
- lastError = error61;
37377
- if (!isRetryableWakeError(error61, isDeploymentUnavailableError)) break;
37378
- const delayMs = HOOK_WAKE_RETRY_DELAYS_MS[attempt];
37379
- if (delayMs !== void 0) {
37380
- await new Promise((resolve) => setTimeout(resolve, delayMs));
37381
- }
37382
- }
37383
- }
37384
- if (HookNotFoundError.is(lastError)) {
37385
- throw new WorkflowRuntimeError("The hook resume was committed, but its workflow wake could not be published", {
37386
- cause: lastError
37387
- });
37388
- }
37389
- throw lastError;
37390
- }
37391
37556
  function resumeContextFromRun(run2) {
37392
37557
  const coreVersion = run2.executionContext?.workflowCoreVersion;
37393
37558
  const traceCarrier = run2.executionContext?.traceCarrier;
@@ -37469,163 +37634,268 @@ async function getHookByToken(token) {
37469
37634
  async function resumeHook(tokenOrHook, payload, encryptionKeyOverride) {
37470
37635
  return resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, false, Date.now());
37471
37636
  }
37472
- async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs) {
37637
+ async function resumeHookImpl(tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, webhookOnly = false) {
37473
37638
  return await waitedUntil(() => {
37474
37639
  return trace("hook.resume", async (span) => {
37475
37640
  const world = await getWorldLazy();
37476
- try {
37477
- const suppliedToken = typeof tokenOrHook === "string";
37478
- const hook = suppliedToken ? await world.hooks.getByToken(tokenOrHook) : tokenOrHook;
37479
- const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
37480
- const info = await resolveHookResumeInfo(hook);
37481
- const { resumeContext } = info;
37482
- span?.setAttributes({
37483
- ...HookToken(hook.token),
37484
- ...HookId(hook.hookId),
37485
- ...WorkflowRunId(hook.runId),
37486
- "workflow.hook.resume_context_source": info.source
37487
- });
37488
- if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
37489
- throw new HookNotFoundError(hook.token);
37490
- }
37491
- const capabilities = getRunCapabilities(resumeContext.workflowCoreVersion);
37492
- let payloadKey;
37493
- const runPublicKey = encryptionKeyOverride ? (
37494
- // hydrate hook metadata), so sealing would add an ECDH for no
37495
- // saved round trip. Reuse what it resolved.
37496
- void 0
37497
- ) : decodeRunPublicKey(resumeContext.encryptionPublicKey);
37498
- if (runPublicKey) {
37499
- payloadKey = sealTo(runPublicKey);
37500
- } else {
37501
- let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey(hook, info);
37502
- if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
37503
- encryptionKey = void 0;
37504
- }
37505
- payloadKey = encryptionKey;
37506
- }
37507
- const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
37508
- const ops = [];
37509
- const readbackOps = [];
37510
- const v1Compat = isLegacySpecVersion(hook.specVersion);
37511
- const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
37512
- await Promise.all(ops.map((op) => op.catch((error61) => {
37513
- if (error61 !== void 0) throw error61;
37514
- })));
37515
- safeWaitUntil(Promise.all(readbackOps), (err) => {
37516
- if (err === void 0) return;
37517
- runtimeLogger.warn("Background readback of hook payload failed", {
37518
- workflowRunId: hook.runId,
37519
- hookId: hook.hookId,
37520
- error: err instanceof Error ? err.message : String(err)
37521
- });
37522
- });
37523
- span?.setAttributes({
37524
- ...WorkflowName(resumeContext.workflowName)
37525
- });
37526
- const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
37527
- if (originLink) {
37528
- span?.addLink?.(originLink);
37529
- }
37530
- if (world.capabilities?.invoke === true && !v1Compat && dehydratedPayload instanceof Uint8Array) {
37531
- if (!world.invoke) {
37532
- throw new WorkflowRuntimeError("World advertises invoke without implementing it");
37533
- }
37641
+ const token = typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token;
37642
+ let target = tokenOrHook;
37643
+ let fresh = hookFreshlyLookedUp;
37644
+ let keyOverride = encryptionKeyOverride;
37645
+ let redirects = 0;
37646
+ let lookupsAfterRedirect = 0;
37647
+ const MAX_LOOKUPS_AFTER_REDIRECT = 5;
37648
+ const resumeId = generateResumeId();
37649
+ const assertResendable = /* @__PURE__ */ __name((cause) => {
37650
+ if (payload instanceof Request && payload.body !== null && payload.bodyUsed) {
37534
37651
  span?.setAttributes({
37535
- "workflow.hook.resume_strategy": "invoke"
37652
+ "workflow.hook.resume_redirect_unresendable": true
37536
37653
  });
37537
- const result = HookInvocationResultSchema.parse(await world.invoke(hook.runId, {
37538
- type: "hook_resume",
37539
- version: 1,
37540
- hookId: hook.hookId,
37541
- token: hook.token,
37542
- payload: dehydratedPayload
37543
- }, {
37544
- idempotencyKey: generateResumeId()
37545
- }));
37546
- if (result.status === "rejected") {
37547
- if (result.code === "HOOK_NOT_FOUND") throw new HookNotFoundError(hook.token);
37548
- throw new WorkflowRuntimeError("Executor rejected the hook invocation input");
37549
- }
37550
- span?.setAttributes(HookResumeCommitted(true));
37551
- return asLazyMetadataHook(hook);
37552
- }
37553
- const queueName = getWorkflowQueueName(resumeContext.workflowName);
37554
- const queueOptions = {
37555
- deploymentId: resumeContext.deploymentId,
37556
- specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
37557
- };
37558
- const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
37559
- const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
37560
- span?.setAttributes({
37561
- "workflow.hook.resume_strategy": "sequential"
37562
- });
37563
- const resumeId = canClaimResume ? generateResumeId() : void 0;
37564
- const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
37565
- if (resumeId) {
37566
- span?.setAttributes({
37567
- "workflow.hook.resume_id": resumeId
37654
+ throw new WorkflowRuntimeError(`Hook token "${token}" changed owner while this webhook request was being delivered; a request body can be sent only once and it was not delivered anywhere \u2014 retry the request, which will reach the token's new owner`, {
37655
+ cause
37568
37656
  });
37569
37657
  }
37570
- const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || RunExpiredError.is(err), "isHookGoneError");
37658
+ }, "assertResendable");
37659
+ for (; ; ) {
37571
37660
  try {
37572
- await world.events.create(hook.runId, {
37573
- eventType: "hook_received",
37574
- specVersion: SPEC_VERSION_CURRENT,
37575
- correlationId: hook.hookId,
37576
- eventData: {
37577
- ...v1Compat ? {} : {
37578
- token: hook.token
37579
- },
37580
- payload: dehydratedPayload
37581
- }
37582
- }, {
37583
- v1Compat,
37584
- ...resumeId && payloadDigest ? {
37585
- resumeId,
37586
- resumePayloadDigest: payloadDigest
37587
- } : {}
37588
- });
37661
+ return await resumeHookAttempt(world, span, target, payload, keyOverride, fresh, resumeRequestedAtMs, resumeId, webhookOnly);
37589
37662
  } catch (err) {
37590
- if (isHookGoneError(err)) {
37591
- throw new HookNotFoundError(hook.token);
37663
+ if (err !== null && typeof err === "object" && notFoundReasons.get(err) === "not-webhook") {
37664
+ throw err;
37665
+ }
37666
+ if (redirects >= MAX_FORCE_CLAIM_REDIRECTS) {
37667
+ if (HookForceClaimedError.is(err)) {
37668
+ span?.setAttributes({
37669
+ "workflow.hook.resume_redirects_exhausted": true
37670
+ });
37671
+ throw new WorkflowRuntimeError(`Hook token "${token}" changed owner ${redirects} times while this resume was in flight; nothing was delivered \u2014 retry the resume`, {
37672
+ cause: err
37673
+ });
37674
+ }
37675
+ throw err;
37676
+ }
37677
+ if (HookForceClaimedError.is(err)) {
37678
+ assertResendable(err);
37679
+ redirects++;
37680
+ span?.setAttributes({
37681
+ "workflow.hook.resume_redirects": redirects,
37682
+ "workflow.hook.resume_redirect_to_run": err.claimedByRunId
37683
+ });
37684
+ target = token;
37685
+ fresh = true;
37686
+ keyOverride = void 0;
37687
+ lookupsAfterRedirect = 0;
37688
+ continue;
37689
+ }
37690
+ if (HookNotFoundError.is(err) && redirects > 0 && typeof target === "string" && lookupsAfterRedirect < MAX_LOOKUPS_AFTER_REDIRECT) {
37691
+ assertResendable(err);
37692
+ lookupsAfterRedirect++;
37693
+ await new Promise((resolve) => setTimeout(resolve, 50));
37694
+ continue;
37695
+ }
37696
+ if (HookNotFoundError.is(err) && notFoundReasons.get(err) !== "lookup") {
37697
+ const attemptedHookId = typeof target === "string" ? void 0 : target.hookId;
37698
+ let relocated;
37699
+ try {
37700
+ relocated = await world.hooks.getByToken(token);
37701
+ } catch (lookupError) {
37702
+ if (!HookNotFoundError.is(lookupError)) {
37703
+ runtimeLogger.warn("Hook resume: re-resolving the token after a not-found failed; surfacing the original error", {
37704
+ token,
37705
+ error: lookupError instanceof Error ? lookupError.message : String(lookupError)
37706
+ });
37707
+ }
37708
+ }
37709
+ if (relocated?.claimedFrom !== void 0 && relocated.hookId !== attemptedHookId && (attemptedHookId === void 0 || relocated.claimedFrom.hookId === attemptedHookId) && !(webhookOnly && relocated.isWebhook === false)) {
37710
+ assertResendable(err);
37711
+ redirects++;
37712
+ span?.setAttributes({
37713
+ "workflow.hook.resume_redirects": redirects,
37714
+ "workflow.hook.resume_redirect_to_run": relocated.runId
37715
+ });
37716
+ target = relocated;
37717
+ fresh = true;
37718
+ keyOverride = void 0;
37719
+ continue;
37720
+ }
37592
37721
  }
37593
37722
  throw err;
37594
37723
  }
37595
- span?.setAttributes(HookResumeCommitted(true));
37596
- const queuePublishRequestedAtMs = Date.now();
37597
- await publishHookWakeWithRetry(() => world.queue(queueName, {
37598
- runId: hook.runId,
37599
- traceCarrier: resumeContext.traceCarrier ?? void 0,
37600
- hookResumeTiming: {
37601
- resumeRequestedAtMs,
37602
- queuePublishRequestedAtMs,
37603
- strategy: "sequential"
37604
- }
37605
- }, {
37606
- ...queueOptions,
37607
- // Dedup retried publishes whose response was lost: a
37608
- // duplicate wake is harmless for correctness (deterministic
37609
- // replay) but costs a full replay of the run, and the queue
37610
- // accepts a repeated idempotency key by delivering only one
37611
- // of the messages. Claim-less writes have no resumeId and
37612
- // keep the previous behavior.
37613
- ...resumeId ? {
37614
- idempotencyKey: `hook-${resumeId}`
37615
- } : {}
37616
- }), world.isDeploymentUnavailableError?.bind(world));
37617
- span?.setAttributes(HookWakePublished(true));
37618
- return asLazyMetadataHook(hook);
37619
- } catch (err) {
37620
- span?.setAttributes({
37621
- ...HookToken(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
37622
- ...HookFound(false)
37623
- });
37624
- throw err;
37625
37724
  }
37626
37725
  });
37627
37726
  });
37628
37727
  }
37728
+ async function resumeHookAttempt(world, span, tokenOrHook, payload, encryptionKeyOverride, hookFreshlyLookedUp, resumeRequestedAtMs, logicalResumeId, webhookOnly) {
37729
+ try {
37730
+ const suppliedToken = typeof tokenOrHook === "string";
37731
+ let hook;
37732
+ if (suppliedToken) {
37733
+ try {
37734
+ hook = await world.hooks.getByToken(tokenOrHook);
37735
+ } catch (lookupError) {
37736
+ if (HookNotFoundError.is(lookupError)) {
37737
+ notFoundReasons.set(lookupError, "lookup");
37738
+ }
37739
+ throw lookupError;
37740
+ }
37741
+ } else {
37742
+ hook = tokenOrHook;
37743
+ }
37744
+ if (webhookOnly && hook.isWebhook === false) {
37745
+ const notWebhook = new HookNotFoundError(hook.token);
37746
+ notFoundReasons.set(notWebhook, "not-webhook");
37747
+ throw notWebhook;
37748
+ }
37749
+ const hookResumeCapabilitiesAreFresh = suppliedToken || hookFreshlyLookedUp;
37750
+ const info = await resolveHookResumeInfo(hook);
37751
+ const { resumeContext } = info;
37752
+ span?.setAttributes({
37753
+ ...HookToken(hook.token),
37754
+ ...HookId(hook.hookId),
37755
+ ...WorkflowRunId(hook.runId),
37756
+ "workflow.hook.resume_context_source": info.source
37757
+ });
37758
+ if (info.run && isTerminalWorkflowRunStatus(info.run.status)) {
37759
+ throw new HookNotFoundError(hook.token);
37760
+ }
37761
+ const capabilities = getRunCapabilities(resumeContext.workflowCoreVersion);
37762
+ let payloadKey;
37763
+ const runPublicKey = encryptionKeyOverride ? (
37764
+ // hydrate hook metadata), so sealing would add an ECDH for no
37765
+ // saved round trip. Reuse what it resolved.
37766
+ void 0
37767
+ ) : decodeRunPublicKey(resumeContext.encryptionPublicKey);
37768
+ if (runPublicKey) {
37769
+ payloadKey = sealTo(runPublicKey);
37770
+ } else {
37771
+ let encryptionKey = encryptionKeyOverride ?? await resolveHookEncryptionKey(hook, info);
37772
+ if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
37773
+ encryptionKey = void 0;
37774
+ }
37775
+ payloadKey = encryptionKey;
37776
+ }
37777
+ const compression = (resumeContext.runSpecVersion ?? 0) >= SPEC_VERSION_SUPPORTS_COMPRESSION && capabilities.supportedFormats.has(SerializationFormat.GZIP);
37778
+ const ops = [];
37779
+ const readbackOps = [];
37780
+ const v1Compat = isLegacySpecVersion(hook.specVersion);
37781
+ const dehydratedPayload = await dehydrateStepReturnValue(payload, hook.runId, payloadKey, ops, globalThis, v1Compat, capabilities.framedByteStreams, compression, void 0, readbackOps);
37782
+ await Promise.all(ops.map((op) => op.catch((error61) => {
37783
+ if (error61 !== void 0) throw error61;
37784
+ })));
37785
+ safeWaitUntil(Promise.all(readbackOps), (err) => {
37786
+ if (err === void 0) return;
37787
+ runtimeLogger.warn("Background readback of hook payload failed", {
37788
+ workflowRunId: hook.runId,
37789
+ hookId: hook.hookId,
37790
+ error: err instanceof Error ? err.message : String(err)
37791
+ });
37792
+ });
37793
+ if (world.capabilities?.invoke === true && !v1Compat && dehydratedPayload instanceof Uint8Array) {
37794
+ if (!world.invoke) {
37795
+ throw new WorkflowRuntimeError("World advertises invoke without implementing it");
37796
+ }
37797
+ span?.setAttributes({
37798
+ "workflow.hook.resume_strategy": "invoke"
37799
+ });
37800
+ const result = HookInvocationResultSchema.parse(await world.invoke(hook.runId, {
37801
+ type: "hook_resume",
37802
+ version: 1,
37803
+ hookId: hook.hookId,
37804
+ token: hook.token,
37805
+ payload: dehydratedPayload
37806
+ }, {
37807
+ idempotencyKey: logicalResumeId
37808
+ }));
37809
+ if (result.status === "rejected") {
37810
+ if (result.code === "HOOK_NOT_FOUND") throw new HookNotFoundError(hook.token);
37811
+ throw new WorkflowRuntimeError("Executor rejected the hook invocation input");
37812
+ }
37813
+ span?.setAttributes(HookResumeCommitted(true));
37814
+ return asLazyMetadataHook(hook);
37815
+ }
37816
+ span?.setAttributes({
37817
+ ...WorkflowName(resumeContext.workflowName)
37818
+ });
37819
+ const originLink = await linkToTraceCarrier(resumeContext.traceCarrier);
37820
+ if (originLink) {
37821
+ span?.addLink?.(originLink);
37822
+ }
37823
+ const queueName = getWorkflowQueueName(resumeContext.workflowName);
37824
+ const queueOptions = {
37825
+ deploymentId: resumeContext.deploymentId,
37826
+ specVersion: resumeContext.runSpecVersion ?? SPEC_VERSION_LEGACY
37827
+ };
37828
+ const backendDedupSupported = (hookResumeCapabilitiesAreFresh ? hook.resumeCapabilities?.hookResumeDedupVersion ?? 0 : 0) >= HOOK_RESUME_DEDUP_VERSION || world.capabilities?.hookResumeDedup === true;
37829
+ const canClaimResume = backendDedupSupported && !v1Compat && dehydratedPayload instanceof Uint8Array;
37830
+ span?.setAttributes({
37831
+ "workflow.hook.resume_strategy": "sequential"
37832
+ });
37833
+ const resumeId = canClaimResume ? logicalResumeId : void 0;
37834
+ const payloadDigest = canClaimResume ? await computeResumePayloadDigest(dehydratedPayload) : void 0;
37835
+ if (resumeId) {
37836
+ span?.setAttributes({
37837
+ "workflow.hook.resume_id": resumeId
37838
+ });
37839
+ }
37840
+ const isHookGoneError = /* @__PURE__ */ __name((err) => HookNotFoundError.is(err) || RunExpiredError.is(err), "isHookGoneError");
37841
+ try {
37842
+ await world.events.create(hook.runId, {
37843
+ eventType: "hook_received",
37844
+ // The payload is already encoded for the run (see `compression`).
37845
+ specVersion: specVersionForRunWrite(resumeContext.runSpecVersion),
37846
+ correlationId: hook.hookId,
37847
+ eventData: {
37848
+ ...v1Compat ? {} : {
37849
+ token: hook.token
37850
+ },
37851
+ payload: dehydratedPayload
37852
+ }
37853
+ }, {
37854
+ v1Compat,
37855
+ ...resumeId && payloadDigest ? {
37856
+ resumeId,
37857
+ resumePayloadDigest: payloadDigest
37858
+ } : {}
37859
+ });
37860
+ } catch (err) {
37861
+ if (HookForceClaimedError.is(err)) throw err;
37862
+ if (isHookGoneError(err)) {
37863
+ throw new HookNotFoundError(hook.token);
37864
+ }
37865
+ throw err;
37866
+ }
37867
+ span?.setAttributes(HookResumeCommitted(true));
37868
+ const queuePublishRequestedAtMs = Date.now();
37869
+ await publishHookWakeWithRetry(() => world.queue(queueName, {
37870
+ runId: hook.runId,
37871
+ traceCarrier: resumeContext.traceCarrier ?? void 0,
37872
+ hookResumeTiming: {
37873
+ resumeRequestedAtMs,
37874
+ queuePublishRequestedAtMs,
37875
+ strategy: "sequential"
37876
+ }
37877
+ }, {
37878
+ ...queueOptions,
37879
+ // Dedup retried publishes whose response was lost: a
37880
+ // duplicate wake is harmless for correctness (deterministic
37881
+ // replay) but costs a full replay of the run, and the queue
37882
+ // accepts a repeated idempotency key by delivering only one
37883
+ // of the messages. Claim-less writes have no resumeId and
37884
+ // keep the previous behavior.
37885
+ ...resumeId ? {
37886
+ idempotencyKey: `hook-${resumeId}`
37887
+ } : {}
37888
+ }), world.isDeploymentUnavailableError?.bind(world));
37889
+ span?.setAttributes(HookWakePublished(true));
37890
+ return asLazyMetadataHook(hook);
37891
+ } catch (err) {
37892
+ span?.setAttributes({
37893
+ ...HookToken(typeof tokenOrHook === "string" ? tokenOrHook : tokenOrHook.token),
37894
+ ...HookFound(false)
37895
+ });
37896
+ throw err;
37897
+ }
37898
+ }
37629
37899
  async function resumeWebhook(token, request) {
37630
37900
  const resumeRequestedAtMs = Date.now();
37631
37901
  const world = await getWorldLazy();
@@ -37653,7 +37923,7 @@ async function resumeWebhook(token, request) {
37653
37923
  status: 202
37654
37924
  });
37655
37925
  }
37656
- await resumeHookImpl(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs);
37926
+ await resumeHookImpl(hook, request, metadataEncryptionKey(), true, resumeRequestedAtMs, true);
37657
37927
  if (responseReadable) {
37658
37928
  const reader = responseReadable.getReader();
37659
37929
  const chunk = await reader.read();
@@ -37669,7 +37939,7 @@ async function resumeWebhook(token, request) {
37669
37939
  }
37670
37940
  return response;
37671
37941
  }
37672
- var generateResumeId, HOOK_WAKE_RETRY_DELAYS_MS;
37942
+ var generateResumeId, MAX_FORCE_CLAIM_REDIRECTS, notFoundReasons;
37673
37943
  var init_resume_hook = __esm({
37674
37944
  "../core/dist/runtime/resume-hook.js"() {
37675
37945
  "use strict";
@@ -37687,16 +37957,12 @@ var init_resume_hook = __esm({
37687
37957
  init_telemetry();
37688
37958
  init_get_world_lazy();
37689
37959
  init_helpers();
37960
+ init_hook_wake();
37690
37961
  init_invocations();
37962
+ init_run_spec_version();
37691
37963
  init_wait_until();
37692
37964
  generateResumeId = monotonicFactory();
37693
37965
  __name(computeResumePayloadDigest, "computeResumePayloadDigest");
37694
- HOOK_WAKE_RETRY_DELAYS_MS = [
37695
- 25,
37696
- 100
37697
- ];
37698
- __name(isRetryableWakeError, "isRetryableWakeError");
37699
- __name(publishHookWakeWithRetry, "publishHookWakeWithRetry");
37700
37966
  __name(resumeContextFromRun, "resumeContextFromRun");
37701
37967
  __name(resolveHookResumeInfo, "resolveHookResumeInfo");
37702
37968
  __name(resolveHookEncryptionKey, "resolveHookEncryptionKey");
@@ -37705,7 +37971,10 @@ var init_resume_hook = __esm({
37705
37971
  __name(asLazyMetadataHook, "asLazyMetadataHook");
37706
37972
  __name(getHookByToken, "getHookByToken");
37707
37973
  __name(resumeHook, "resumeHook");
37974
+ MAX_FORCE_CLAIM_REDIRECTS = 3;
37975
+ notFoundReasons = /* @__PURE__ */ new WeakMap();
37708
37976
  __name(resumeHookImpl, "resumeHookImpl");
37977
+ __name(resumeHookAttempt, "resumeHookAttempt");
37709
37978
  __name(resumeWebhook, "resumeWebhook");
37710
37979
  }
37711
37980
  });
@@ -39145,13 +39414,13 @@ async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = g
39145
39414
  });
39146
39415
  }
39147
39416
  }
39148
- async function hydrateRunError(value, runId, key, ops = [], global2 = globalThis, extraRevivers = {}) {
39417
+ async function hydrateRunError(value, runId, key, ops = [], global2 = globalThis, extraRevivers = {}, options) {
39149
39418
  const compressionStats = {};
39150
39419
  const decrypted = await decompress(await decrypt2(value, key), compressionStats);
39151
39420
  await recordCompression(compressionStats, "deserialize");
39152
39421
  if (!(decrypted instanceof Uint8Array)) {
39153
39422
  return unflatten(decrypted, {
39154
- ...getExternalRevivers(global2, ops, runId, key),
39423
+ ...getExternalRevivers(global2, ops, runId, key, options),
39155
39424
  ...extraRevivers
39156
39425
  });
39157
39426
  }
@@ -39159,7 +39428,7 @@ async function hydrateRunError(value, runId, key, ops = [], global2 = globalThis
39159
39428
  if (format === SerializationFormat.DEVALUE_V1) {
39160
39429
  const str = new TextDecoder().decode(payload);
39161
39430
  return parse(str, {
39162
- ...getExternalRevivers(global2, ops, runId, key),
39431
+ ...getExternalRevivers(global2, ops, runId, key, options),
39163
39432
  ...extraRevivers
39164
39433
  });
39165
39434
  }
@@ -39685,11 +39954,11 @@ __builtin_set_attributes.maxRetries = INTERNAL_ATTRIBUTES_MAX_ATTEMPTS - 1;
39685
39954
  init_dist2();
39686
39955
  init_dist3();
39687
39956
  init_env_config();
39688
- init_spec_version();
39689
39957
  init_encryption2();
39690
39958
  init_serialization2();
39691
39959
  init_util2();
39692
39960
  init_get_world_lazy();
39961
+ init_run_spec_version();
39693
39962
 
39694
39963
  // ../core/dist/runtime/runs.js
39695
39964
  init_dist2();
@@ -39697,6 +39966,7 @@ init_dist4();
39697
39966
  init_encryption2();
39698
39967
  init_serialization2();
39699
39968
  init_helpers();
39969
+ init_run_spec_version();
39700
39970
 
39701
39971
  // ../core/dist/runtime/start.js
39702
39972
  init_dist2();
@@ -39814,8 +40084,34 @@ __name(getWorkflowVmFromEnv, "getWorkflowVmFromEnv");
39814
40084
  // ../core/dist/runtime/start.js
39815
40085
  init_wait_until();
39816
40086
  init_world_compatibility();
39817
- var CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS = 2e3;
40087
+ var CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS = 1e4;
40088
+ var CROSS_DEPLOYMENT_PROBE_RETRY_TIMEOUT_MS = 2e3;
40089
+ var CROSS_DEPLOYMENT_PROBE_CACHE_TTL_MS = 10 * 6e4;
40090
+ var CROSS_DEPLOYMENT_PROBE_MISS_TTL_MS = 6e4;
40091
+ var CROSS_DEPLOYMENT_PROBE_CACHE_MAX_ENTRIES = 256;
39818
40092
  var RETENTION_ZERO_ATTRIBUTE_VALUE = "0";
40093
+ function resolveCrossDeploymentSpecVersion(probe, callerSpecVersion) {
40094
+ let target;
40095
+ let source;
40096
+ if (typeof probe?.specVersion === "number" && Number.isInteger(probe.specVersion) && probe.specVersion >= 1) {
40097
+ target = probe.specVersion;
40098
+ source = "probe";
40099
+ } else if (probe?.format === "json") {
40100
+ target = SPEC_VERSION_SUPPORTS_CBOR_QUEUE_TRANSPORT;
40101
+ source = "probe-malformed";
40102
+ } else if (probe?.healthy) {
40103
+ target = SPEC_VERSION_SUPPORTS_EVENT_SOURCING;
40104
+ source = "probe-unversioned";
40105
+ } else {
40106
+ target = SPEC_VERSION_SUPPORTS_SLOT_IDENTITY;
40107
+ source = probe ? "probe-miss" : "no-probe-channel";
40108
+ }
40109
+ return {
40110
+ specVersion: Math.min(target, callerSpecVersion),
40111
+ source
40112
+ };
40113
+ }
40114
+ __name(resolveCrossDeploymentSpecVersion, "resolveCrossDeploymentSpecVersion");
39819
40115
  var ulid3 = monotonicFactory();
39820
40116
  function resolveLineageAttributes() {
39821
40117
  const store = contextStorage.getStore();
@@ -39830,6 +40126,54 @@ __name(resolveLineageAttributes, "resolveLineageAttributes");
39830
40126
  var latestNoOpWarning = globalSingleton("@workflow/core//latestNoOpWarning", 1, () => ({
39831
40127
  warned: false
39832
40128
  }));
40129
+ var probeMissWarning = globalSingleton("@workflow/core//crossDeploymentProbeMissWarning", 1, () => ({
40130
+ warned: false
40131
+ }));
40132
+ var crossDeploymentProbeCache = globalSingleton("@workflow/core//crossDeploymentProbeCache", 1, () => /* @__PURE__ */ new WeakMap());
40133
+ async function probeCrossDeployment(world, options) {
40134
+ let byDeployment = crossDeploymentProbeCache.get(world);
40135
+ if (!byDeployment) {
40136
+ byDeployment = /* @__PURE__ */ new Map();
40137
+ crossDeploymentProbeCache.set(world, byDeployment);
40138
+ }
40139
+ const key = `${options.namespace ?? ""}\0${options.deploymentId}`;
40140
+ const now = Date.now();
40141
+ const entry = byDeployment.get(key);
40142
+ if (entry?.probe !== void 0 && now - entry.at < CROSS_DEPLOYMENT_PROBE_CACHE_TTL_MS) {
40143
+ return {
40144
+ probe: entry.probe,
40145
+ cached: true
40146
+ };
40147
+ }
40148
+ const recentMiss = entry !== void 0 && entry.probe === void 0 && now - entry.at < CROSS_DEPLOYMENT_PROBE_MISS_TTL_MS;
40149
+ const probe = await healthCheck(world, {
40150
+ deploymentId: options.deploymentId,
40151
+ runId: options.runId,
40152
+ timeout: recentMiss ? CROSS_DEPLOYMENT_PROBE_RETRY_TIMEOUT_MS : CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS,
40153
+ namespace: options.namespace
40154
+ }).catch(() => void 0);
40155
+ const answered = probe?.format !== void 0;
40156
+ byDeployment.delete(key);
40157
+ byDeployment.set(key, {
40158
+ // A repeated miss keeps the first miss's time, so the short budget ends
40159
+ // `CROSS_DEPLOYMENT_PROBE_MISS_TTL_MS` after it.
40160
+ at: !answered && recentMiss ? entry.at : Date.now(),
40161
+ // The run public key is per run, so it is never reused.
40162
+ probe: answered ? {
40163
+ ...probe,
40164
+ encryptionPublicKey: void 0
40165
+ } : void 0
40166
+ });
40167
+ if (byDeployment.size > CROSS_DEPLOYMENT_PROBE_CACHE_MAX_ENTRIES) {
40168
+ const oldest = byDeployment.keys().next().value;
40169
+ if (oldest !== void 0) byDeployment.delete(oldest);
40170
+ }
40171
+ return {
40172
+ probe,
40173
+ cached: false
40174
+ };
40175
+ }
40176
+ __name(probeCrossDeployment, "probeCrossDeployment");
39833
40177
  async function start(workflow, argsOrOptions, options) {
39834
40178
  return await waitedUntil(() => {
39835
40179
  const workflowName = workflow?.workflowId;
@@ -39856,19 +40200,34 @@ async function start(workflow, argsOrOptions, options) {
39856
40200
  });
39857
40201
  const world = opts.world ?? await getWorldLazy();
39858
40202
  assertWorldSupportsRuntimeProtocol(world);
39859
- const currentDeploymentId = await world.getDeploymentId();
39860
- let deploymentId = opts.deploymentId ?? currentDeploymentId;
39861
- if (deploymentId === "latest") {
39862
- if (world.resolveLatestDeploymentId) {
39863
- deploymentId = await world.resolveLatestDeploymentId();
39864
- } else {
39865
- if (!latestNoOpWarning.warned) {
39866
- latestNoOpWarning.warned = true;
39867
- runtimeLogger.warn("deploymentId: 'latest' has no effect in this world and was ignored. It is only supported by worlds with atomic deployments, such as Vercel. The run will target the current deployment.", {
39868
- currentDeploymentId
39869
- });
40203
+ let currentDeploymentId;
40204
+ let deploymentId;
40205
+ if (opts.deploymentId === void 0 || opts.deploymentId === "latest") {
40206
+ const current = await world.getDeploymentId();
40207
+ currentDeploymentId = current;
40208
+ deploymentId = opts.deploymentId ?? current;
40209
+ if (deploymentId === "latest") {
40210
+ if (world.resolveLatestDeploymentId) {
40211
+ deploymentId = await world.resolveLatestDeploymentId();
40212
+ } else {
40213
+ if (!latestNoOpWarning.warned) {
40214
+ latestNoOpWarning.warned = true;
40215
+ runtimeLogger.warn("deploymentId: 'latest' has no effect in this world and was ignored. It is only supported by worlds with atomic deployments, such as Vercel. The run will target the current deployment.", {
40216
+ currentDeploymentId
40217
+ });
40218
+ }
40219
+ deploymentId = current;
39870
40220
  }
39871
- deploymentId = currentDeploymentId;
40221
+ }
40222
+ } else {
40223
+ deploymentId = opts.deploymentId;
40224
+ try {
40225
+ currentDeploymentId = await world.getDeploymentId();
40226
+ } catch (err) {
40227
+ runtimeLogger.debug("Current deployment is unavailable; starting as a cross-deployment run", {
40228
+ deploymentId,
40229
+ error: String(err)
40230
+ });
39872
40231
  }
39873
40232
  }
39874
40233
  const runId = `wrun_${world.createRunId ? world.createRunId(opts) : ulid3()}`;
@@ -39876,36 +40235,61 @@ async function start(workflow, argsOrOptions, options) {
39876
40235
  let targetSupportsCompression;
39877
40236
  let targetHookResumeInputVersion;
39878
40237
  let probedRunPublicKey;
39879
- if (deploymentId === currentDeploymentId) {
40238
+ let targetSpecVersion;
40239
+ let specVersionSource;
40240
+ const crossDeployment = deploymentId !== currentDeploymentId;
40241
+ if (!crossDeployment) {
39880
40242
  framedByteStreams = true;
39881
40243
  targetSupportsCompression = true;
39882
40244
  targetHookResumeInputVersion = HOOK_RESUME_INPUT_VERSION;
40245
+ targetSpecVersion = world.specVersion;
40246
+ specVersionSource = "same-deployment";
39883
40247
  } else if (typeof world.streams?.get !== "function") {
39884
40248
  framedByteStreams = false;
39885
40249
  targetSupportsCompression = false;
39886
40250
  targetHookResumeInputVersion = void 0;
40251
+ ({ specVersion: targetSpecVersion, source: specVersionSource } = resolveCrossDeploymentSpecVersion(void 0, world.specVersion));
39887
40252
  } else {
39888
- const probe = await healthCheck(world, {
40253
+ const { probe, cached: cached2 } = await probeCrossDeployment(world, {
39889
40254
  deploymentId,
39890
40255
  runId,
39891
- timeout: CROSS_DEPLOYMENT_CAPABILITY_PROBE_TIMEOUT_MS,
39892
40256
  namespace: opts.namespace
39893
- }).catch(() => void 0);
40257
+ });
39894
40258
  probedRunPublicKey = probe?.encryptionPublicKey;
39895
40259
  const capabilities = getRunCapabilities(probe?.workflowCoreVersion);
39896
40260
  framedByteStreams = capabilities.framedByteStreams;
39897
40261
  targetSupportsCompression = capabilities.supportedFormats.has(SerializationFormat.GZIP);
39898
40262
  targetHookResumeInputVersion = probe?.hookResumeInputVersion;
40263
+ ({ specVersion: targetSpecVersion, source: specVersionSource } = resolveCrossDeploymentSpecVersion(probe, world.specVersion));
40264
+ span?.setAttributes({
40265
+ ...WorkflowCapabilityProbeCached(cached2),
40266
+ ...!cached2 && probe?.latencyMs !== void 0 ? WorkflowCapabilityProbeLatencyMs(probe.latencyMs) : {},
40267
+ ...!cached2 && probe?.error ? WorkflowCapabilityProbeError(probe.error) : {}
40268
+ });
40269
+ if (specVersionSource === "probe-miss" && opts.specVersion === void 0 && !probeMissWarning.warned) {
40270
+ probeMissWarning.warned = true;
40271
+ runtimeLogger.warn("The target deployment did not answer the capability probe, so the run was stamped with a fallback spec version instead of the target's own. A target on an older major version may not be able to execute it.", {
40272
+ deploymentId,
40273
+ specVersion: targetSpecVersion,
40274
+ error: probe?.error
40275
+ });
40276
+ }
39899
40277
  }
39900
40278
  const ops = [];
39901
40279
  const traceCarrier = await serializeTraceCarrier();
39902
- const specVersion = opts.specVersion ?? world.specVersion;
40280
+ const specVersion = opts.specVersion ?? targetSpecVersion;
40281
+ if (opts.specVersion !== void 0) specVersionSource = "explicit";
40282
+ span?.setAttributes({
40283
+ ...WorkflowRunSpecVersion(specVersion),
40284
+ ...WorkflowRunSpecVersionSource(specVersionSource)
40285
+ });
40286
+ const specGateError = /* @__PURE__ */ __name((featureRequires) => new WorkflowRuntimeError(crossDeployment && opts.specVersion === void 0 ? `${featureRequires} spec version ${SPEC_VERSION_SUPPORTS_ATTRIBUTES} or later, but the target deployment (${deploymentId}) runs spec version ${specVersion}.` : `${featureRequires} a World that supports spec version ${SPEC_VERSION_SUPPORTS_ATTRIBUTES} or later.`), "specGateError");
39903
40287
  const v1Compat = isLegacySpecVersion(specVersion);
39904
40288
  const allowReservedAttributes = opts.allowReservedAttributes === true;
39905
40289
  let attributes;
39906
40290
  if (opts.attributes && Object.keys(opts.attributes).length > 0) {
39907
40291
  if (specVersion < SPEC_VERSION_SUPPORTS_ATTRIBUTES) {
39908
- throw new WorkflowRuntimeError("Initial workflow attributes require a World that supports spec version 4 or later.");
40292
+ throw specGateError("Initial workflow attributes require");
39909
40293
  }
39910
40294
  for (const [key, value] of Object.entries(opts.attributes)) {
39911
40295
  if (typeof value !== "string") {
@@ -39926,7 +40310,7 @@ async function start(workflow, argsOrOptions, options) {
39926
40310
  throw new WorkflowRuntimeError(`start({ experimental_retention }) must be 0 or 'default'; received ${JSON.stringify(opts.experimental_retention)}.`);
39927
40311
  }
39928
40312
  if (specVersion < SPEC_VERSION_SUPPORTS_ATTRIBUTES) {
39929
- throw new WorkflowRuntimeError("start({ experimental_retention }) requires a World that supports spec version 4 or later.");
40313
+ throw specGateError("start({ experimental_retention }) requires");
39930
40314
  }
39931
40315
  retentionAttribute = {
39932
40316
  [RETENTION_ATTRIBUTE]: RETENTION_ZERO_ATTRIBUTE_VALUE
@@ -40086,7 +40470,7 @@ __name(start, "start");
40086
40470
  value: "start",
40087
40471
  configurable: true
40088
40472
  });
40089
- })(start, "step//@workflow/core/runtime/start@5.0.0-beta.55//start");
40473
+ })(start, "step//@workflow/core/runtime/start@5.0.0-beta.57//start");
40090
40474
 
40091
40475
  // ../core/dist/runtime/runs.js
40092
40476
  async function wakeUpRun(world, runId, options) {
@@ -40128,7 +40512,7 @@ async function wakeUpRun(world, runId, options) {
40128
40512
  } : {
40129
40513
  eventType: "wait_completed",
40130
40514
  correlationId: waitEvent.correlationId,
40131
- specVersion: run2.specVersion,
40515
+ specVersion: specVersionForRunWrite(run2.specVersion),
40132
40516
  eventData: {
40133
40517
  resumeAt: waitEvent.eventData.resumeAt
40134
40518
  }
@@ -40151,7 +40535,7 @@ async function wakeUpRun(world, runId, options) {
40151
40535
  runId
40152
40536
  }, {
40153
40537
  deploymentId: run2.deploymentId,
40154
- specVersion: run2.specVersion ?? SPEC_VERSION_LEGACY
40538
+ specVersion: specVersionForRunWrite(run2.specVersion, SPEC_VERSION_LEGACY)
40155
40539
  });
40156
40540
  }
40157
40541
  if (errors.length > 0) {
@@ -40302,9 +40686,12 @@ var Run = class _Run {
40302
40686
  */
40303
40687
  async cancel(options) {
40304
40688
  const world = await this.#lazyWorldPromise;
40689
+ const run2 = await world.runs.get(this.runId, {
40690
+ resolveData: "none"
40691
+ });
40305
40692
  await world.events.create(this.runId, {
40306
40693
  eventType: "run_cancelled",
40307
- specVersion: SPEC_VERSION_CURRENT,
40694
+ specVersion: specVersionForRunWrite(run2.specVersion),
40308
40695
  ...options?.cancelReason !== void 0 ? {
40309
40696
  eventData: {
40310
40697
  cancelReason: options.cancelReason
@@ -40557,7 +40944,7 @@ var Run = class _Run {
40557
40944
  value: "wakeUp",
40558
40945
  configurable: true
40559
40946
  });
40560
- })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#wakeUp");
40947
+ })(Run.prototype["wakeUp"], "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#wakeUp");
40561
40948
  (function(__wf_fn, __wf_id) {
40562
40949
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40563
40950
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40566,7 +40953,7 @@ var Run = class _Run {
40566
40953
  value: "cancel",
40567
40954
  configurable: true
40568
40955
  });
40569
- })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#cancel");
40956
+ })(Run.prototype["cancel"], "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#cancel");
40570
40957
  (function(__wf_fn, __wf_id) {
40571
40958
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40572
40959
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40575,7 +40962,7 @@ var Run = class _Run {
40575
40962
  value: "getReadable",
40576
40963
  configurable: true
40577
40964
  });
40578
- })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#getReadable");
40965
+ })(Run.prototype["getReadable"], "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#getReadable");
40579
40966
  (function(__wf_fn, __wf_id) {
40580
40967
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40581
40968
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40584,7 +40971,7 @@ var Run = class _Run {
40584
40971
  value: "getWritable",
40585
40972
  configurable: true
40586
40973
  });
40587
- })(Run.prototype["getWritable"], "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#getWritable");
40974
+ })(Run.prototype["getWritable"], "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#getWritable");
40588
40975
  (function(__wf_fn, __wf_id) {
40589
40976
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40590
40977
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40593,7 +40980,7 @@ var Run = class _Run {
40593
40980
  value: "exists",
40594
40981
  configurable: true
40595
40982
  });
40596
- })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#exists");
40983
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "exists").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#exists");
40597
40984
  (function(__wf_fn, __wf_id) {
40598
40985
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40599
40986
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40602,7 +40989,7 @@ var Run = class _Run {
40602
40989
  value: "status",
40603
40990
  configurable: true
40604
40991
  });
40605
- })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#status");
40992
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "status").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#status");
40606
40993
  (function(__wf_fn, __wf_id) {
40607
40994
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40608
40995
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40611,7 +40998,7 @@ var Run = class _Run {
40611
40998
  value: "returnValue",
40612
40999
  configurable: true
40613
41000
  });
40614
- })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#returnValue");
41001
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "returnValue").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#returnValue");
40615
41002
  (function(__wf_fn, __wf_id) {
40616
41003
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40617
41004
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40620,7 +41007,7 @@ var Run = class _Run {
40620
41007
  value: "workflowName",
40621
41008
  configurable: true
40622
41009
  });
40623
- })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#workflowName");
41010
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "workflowName").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#workflowName");
40624
41011
  (function(__wf_fn, __wf_id) {
40625
41012
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40626
41013
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40629,7 +41016,7 @@ var Run = class _Run {
40629
41016
  value: "createdAt",
40630
41017
  configurable: true
40631
41018
  });
40632
- })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#createdAt");
41019
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "createdAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#createdAt");
40633
41020
  (function(__wf_fn, __wf_id) {
40634
41021
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40635
41022
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40638,7 +41025,7 @@ var Run = class _Run {
40638
41025
  value: "startedAt",
40639
41026
  configurable: true
40640
41027
  });
40641
- })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#startedAt");
41028
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "startedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#startedAt");
40642
41029
  (function(__wf_fn, __wf_id) {
40643
41030
  var __wf_sym = /* @__PURE__ */ Symbol.for("@workflow/core//registeredSteps"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40644
41031
  __wf_reg.set(__wf_id, __wf_fn);
@@ -40647,7 +41034,7 @@ var Run = class _Run {
40647
41034
  value: "completedAt",
40648
41035
  configurable: true
40649
41036
  });
40650
- })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.55//Run#completedAt");
41037
+ })(Object.getOwnPropertyDescriptor(Run.prototype, "completedAt").get, "step//@workflow/core/runtime/run@5.0.0-beta.57//Run#completedAt");
40651
41038
  (function(__wf_cls, __wf_id) {
40652
41039
  var __wf_sym = /* @__PURE__ */ Symbol.for("workflow-class-registry"), __wf_reg = globalThis[__wf_sym] || (globalThis[__wf_sym] = /* @__PURE__ */ new Map());
40653
41040
  __wf_reg.set(__wf_id, __wf_cls);
@@ -40657,7 +41044,7 @@ var Run = class _Run {
40657
41044
  enumerable: false,
40658
41045
  configurable: false
40659
41046
  });
40660
- })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.55//Run");
41047
+ })(Run, "class//@workflow/core/runtime/run@5.0.0-beta.57//Run");
40661
41048
 
40662
41049
  // ../workflow/dist/stdlib.js
40663
41050
  async function fetch2(...args) {