@workflow/world-testing 4.1.19 → 4.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  });
@@ -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.5";
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}`);
@@ -52523,8 +52563,81 @@ async function deleteAllWaitsForRun(basedir, runId) {
52523
52563
  }
52524
52564
  __name(deleteAllWaitsForRun, "deleteAllWaitsForRun");
52525
52565
  function createEventsStorage(basedir, tag) {
52566
+ const maxCachedEventBytes = 4 * 1024 * 1024;
52567
+ const maxCachedEventEntries = 1e3;
52568
+ const eventCache = /* @__PURE__ */ new Map();
52569
+ const cachedEventBytes = /* @__PURE__ */ new Map();
52570
+ const cachedPathsByRunId = /* @__PURE__ */ new Map();
52571
+ let totalCachedEventBytes = 0;
52572
+ function deleteCachedEvent(eventPath) {
52573
+ const event = eventCache.get(eventPath);
52574
+ if (!event) {
52575
+ return;
52576
+ }
52577
+ eventCache.delete(eventPath);
52578
+ totalCachedEventBytes -= cachedEventBytes.get(eventPath) ?? 0;
52579
+ cachedEventBytes.delete(eventPath);
52580
+ const cachedPaths = cachedPathsByRunId.get(event.runId);
52581
+ cachedPaths?.delete(eventPath);
52582
+ if (cachedPaths?.size === 0) {
52583
+ cachedPathsByRunId.delete(event.runId);
52584
+ }
52585
+ }
52586
+ __name(deleteCachedEvent, "deleteCachedEvent");
52587
+ function clearRunCache(runId) {
52588
+ for (const cachedPath of cachedPathsByRunId.get(runId) ?? []) {
52589
+ deleteCachedEvent(cachedPath);
52590
+ }
52591
+ }
52592
+ __name(clearRunCache, "clearRunCache");
52593
+ function clearCache() {
52594
+ eventCache.clear();
52595
+ cachedEventBytes.clear();
52596
+ cachedPathsByRunId.clear();
52597
+ totalCachedEventBytes = 0;
52598
+ }
52599
+ __name(clearCache, "clearCache");
52600
+ function cacheEvent(eventPath, cachedEvent, serializedBytes) {
52601
+ if (serializedBytes > maxCachedEventBytes) {
52602
+ return;
52603
+ }
52604
+ while (eventCache.size > 0 && (eventCache.size >= maxCachedEventEntries || totalCachedEventBytes + serializedBytes > maxCachedEventBytes)) {
52605
+ const oldestPath = eventCache.keys().next().value;
52606
+ deleteCachedEvent(oldestPath);
52607
+ }
52608
+ eventCache.set(eventPath, cachedEvent);
52609
+ cachedEventBytes.set(eventPath, serializedBytes);
52610
+ totalCachedEventBytes += serializedBytes;
52611
+ const cachedPaths = cachedPathsByRunId.get(cachedEvent.runId) ?? /* @__PURE__ */ new Set();
52612
+ cachedPaths.add(eventPath);
52613
+ cachedPathsByRunId.set(cachedEvent.runId, cachedPaths);
52614
+ }
52615
+ __name(cacheEvent, "cacheEvent");
52616
+ function rememberStoredEvent(event, eventPath, serializedEvent) {
52617
+ if (event.eventType === "run_completed" || event.eventType === "run_failed" || event.eventType === "run_cancelled") {
52618
+ clearRunCache(event.runId);
52619
+ return;
52620
+ }
52621
+ const serializedBytes = Buffer.byteLength(serializedEvent);
52622
+ if (serializedBytes > maxCachedEventBytes) {
52623
+ return;
52624
+ }
52625
+ const cachedEvent = EventSchema.safeParse(JSON.parse(serializedEvent, jsonReviver));
52626
+ if (cachedEvent.success) {
52627
+ cacheEvent(eventPath, cachedEvent.data, serializedBytes);
52628
+ }
52629
+ }
52630
+ __name(rememberStoredEvent, "rememberStoredEvent");
52631
+ async function storeEvent(event) {
52632
+ const eventPath = taggedPath(basedir, "events", `${event.runId}-${event.eventId}`, tag);
52633
+ const serializedEvent = JSON.stringify(event, jsonReplacer, 2);
52634
+ await write(eventPath, serializedEvent);
52635
+ rememberStoredEvent(event, eventPath, serializedEvent);
52636
+ }
52637
+ __name(storeEvent, "storeEvent");
52526
52638
  const hookLocks = /* @__PURE__ */ new Map();
52527
52639
  return {
52640
+ clearCache,
52528
52641
  async create(runId, data, params) {
52529
52642
  if (runId != null && runId !== "") {
52530
52643
  assertSafeEntityId("runId", runId);
@@ -52594,8 +52707,7 @@ function createEventsStorage(basedir, tag) {
52594
52707
  executionContext: runInputData.executionContext
52595
52708
  }
52596
52709
  };
52597
- const createdCompositeKey = `${effectiveRunId}-${runCreatedEventId}`;
52598
- await writeJSON(taggedPath(basedir, "events", createdCompositeKey, tag), runCreatedEvent);
52710
+ await storeEvent(runCreatedEvent);
52599
52711
  currentRun = createdRun;
52600
52712
  } else {
52601
52713
  currentRun = await readJSONWithFallback(basedir, "runs", effectiveRunId, WorkflowRunSchema, tag);
@@ -52625,8 +52737,7 @@ function createEventsStorage(basedir, tag) {
52625
52737
  createdAt: now,
52626
52738
  specVersion: effectiveSpecVersion
52627
52739
  };
52628
- const compositeKey2 = `${effectiveRunId}-${eventId}`;
52629
- await writeJSON(taggedPath(basedir, "events", compositeKey2, tag), event2);
52740
+ await storeEvent(event2);
52630
52741
  const resolveData2 = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
52631
52742
  return {
52632
52743
  event: stripEventDataRefs(event2, resolveData2),
@@ -52975,8 +53086,7 @@ function createEventsStorage(basedir, tag) {
52975
53086
  createdAt: now,
52976
53087
  specVersion: effectiveSpecVersion
52977
53088
  };
52978
- const compositeKey2 = `${effectiveRunId}-${eventId}`;
52979
- await writeJSON(taggedPath(basedir, "events", compositeKey2, tag), conflictEvent);
53089
+ await storeEvent(conflictEvent);
52980
53090
  const resolveData2 = params?.resolveData ?? DEFAULT_RESOLVE_DATA_OPTION;
52981
53091
  const filteredEvent2 = stripEventDataRefs(conflictEvent, resolveData2);
52982
53092
  return {
@@ -53060,13 +53170,16 @@ function createEventsStorage(basedir, tag) {
53060
53170
  await writeJSON(taggedPath(basedir, "waits", waitCompositeKey, tag), wait, { overwrite: true });
53061
53171
  }
53062
53172
  const compositeKey = `${effectiveRunId}-${eventId}`;
53063
- const eventPublished = await writeExclusive(taggedPath(basedir, "events", compositeKey, tag), JSON.stringify(event, jsonReplacer, 2));
53173
+ const eventPath = taggedPath(basedir, "events", compositeKey, tag);
53174
+ const serializedEvent = JSON.stringify(event, jsonReplacer, 2);
53175
+ const eventPublished = await writeExclusive(eventPath, serializedEvent);
53064
53176
  if (!eventPublished) {
53065
53177
  if (data.eventType === "hook_created" && data.correlationId) {
53066
53178
  await repairHookEntityFromPersistedEvent(basedir, effectiveRunId, data.correlationId, eventId, tag);
53067
53179
  }
53068
53180
  throw new EntityConflictError(`Event "${eventId}" already exists for run "${effectiveRunId}"`);
53069
53181
  }
53182
+ rememberStoredEvent(event, eventPath, serializedEvent);
53070
53183
  if (hook && data.eventType === "hook_created") {
53071
53184
  await writeJSON(taggedPath(basedir, "hooks", hook.hookId, tag), hook, hookEntityWriteOptions);
53072
53185
  }
@@ -53079,6 +53192,7 @@ function createEventsStorage(basedir, tag) {
53079
53192
  const allEvents = await paginatedFileSystemQuery({
53080
53193
  directory: import_node_path5.default.join(basedir, "events"),
53081
53194
  schema: EventSchema,
53195
+ cachedItems: eventCache,
53082
53196
  filePrefix: `${effectiveRunId}-`,
53083
53197
  sortOrder: "asc",
53084
53198
  limit: 1e3,
@@ -53122,6 +53236,7 @@ function createEventsStorage(basedir, tag) {
53122
53236
  const result = await paginatedFileSystemQuery({
53123
53237
  directory: import_node_path5.default.join(basedir, "events"),
53124
53238
  schema: EventSchema,
53239
+ cachedItems: eventCache,
53125
53240
  filePrefix: `${runId}-`,
53126
53241
  // Events in chronological order (oldest first) by default,
53127
53242
  // different from the default for other list calls.
@@ -53146,8 +53261,9 @@ function createEventsStorage(basedir, tag) {
53146
53261
  const result = await paginatedFileSystemQuery({
53147
53262
  directory: import_node_path5.default.join(basedir, "events"),
53148
53263
  schema: EventSchema,
53264
+ cachedItems: eventCache,
53149
53265
  // No filePrefix - search all events
53150
- filter: /* @__PURE__ */ __name((event) => event.correlationId === correlationId, "filter"),
53266
+ filter: /* @__PURE__ */ __name((event) => event.correlationId === correlationId && (params.runId === void 0 || event.runId === params.runId), "filter"),
53151
53267
  // Events in chronological order (oldest first) by default,
53152
53268
  // different from the default for other list calls.
53153
53269
  sortOrder: params.pagination?.sortOrder ?? "asc",
@@ -53283,7 +53399,8 @@ function createStorage(basedir, tag) {
53283
53399
  runs: instrumentObject("world.runs", runs),
53284
53400
  steps: instrumentObject("world.steps", steps),
53285
53401
  events: instrumentObject("world.events", events),
53286
- hooks: instrumentObject("world.hooks", hooks)
53402
+ hooks: instrumentObject("world.hooks", hooks),
53403
+ clearCache: /* @__PURE__ */ __name(() => events.clearCache(), "clearCache")
53287
53404
  };
53288
53405
  }
53289
53406
  __name(createStorage, "createStorage");
@@ -53683,8 +53800,8 @@ function createLocalWorld(args) {
53683
53800
  const mergedConfig = { ...config2.value, ...definedArgs };
53684
53801
  const tag = mergedConfig.tag;
53685
53802
  const queue = createQueue(mergedConfig);
53686
- const storage = createStorage(mergedConfig.dataDir, tag);
53687
- const recoverActiveRuns = mergedConfig.recoverActiveRuns ?? true;
53803
+ const { clearCache: clearStorageCache, ...storage } = createStorage(mergedConfig.dataDir, tag);
53804
+ const recoverActiveRuns = resolveRecoverActiveRuns(mergedConfig);
53688
53805
  return {
53689
53806
  specVersion: SPEC_VERSION_CURRENT,
53690
53807
  ...queue,
@@ -53711,9 +53828,11 @@ function createLocalWorld(args) {
53711
53828
  await reenqueueActiveRuns(recoveryRuns, queue.queue, "world-local");
53712
53829
  },
53713
53830
  async close() {
53831
+ clearStorageCache();
53714
53832
  await queue.close();
53715
53833
  },
53716
53834
  async clear() {
53835
+ clearStorageCache();
53717
53836
  if (tag) {
53718
53837
  const basedir = mergedConfig.dataDir;
53719
53838
  const hooksDir = import_node_path9.default.join(basedir, "hooks");
@@ -53747,6 +53866,7 @@ function createLocalWorld(args) {
53747
53866
  })));
53748
53867
  clearCreatedFilesCache();
53749
53868
  } else {
53869
+ clearCreatedFilesCache();
53750
53870
  await (0, import_promises6.rm)(mergedConfig.dataDir, { recursive: true, force: true });
53751
53871
  await initDataDir(mergedConfig.dataDir);
53752
53872
  }
@@ -61451,7 +61571,7 @@ var import_oidc3 = __toESM(require_dist(), 1);
61451
61571
  init_dist();
61452
61572
 
61453
61573
  // ../world-vercel/dist/version.js
61454
- var version3 = "4.7.0";
61574
+ var version3 = "4.7.1";
61455
61575
 
61456
61576
  // ../world-vercel/dist/utils.js
61457
61577
  var WORKFLOW_SERVER_URL_OVERRIDE = "";
@@ -62473,10 +62593,12 @@ async function getWorkflowRunEventsV4(runId, params = {}, config3) {
62473
62593
  return consumeListFrameStream(url2, headers, config3, "listEvents");
62474
62594
  }
62475
62595
  __name(getWorkflowRunEventsV4, "getWorkflowRunEventsV4");
62476
- async function getEventsByCorrelationIdV4(correlationId, params = {}, config3) {
62596
+ async function getEventsByCorrelationIdV4(correlationId, params = {}, config3, runId) {
62477
62597
  const { baseUrl, headers } = await getHttpConfig(config3);
62478
62598
  const sp = new URLSearchParams();
62479
62599
  sp.set("correlationId", correlationId);
62600
+ if (runId !== void 0)
62601
+ sp.set("runId", runId);
62480
62602
  appendListParams(sp, params);
62481
62603
  const url2 = `${baseUrl}/v4/events?${sp.toString()}`;
62482
62604
  return consumeListFrameStream(url2, headers, config3, "listEventsByCorrelationId");
@@ -62889,10 +63011,13 @@ async function getWorkflowRunEvents(params, config3) {
62889
63011
  sortOrder: pagination?.sortOrder,
62890
63012
  remoteRefBehavior: resolveData === "none" ? "lazy" : "resolve"
62891
63013
  };
62892
- const result = await ("correlationId" in params ? getEventsByCorrelationIdV4(params.correlationId, wirePagination, config3) : getWorkflowRunEventsV4(params.runId, wirePagination, config3));
63014
+ const runId = "correlationId" in params ? params.runId : void 0;
63015
+ const result = await ("correlationId" in params ? getEventsByCorrelationIdV4(params.correlationId, wirePagination, config3, runId) : getWorkflowRunEventsV4(params.runId, wirePagination, config3));
62893
63016
  const events = result.events.map((listed) => buildEventFromV4(listed.event, listed.body, resolveData));
62894
63017
  return {
62895
- data: events,
63018
+ // Older servers may ignore the runId query parameter. Keep the client
63019
+ // filter as a compatibility guard until every server honors it.
63020
+ data: runId !== void 0 ? events.filter((event) => event.runId === runId) : events,
62896
63021
  cursor: result.next ?? null,
62897
63022
  hasMore: Boolean(result.next)
62898
63023
  };
@@ -64466,7 +64591,7 @@ function getStepFunction(stepId) {
64466
64591
  }
64467
64592
  __name(getStepFunction, "getStepFunction");
64468
64593
  var DEFER_BEHIND = {
64469
- hook: ["wait", "step"],
64594
+ hook: ["hook", "wait", "step"],
64470
64595
  wait: ["hook", "step"],
64471
64596
  step: ["wait", "hook", "step"]
64472
64597
  };
@@ -64528,12 +64653,6 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64528
64653
  }
64529
64654
  let done = false;
64530
64655
  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
64656
  const finish = /* @__PURE__ */ __name(() => {
64538
64657
  if (done) {
64539
64658
  return;
@@ -64544,7 +64663,14 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64544
64663
  }
64545
64664
  resolve3();
64546
64665
  }, "finish");
64547
- scheduleWhenIdle(ctx, finish);
64666
+ const entry = {
64667
+ kind,
64668
+ delivered: promise2,
64669
+ armed: options.armed ?? true,
64670
+ retire: finish
64671
+ };
64672
+ barriers.set(eventIndex, entry);
64673
+ ensureBarrierSafetyNet(ctx);
64548
64674
  return {
64549
64675
  markDelivered: finish,
64550
64676
  arm: /* @__PURE__ */ __name(() => {
@@ -64553,6 +64679,48 @@ function registerDeliveryBarrier(ctx, eventIndex, kind, options = {}) {
64553
64679
  };
64554
64680
  }
64555
64681
  __name(registerDeliveryBarrier, "registerDeliveryBarrier");
64682
+ var activeBarrierSafetyNets = /* @__PURE__ */ new WeakSet();
64683
+ function ensureBarrierSafetyNet(ctx) {
64684
+ const barriers = ctx.pendingDeliveryBarriers;
64685
+ if (!barriers || activeBarrierSafetyNets.has(ctx)) {
64686
+ return;
64687
+ }
64688
+ activeBarrierSafetyNets.add(ctx);
64689
+ const rearm = /* @__PURE__ */ __name(() => {
64690
+ setTimeout(check2, 0);
64691
+ }, "rearm");
64692
+ const rearmAfterRejection = /* @__PURE__ */ __name(() => {
64693
+ setTimeout(check2, 50);
64694
+ }, "rearmAfterRejection");
64695
+ const check2 = /* @__PURE__ */ __name(() => {
64696
+ if (barriers.size === 0) {
64697
+ activeBarrierSafetyNets.delete(ctx);
64698
+ return;
64699
+ }
64700
+ if (!canRetireAbandonedBarriers(ctx)) {
64701
+ ctx.promiseQueue.then(rearm, rearmAfterRejection);
64702
+ return;
64703
+ }
64704
+ while (barriers.size > 0 && canRetireAbandonedBarriers(ctx)) {
64705
+ let lowestIndex;
64706
+ let lowestEntry;
64707
+ for (const [index, entry] of barriers) {
64708
+ if (lowestIndex === void 0 || index < lowestIndex) {
64709
+ lowestIndex = index;
64710
+ lowestEntry = entry;
64711
+ }
64712
+ }
64713
+ lowestEntry?.retire();
64714
+ }
64715
+ setTimeout(check2, 0);
64716
+ }, "check");
64717
+ setTimeout(check2, 0);
64718
+ }
64719
+ __name(ensureBarrierSafetyNet, "ensureBarrierSafetyNet");
64720
+ function canRetireAbandonedBarriers(ctx) {
64721
+ return ctx.pendingDeliveries === 0 && !hasParkedCommittedDelivery(ctx);
64722
+ }
64723
+ __name(canRetireAbandonedBarriers, "canRetireAbandonedBarriers");
64556
64724
  function hasParkedCommittedDelivery(ctx) {
64557
64725
  const barriers = ctx.pendingDeliveryBarriers;
64558
64726
  if (!barriers || barriers.size === 0) {
@@ -64568,7 +64736,7 @@ function hasParkedCommittedDelivery(ctx) {
64568
64736
  }
64569
64737
  __name(hasParkedCommittedDelivery, "hasParkedCommittedDelivery");
64570
64738
  function isDeliveryIdle(ctx) {
64571
- return ctx.pendingDeliveries === 0 && !hasParkedCommittedDelivery(ctx);
64739
+ return ctx.pendingDeliveries === 0 && (!ctx.pendingDeliveryBarriers || ctx.pendingDeliveryBarriers.size === 0);
64572
64740
  }
64573
64741
  __name(isDeliveryIdle, "isDeliveryIdle");
64574
64742
  function scheduleWhenIdle(ctx, fn) {
@@ -65713,6 +65881,23 @@ async function hydrateStepReturnValue(value, _runId, key, global2 = globalThis,
65713
65881
  }
65714
65882
  __name(hydrateStepReturnValue, "hydrateStepReturnValue");
65715
65883
 
65884
+ // ../core/dist/runtime/unserializable-step.js
65885
+ var UNSERIALIZABLE_STEP_INPUT_MARKER = "[input unavailable: step argument serialization failed]";
65886
+ var UNSERIALIZABLE_FLAG = "__workflowUnserializableStepInput";
65887
+ function unserializableStepInputPlaceholder() {
65888
+ return {
65889
+ args: [UNSERIALIZABLE_STEP_INPUT_MARKER],
65890
+ closureVars: [],
65891
+ thisVal: void 0,
65892
+ [UNSERIALIZABLE_FLAG]: true
65893
+ };
65894
+ }
65895
+ __name(unserializableStepInputPlaceholder, "unserializableStepInputPlaceholder");
65896
+ function isUnserializableStepInputPlaceholder(hydratedInput) {
65897
+ return typeof hydratedInput === "object" && hydratedInput !== null && hydratedInput[UNSERIALIZABLE_FLAG] === true;
65898
+ }
65899
+ __name(isUnserializableStepInputPlaceholder, "isUnserializableStepInputPlaceholder");
65900
+
65716
65901
  // ../core/dist/runtime/suspension-handler.js
65717
65902
  function extractTraceHeaders(traceCarrier) {
65718
65903
  const headers = {};
@@ -65849,15 +66034,84 @@ async function handleSuspension({ suspension, world, run: run2, span, requestId,
65849
66034
  }));
65850
66035
  }
65851
66036
  const stepsNeedingCreation = new Set(stepItems.filter((queueItem) => !queueItem.hasCreatedEvent).map((queueItem) => queueItem.correlationId));
66037
+ const failedStepCorrelationIds = /* @__PURE__ */ new Set();
66038
+ const finalizeUnserializableStep = /* @__PURE__ */ __name(async (queueItem, error48) => {
66039
+ runtimeLogger.warn("Step arguments failed to serialize; failing the step so the workflow can observe the error", {
66040
+ workflowRunId: runId,
66041
+ correlationId: queueItem.correlationId,
66042
+ stepName: queueItem.stepName,
66043
+ error: error48.message
66044
+ });
66045
+ const placeholderInput = await dehydrateStepArguments(unserializableStepInputPlaceholder(), runId, encryptionKey, suspension.globalThis);
66046
+ try {
66047
+ await createGuarded({
66048
+ eventType: "step_created",
66049
+ specVersion: SPEC_VERSION_CURRENT,
66050
+ correlationId: queueItem.correlationId,
66051
+ eventData: {
66052
+ stepName: queueItem.stepName,
66053
+ workflowName: run2.workflowName,
66054
+ input: placeholderInput
66055
+ }
66056
+ }, { requestId });
66057
+ } catch (createErr) {
66058
+ if (EntityConflictError.is(createErr)) {
66059
+ runtimeLogger.info("Step already exists, continuing", {
66060
+ workflowRunId: runId,
66061
+ correlationId: queueItem.correlationId,
66062
+ message: createErr.message
66063
+ });
66064
+ } else if (RunExpiredError.is(createErr)) {
66065
+ return;
66066
+ } else {
66067
+ throw createErr;
66068
+ }
66069
+ }
66070
+ try {
66071
+ await createGuarded({
66072
+ eventType: "step_failed",
66073
+ specVersion: SPEC_VERSION_CURRENT,
66074
+ correlationId: queueItem.correlationId,
66075
+ eventData: {
66076
+ stepName: queueItem.stepName,
66077
+ // The message carries the framed serialization hint; the step
66078
+ // consumer rejects the step's promise with a FatalError built
66079
+ // from it, exactly like any other step failure.
66080
+ error: error48.message,
66081
+ stack: error48.stack
66082
+ }
66083
+ }, { requestId });
66084
+ } catch (failErr) {
66085
+ if (EntityConflictError.is(failErr) || RunExpiredError.is(failErr)) {
66086
+ runtimeLogger.info("Tried failing step, but step or run has already finished.", {
66087
+ workflowRunId: runId,
66088
+ correlationId: queueItem.correlationId,
66089
+ message: failErr.message
66090
+ });
66091
+ } else {
66092
+ throw failErr;
66093
+ }
66094
+ }
66095
+ failedStepCorrelationIds.add(queueItem.correlationId);
66096
+ }, "finalizeUnserializableStep");
65852
66097
  const ops = [];
65853
66098
  for (const queueItem of stepItems) {
65854
66099
  ops.push((async () => {
65855
66100
  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);
66101
+ let dehydratedInput;
66102
+ try {
66103
+ dehydratedInput = await dehydrateStepArguments({
66104
+ args: queueItem.args,
66105
+ closureVars: queueItem.closureVars,
66106
+ thisVal: queueItem.thisVal
66107
+ }, runId, encryptionKey, suspension.globalThis);
66108
+ } catch (err) {
66109
+ if (RuntimeDecryptionError.is(err)) {
66110
+ throw err;
66111
+ }
66112
+ await finalizeUnserializableStep(queueItem, err instanceof Error ? err : new Error(String(err)));
66113
+ return;
66114
+ }
65861
66115
  const stepEvent = {
65862
66116
  eventType: "step_created",
65863
66117
  specVersion: SPEC_VERSION_CURRENT,
@@ -65939,8 +66193,12 @@ async function handleSuspension({ suspension, world, run: run2, span, requestId,
65939
66193
  ...WorkflowRunStatus("workflow_suspended"),
65940
66194
  ...WorkflowStepsCreated(stepItems.length),
65941
66195
  ...WorkflowHooksCreated(hooksNeedingCreation.length),
65942
- ...WorkflowWaitsCreated(waitItems.length)
66196
+ ...WorkflowWaitsCreated(waitItems.length),
66197
+ ...failedStepCorrelationIds.size > 0 ? WorkflowStepsFailedSerialization(failedStepCorrelationIds.size) : {}
65943
66198
  });
66199
+ if (failedStepCorrelationIds.size > 0) {
66200
+ return { timeoutSeconds: 0, failedStepCorrelationIds };
66201
+ }
65944
66202
  if (hasHookConflict) {
65945
66203
  return { timeoutSeconds: 0 };
65946
66204
  }
@@ -68770,6 +69028,9 @@ var stepHandler = createQueueHandler(stepPrefix, async (message_, metadata) => {
68770
69028
  let userCodeFailed = false;
68771
69029
  const executionStartTime = Date.now();
68772
69030
  try {
69031
+ if (isUnserializableStepInputPlaceholder(hydratedInput)) {
69032
+ throw new FatalError(formatSerializationError("step arguments", void 0));
69033
+ }
68773
69034
  result = await trace2("step.execute", {}, async () => {
68774
69035
  return await contextStorage.run({
68775
69036
  stepMetadata: {