@workflow/web 4.1.14 → 4.1.15

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.
@@ -9176,7 +9176,7 @@ const app = express();
9176
9176
  app.all(
9177
9177
  "/{*splat}",
9178
9178
  createRequestHandler({
9179
- build: () => import("./server-build-CAufQfpc.js").then((n) => n.a2)
9179
+ build: () => import("./server-build-CZTBct8I.js").then((n) => n.a2)
9180
9180
  })
9181
9181
  );
9182
9182
  app.use(
@@ -1,5 +1,5 @@
1
- import { Y as R, Z as Ks, _ as jsxRuntimeExports, $ as Qe } from "./server-build-CAufQfpc.js";
2
- import { r as reactExports } from "./app-B2hObQJu.js";
1
+ import { Y as R, Z as Ks, _ as jsxRuntimeExports, $ as Qe } from "./server-build-CZTBct8I.js";
2
+ import { r as reactExports } from "./app-C0o0w-Mo.js";
3
3
  import "node:stream";
4
4
  import "util";
5
5
  import "crypto";
@@ -1,6 +1,6 @@
1
- import { H as HookSchema } from "./server-build-CAufQfpc.js";
2
- import { B, D, a, E, b, c, d, e, L, M, P, Q, f, R, S, g, h, i, j, k, l, m, n, T, o, p, q, r, s, V, W, t, u, v, w, x, y, z, A, C, F, G, I, J, K, O, U, X } from "./server-build-CAufQfpc.js";
3
- import "./app-B2hObQJu.js";
1
+ import { H as HookSchema } from "./server-build-CZTBct8I.js";
2
+ import { B, D, a, E, b, c, d, e, L, M, P, Q, f, R, S, g, h, i, j, k, l, m, n, T, o, p, q, r, s, V, W, t, u, v, w, x, y, z, A, C, F, G, I, J, K, O, U, X } from "./server-build-CZTBct8I.js";
3
+ import "./app-C0o0w-Mo.js";
4
4
  import "stream";
5
5
  import "express";
6
6
  import "node:stream";
@@ -1,5 +1,5 @@
1
- import { N as Nt } from "./server-build-CAufQfpc.js";
2
- import "./app-B2hObQJu.js";
1
+ import { N as Nt } from "./server-build-CZTBct8I.js";
2
+ import "./app-C0o0w-Mo.js";
3
3
  import "stream";
4
4
  import "express";
5
5
  import "node:stream";
@@ -14,7 +14,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
14
14
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
15
15
  var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
16
16
  var _a2, _b, _root, _hasMagic, _uflag, _parts, _parent, _parentIndex, _negs, _filledNegs, _options, _toString, _emptyExt, _AST_instances, fillNegs_fn, _AST_static, parseAST_fn, canAdoptWithSpace_fn, canAdopt_fn, canAdoptType_fn, adoptWithSpace_fn, adopt_fn, canUsurpType_fn, canUsurp_fn, usurp_fn, flatten_fn, partsToRegExp_fn, parseGlob_fn, _Minimatch_instances, matchGlobstar_fn, matchGlobStarBodySections_fn, matchOne_fn, _reader;
17
- import { a as requireReact, S as ServerRouter, c as createReadableStreamFromReadable, r as reactExports, g as getDefaultExportFromCjs, R as React, b as ReactExports, w as withComponentProps, d as withErrorBoundaryProps, M as Meta, L as Links, e as ScrollRestoration, f as Scripts, O as Outlet, u as useNavigate, h as useSearchParams, i as Link$1, j as useRouteError, k as isRouteErrorResponse, l as useLocation, m as useParams } from "./app-B2hObQJu.js";
17
+ import { a as requireReact, S as ServerRouter, c as createReadableStreamFromReadable, r as reactExports, g as getDefaultExportFromCjs, R as React, b as ReactExports, w as withComponentProps, d as withErrorBoundaryProps, M as Meta, L as Links, e as ScrollRestoration, f as Scripts, O as Outlet, u as useNavigate, h as useSearchParams, i as Link$1, j as useRouteError, k as isRouteErrorResponse, l as useLocation, m as useParams } from "./app-C0o0w-Mo.js";
18
18
  import require$$0$5, { PassThrough } from "node:stream";
19
19
  import require$$0 from "util";
20
20
  import require$$1 from "crypto";
@@ -81828,7 +81828,7 @@ var tn = f("block", "before:content-[counter(line)]", "before:inline-block", "be
81828
81828
  var et = ({ className: e, language: t, style: o, isIncomplete: n, ...s2 }) => jsxRuntimeExports.jsx("div", { className: f("my-4 flex w-full flex-col gap-2 rounded-xl border border-border bg-sidebar p-2", e), "data-incomplete": n || void 0, "data-language": t, "data-streamdown": "code-block", style: { contentVisibility: "auto", containIntrinsicSize: "auto 200px", ...o }, ...s2 });
81829
81829
  var Se = reactExports.createContext({ code: "" }), de = () => reactExports.useContext(Se);
81830
81830
  var ot = ({ language: e }) => jsxRuntimeExports.jsx("div", { className: "flex h-8 items-center text-muted-foreground text-xs", "data-language": e, "data-streamdown": "code-block-header", children: jsxRuntimeExports.jsx("span", { className: "ml-1 font-mono lowercase", children: e }) });
81831
- var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-c3Vtq09H.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
81831
+ var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-DyZmWYQX.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
81832
81832
  let i = reactExports.useMemo(() => e.replace(cn$1, ""), [e]), c = reactExports.useMemo(() => ({ bg: "transparent", fg: "inherit", tokens: i.split(`
81833
81833
  `).map((a2) => [{ content: a2, color: "inherit", bgColor: "transparent", htmlStyle: {}, offset: 0 }]) }), [i]);
81834
81834
  return jsxRuntimeExports.jsx(Se.Provider, { value: { code: e }, children: jsxRuntimeExports.jsxs(et, { isIncomplete: s2, language: t, children: [jsxRuntimeExports.jsx(ot, { language: t }), n ? jsxRuntimeExports.jsx("div", { className: "pointer-events-none sticky top-2 z-10 -mt-10 flex h-8 items-center justify-end", children: jsxRuntimeExports.jsx("div", { className: "pointer-events-auto flex shrink-0 items-center gap-2 rounded-md border border-sidebar bg-sidebar/80 px-1.5 py-1 supports-[backdrop-filter]:bg-sidebar/70 supports-[backdrop-filter]:backdrop-blur", "data-streamdown": "code-block-actions", children: n }) }) : null, jsxRuntimeExports.jsx(reactExports.Suspense, { fallback: jsxRuntimeExports.jsx(Qe, { className: o, language: t, result: c, ...r2 }), children: jsxRuntimeExports.jsx(dn, { className: o, code: i, language: t, raw: c, ...r2 }) })] }) });
@@ -82150,7 +82150,7 @@ var Dt = ({ children: e, className: t, onDownload: o, onError: n }) => {
82150
82150
  }, []), jsxRuntimeExports.jsxs("div", { className: "relative", ref: i, children: [jsxRuntimeExports.jsx("button", { className: f("cursor-pointer p-1 text-muted-foreground transition-all hover:text-foreground disabled:cursor-not-allowed disabled:opacity-50", t), disabled: c, onClick: () => r2(!s2), title: "Download table", type: "button", children: e != null ? e : jsxRuntimeExports.jsx(Z, { size: 14 }) }), s2 ? jsxRuntimeExports.jsxs("div", { className: "absolute top-full right-0 z-10 mt-1 min-w-[120px] overflow-hidden rounded-md border border-border bg-background shadow-lg", children: [jsxRuntimeExports.jsx("button", { className: "w-full px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40", onClick: () => a2("csv"), title: "Download table as CSV", type: "button", children: "CSV" }), jsxRuntimeExports.jsx("button", { className: "w-full px-3 py-2 text-left text-sm transition-colors hover:bg-muted/40", onClick: () => a2("markdown"), title: "Download table as Markdown", type: "button", children: "Markdown" })] }) : null] });
82151
82151
  };
