@workflow/world-testing 4.1.19 → 4.1.21

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.
@@ -15411,7 +15411,8 @@ var init_queue = __esm({
15411
15411
  });
15412
15412
 
15413
15413
  // ../world/dist/recovery.js
15414
- async function reenqueueActiveRuns(runs, enqueue, label) {
15414
+ async function reenqueueActiveRuns(runs, enqueue, label, namespace) {
15415
+ const workflowQueuePrefix = getQueueTopicPrefix("workflow", resolveQueueNamespace(namespace));
15415
15416
  let reenqueued = 0;
15416
15417
  for (const status of ["pending", "running"]) {
15417
15418
  let cursor;
@@ -15424,7 +15425,7 @@ async function reenqueueActiveRuns(runs, enqueue, label) {
15424
15425
  });
15425
15426
  for (const run2 of page.data) {
15426
15427
  try {
15427
- const queueName = `__wkf_workflow_${run2.workflowName}`;
15428
+ const queueName = `${workflowQueuePrefix}${run2.workflowName}`;
15428
15429
  await enqueue(queueName, { runId: run2.runId });
15429
15430
  reenqueued++;
15430
15431
  } catch (err) {
@@ -15442,6 +15443,7 @@ async function reenqueueActiveRuns(runs, enqueue, label) {
15442
15443
  var init_recovery = __esm({
15443
15444
  "../world/dist/recovery.js"() {
15444
15445
  "use strict";
15446
+ init_queue();
15445
15447
  __name(reenqueueActiveRuns, "reenqueueActiveRuns");
15446
15448
  }
15447
15449
  });
@@ -44744,7 +44746,7 @@ var require_token_util = __commonJS({
44744
44746
  findProjectInfo: /* @__PURE__ */ __name(() => findProjectInfo, "findProjectInfo"),
44745
44747
  getTokenPayload: /* @__PURE__ */ __name(() => getTokenPayload, "getTokenPayload"),
44746
44748
  getVercelDataDir: /* @__PURE__ */ __name(() => getVercelDataDir, "getVercelDataDir"),
44747
- getVercelOidcToken: /* @__PURE__ */ __name(() => getVercelOidcToken5, "getVercelOidcToken"),
44749
+ getVercelOidcToken: /* @__PURE__ */ __name(() => getVercelOidcToken6, "getVercelOidcToken"),
44748
44750
  getVercelToken: /* @__PURE__ */ __name(() => getVercelToken2, "getVercelToken"),
44749
44751
  isExpired: /* @__PURE__ */ __name(() => isExpired, "isExpired"),
44750
44752
  loadToken: /* @__PURE__ */ __name(() => loadToken, "loadToken"),
@@ -44806,7 +44808,7 @@ var require_token_util = __commonJS({
44806
44808
  }
44807
44809
  }
44808
44810
  __name(getVercelToken2, "getVercelToken");
44809
- async function getVercelOidcToken5(authToken, projectId, teamId) {
44811
+ async function getVercelOidcToken6(authToken, projectId, teamId) {
44810
44812
  const url2 = `https://api.vercel.com/v1/projects/${projectId}/token?source=vercel-oidc-refresh${teamId ? `&teamId=${teamId}` : ""}`;
44811
44813
  const res = await fetch(url2, {
44812
44814
  method: "POST",
@@ -44823,7 +44825,7 @@ var require_token_util = __commonJS({
44823
44825
  assertVercelOidcTokenResponse(tokenRes);
44824
44826
  return tokenRes;
44825
44827
  }
44826
- __name(getVercelOidcToken5, "getVercelOidcToken");
44828
+ __name(getVercelOidcToken6, "getVercelOidcToken");
44827
44829
  function assertVercelOidcTokenResponse(res) {
44828
44830
  if (!res || typeof res !== "object") {
44829
44831
  throw new TypeError(
@@ -44998,13 +45000,13 @@ var require_get_vercel_oidc_token = __commonJS({
44998
45000
  var __toCommonJS2 = /* @__PURE__ */ __name((mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod), "__toCommonJS");
44999
45001
  var get_vercel_oidc_token_exports = {};
45000
45002
  __export2(get_vercel_oidc_token_exports, {
45001
- getVercelOidcToken: /* @__PURE__ */ __name(() => getVercelOidcToken5, "getVercelOidcToken"),
45003
+ getVercelOidcToken: /* @__PURE__ */ __name(() => getVercelOidcToken6, "getVercelOidcToken"),
45002
45004
  getVercelOidcTokenSync: /* @__PURE__ */ __name(() => getVercelOidcTokenSync2, "getVercelOidcTokenSync")
45003
45005
  });
45004
45006
  module2.exports = __toCommonJS2(get_vercel_oidc_token_exports);
45005
45007
  var import_get_context = require_get_context();
45006
45008
  var import_token_error = require_token_error();
45007
- async function getVercelOidcToken5(options) {
45009
+ async function getVercelOidcToken6(options) {
45008
45010
  let token = "";
45009
45011
  let err;
45010
45012
  try {
@@ -45034,7 +45036,7 @@ ${error48.message}`;
45034
45036
  }
45035
45037
  return token;
45036
45038
  }
45037
- __name(getVercelOidcToken5, "getVercelOidcToken");
45039
+ __name(getVercelOidcToken6, "getVercelOidcToken");
45038
45040
  function getVercelOidcTokenSync2() {
45039
45041
  const token = (0, import_get_context.getContext)().headers?.["x-vercel-oidc-token"] ?? process.env.VERCEL_OIDC_TOKEN;
45040
45042
  if (!token) {
@@ -50258,6 +50260,7 @@ var WorkflowErrorCode = SemanticConvention("workflow.error.code");
50258
50260
  var WorkflowStepsCreated = SemanticConvention("workflow.steps.created");
50259
50261
  var WorkflowHooksCreated = SemanticConvention("workflow.hooks.created");
50260
50262
  var WorkflowWaitsCreated = SemanticConvention("workflow.waits.created");
50263
+ var WorkflowStepsFailedSerialization = SemanticConvention("workflow.steps.failed_serialization");
50261
50264
  var StepName = SemanticConvention("step.name");
50262
50265
  var StepId = SemanticConvention("step.id");
50263
50266
  var StepAttempt = SemanticConvention("step.attempt");
@@ -50523,7 +50526,7 @@ init_dist();
50523
50526
  init_node();
50524
50527
 
50525
50528
  // ../core/dist/version.js
50526
- var version2 = "4.8.4";
50529
+ var version2 = "4.8.6";
50527
50530
 
50528
50531
  // ../core/dist/runtime/world.js
50529
50532
  var import_node_module = require("node:module");
@@ -50800,6 +50803,18 @@ var config2 = once2(() => {
50800
50803
  const baseUrl = getBaseUrlFromEnv();
50801
50804
  return { dataDir, baseUrl };
50802
50805
  });
50806
+ function resolveRecoverActiveRuns(config3) {
50807
+ if (config3.recoverActiveRuns !== void 0) {
50808
+ return config3.recoverActiveRuns;
50809
+ }
50810
+ const raw = process.env.WORKFLOW_LOCAL_RECOVER_ACTIVE_RUNS?.toLowerCase();
50811
+ if (raw === "0" || raw === "false")
50812
+ return false;
50813
+ if (raw === "1" || raw === "true")
50814
+ return true;
50815
+ return true;
50816
+ }
50817
+ __name(resolveRecoverActiveRuns, "resolveRecoverActiveRuns");
50803
50818
  function resolveDirectBaseUrl(config3) {
50804
50819
  return config3.baseUrl ?? process.env.WORKFLOW_LOCAL_BASE_URL ?? createWorkflowBaseUrl("http://localhost");
50805
50820
  }
@@ -50888,8 +50903,10 @@ async function withWindowsRetry(fn, maxRetries = 5) {
50888
50903
  }
50889
50904
  __name(withWindowsRetry, "withWindowsRetry");
50890
50905
  var createdFilesCache = /* @__PURE__ */ new Set();
50906
+ var createdDirectoriesCache = /* @__PURE__ */ new Set();
50891
50907
  function clearCreatedFilesCache() {
50892
50908
  createdFilesCache.clear();
50909
+ createdDirectoriesCache.clear();
50893
50910
  }
50894
50911
  __name(clearCreatedFilesCache, "clearCreatedFilesCache");
50895
50912
  var TAG_PATTERN = /\.[a-zA-Z][a-zA-Z0-9-]*$/;
@@ -50950,12 +50967,31 @@ async function listTaggedFilesByExtension(dirPath, tag, extension) {
50950
50967
  }
50951
50968
  __name(listTaggedFilesByExtension, "listTaggedFilesByExtension");
50952
50969
  async function ensureDir(dirPath) {
50970
+ const resolvedPath = import_node_path.default.resolve(dirPath);
50971
+ if (createdDirectoriesCache.has(resolvedPath)) {
50972
+ return;
50973
+ }
50953
50974
  try {
50954
- await import_node_fs.promises.mkdir(dirPath, { recursive: true });
50975
+ await import_node_fs.promises.mkdir(resolvedPath, { recursive: true });
50976
+ createdDirectoriesCache.add(resolvedPath);
50955
50977
  } catch (_error) {
50956
50978
  }
50957
50979
  }
50958
50980
  __name(ensureDir, "ensureDir");
50981
+ async function withEnsuredDirectory(dirPath, operation) {
50982
+ await ensureDir(dirPath);
50983
+ try {
50984
+ return await operation();
50985
+ } catch (error48) {
50986
+ if (error48.code !== "ENOENT") {
50987
+ throw error48;
50988
+ }
50989
+ createdDirectoriesCache.delete(import_node_path.default.resolve(dirPath));
50990
+ await ensureDir(dirPath);
50991
+ return operation();
50992
+ }
50993
+ }
50994
+ __name(withEnsuredDirectory, "withEnsuredDirectory");
50959
50995
  function jsonReplacer(_key, value) {
50960
50996
  if (value instanceof Uint8Array) {
50961
50997
  return {
@@ -50995,10 +51031,11 @@ async function write(filePath, data, opts) {
50995
51031
  const tempPath = `${filePath}.tmp.${ulid3()}`;
50996
51032
  let tempFileCreated = false;
50997
51033
  try {
50998
- await ensureDir(import_node_path.default.dirname(filePath));
50999
- await import_node_fs.promises.writeFile(tempPath, data);
51000
- tempFileCreated = true;
51001
- await withWindowsRetry(() => import_node_fs.promises.rename(tempPath, filePath));
51034
+ await withEnsuredDirectory(import_node_path.default.dirname(filePath), async () => {
51035
+ await import_node_fs.promises.writeFile(tempPath, data);
51036
+ tempFileCreated = true;
51037
+ await withWindowsRetry(() => import_node_fs.promises.rename(tempPath, filePath));
51038
+ });
51002
51039
  createdFilesCache.add(filePath);
51003
51040
  } catch (error48) {
51004
51041
  if (tempFileCreated) {
@@ -51046,21 +51083,22 @@ async function deleteJSON(filePath) {
51046
51083
  }
51047
51084
  __name(deleteJSON, "deleteJSON");
51048
51085
  async function writeExclusive(filePath, data) {
51049
- await ensureDir(import_node_path.default.dirname(filePath));
51050
51086
  const tempPath = `${filePath}.tmp.${ulid3()}`;
51051
51087
  let tempFileCreated = false;
51052
51088
  try {
51053
- await import_node_fs.promises.writeFile(tempPath, data, { flag: "wx" });
51054
- tempFileCreated = true;
51055
- try {
51056
- await withWindowsRetry(() => import_node_fs.promises.link(tempPath, filePath));
51057
- return true;
51058
- } catch (error48) {
51059
- if (error48.code === "EEXIST") {
51060
- return false;
51089
+ return await withEnsuredDirectory(import_node_path.default.dirname(filePath), async () => {
51090
+ await import_node_fs.promises.writeFile(tempPath, data, { flag: "wx" });
51091
+ tempFileCreated = true;
51092
+ try {
51093
+ await withWindowsRetry(() => import_node_fs.promises.link(tempPath, filePath));
51094
+ return true;
51095
+ } catch (error48) {
51096
+ if (error48.code === "EEXIST") {
51097
+ return false;
51098
+ }
51099
+ throw error48;
51061
51100
  }
51062
- throw error48;
51063
- }
51101
+ });
51064
51102
  } finally {
51065
51103
  if (tempFileCreated) {
51066
51104
  await withWindowsRetry(() => import_node_fs.promises.unlink(tempPath), 3).catch(() => {
@@ -51099,11 +51137,12 @@ function createCursor(timestamp, id) {
51099
51137
  }
51100
51138
  __name(createCursor, "createCursor");
51101
51139
  async function paginatedFileSystemQuery(config3) {
51102
- const { directory, schema, filePrefix, fileIdFilter, filter: filter2, sortOrder = "desc", limit = 20, cursor, getCreatedAt, getId } = config3;
51140
+ const { directory, schema, cachedItems, filePrefix, fileIdFilter, filter: filter2, sortOrder = "desc", limit = 20, cursor, getCreatedAt, getId } = config3;
51103
51141
  if (filePrefix !== void 0) {
51104
51142
  assertSafeEntityId("filePrefix", filePrefix);
51105
51143
  }
51106
- const fileIds = await listJSONFiles(directory);
51144
+ const resolvedDirectory = import_node_path.default.resolve(directory);
51145
+ const fileIds = await listJSONFiles(resolvedDirectory);
51107
51146
  const relevantFileIds = filePrefix ? fileIds.filter((fileId) => fileId.startsWith(filePrefix)) : fileIds;
51108
51147
  const filteredFileIds = fileIdFilter ? relevantFileIds.filter(fileIdFilter) : relevantFileIds;
51109
51148
  const parsedCursor = parseCursor(cursor);
@@ -51125,10 +51164,11 @@ async function paginatedFileSystemQuery(config3) {
51125
51164
  }
51126
51165
  const validItems = [];
51127
51166
  for (const fileId of candidateFileIds) {
51128
- const filePath = import_node_path.default.join(directory, `${fileId}.json`);
51167
+ const filePath = import_node_path.default.join(resolvedDirectory, `${fileId}.json`);
51129
51168
  let item = null;
51130
51169
  try {
51131
- item = await readJSON(filePath, schema);
51170
+ const cachedItem = cachedItems?.get(filePath);
51171
+ item = cachedItem === void 0 ? await readJSON(filePath, schema) : structuredClone(cachedItem);
51132
51172
  } catch (error48) {
51133
51173
  if (error48 instanceof external_exports.ZodError) {
51134
51174
  console.warn(`Skipping item ${fileId} due to malformed JSON: ${error48.message}`);
@@ -51888,6 +51928,8 @@ function createQueue(config3) {
51888
51928
  const transport = new TypedJsonTransport();
51889
51929
  const generateId2 = monotonicFactory();
51890
51930
  const semaphore = new import_async_sema.Sema(WORKFLOW_LOCAL_QUEUE_CONCURRENCY);
51931
+ const closeController = new AbortController();
51932
+ const closeSignal = closeController.signal;
51891
51933
  const inflightMessages = /* @__PURE__ */ new Map();
51892
51934
  const directHandlers = /* @__PURE__ */ new Map();
51893
51935
  const queue = /* @__PURE__ */ __name(async (queueName, message, opts) => {
@@ -51946,6 +51988,7 @@ function createQueue(config3) {
51946
51988
  headers: new Headers(headers),
51947
51989
  body,
51948
51990
  agents: nodeHttpAgents,
51991
+ signal: closeSignal,
51949
51992
  headersTimeoutMs: agentOptions.headersTimeout,
51950
51993
  bodyTimeoutMs: agentOptions.bodyTimeout
51951
51994
  }) : (
@@ -51955,7 +51998,8 @@ function createQueue(config3) {
51955
51998
  duplex: "half",
51956
51999
  dispatcher: httpAgent,
51957
52000
  headers,
51958
- body
52001
+ body,
52002
+ signal: closeSignal
51959
52003
  })
51960
52004
  );
51961
52005
  }
@@ -52061,6 +52105,9 @@ function createQueue(config3) {
52061
52105
  directHandlers.set(prefix, handler);
52062
52106
  },
52063
52107
  async close() {
52108
+ if (closeSignal.aborted)
52109
+ return;
52110
+ closeController.abort();
52064
52111
  if (nodeHttpAgents)
52065
52112
  destroyNodeHttpAgents(nodeHttpAgents);
52066
52113
  await httpAgent?.close();
@@ -52523,8 +52570,81 @@ async function deleteAllWaitsForRun(basedir, runId) {
52523
52570
  }
52524
52571
  __name(deleteAllWaitsForRun, "deleteAllWaitsForRun");
52525
52572
  function createEventsStorage(basedir, tag) {
52573
+ const maxCachedEventBytes = 4 * 1024 * 1024;
52574
+ const maxCachedEventEntries = 1e3;
52575
+ const eventCache = /* @__PURE__ */ new Map();
52576
+ const cachedEventBytes = /* @__PURE__ */ new Map();
52577
+ const cachedPathsByRunId = /* @__PURE__ */ new Map();
52578
+ let totalCachedEventBytes = 0;
52579
+ function deleteCachedEvent(eventPath) {
52580
+ const event = eventCache.get(eventPath);
52581
+ if (!event) {
52582
+ return;
52583
+ }
52584
+ eventCache.delete(eventPath);
52585
+ totalCachedEventBytes -= cachedEventBytes.get(eventPath) ?? 0;
52586
+ cachedEventBytes.delete(eventPath);
52587
+ const cachedPaths = cachedPathsByRunId.get(event.runId);
52588
+ cachedPaths?.delete(eventPath);
52589
+ if (cachedPaths?.size === 0) {
52590
+ cachedPathsByRunId.delete(event.runId);
52591
+ }
52592
+ }
52593
+ __name(deleteCachedEvent, "deleteCachedEvent");
52594
+ function clearRunCache(runId) {
52595
+ for (const cachedPath of cachedPathsByRunId.get(runId) ?? []) {
52596
+ deleteCachedEvent(cachedPath);
52597
+ }
52598
+ }
52599
+ __name(clearRunCache, "clearRunCache");
52600
+ function clearCache() {
52601
+ eventCache.clear();
52602
+ cachedEventBytes.clear();
52603
+ cachedPathsByRunId.clear();
52604
+ totalCachedEventBytes = 0;
52605
+ }
52606
+ __name(clearCache, "clearCache");
52607
+ function cacheEvent(eventPath, cachedEvent, serializedBytes) {
52608
+ if (serializedBytes > maxCachedEventBytes) {
52609
+ return;
52610
+ }
52611
+ while (eventCache.size > 0 && (eventCache.size >= maxCachedEventEntries || totalCachedEventBytes + serializedBytes > maxCachedEventBytes)) {
52612
+ const oldestPath = eventCache.keys().next().value;
52613
+ deleteCachedEvent(oldestPath);
52614
+ }
52615
+ eventCache.set(eventPath, cachedEvent);
52616
+ cachedEventBytes.set(eventPath, serializedBytes);
52617
+ totalCachedEventBytes += serializedBytes;
52618
+ const cachedPaths = cachedPathsByRunId.get(cachedEvent.runId) ?? /* @__PURE__ */ new Set();
52619
+ cachedPaths.add(eventPath);
52620
+ cachedPathsByRunId.set(cachedEvent.runId, cachedPaths);
52621
+ }
52622
+ __name(cacheEvent, "cacheEvent");
52623
+ function rememberStoredEvent(event, eventPath, serializedEvent) {
52624
+ if (event.eventType === "run_completed" || event.eventType === "run_failed" || event.eventType === "run_cancelled") {
52625
+ clearRunCache(event.runId);
52626
+ return;
52627
+ }
52628
+ const serializedBytes = Buffer.byteLength(serializedEvent);
52629
+ if (serializedBytes > maxCachedEventBytes) {
52630
+ return;
52631
+ }
52632
+ const cachedEvent = EventSchema.safeParse(JSON.parse(serializedEvent, jsonReviver));
52633
+ if (cachedEvent.success) {
52634
+ cacheEvent(eventPath, cachedEvent.data, serializedBytes);
52635
+ }
52636
+ }
52637
+ __name(rememberStoredEvent, "rememberStoredEvent");
52638
+ async function storeEvent(event) {
52639
+ const eventPath = taggedPath(basedir, "events", `${event.runId}-${event.eventId}`, tag);
52640
+ const serializedEvent = JSON.stringify(event, jsonReplacer, 2);
52641
+ await write(eventPath, serializedEvent);
52642
+ rememberStoredEvent(event, eventPath, serializedEvent);
52643
+ }
52644
+ __name(storeEvent, "storeEvent");
52526
52645
  const hookLocks = /* @__PURE__ */ new Map();
52527
52646
  return {
52647
+ clearCache,
52528
52648
  async create(runId, data, params) {
52529
52649
  if (runId != null && runId !== "") {
52530
52650
  assertSafeEntityId("runId", runId);
@@ -52594,8 +52714,7 @@ function createEventsStorage(basedir, tag) {
52594
52714
  executionContext: runInputData.executionContext
52595
52715
  }
52596
52716
  };
52597
- const createdCompositeKey = `${effectiveRunId}-${runCreatedEventId}`;
52598
- await writeJSON(taggedPath(basedir, "events", createdCompositeKey, tag), runCreatedEvent);
52717
+ await storeEvent(runCreatedEvent);
52599
52718
  currentRun = createdRun;
52600
52719
  } else {
52601
52720
  currentRun = await readJSONWithFallback(basedir, "runs", effectiveRunId, WorkflowRunSchema, tag);
@@ -52625,8 +52744,7 @@ function createEventsStorage(basedir, tag) {
52625
52744
  createdAt: now,
52626
52745
  specVersion: effectiveSpecVersion
52627
52746
  };
52628
- const compositeKey2 = `${effectiveRunId}-${eventId}`;
52629
- await writeJSON(taggedPath(basedir, "events", compositeKey2, tag), event2);
52747
+ await storeEvent(event2);
52630
52748
  const resolveData2 = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
52631
52749
  return {
52632
52750
  event: stripEventDataRefs(event2, resolveData2),
@@ -52975,8 +53093,7 @@ function createEventsStorage(basedir, tag) {
52975
53093
  createdAt: now,
52976
53094
  specVersion: effectiveSpecVersion
52977
53095
  };
52978
- const compositeKey2 = `${effectiveRunId}-${eventId}`;
52979
- await writeJSON(taggedPath(basedir, "events", compositeKey2, tag), conflictEvent);
53096
+ await storeEvent(conflictEvent);
52980
53097
  const resolveData2 = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
52981
53098
  const filteredEvent2 = stripEventDataRefs(conflictEvent, resolveData2);
52982
53099
  return {
@@ -53060,13 +53177,16 @@ function createEventsStorage(basedir, tag) {
53060
53177
  await writeJSON(taggedPath(basedir, "waits", waitCompositeKey, tag), wait, { overwrite: true });
53061
53178
  }
53062
53179
  const compositeKey = `${effectiveRunId}-${eventId}`;
53063
- const eventPublished = await writeExclusive(taggedPath(basedir, "events", compositeKey, tag), JSON.stringify(event, jsonReplacer, 2));
53180
+ const eventPath = taggedPath(basedir, "events", compositeKey, tag);
53181
+ const serializedEvent = JSON.stringify(event, jsonReplacer, 2);
53182
+ const eventPublished = await writeExclusive(eventPath, serializedEvent);
53064
53183
  if (!eventPublished) {
53065
53184
  if (data.eventType === "hook_created" && data.correlationId) {
53066
53185
  await repairHookEntityFromPersistedEvent(basedir, effectiveRunId, data.correlationId, eventId, tag);
53067
53186
  }
53068
53187
  throw new EntityConflictError(`Event "${eventId}" already exists for run "${effectiveRunId}"`);
53069
53188
  }
53189
+ rememberStoredEvent(event, eventPath, serializedEvent);
53070
53190
  if (hook && data.eventType === "hook_created") {
53071
53191
  await writeJSON(taggedPath(basedir, "hooks", hook.hookId, tag), hook, hookEntityWriteOptions);
53072
53192
  }
@@ -53079,6 +53199,7 @@ function createEventsStorage(basedir, tag) {
53079
53199
  const allEvents = await paginatedFileSystemQuery({
53080
53200
  directory: import_node_path5.default.join(basedir, "events"),
53081
53201
  schema: EventSchema,
53202
+ cachedItems: eventCache,
53082
53203
  filePrefix: `${effectiveRunId}-`,
53083
53204
  sortOrder: "asc",
53084
53205
  limit: 1e3,
@@ -53122,6 +53243,7 @@ function createEventsStorage(basedir, tag) {
53122
53243
  const result = await paginatedFileSystemQuery({
53123
53244
  directory: import_node_path5.default.join(basedir, "events"),
53124
53245
  schema: EventSchema,
53246
+ cachedItems: eventCache,
53125
53247
  filePrefix: `${runId}-`,
53126
53248
  // Events in chronological order (oldest first) by default,
53127
53249
  // different from the default for other list calls.
@@ -53146,8 +53268,9 @@ function createEventsStorage(basedir, tag) {
53146
53268
  const result = await paginatedFileSystemQuery({
53147
53269
  directory: import_node_path5.default.join(basedir, "events"),
53148
53270
  schema: EventSchema,
53271
+ cachedItems: eventCache,
53149
53272
  // No filePrefix - search all events
53150
- filter: /* @__PURE__ */ __name((event) => event.correlationId === correlationId, "filter"),
53273
+ filter: /* @__PURE__ */ __name((event) => event.correlationId === correlationId && (params.runId === void 0 || event.runId === params.runId), "filter"),
53151
53274
  // Events in chronological order (oldest first) by default,
53152
53275
  // different from the default for other list calls.
53153
53276
  sortOrder: params.pagination?.sortOrder ?? "asc",
@@ -53283,7 +53406,8 @@ function createStorage(basedir, tag) {
53283
53406
  runs: instrumentObject("world.runs", runs),
53284
53407
  steps: instrumentObject("world.steps", steps),
53285
53408
  events: instrumentObject("world.events", events),
53286
- hooks: instrumentObject("world.hooks", hooks)
53409
+ hooks: instrumentObject("world.hooks", hooks),
53410
+ clearCache: /* @__PURE__ */ __name(() => events.clearCache(), "clearCache")
53287
53411
  };
53288
53412
  }
53289
53413
  __name(createStorage, "createStorage");
@@ -53683,8 +53807,8 @@ function createLocalWorld(args) {
53683
53807
  const mergedConfig = { ...config2.value, ...definedArgs };
53684
53808
  const tag = mergedConfig.tag;
53685
53809
  const queue = createQueue(mergedConfig);
53686
- const storage = createStorage(mergedConfig.dataDir, tag);
53687
- const recoverActiveRuns = mergedConfig.recoverActiveRuns ?? true;
53810
+ const { clearCache: clearStorageCache, ...storage } = createStorage(mergedConfig.dataDir, tag);
53811
+ const recoverActiveRuns = resolveRecoverActiveRuns(mergedConfig);
53688
53812
  return {
53689
53813
  specVersion: SPEC_VERSION_CURRENT,
53690
53814
  ...queue,
@@ -53711,9 +53835,11 @@ function createLocalWorld(args) {
53711
53835
  await reenqueueActiveRuns(recoveryRuns, queue.queue, "world-local");
53712
53836
  },
53713
53837
  async close() {
53838
+ clearStorageCache();
53714
53839
  await queue.close();
53715
53840
  },
53716
53841
  async clear() {
53842
+ clearStorageCache();
53717
53843
  if (tag) {
53718
53844
  const basedir = mergedConfig.dataDir;
53719
53845
  const hooksDir = import_node_path9.default.join(basedir, "hooks");
@@ -53747,6 +53873,7 @@ function createLocalWorld(args) {
53747
53873
  })));
53748
53874
  clearCreatedFilesCache();
53749
53875
  } else {
53876
+ clearCreatedFilesCache();
53750
53877
  await (0, import_promises6.rm)(mergedConfig.dataDir, { recursive: true, force: true });
53751
53878
  await initDataDir(mergedConfig.dataDir);
53752
53879
  }
@@ -54247,7 +54374,7 @@ function httpClientSpanAttributes(args) {
54247
54374
  }
54248
54375
  __name(httpClientSpanAttributes, "httpClientSpanAttributes");
54249
54376
  async function instrumentedFetch(opts) {
54250
- const { method, url: url2, headers, body, dispatcher, peerService = "workflow-server", timeoutMs = REQUEST_TIMEOUT_MS, signal: callerSignal, injectTraceContext = true, cacheBust = true, logLabel, buildError, onTransportOutcome } = opts;
54377
+ const { method, url: url2, headers, body, dispatcher, peerService = "workflow-server", timeoutMs = REQUEST_TIMEOUT_MS, signal: callerSignal, injectTraceContext = true, cacheBust = true, logLabel, buildError, onTransportOutcome, deferTransportSuccessUntilBody = false } = opts;
54251
54378
  const label = logLabel ?? url2;
54252
54379
  return trace4(`http ${method}`, { kind: await getSpanKind3("CLIENT") }, async (span) => {
54253
54380
  span?.setAttributes(httpClientSpanAttributes({ method, url: url2, peerService }));
@@ -54295,18 +54422,31 @@ async function instrumentedFetch(opts) {
54295
54422
  throw error48;
54296
54423
  }
54297
54424
  const ms2 = Date.now() - start2;
54298
- onTransportOutcome?.();
54425
+ if (!deferTransportSuccessUntilBody)
54426
+ onTransportOutcome?.();
54299
54427
  httpLog(method, label, response, ms2);
54300
54428
  span?.setAttributes({ ...HttpResponseStatusCode2(response.status) });
54301
54429
  if (!response.ok) {
54302
54430
  span?.setAttributes({ ...ErrorType2(`HTTP ${response.status}`) });
54303
54431
  logCurlRepro(method, url2, headers);
54304
54432
  if (buildError) {
54305
- const error49 = await buildError(response);
54433
+ let error49;
54434
+ try {
54435
+ error49 = await buildError(response);
54436
+ } catch (cause) {
54437
+ if (deferTransportSuccessUntilBody) {
54438
+ onTransportOutcome?.(cause);
54439
+ }
54440
+ throw cause;
54441
+ }
54442
+ if (deferTransportSuccessUntilBody)
54443
+ onTransportOutcome?.();
54306
54444
  span?.recordException?.(error49);
54307
54445
  throw error49;
54308
54446
  }
54309
54447
  const text = await response.text().catch(() => "");
54448
+ if (deferTransportSuccessUntilBody)
54449
+ onTransportOutcome?.();
54310
54450
  const error48 = errorForResponse(response.status, `${method} ${label} -> HTTP ${response.status}: ${response.statusText}${text ? ` ${text}` : ""}${formatVercelDiagnostics(response.headers)}`, {
54311
54451
  url: url2,
54312
54452
  retryAfter: parseRetryAfter(response.headers.get("Retry-After"))
@@ -61451,7 +61591,7 @@ var import_oidc3 = __toESM(require_dist(), 1);
61451
61591
  init_dist();
61452
61592
 
61453
61593
  // ../world-vercel/dist/version.js
61454
- var version3 = "4.7.0";
61594
+ var version3 = "4.7.2";
61455
61595
 
61456
61596
  // ../world-vercel/dist/utils.js
61457
61597
  var WORKFLOW_SERVER_URL_OVERRIDE = "";
@@ -61968,21 +62108,35 @@ function createQueue2(config3) {
61968
62108
  __name(createQueue2, "createQueue");
61969
62109
 
61970
62110
  // ../world-vercel/dist/resolve-latest-deployment.js
62111
+ var import_oidc4 = __toESM(require_dist(), 1);
61971
62112
  init_zod();
61972
62113
  var ResolveLatestDeploymentResponseSchema = object({
61973
62114
  id: string2()
61974
62115
  });
62116
+ async function resolveDeploymentIdentityToken(config3) {
62117
+ if (config3?.token)
62118
+ return config3.token;
62119
+ if (process.env.VERCEL === "1") {
62120
+ const oidcToken = await (0, import_oidc4.getVercelOidcToken)().catch(() => null);
62121
+ if (oidcToken)
62122
+ return oidcToken;
62123
+ }
62124
+ return resolveVercelApiToken(config3);
62125
+ }
62126
+ __name(resolveDeploymentIdentityToken, "resolveDeploymentIdentityToken");
61975
62127
  function createResolveLatestDeploymentId(config3) {
61976
62128
  return /* @__PURE__ */ __name(async function resolveLatestDeploymentId() {
61977
62129
  const currentDeploymentId = process.env.VERCEL_DEPLOYMENT_ID;
61978
62130
  if (!currentDeploymentId) {
61979
62131
  throw new Error("Cannot resolve latest deployment: VERCEL_DEPLOYMENT_ID environment variable is not set");
61980
62132
  }
61981
- const token = await resolveVercelApiToken(config3);
62133
+ const token = await resolveDeploymentIdentityToken(config3);
61982
62134
  if (!token) {
61983
62135
  throw new Error("Cannot resolve latest deployment: no OIDC token or VERCEL_TOKEN available");
61984
62136
  }
61985
- const url2 = `https://api.vercel.com/v1/workflow/resolve-latest-deployment/${encodeURIComponent(currentDeploymentId)}`;
62137
+ const teamId = config3?.projectConfig?.teamId;
62138
+ const query = teamId ? `?${new URLSearchParams({ teamId })}` : "";
62139
+ const url2 = `https://api.vercel.com/v1/workflow/resolve-latest-deployment/${encodeURIComponent(currentDeploymentId)}${query}`;
61986
62140
  const response = await instrumentedFetch({
61987
62141
  method: "GET",
61988
62142
  url: url2,
@@ -61999,7 +62153,8 @@ function createResolveLatestDeploymentId(config3) {
61999
62153
  } catch {
62000
62154
  body = "<unable to read response body>";
62001
62155
  }
62002
- return new Error(`Failed to resolve latest deployment for ${currentDeploymentId}: HTTP ${res.status} ${res.statusText}${body ? ` \u2014 ${body}` : ""}`);
62156
+ const hint = res.status === 404 ? ". The deployment exists but was not visible to the identity this request authenticated as, which means the request resolved to a different team. Set the World's `projectConfig.teamId` to scope it explicitly." : "";
62157
+ return new Error(`Failed to resolve latest deployment for ${currentDeploymentId}: HTTP ${res.status} ${res.statusText}${body ? ` \u2014 ${body}` : ""}${hint}`);
62003
62158
  }, "buildError")
62004
62159
  });
62005
62160
  const data = await response.json();
@@ -62280,7 +62435,7 @@ __name(readerToIterator, "readerToIterator");
62280
62435
  // ../world-vercel/dist/events-v4.js
62281
62436
  async function fetchV4(url2, init, config3, opName) {
62282
62437
  const dispatcher = getEventsDispatcher(config3);
62283
- return instrumentedFetch({
62438
+ const response = await instrumentedFetch({
62284
62439
  method: init.method,
62285
62440
  url: url2,
62286
62441
  headers: init.headers,
@@ -62291,9 +62446,40 @@ async function fetchV4(url2, init, config3, opName) {
62291
62446
  // service indefinitely, so without this every request routed onto it fails
62292
62447
  // until the compute instance is recycled — see noteEventsTransportOutcome.
62293
62448
  onTransportOutcome: /* @__PURE__ */ __name((error48) => noteEventsTransportOutcome(dispatcher, error48), "onTransportOutcome"),
62449
+ deferTransportSuccessUntilBody: true,
62294
62450
  timeoutMs: null,
62295
62451
  logLabel: opName,
62296
- buildError: /* @__PURE__ */ __name(async (response) => errorFromV4Response(response.status, headersToRecord(response.headers), await response.text(), opName, url2), "buildError")
62452
+ buildError: /* @__PURE__ */ __name(async (response2) => errorFromV4Response(response2.status, headersToRecord(response2.headers), await response2.text(), opName, url2), "buildError")
62453
+ });
62454
+ if (!response.body) {
62455
+ noteEventsTransportOutcome(dispatcher);
62456
+ return response;
62457
+ }
62458
+ const reader = response.body.getReader();
62459
+ const body = new ReadableStream({
62460
+ async pull(controller) {
62461
+ try {
62462
+ const chunk = await reader.read();
62463
+ if (chunk.done) {
62464
+ noteEventsTransportOutcome(dispatcher);
62465
+ controller.close();
62466
+ } else {
62467
+ controller.enqueue(chunk.value);
62468
+ }
62469
+ } catch (cause) {
62470
+ noteEventsTransportOutcome(dispatcher, cause);
62471
+ controller.error(cause);
62472
+ }
62473
+ },
62474
+ cancel(reason) {
62475
+ noteEventsTransportOutcome(dispatcher);
62476
+ return reader.cancel(reason);
62477
+ }
62478
+ });
62479
+ return new Response(body, {
62480
+ status: response.status,
62481
+ statusText: response.statusText,
62482
+ headers: response.headers
62297
62483
  });
62298
62484
  }
62299
62485
  __name(fetchV4, "fetchV4");
@@ -62473,10 +62659,12 @@ async function getWorkflowRunEventsV4(runId, params = {}, config3) {
62473
62659
  return consumeListFrameStream(url2, headers, config3, "listEvents");
62474
62660
  }
62475
62661
  __name(getWorkflowRunEventsV4, "getWorkflowRunEventsV4");
62476
- async function getEventsByCorrelationIdV4(correlationId, params = {}, config3) {
62662
+ async function getEventsByCorrelationIdV4(correlationId, params = {}, config3, runId) {
62477
62663
  const { baseUrl, headers } = await getHttpConfig(config3);
62478
62664
  const sp = new URLSearchParams();
62479
62665
  sp.set("correlationId", correlationId);
62666
+ if (runId !== void 0)
62667
+ sp.set("runId", runId);
62480
62668
  appendListParams(sp, params);
62481
62669
  const url2 = `${baseUrl}/v4/events?${sp.toString()}`;
62482
62670
  return consumeListFrameStream(url2, headers, config3, "listEventsByCorrelationId");
@@ -62889,10 +63077,13 @@ async function getWorkflowRunEvents(params, config3) {
62889
63077
  sortOrder: pagination?.sortOrder,
62890
63078
  remoteRefBehavior: resolveData === "none" ? "lazy" : "resolve"
62891
63079
  };
62892
- const result = await ("correlationId" in params ? getEventsByCorrelationIdV4(params.correlationId, wirePagination, config3) : getWorkflowRunEventsV4(params.runId, wirePagination, config3));
63080
+ const runId = "correlationId" in params ? params.runId : void 0;
63081
+ const result = await ("correlationId" in params ? getEventsByCorrelationIdV4(params.correlationId, wirePagination, config3, runId) : getWorkflowRunEventsV4(params.runId, wirePagination, config3));
62893
63082
  const events = result.events.map((listed) => buildEventFromV4(listed.event, listed.body, resolveData));
62894
63083
  return {
62895
- data: events,
63084
+ // Older servers may ignore the runId query parameter. Keep the client
63085
+ // filter as a compatibility guard until every server honors it.
63086
+ data: runId !== void 0 ? events.filter((event) => event.runId === runId) : events,
62896
63087
  cursor: result.next ?? null,
62897
63088
  hasMore: Boolean(result.next)
62898
63089
  };
@@ -64466,7 +64657,7 @@ function getStepFunction(stepId) {
64466
64657
  }
64467
64658
  __name(getStepFunction, "getStepFunction");
64468
64659
  var DEFER_BEHIND = {
64469
- hook: ["wait", "step"],
64660
+ hook: ["hook", "wait", "step"],
64470
64661
  wait: ["hook", "step"],
64471
64662
  step: ["wait", "hook", "step"]
64472
64663
  };
@@ -64528,12 +64719,6 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64528
64719
  }
64529
64720
  let done = false;
64530
64721
  const { promise: promise2, resolve: resolve3 } = withResolvers();
64531
- const entry = {
64532
- kind,
64533
- delivered: promise2,
64534
- armed: options.armed ?? true
64535
- };
64536
- barriers.set(eventIndex, entry);
64537
64722
  const finish = /* @__PURE__ */ __name(() => {
64538
64723
  if (done) {
64539
64724
  return;
@@ -64544,7 +64729,14 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64544
64729
  }
64545
64730
  resolve3();
64546
64731
  }, "finish");
64547
- scheduleWhenIdle(ctx, finish);
64732
+ const entry = {
64733
+ kind,
64734
+ delivered: promise2,
64735
+ armed: options.armed ?? true,
64736
+ retire: finish
64737
+ };
64738
+ barriers.set(eventIndex, entry);
64739
+ ensureBarrierSafetyNet(ctx);
64548
64740
  return {
64549
64741
  markDelivered: finish,
64550
64742
  arm: /* @__PURE__ */ __name(() => {
@@ -64553,6 +64745,48 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64553
64745
  };
64554
64746
  }
64555
64747
  __name(registerDeliveryBarrier, "registerDeliveryBarrier");
64748
+ var activeBarrierSafetyNets = /* @__PURE__ */ new WeakSet();
64749
+ function ensureBarrierSafetyNet(ctx) {
64750
+ const barriers = ctx.pendingDeliveryBarriers;
64751
+ if (!barriers || activeBarrierSafetyNets.has(ctx)) {
64752
+ return;
64753
+ }
64754
+ activeBarrierSafetyNets.add(ctx);
64755
+ const rearm = /* @__PURE__ */ __name(() => {
64756
+ setTimeout(check2, 0);
64757
+ }, "rearm");
64758
+ const rearmAfterRejection = /* @__PURE__ */ __name(() => {
64759
+ setTimeout(check2, 50);
64760
+ }, "rearmAfterRejection");
64761
+ const check2 = /* @__PURE__ */ __name(() => {
64762
+ if (barriers.size === 0) {
64763
+ activeBarrierSafetyNets.delete(ctx);
64764
+ return;
64765
+ }
64766
+ if (!canRetireAbandonedBarriers(ctx)) {
64767
+ ctx.promiseQueue.then(rearm, rearmAfterRejection);
64768
+ return;
64769
+ }
64770
+ while (barriers.size > 0 && canRetireAbandonedBarriers(ctx)) {
64771
+ let lowestIndex;
64772
+ let lowestEntry;
64773
+ for (const [index, entry] of barriers) {
64774
+ if (lowestIndex === void 0 || index < lowestIndex) {
64775
+ lowestIndex = index;
64776
+ lowestEntry = entry;
64777
+ }
64778
+ }
64779
+ lowestEntry?.retire();
64780
+ }
64781
+ setTimeout(check2, 0);
64782
+ }, "check");
64783
+ setTimeout(check2, 0);
64784
+ }
64785
+ __name(ensureBarrierSafetyNet, "ensureBarrierSafetyNet");
64786
+ function canRetireAbandonedBarriers(ctx) {
64787
+ return ctx.pendingDeliveries === 0 && !hasParkedCommittedDelivery(ctx);
64788
+ }
64789
+ __name(canRetireAbandonedBarriers, "canRetireAbandonedBarriers");
64556
64790
  function hasParkedCommittedDelivery(ctx) {
64557
64791
  const barriers = ctx.pendingDeliveryBarriers;
64558
64792
  if (!barriers || barriers.size === 0) {
@@ -64568,7 +64802,7 @@ function hasParkedCommittedDelivery(ctx) {
64568
64802
  }
64569
64803
  __name(hasParkedCommittedDelivery, "hasParkedCommittedDelivery");
64570
64804
  function isDeliveryIdle(ctx) {
64571
- return ctx.pendingDeliveries === 0 && !hasParkedCommittedDelivery(ctx);
64805
+ return ctx.pendingDeliveries === 0 && (!ctx.pendingDeliveryBarriers || ctx.pendingDeliveryBarriers.size === 0);
64572
64806
  }
64573
64807
  __name(isDeliveryIdle, "isDeliveryIdle");
64574
64808
  function scheduleWhenIdle(ctx, fn) {
@@ -65713,6 +65947,23 @@ async function hydrateStepReturnValue(value, _runId, key, global2 = globalThis,
65713
65947
  }
65714
65948
  __name(hydrateStepReturnValue, "hydrateStepReturnValue");
65715
65949
 
65950
+ // ../core/dist/runtime/unserializable-step.js
65951
+ var UNSERIALIZABLE_STEP_INPUT_MARKER = "[input unavailable: step argument serialization failed]";
65952
+ var UNSERIALIZABLE_FLAG = "__workflowUnserializableStepInput";
65953
+ function unserializableStepInputPlaceholder() {
65954
+ return {
65955
+ args: [UNSERIALIZABLE_STEP_INPUT_MARKER],
65956
+ closureVars: [],
65957
+ thisVal: void 0,
65958
+ [UNSERIALIZABLE_FLAG]: true
65959
+ };
65960
+ }
65961
+ __name(unserializableStepInputPlaceholder, "unserializableStepInputPlaceholder");
65962
+ function isUnserializableStepInputPlaceholder(hydratedInput) {
65963
+ return typeof hydratedInput === "object" && hydratedInput !== null && hydratedInput[UNSERIALIZABLE_FLAG] === true;
65964
+ }
65965
+ __name(isUnserializableStepInputPlaceholder, "isUnserializableStepInputPlaceholder");
65966
+
65716
65967
  // ../core/dist/runtime/suspension-handler.js
65717
65968
  function extractTraceHeaders(traceCarrier) {
65718
65969
  const headers = {};
@@ -65849,15 +66100,84 @@ async function handleSuspension({ suspension, world, run: run2, span, requestId,
65849
66100
  }));
65850
66101
  }
65851
66102
  const stepsNeedingCreation = new Set(stepItems.filter((queueItem) => !queueItem.hasCreatedEvent).map((queueItem) => queueItem.correlationId));
66103
+ const failedStepCorrelationIds = /* @__PURE__ */ new Set();
66104
+ const finalizeUnserializableStep = /* @__PURE__ */ __name(async (queueItem, error48) => {
66105
+ runtimeLogger.warn("Step arguments failed to serialize; failing the step so the workflow can observe the error", {
66106
+ workflowRunId: runId,
66107
+ correlationId: queueItem.correlationId,
66108
+ stepName: queueItem.stepName,
66109
+ error: error48.message
66110
+ });
66111
+ const placeholderInput = await dehydrateStepArguments(unserializableStepInputPlaceholder(), runId, encryptionKey, suspension.globalThis);
66112
+ try {
66113
+ await createGuarded({
66114
+ eventType: "step_created",
66115
+ specVersion: SPEC_VERSION_CURRENT,
66116
+ correlationId: queueItem.correlationId,
66117
+ eventData: {
66118
+ stepName: queueItem.stepName,
66119
+ workflowName: run2.workflowName,
66120
+ input: placeholderInput
66121
+ }
66122
+ }, { requestId });
66123
+ } catch (createErr) {
66124
+ if (EntityConflictError.is(createErr)) {
66125
+ runtimeLogger.info("Step already exists, continuing", {
66126
+ workflowRunId: runId,
66127
+ correlationId: queueItem.correlationId,
66128
+ message: createErr.message
66129
+ });
66130
+ } else if (RunExpiredError.is(createErr)) {
66131
+ return;
66132
+ } else {
66133
+ throw createErr;
66134
+ }
66135
+ }
66136
+ try {
66137
+ await createGuarded({
66138
+ eventType: "step_failed",
66139
+ specVersion: SPEC_VERSION_CURRENT,
66140
+ correlationId: queueItem.correlationId,
66141
+ eventData: {
66142
+ stepName: queueItem.stepName,
66143
+ // The message carries the framed serialization hint; the step
66144
+ // consumer rejects the step's promise with a FatalError built
66145
+ // from it, exactly like any other step failure.
66146
+ error: error48.message,
66147
+ stack: error48.stack
66148
+ }
66149
+ }, { requestId });
66150
+ } catch (failErr) {
66151
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
66152
+ runtimeLogger.info("Tried failing step, but step or run has already finished.", {
66153
+ workflowRunId: runId,
66154
+ correlationId: queueItem.correlationId,
66155
+ message: failErr.message
66156
+ });
66157
+ } else {
66158
+ throw failErr;
66159
+ }
66160
+ }
66161
+ failedStepCorrelationIds.add(queueItem.correlationId);
66162
+ }, "finalizeUnserializableStep");
65852
66163
  const ops = [];
65853
66164
  for (const queueItem of stepItems) {
65854
66165
  ops.push((async () => {
65855
66166
  if (stepsNeedingCreation.has(queueItem.correlationId)) {
65856
- const dehydratedInput = await dehydrateStepArguments({
65857
- args: queueItem.args,
65858
- closureVars: queueItem.closureVars,
65859
- thisVal: queueItem.thisVal
65860
- }, runId, encryptionKey, suspension.globalThis);
66167
+ let dehydratedInput;
66168
+ try {
66169
+ dehydratedInput = await dehydrateStepArguments({
66170
+ args: queueItem.args,
66171
+ closureVars: queueItem.closureVars,
66172
+ thisVal: queueItem.thisVal
66173
+ }, runId, encryptionKey, suspension.globalThis);
66174
+ } catch (err) {
66175
+ if (RuntimeDecryptionError.is(err)) {
66176
+ throw err;
66177
+ }
66178
+ await finalizeUnserializableStep(queueItem, err instanceof Error ? err : new Error(String(err)));
66179
+ return;
66180
+ }
65861
66181
  const stepEvent = {
65862
66182
  eventType: "step_created",
65863
66183
  specVersion: SPEC_VERSION_CURRENT,
@@ -65939,8 +66259,12 @@ async function handleSuspension({ suspension, world, run: run2, span, requestId,
65939
66259
  ...WorkflowRunStatus("workflow_suspended"),
65940
66260
  ...WorkflowStepsCreated(stepItems.length),
65941
66261
  ...WorkflowHooksCreated(hooksNeedingCreation.length),
65942
- ...WorkflowWaitsCreated(waitItems.length)
66262
+ ...WorkflowWaitsCreated(waitItems.length),
66263
+ ...failedStepCorrelationIds.size > 0 ? WorkflowStepsFailedSerialization(failedStepCorrelationIds.size) : {}
65943
66264
  });
66265
+ if (failedStepCorrelationIds.size > 0) {
66266
+ return { timeoutSeconds: 0, failedStepCorrelationIds };
66267
+ }
65944
66268
  if (hasHookConflict) {
65945
66269
  return { timeoutSeconds: 0 };
65946
66270
  }
@@ -68770,6 +69094,9 @@ var stepHandler = createQueueHandler(stepPrefix, async (message_, metadata) => {
68770
69094
  let userCodeFailed = false;
68771
69095
  const executionStartTime = Date.now();
68772
69096
  try {
69097
+ if (isUnserializableStepInputPlaceholder(hydratedInput)) {
69098
+ throw new FatalError(formatSerializationError("step arguments", void 0));
69099
+ }
68773
69100
  result = await trace2("step.execute", {}, async () => {
68774
69101
  return await contextStorage.run({
68775
69102
  stepMetadata: {