82152
82152
  var Vt = ({ children: e, className: t, showControls: o, ...n }) => jsxRuntimeExports.jsxs("div", { className: "my-4 flex flex-col gap-2 rounded-lg border border-border bg-sidebar p-2", "data-streamdown": "table-wrapper", children: [o ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-1", children: [jsxRuntimeExports.jsx(Ht, {}), jsxRuntimeExports.jsx(Dt, {})] }) : null, jsxRuntimeExports.jsx("div", { className: "border-collapse overflow-x-auto overscroll-y-auto rounded-md border border-border bg-background", children: jsxRuntimeExports.jsx("table", { className: f("w-full divide-y divide-border", t), "data-streamdown": "table", ...n, children: e }) })] });
82153
- var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-D9FphmOZ.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
82153
+ var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-Cf251uS3.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
82154
82154
  function ke(e, t) {
82155
82155
  if (!(e != null && e.position || t != null && t.position)) return true;
82156
82156
  if (!(e != null && e.position && (t != null && t.position))) return false;
@@ -90910,6 +90910,15 @@ class ThrottleError extends WorkflowWorldError {
90910
90910
  return isError(value) && value.name === "ThrottleError";
90911
90911
  }
90912
90912
  }
90913
+ class PreconditionFailedError extends WorkflowWorldError {
90914
+ constructor(message2, options) {
90915
+ super(message2, { status: 412, retryAfter: options == null ? void 0 : options.retryAfter });
90916
+ this.name = "PreconditionFailedError";
90917
+ }
90918
+ static is(value) {
90919
+ return isError(value) && value.name === "PreconditionFailedError";
90920
+ }
90921
+ }
90913
90922
  class WorkflowRunCancelledError extends WorkflowError {
90914
90923
  constructor(runId) {
90915
90924
  super(`Workflow run "${runId}" cancelled`, {});
@@ -92033,7 +92042,7 @@ createLogger("build", {
92033
92042
  debugNamespace: "workflow:build"
92034
92043
  });
92035
92044
  const MAX_QUEUE_DELIVERIES = 48;
92036
- const version$1 = "4.6.2";
92045
+ const version$1 = "4.7.0";
92037
92046
  const execFileAsync = promisify(execFile);
92038
92047
  function parsePort$1(value, radix = 10) {
92039
92048
  const port = parseInt(value, radix);
@@ -120294,7 +120303,7 @@ function createLocalWorld(args) {
120294
120303
  const basedir = mergedConfig.dataDir;
120295
120304
  const hooksDir = path$3.join(basedir, "hooks");
120296
120305
  const taggedHookFiles = await listTaggedFiles(hooksDir, tag);
120297
- const { HookSchema: HookSchema2 } = await import("./index-ulh-Ko1q.js");
120306
+ const { HookSchema: HookSchema2 } = await import("./index-D86iFXiQ.js");
120298
120307
  await Promise.all(taggedHookFiles.map(async (hookFile) => {
120299
120308
  const hook = await readJSON(path$3.join(hooksDir, hookFile), HookSchema2);
120300
120309
  if (hook == null ? void 0 : hook.token) {
@@ -120447,8 +120456,8 @@ function requireGetVercelOidcToken() {
120447
120456
  }
120448
120457
  try {
120449
120458
  const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
120450
- await import("./token-util-TwMjSZSF.js").then((n) => n.t),
120451
- await import("./token-COKbCOS0.js").then((n) => n.t)
120459
+ await import("./token-util-BCX_82dS.js").then((n) => n.t),
120460
+ await import("./token-wXB5G-Q6.js").then((n) => n.t)
120452
120461
  ]);
120453
120462
  if (!token || isExpired(getTokenPayload(token), options == null ? void 0 : options.expirationBufferMs)) {
120454
120463
  await refreshToken(options);
@@ -121012,22 +121021,50 @@ function requireDist() {
121012
121021
  }
121013
121022
  var distExports = requireDist();
121014
121023
  let _dispatcher;
121024
+ const DEFAULT_HEADERS_TIMEOUT_MS = 3e4;
121025
+ const DEFAULT_BODY_TIMEOUT_MS = 3e4;
121026
+ function envTimeoutMs(name2, fallback) {
121027
+ const raw2 = process.env[name2];
121028
+ if (raw2 === void 0 || raw2 === "")
121029
+ return fallback;
121030
+ const parsed = Number.parseInt(raw2, 10);
121031
+ return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;
121032
+ }
121033
+ const RETRY_ERROR_CODES = [
121034
+ "ECONNRESET",
121035
+ "ECONNREFUSED",
121036
+ "ENOTFOUND",
121037
+ "ENETDOWN",
121038
+ "ENETUNREACH",
121039
+ "EHOSTDOWN",
121040
+ "EHOSTUNREACH",
121041
+ "EPIPE",
121042
+ "UND_ERR_SOCKET",
121043
+ "UND_ERR_HEADERS_TIMEOUT",
121044
+ "UND_ERR_BODY_TIMEOUT"
121045
+ ];
121046
+ const MAX_RETRIES = 2;
121047
+ function getAgentOptions() {
121048
+ return {
121049
+ connections: 8,
121050
+ keepAliveTimeout: 1e4,
121051
+ // H2 is specifically incompatible with SvelteKit on Vercel prod. Everything else
121052
+ // runs fine.
121053
+ // TODO: Investigate/fix the failure on SvelteKit so we can re-enable H2.
121054
+ allowH2: false,
121055
+ // HTTP/1.1 pipelining is disabled (pipelining: 1) because it causes
121056
+ // head-of-line blocking that deadlocks the webhook respondWith mechanism.
121057
+ pipelining: 1,
121058
+ headersTimeout: envTimeoutMs("WORKFLOW_VERCEL_HEADERS_TIMEOUT_MS", DEFAULT_HEADERS_TIMEOUT_MS),
121059
+ bodyTimeout: envTimeoutMs("WORKFLOW_VERCEL_BODY_TIMEOUT_MS", DEFAULT_BODY_TIMEOUT_MS)
121060
+ };
121061
+ }
121015
121062
  function getDispatcher(config2) {
121016
121063
  return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultDispatcher();
121017
121064
  }
121018
121065
  function getDefaultDispatcher() {
121019
121066
  if (!_dispatcher) {
121020
- _dispatcher = new undiciExports.RetryAgent(new undiciExports.Agent({
121021
- connections: 8,
121022
- keepAliveTimeout: 1e4,
121023
- // H2 is specifically incompatible with SvelteKit on Vercel prod. Everything else
121024
- // runs fine.
121025
- // TODO: Investigate/fix the failure on SvelteKit so we can re-enable H2.
121026
- allowH2: false,
121027
- // HTTP/1.1 pipelining is disabled (pipelining: 1) because it causes
121028
- // head-of-line blocking that deadlocks the webhook respondWith mechanism.
121029
- pipelining: 1
121030
- }), {
121067
+ const retryOptions = {
121031
121068
  // Observe Retry-After header if received
121032
121069
  retryAfter: true,
121033
121070
  // Retry 5xx in-process (genuine transient blips recover fast), but NOT
@@ -121039,8 +121076,11 @@ function getDefaultDispatcher() {
121039
121076
  // ThrottleError carrying the `x-vercel-mitigated` / `x-vercel-id`
121040
121077
  // headers — and the queue does the (backed-off) retry instead.
121041
121078
  // (undici default is [500, 502, 503, 504, 429].)
121042
- statusCodes: [500, 502, 503, 504]
121043
- });
121079
+ statusCodes: [500, 502, 503, 504],
121080
+ errorCodes: RETRY_ERROR_CODES,
121081
+ maxRetries: MAX_RETRIES
121082
+ };
121083
+ _dispatcher = new undiciExports.RetryAgent(new undiciExports.Agent(getAgentOptions()), retryOptions);
121044
121084
  }
121045
121085
  return _dispatcher;
121046
121086
  }
@@ -125793,7 +125833,7 @@ var QueueClient = class {
125793
125833
  setApi(this, new ApiClient({ ...options, region }));
125794
125834
  }
125795
125835
  };
125796
- const version = "4.5.1";
125836
+ const version = "4.6.0";
125797
125837
  const HTTP_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
125798
125838
  function httpLog(method, endpoint, response2, ms2) {
125799
125839
  if (HTTP_DEBUG_ENABLED) {
@@ -126052,6 +126092,9 @@ curl -X ${request2.method} ${stringifiedHeaders} "${url2}"`);
126052
126092
  if (response2.status === 410) {
126053
126093
  throwWithTrace(new RunExpiredError(defaultMessage));
126054
126094
  }
126095
+ if (response2.status === 412) {
126096
+ throwWithTrace(new PreconditionFailedError(defaultMessage, { retryAfter }));
126097
+ }
126055
126098
  if (response2.status === 425) {
126056
126099
  throwWithTrace(new TooEarlyError(defaultMessage, { retryAfter }));
126057
126100
  }
@@ -126386,6 +126429,176 @@ function createResolveLatestDeploymentId(config2) {
126386
126429
  return result.data.id;
126387
126430
  };
126388
126431
  }
126432
+ const EVENT_RETRY_ELIGIBILITY = {
126433
+ // Creates: conditional create → 409 EntityConflictError if it already exists.
126434
+ run_created: {
126435
+ retryable: true,
126436
+ reason: "conditional create → 409 if exists"
126437
+ },
126438
+ step_created: {
126439
+ retryable: true,
126440
+ reason: "conditional create → 409 if exists"
126441
+ },
126442
+ wait_created: {
126443
+ retryable: true,
126444
+ reason: "conditional create → 409 if exists"
126445
+ },
126446
+ hook_created: {
126447
+ retryable: true,
126448
+ reason: "transactional token uniqueness → 409 if exists"
126449
+ },
126450
+ // Run start: early-returns if already running, writes no duplicate row.
126451
+ run_started: {
126452
+ retryable: true,
126453
+ reason: "early-returns if already running, no duplicate row"
126454
+ },
126455
+ // Terminal transitions: conditional `.where()` excludes terminal states →
126456
+ // 409 before the event row is written.
126457
+ run_completed: {
126458
+ retryable: true,
126459
+ reason: "terminal-state guard → 409, no duplicate row"
126460
+ },
126461
+ run_failed: {
126462
+ retryable: true,
126463
+ reason: "terminal-state guard → 409, no duplicate row"
126464
+ },
126465
+ run_cancelled: {
126466
+ retryable: true,
126467
+ reason: "terminal-state guard → 409, no duplicate row"
126468
+ },
126469
+ step_completed: {
126470
+ retryable: true,
126471
+ reason: "terminal-state guard → 409, no duplicate row"
126472
+ },
126473
+ step_failed: {
126474
+ retryable: true,
126475
+ reason: "terminal-state guard → 409, no duplicate row"
126476
+ },
126477
+ wait_completed: {
126478
+ retryable: true,
126479
+ reason: "waiting-state guard → 409, no duplicate row"
126480
+ },
126481
+ hook_disposed: {
126482
+ retryable: true,
126483
+ reason: "conditional delete (exists) → 409, no duplicate row"
126484
+ },
126485
+ // NOT safe to retry — see the module comment.
126486
+ step_started: {
126487
+ retryable: false,
126488
+ reason: "unconditional attempt increment → a retry double-counts attempts"
126489
+ },
126490
+ step_retrying: {
126491
+ retryable: false,
126492
+ reason: "no duplicate guard → a retry appends a second event row"
126493
+ },
126494
+ hook_received: {
126495
+ retryable: false,
126496
+ reason: "no server guard → a retry duplicates the row / re-delivers payload"
126497
+ },
126498
+ // Server-originated; the SDK never POSTs it.
126499
+ hook_conflict: {
126500
+ retryable: false,
126501
+ reason: "server-originated; never POSTed by the SDK"
126502
+ }
126503
+ };
126504
+ const MAX_EVENT_POST_RETRIES = 2;
126505
+ const EVENT_POST_RETRY_BASE_MS = 100;
126506
+ const EVENT_POST_RETRY_JITTER_MS = 50;
126507
+ const TRANSIENT_CODES = /* @__PURE__ */ new Set([
126508
+ "ECONNRESET",
126509
+ "ECONNREFUSED",
126510
+ "ENOTFOUND",
126511
+ "ENETDOWN",
126512
+ "ENETUNREACH",
126513
+ "EHOSTDOWN",
126514
+ "EHOSTUNREACH",
126515
+ "EPIPE",
126516
+ "ETIMEDOUT",
126517
+ "UND_ERR_SOCKET",
126518
+ "UND_ERR_REQ_RETRY",
126519
+ "UND_ERR_CONNECT_TIMEOUT",
126520
+ "UND_ERR_HEADERS_TIMEOUT",
126521
+ "UND_ERR_BODY_TIMEOUT",
126522
+ // Names (undici/Node surface these on the error or its cause).
126523
+ // `TimeoutError` is our own per-request deadline (`AbortSignal.timeout` in
126524
+ // makeRequest) — a genuinely ambiguous failure worth retrying. We deliberately
126525
+ // do NOT include `AbortError`: that is how an external/caller-supplied
126526
+ // cancellation surfaces (makeRequest composes the caller's signal via
126527
+ // `AbortSignal.any`), and re-issuing a write the caller asked to cancel —
126528
+ // stalling the abort by the full backoff budget — would be wrong.
126529
+ "TimeoutError",
126530
+ "RequestRetryError"
126531
+ ]);
126532
+ function collectErrorMarkers(err, depth = 0) {
126533
+ if (depth > 5 || err === null || typeof err !== "object")
126534
+ return [];
126535
+ const markers2 = [];
126536
+ const e = err;
126537
+ if (typeof e.code === "string")
126538
+ markers2.push(e.code);
126539
+ if (typeof e.name === "string")
126540
+ markers2.push(e.name);
126541
+ if (e.cause)
126542
+ markers2.push(...collectErrorMarkers(e.cause, depth + 1));
126543
+ return markers2;
126544
+ }
126545
+ function isRetryableEventPostError(err) {
126546
+ if (EntityConflictError.is(err) || RunExpiredError.is(err) || TooEarlyError.is(err) || ThrottleError.is(err)) {
126547
+ return false;
126548
+ }
126549
+ if (WorkflowWorldError.is(err)) {
126550
+ if (err.code === "PARSE_ERROR")
126551
+ return true;
126552
+ if (typeof err.status === "number") {
126553
+ return err.status >= 500 && err.status <= 599;
126554
+ }
126555
+ }
126556
+ return collectErrorMarkers(err).some((m2) => TRANSIENT_CODES.has(m2));
126557
+ }
126558
+ const sleep$1 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
126559
+ const RETRY_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
126560
+ function logRetry(message2, fields) {
126561
+ if (!RETRY_DEBUG_ENABLED)
126562
+ return;
126563
+ const suffix = Object.entries(fields).map(([k2, v2]) => `${k2}=${v2}`).join(" ");
126564
+ console.debug(`[workflow:world-vercel:event-retry] ${message2} ${suffix}`);
126565
+ }
126566
+ function errorMarker(err) {
126567
+ if (WorkflowWorldError.is(err)) {
126568
+ return err.code ?? (err.status != null ? `status_${err.status}` : err.name);
126569
+ }
126570
+ return collectErrorMarkers(err)[0] ?? (err instanceof Error ? err.name : "unknown");
126571
+ }
126572
+ async function withEventPostRetry(fn2, eventType) {
126573
+ var _a3;
126574
+ const retryable = ((_a3 = EVENT_RETRY_ELIGIBILITY[eventType]) == null ? void 0 : _a3.retryable) ?? false;
126575
+ for (let attempt = 0; ; attempt++) {
126576
+ try {
126577
+ return await fn2();
126578
+ } catch (err) {
126579
+ const transient = retryable && isRetryableEventPostError(err);
126580
+ if (transient && attempt < MAX_EVENT_POST_RETRIES) {
126581
+ const backoff = EVENT_POST_RETRY_BASE_MS * 2 ** attempt + Math.floor(Math.random() * EVENT_POST_RETRY_JITTER_MS);
126582
+ logRetry("retrying event POST after transient failure", {
126583
+ eventType,
126584
+ attempt: attempt + 1,
126585
+ backoffMs: backoff,
126586
+ error: errorMarker(err)
126587
+ });
126588
+ await sleep$1(backoff);
126589
+ continue;
126590
+ }
126591
+ if (transient) {
126592
+ logRetry("exhausted in-process retries; surfacing for queue redelivery", {
126593
+ eventType,
126594
+ attempts: attempt + 1,
126595
+ error: errorMarker(err)
126596
+ });
126597
+ }
126598
+ throw err;
126599
+ }
126600
+ }
126601
+ }
126389
126602
  const V4_FRAME_CONTENT_TYPE = "application/vnd.workflow.v4-frames";
126390
126603
  function encodeFrame(meta2, body2) {
126391
126604
  const metaBytes = new Uint8Array(encode(meta2));
@@ -126500,6 +126713,9 @@ function buildPostFrameMeta(input) {
126500
126713
  if (input.executionContext !== void 0) {
126501
126714
  meta2.executionContext = input.executionContext;
126502
126715
  }
126716
+ if (input.stateUpdatedAt !== void 0) {
126717
+ meta2.stateUpdatedAt = input.stateUpdatedAt;
126718
+ }
126503
126719
  return meta2;
126504
126720
  }
126505
126721
  function throwForErrorResponse(statusCode, responseHeaders, errorBody, opName, url2) {
@@ -126526,6 +126742,8 @@ function throwForErrorResponse(statusCode, responseHeaders, errorBody, opName, u
126526
126742
  throw new EntityConflictError(message2);
126527
126743
  if (statusCode === 410)
126528
126744
  throw new RunExpiredError(message2);
126745
+ if (statusCode === 412)
126746
+ throw new PreconditionFailedError(message2, { retryAfter });
126529
126747
  if (statusCode === 425)
126530
126748
  throw new TooEarlyError(message2, { retryAfter });
126531
126749
  if (statusCode === 429) {
@@ -127066,7 +127284,7 @@ async function getWorkflowRunEvents(params, config2) {
127066
127284
  }
127067
127285
  async function createWorkflowRunEvent(id2, data, params, config2) {
127068
127286
  try {
127069
- return await createWorkflowRunEventInner(id2, data, params, config2);
127287
+ return await withEventPostRetry(() => createWorkflowRunEventInner(id2, data, params, config2), data.eventType);
127070
127288
  } catch (err) {
127071
127289
  if (hookEventsRequiringExistence.has(data.eventType) && WorkflowWorldError.is(err) && err.status === 404 && data.correlationId) {
127072
127290
  throw new HookNotFoundError(data.correlationId);
@@ -127113,6 +127331,7 @@ async function createWorkflowRunEventInner(id2, data, params, config2) {
127113
127331
  specVersion: data.specVersion ?? 2,
127114
127332
  ...data.correlationId ? { correlationId: data.correlationId } : {},
127115
127333
  ...(params == null ? void 0 : params.requestId) ? { vercelId: params.requestId } : {},
127334
+ ...(params == null ? void 0 : params.stateUpdatedAt) !== void 0 ? { stateUpdatedAt: params.stateUpdatedAt } : {},
127116
127335
  occurredAt: (params == null ? void 0 : params.occurredAt) ?? /* @__PURE__ */ new Date(),
127117
127336
  remoteRefBehavior,
127118
127337
  payload,
@@ -1,5 +1,5 @@
1
- import { g as getDefaultExportFromCjs } from "./app-B2hObQJu.js";
2
- import { a0 as requireTokenUtil } from "./server-build-CAufQfpc.js";
1
+ import { g as getDefaultExportFromCjs } from "./app-C0o0w-Mo.js";
2
+ import { a0 as requireTokenUtil } from "./server-build-CZTBct8I.js";
3
3
  function _mergeNamespaces(n, m) {
4
4
  for (var i = 0; i < m.length; i++) {
5
5
  const e = m[i];
@@ -1,5 +1,5 @@
1
- import { g as getDefaultExportFromCjs } from "./app-B2hObQJu.js";
2
- import { a1 as requireTokenError, a0 as requireTokenUtil } from "./server-build-CAufQfpc.js";
1
+ import { g as getDefaultExportFromCjs } from "./app-C0o0w-Mo.js";
2
+ import { a1 as requireTokenError, a0 as requireTokenUtil } from "./server-build-CZTBct8I.js";
3
3
  function _mergeNamespaces(n, m) {
4
4
  for (var i = 0; i < m.length; i++) {
5
5
  const e = m[i];
@@ -1,4 +1,4 @@
1
- import { n } from "./assets/app-B2hObQJu.js";
1
+ import { n } from "./assets/app-C0o0w-Mo.js";
2
2
  import "express";
3
3
  import "stream";
4
4
  export {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@workflow/web",
3
3
  "description": "Workflow Observability UI",
4
- "version": "4.1.14",
4
+ "version": "4.1.15",
5
5
  "type": "module",
6
6
  "private": false,
7
7
  "files": [
@@ -71,12 +71,12 @@
71
71
  "vite": "^6",
72
72
  "vitest": "^3",
73
73
  "jsdom": "^26",
74
- "@workflow/core": "4.6.2",
75
- "@workflow/errors": "4.1.5",
74
+ "@workflow/core": "4.7.0",
75
+ "@workflow/errors": "4.2.0",
76
76
  "@workflow/utils": "4.1.4",
77
- "@workflow/web-shared": "4.1.14",
78
- "@workflow/world": "4.2.1",
79
- "@workflow/world-vercel": "4.5.1"
77
+ "@workflow/web-shared": "4.1.15",
78
+ "@workflow/world": "4.3.0",
79
+ "@workflow/world-vercel": "4.6.0"
80
80
  },
81
81
  "scripts": {
82
82
  "dev": "react-router dev",