@workflow/web 5.0.0-beta.35 → 5.0.0-beta.36

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.
Files changed (23) hide show
  1. package/build/client/assets/{arrow-up-right-B9knAxIp.js → arrow-up-right-Dv3gGqIf.js} +1 -1
  2. package/build/client/assets/{highlighted-body-B3W2YXNL-nasOj6sE.js → highlighted-body-B3W2YXNL-C5gyMelW.js} +1 -1
  3. package/build/client/assets/{home-BasVp7zv.js → home-0OfTSXd1.js} +2 -2
  4. package/build/client/assets/{manifest-47657566.js → manifest-485c4078.js} +1 -1
  5. package/build/client/assets/{mermaid-3ZIDBTTL-g3vDTGSb.js → mermaid-3ZIDBTTL-C_EWPx9a.js} +90 -21
  6. package/build/client/assets/root-15oK726f.css +1 -0
  7. package/build/client/assets/{root-DfwDd0Zj.js → root-BPK1T9Ck.js} +2 -2
  8. package/build/client/assets/{run-detail-BGMnsQO5.js → run-detail-CrqNzQ_y.js} +30 -25
  9. package/build/client/assets/server-build-DblSGQ6A.css +1 -0
  10. package/build/client/assets/{workflow-graph-viewer-VUIB71kS.js → workflow-graph-viewer-DrfqsDRu.js} +1 -1
  11. package/build/client/assets/{zstd-browser-decoder-B6lDon6D.js → zstd-browser-decoder-Ds2MNSdp.js} +1 -1
  12. package/build/server/assets/{app-BpmTURgx.js → app-BSsmG188.js} +1 -1
  13. package/build/server/assets/{highlighted-body-B3W2YXNL-BGkarUSx.js → highlighted-body-B3W2YXNL-C7tx66m_.js} +2 -2
  14. package/build/server/assets/{index-Dt3nkvmG.js → index-Cnj8rNtV.js} +46 -45
  15. package/build/server/assets/{mermaid-3ZIDBTTL-DUb3plqq.js → mermaid-3ZIDBTTL-DStR4R-M.js} +2 -2
  16. package/build/server/assets/{server-build-vDim5aBz.js → server-build-4Pq8AwvA.js} +835 -324
  17. package/build/server/assets/{token-BaQZqFlF.js → token-CYc8-6E0.js} +2 -2
  18. package/build/server/assets/{token-util-DHXhfd_v.js → token-util-D94FNaX0.js} +2 -2
  19. package/build/server/assets/{zstd-browser-decoder-Bnx_AJNv.js → zstd-browser-decoder-DXnLXD-w.js} +2 -2
  20. package/build/server/index.js +1 -1
  21. package/package.json +7 -7
  22. package/build/client/assets/root-CQggqXow.css +0 -1
  23. package/build/client/assets/server-build-C5ehvmav.css +0 -1
@@ -18,7 +18,7 @@ import { createRequire as __wkfCreateRequire } from "node:module";
18
18
  if (typeof require === "undefined") {
19
19
  globalThis.require = __wkfCreateRequire(import.meta.url);
20
20
  }
21
- 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-BpmTURgx.js";
21
+ 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-BSsmG188.js";
22
22
  import require$$0$4, { PassThrough } from "node:stream";
23
23
  import require$$0 from "util";
24
24
  import require$$1 from "crypto";
@@ -48124,6 +48124,7 @@ const HookCreatedEventSchema = BaseEventSchema.extend({
48124
48124
  correlationId: string$3(),
48125
48125
  eventData: object$1({
48126
48126
  token: string$3(),
48127
+ tokenRetentionUntil: date$2().optional(),
48127
48128
  metadata: SerializedDataSchema.optional(),
48128
48129
  isWebhook: boolean$3().optional(),
48129
48130
  isSystem: boolean$3().optional()
@@ -48751,7 +48752,7 @@ const PaginatedResponseSchema = (dataSchema) => object$1({
48751
48752
  hasMore: boolean$3(),
48752
48753
  pageInfo: PageInfoSchema.optional()
48753
48754
  });
48754
- object$1({
48755
+ const StructuredErrorSchema = object$1({
48755
48756
  message: string$3(),
48756
48757
  stack: string$3().optional(),
48757
48758
  code: string$3().optional()
@@ -50169,7 +50170,7 @@ function replaceEncryptedAndExpiredWithMarkers(resource) {
50169
50170
  }
50170
50171
  async function hydrateResourceIOAsync(resource, key) {
50171
50172
  const { hydrateDataWithKey: hydrateDataWithKey2 } = await Promise.resolve().then(() => serializationFormat);
50172
- const { ensureZstdDecoderRegistered } = await import("./zstd-browser-decoder-Bnx_AJNv.js");
50173
+ const { ensureZstdDecoderRegistered } = await import("./zstd-browser-decoder-DXnLXD-w.js");
50173
50174
  ensureZstdDecoderRegistered();
50174
50175
  const cryptoKey = key ? await Promise.resolve().then(() => encryption).then(({ importKey: importKey2 }) => importKey2(key)) : void 0;
50175
50176
  const revivers = getRevivers();
@@ -83134,7 +83135,7 @@ var tn = f("block", "before:content-[counter(line)]", "before:inline-block", "be
83134
83135
  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 });
83135
83136
  var Se = reactExports.createContext({ code: "" }), de = () => reactExports.useContext(Se);
83136
83137
  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 }) });
83137
- var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-BGkarUSx.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
83138
+ var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-C7tx66m_.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
83138
83139
  let i = reactExports.useMemo(() => e.replace(cn$1, ""), [e]), c = reactExports.useMemo(() => ({ bg: "transparent", fg: "inherit", tokens: i.split(`
83139
83140
  `).map((a2) => [{ content: a2, color: "inherit", bgColor: "transparent", htmlStyle: {}, offset: 0 }]) }), [i]);
83140
83141
  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 }) })] }) });
@@ -83456,7 +83457,7 @@ var Dt = ({ children: e, className: t, onDownload: o, onError: n }) => {
83456
83457
  }, []), 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] });
83457
83458
  };
83458
83459
  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 }) })] });
83459
- var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-DUb3plqq.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
83460
+ var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-DStR4R-M.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
83460
83461
  function ke(e, t) {
83461
83462
  if (!(e != null && e.position || t != null && t.position)) return true;
83462
83463
  if (!(e != null && e.position && (t != null && t.position))) return false;
@@ -86779,6 +86780,9 @@ function computeTimeMarkers(viewDuration, offset2) {
86779
86780
  }
86780
86781
  return markers2;
86781
86782
  }
86783
+ function toViewportFrac(ms2, viewStart, range2) {
86784
+ return Math.min(Math.max((ms2 - viewStart) / range2, 0), 1);
86785
+ }
86782
86786
  function computeSpanGaps(spans, viewStart, viewEnd) {
86783
86787
  const range2 = viewEnd - viewStart;
86784
86788
  if (range2 <= 0)
@@ -86790,14 +86794,40 @@ function computeSpanGaps(spans, viewStart, viewEnd) {
86790
86794
  const gapMs = startTime - endTime;
86791
86795
  if (gapMs <= 0)
86792
86796
  continue;
86793
- const leftFrac = Math.min(Math.max((endTime - viewStart) / range2, 0), 1);
86794
- const rightFrac = Math.min(Math.max((startTime - viewStart) / range2, 0), 1);
86797
+ const leftFrac = toViewportFrac(endTime, viewStart, range2);
86798
+ const rightFrac = toViewportFrac(startTime, viewStart, range2);
86795
86799
  if (rightFrac - leftFrac < 1e-3)
86796
86800
  continue;
86797
86801
  gaps.push({ gapMs, leftFrac, rightFrac, rowIndex: i });
86798
86802
  }
86799
86803
  return gaps;
86800
86804
  }
86805
+ function computeSpanDelta(anchor, hovered, viewStart, viewEnd) {
86806
+ const range2 = viewEnd - viewStart;
86807
+ if (range2 <= 0)
86808
+ return null;
86809
+ const anchorStart = getHighResInMs(anchor.startTime);
86810
+ const hoveredStart = getHighResInMs(hovered.startTime);
86811
+ const anchorIsEarlier = anchorStart <= hoveredStart;
86812
+ const earlierStart = anchorIsEarlier ? anchorStart : hoveredStart;
86813
+ const earlierEnd = getHighResInMs(anchorIsEarlier ? anchor.endTime : hovered.endTime);
86814
+ const laterStart = anchorIsEarlier ? hoveredStart : anchorStart;
86815
+ const originMs = earlierEnd <= laterStart ? earlierEnd : earlierStart;
86816
+ const deltaMs = laterStart - originMs;
86817
+ if (laterStart < viewStart || originMs > viewEnd) {
86818
+ return null;
86819
+ }
86820
+ const originFrac = toViewportFrac(originMs, viewStart, range2);
86821
+ const laterFrac = toViewportFrac(laterStart, viewStart, range2);
86822
+ const hoveredEnd = getHighResInMs(hovered.endTime);
86823
+ return {
86824
+ deltaMs,
86825
+ anchorFrac: anchorIsEarlier ? originFrac : laterFrac,
86826
+ hoveredFrac: anchorIsEarlier ? laterFrac : originFrac,
86827
+ anchorEdge: anchorIsEarlier && earlierEnd <= laterStart ? "end" : "start",
86828
+ hoveredOffscreen: hoveredStart > viewEnd ? "right" : hoveredEnd < viewStart ? "left" : null
86829
+ };
86830
+ }
86801
86831
  const RESOURCE_COLORS = {
86802
86832
  run: {
86803
86833
  bg: "var(--ds-blue-200)",
@@ -87112,28 +87142,30 @@ function scrollRowIntoView(listEl, index2, rowHeight, opts) {
87112
87142
  });
87113
87143
  }
87114
87144
  const eventStyles = {
87115
- run: { icon: WorkflowIcon, className: "text-blue-900" },
87116
- step: { icon: StepForwardIcon, className: "text-green-900" },
87117
- hook: { icon: WebhookIcon, className: "text-gray-900" },
87118
- sleep: { icon: SleepIcon, className: "text-gray-900" }
87145
+ run: { icon: WorkflowIcon, className: "text-blue-900", label: "Workflow" },
87146
+ step: { icon: StepForwardIcon, className: "text-green-900", label: "Step" },
87147
+ hook: { icon: WebhookIcon, className: "text-gray-900", label: "Hook" },
87148
+ sleep: { icon: SleepIcon, className: "text-gray-900", label: "Sleep" }
87119
87149
  };
87120
87150
  const defaultStyle = {
87121
87151
  icon: Circle,
87122
- className: "text-gray-900"
87152
+ className: "text-gray-900",
87153
+ label: "Event"
87123
87154
  };
87124
87155
  const ROW_HEIGHT_CLASS = "h-10";
87125
87156
  function getEventStyle(resource, isErrored) {
87126
87157
  const style2 = eventStyles[resource] ?? defaultStyle;
87127
87158
  return {
87128
87159
  icon: style2.icon,
87129
- className: cn$4(isErrored ? "text-red-900" : style2.className)
87160
+ className: cn$4(isErrored ? "text-red-900" : style2.className),
87161
+ label: style2.label
87130
87162
  };
87131
87163
  }
87132
87164
  const EventRow = ({ span, isSelected, isDimmed, onSelectSpan }) => {
87133
87165
  const durationMs = getSpanDurationMs(span);
87134
87166
  const isErrored = isSpanErrored(span);
87135
- const { icon: Icon2, className: tagClassName } = getEventStyle(span.resource, isErrored);
87136
- return jsxRuntimeExports.jsx("li", { className: cn$4("relative overflow-clip group transition-opacity", ROW_HEIGHT_CLASS, isDimmed && "opacity-35"), role: "treeitem", "aria-selected": isSelected, "aria-expanded": isSelected, "aria-level": 1, onClick: () => onSelectSpan(span.spanId), children: jsxRuntimeExports.jsx("div", { className: "h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200", children: jsxRuntimeExports.jsxs("div", { className: "flex h-full min-w-0 items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsx("span", { className: cn$4("shrink-0", tagClassName), children: jsxRuntimeExports.jsx(Icon2, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx("span", { className: "min-w-0 text-label-14", children: jsxRuntimeExports.jsx(MiddleTruncate, { value: span.name }) })] }), jsxRuntimeExports.jsx("div", { className: "ml-2 shrink-0", children: jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900 tabular-nums", children: formatDurationPrecise(durationMs) }) })] }) }) });
87167
+ const { icon: Icon2, className: tagClassName, label: iconLabel } = getEventStyle(span.resource, isErrored);
87168
+ return jsxRuntimeExports.jsx("li", { className: cn$4("relative overflow-clip group transition-opacity", ROW_HEIGHT_CLASS, isDimmed && "opacity-35"), role: "treeitem", "aria-selected": isSelected, "aria-expanded": isSelected, "aria-level": 1, onClick: () => onSelectSpan(span.spanId), children: jsxRuntimeExports.jsx("div", { className: "h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200", children: jsxRuntimeExports.jsxs("div", { className: "flex h-full min-w-0 items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsxs(Tooltip$1, { delayDuration: 500, children: [jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: jsxRuntimeExports.jsx("span", { className: cn$4("shrink-0", tagClassName), children: jsxRuntimeExports.jsx(Icon2, { className: "w-4 h-4" }) }) }), jsxRuntimeExports.jsx(TooltipContent$1, { side: "top", children: iconLabel })] }), jsxRuntimeExports.jsx("span", { className: "min-w-0 text-label-14", children: jsxRuntimeExports.jsx(MiddleTruncate, { value: span.name }) })] }), jsxRuntimeExports.jsx("div", { className: "ml-2 shrink-0", children: jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900 tabular-nums", children: formatDurationPrecise(durationMs) }) })] }) }) });
87137
87169
  };
87138
87170
  const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
87139
87171
  const listRef = reactExports.useRef(null);
@@ -87283,6 +87315,9 @@ function projectSegments(segments, spanStartMs, spanDurationMs, geometry) {
87283
87315
  ];
87284
87316
  });
87285
87317
  }
87318
+ function estimateLabelWidthPx(label) {
87319
+ return label.length * 6 + 12;
87320
+ }
87286
87321
  function DurationLabel({ label, className }) {
87287
87322
  return jsxRuntimeExports.jsx("span", { className: cn$4("pointer-events-none absolute inset-0 flex items-center justify-start overflow-hidden px-1 text-[10px] font-mono font-medium leading-none whitespace-nowrap text-left text-gray-1000 tabular-nums opacity-0 group-hover/timeline-row:opacity-100", className), children: label });
87288
87323
  }
@@ -87303,14 +87338,14 @@ function SegmentBar({ segments, showLabels = true }) {
87303
87338
  return jsxRuntimeExports.jsx("div", { className: "relative h-6 w-full", children: segments.map((seg, i) => {
87304
87339
  if (seg.status === "queued") {
87305
87340
  const leadInLabel = formatDurationPrecise(seg.fullDurationMs);
87306
- const showLeadInLabel = showLabels && seg.pixelWidth >= Math.max(40, leadInLabel.length * 6 + 12);
87341
+ const showLeadInLabel = showLabels && seg.pixelWidth >= Math.max(40, estimateLabelWidthPx(leadInLabel));
87307
87342
  const isFullWidthQueued = segments.length === 1;
87308
87343
  return jsxRuntimeExports.jsxs(reactExports.Fragment, { children: [jsxRuntimeExports.jsx(LeadInConnector, { leftPct: seg.leftPct, widthPct: seg.widthPct, label: showLeadInLabel ? leadInLabel : null }), isFullWidthQueued ? jsxRuntimeExports.jsx("div", { className: "absolute top-1/2 h-4 w-px -translate-y-1/2 bg-gray-500", style: {
87309
87344
  left: `calc(${seg.leftPct + seg.widthPct}% - 1.5px)`
87310
87345
  } }) : null] }, i);
87311
87346
  }
87312
87347
  const label = formatDurationPrecise(seg.fullDurationMs);
87313
- const showLabel = showLabels && seg.pixelWidth >= Math.max(40, label.length * 6 + 12);
87348
+ const showLabel = showLabels && seg.pixelWidth >= Math.max(40, estimateLabelWidthPx(label));
87314
87349
  return jsxRuntimeExports.jsxs("div", { className: cn$4("absolute h-full overflow-hidden rounded-[0.25rem]", SEGMENT_CLASSES[seg.status]), style: {
87315
87350
  // 1px gap between adjacent segments, distributed equally.
87316
87351
  left: `calc(${seg.leftPct}% + 0.5px)`,
@@ -87335,7 +87370,7 @@ const TimelineBar = reactExports.memo(function TimelineBar2({ span, viewStart, v
87335
87370
  const fallbackBg = isErrored ? colors.errorBg ?? "var(--ds-red-200)" : colors.bg;
87336
87371
  const fallbackBorder = isErrored ? colors.errorBorder ?? "var(--ds-red-500)" : colors.border;
87337
87372
  const totalLabel = formatDurationPrecise(totalDurationMs);
87338
- const showTotalLabel = geometry.visiblePixelWidth >= Math.max(40, totalLabel.length * 6 + 12);
87373
+ const showTotalLabel = geometry.visiblePixelWidth >= Math.max(40, estimateLabelWidthPx(totalLabel));
87339
87374
  const handleClick = reactExports.useCallback(() => {
87340
87375
  onSelect(span.spanId);
87341
87376
  }, [onSelect, span.spanId]);
@@ -87345,21 +87380,35 @@ const TimelineBar = reactExports.memo(function TimelineBar2({ span, viewStart, v
87345
87380
  className: offscreen.left ? "pl-10" : void 0
87346
87381
  }) : null] }) : null] }) });
87347
87382
  });
87348
- const DELTA_CAP_HEIGHT_PX = 8;
87349
- const DELTA_ROW_OFFSET_PX = 8;
87350
- const DeltaIndicator = reactExports.memo(function DeltaIndicator2({ leftFrac, rightFrac, label, rowIndex }) {
87351
- const centerY = DELTA_ROW_OFFSET_PX + (rowIndex + 1) * ROW_HEIGHT_PX;
87352
- return jsxRuntimeExports.jsxs("div", { className: "absolute pointer-events-none", style: {
87353
- left: `${leftFrac * 100}%`,
87354
- width: `${(rightFrac - leftFrac) * 100}%`,
87355
- top: centerY - DELTA_CAP_HEIGHT_PX / 2,
87356
- height: DELTA_CAP_HEIGHT_PX
87357
- }, children: [jsxRuntimeExports.jsx("div", { className: "absolute left-0 top-0 w-px h-full bg-amber-800" }), jsxRuntimeExports.jsx("div", { className: "absolute left-0 right-0 top-1/2 h-px bg-amber-800" }), jsxRuntimeExports.jsx("div", { className: "absolute right-0 top-0 w-px h-full bg-amber-800" }), jsxRuntimeExports.jsx("span", { className: "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 text-label-12 leading-none whitespace-nowrap rounded-xs px-1 py-0.5 text-gray-100 bg-amber-800", children: label })] });
87383
+ const MEASURE_GUIDE_OUTSET_PX = 4;
87384
+ const DeltaMeasureLine = reactExports.memo(function DeltaMeasureLine2({ delta, anchorRowIndex, hoveredRowIndex, timelineWidth }) {
87385
+ const anchorCenterY = anchorRowIndex * ROW_HEIGHT_PX + ROW_HEIGHT_PX / 2;
87386
+ const lineY = hoveredRowIndex * ROW_HEIGHT_PX + ROW_HEIGHT_PX / 2;
87387
+ const guideTop = Math.min(anchorCenterY, lineY);
87388
+ const guideBottom = Math.max(anchorCenterY, lineY);
87389
+ const anchorX = delta.anchorFrac * timelineWidth;
87390
+ const guideX = anchorX + (delta.anchorEdge === "end" ? MEASURE_GUIDE_OUTSET_PX : -MEASURE_GUIDE_OUTSET_PX);
87391
+ const arrowClearance = delta.hoveredOffscreen === "right" ? -28 : delta.hoveredOffscreen === "left" ? TINY_BAR_BOX_SIZE_PX + 4 : 0;
87392
+ const hoveredX = delta.hoveredFrac * timelineWidth + arrowClearance;
87393
+ const startX = Math.min(guideX, hoveredX);
87394
+ const endX = Math.max(guideX, hoveredX);
87395
+ const label = formatDurationPrecise(delta.deltaMs);
87396
+ const labelWidthPx = estimateLabelWidthPx(label);
87397
+ const labelPlacement = endX - startX >= labelWidthPx ? { left: (startX + endX) / 2, translate: "-translate-x-1/2" } : endX + 4 + labelWidthPx <= timelineWidth ? { left: endX + 4, translate: "" } : { left: startX - 4, translate: "-translate-x-full" };
87398
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("div", { className: "absolute h-px bg-amber-800", style: {
87399
+ left: Math.min(anchorX, guideX),
87400
+ width: MEASURE_GUIDE_OUTSET_PX,
87401
+ top: anchorCenterY
87402
+ } }), jsxRuntimeExports.jsx("div", { className: "absolute w-px bg-amber-800", style: {
87403
+ left: guideX,
87404
+ top: guideTop,
87405
+ height: guideBottom - guideTop
87406
+ } }), jsxRuntimeExports.jsx("div", { className: "absolute h-px bg-amber-800", style: { left: startX, width: Math.max(endX - startX, 1), top: lineY } }), jsxRuntimeExports.jsx("span", { className: cn$4("absolute -translate-y-1/2 font-mono text-[10px] font-medium leading-none tabular-nums whitespace-nowrap rounded-xs bg-background-100 px-1 py-0.5 text-amber-800", labelPlacement.translate), style: { left: labelPlacement.left, top: lineY }, children: label })] });
87358
87407
  });
87359
87408
  function TimelineHeader({ markers: markers2, hoverInfo: hoverInfo2 }) {
87360
87409
  return jsxRuntimeExports.jsx("div", { className: "relative bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-end px-4 pb-1", children: jsxRuntimeExports.jsxs("div", { className: "relative h-full flex-1", children: [markers2.map((m2) => jsxRuntimeExports.jsx("span", { className: "absolute bottom-1 font-mono text-xs font-normal leading-4 text-gray-900 whitespace-nowrap", style: { left: `${m2.position * 100}%` }, children: m2.label }, String(m2.value))), hoverInfo2 && jsxRuntimeExports.jsx("span", { className: "absolute top-1 pointer-events-none z-10 font-mono text-[11px] leading-4 text-gray-1000 whitespace-nowrap bg-background-100 border border-gray-alpha-400 rounded px-1 -translate-x-1/2", style: { left: `${hoverInfo2.fraction * 100}%` }, children: hoverInfo2.label })] }) });
87361
87410
  }
87362
- function Timeline({ spans, viewStart, viewEnd, markers: markers2, selectedId, searchResult, onSelect, onRevealTime, hoverFraction, altHeld = false }) {
87411
+ function Timeline({ spans, viewStart, viewEnd, markers: markers2, selectedId, searchResult, onSelect, onRevealTime, hover, altHeld = false }) {
87363
87412
  const containerRef = reactExports.useRef(null);
87364
87413
  const [containerWidth, setContainerWidth] = reactExports.useState(0);
87365
87414
  const viewDuration = viewEnd - viewStart;
@@ -87375,11 +87424,33 @@ function Timeline({ spans, viewStart, viewEnd, markers: markers2, selectedId, se
87375
87424
  ro2.observe(el);
87376
87425
  return () => ro2.disconnect();
87377
87426
  }, []);
87378
- const gaps = reactExports.useMemo(() => computeSpanGaps(spans, viewStart, viewEnd), [spans, viewStart, viewEnd]);
87427
+ const gapMeasurements = reactExports.useMemo(() => computeSpanGaps(spans, viewStart, viewEnd).map((gap) => ({
87428
+ delta: {
87429
+ deltaMs: gap.gapMs,
87430
+ anchorFrac: gap.leftFrac,
87431
+ hoveredFrac: gap.rightFrac,
87432
+ anchorEdge: "end",
87433
+ hoveredOffscreen: null
87434
+ },
87435
+ anchorRowIndex: gap.rowIndex,
87436
+ hoveredRowIndex: gap.rowIndex + 1
87437
+ })), [spans, viewStart, viewEnd]);
87438
+ const anchorIndex = reactExports.useMemo(() => selectedId ? spans.findIndex((s2) => s2.spanId === selectedId) : -1, [spans, selectedId]);
87439
+ const measurement = reactExports.useMemo(() => {
87440
+ if (!altHeld || hover == null || hover.rowIndex === anchorIndex) {
87441
+ return null;
87442
+ }
87443
+ const anchorSpan = spans[anchorIndex];
87444
+ const hoveredSpan = spans[hover.rowIndex];
87445
+ if (!anchorSpan || !hoveredSpan)
87446
+ return null;
87447
+ const delta = computeSpanDelta(anchorSpan, hoveredSpan, viewStart, viewEnd);
87448
+ return delta ? { delta, anchorRowIndex: anchorIndex, hoveredRowIndex: hover.rowIndex } : null;
87449
+ }, [altHeld, anchorIndex, hover, spans, viewStart, viewEnd]);
87379
87450
  return jsxRuntimeExports.jsxs("div", { ref: containerRef, className: "relative h-full overflow-hidden", style: { minHeight: spans.length * ROW_HEIGHT_PX }, children: [jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "absolute inset-y-0 pointer-events-none", style: TIMELINE_INSET_STYLE, children: markers2.map((marker2) => (
87380
87451
  // Skip the "0s" origin marker since the left edge already implies it.
87381
87452
  Math.abs(marker2.value) > 1e-6 ? jsxRuntimeExports.jsx("div", { className: "absolute top-0 bottom-0 w-px bg-gray-alpha-300", style: { left: `${marker2.position * 100}%` } }, String(marker2.value)) : null
87382
- )) }), hoverFraction != null && jsxRuntimeExports.jsx("div", { className: "absolute inset-y-0 pointer-events-none z-10", style: TIMELINE_INSET_STYLE, children: jsxRuntimeExports.jsx("div", { className: "absolute top-0 bottom-0 w-px bg-gray-alpha-500", style: { left: `${hoverFraction * 100}%` } }) }), jsxRuntimeExports.jsx("div", { style: { transform: `translateY(${start2 * ROW_HEIGHT_PX}px)` }, children: spans.slice(start2, end).map((span) => jsxRuntimeExports.jsx(TimelineBar, { span, viewStart, viewDuration, containerWidth: timelineWidth, isSelected: selectedId === span.spanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelect, onRevealTime }, span.spanId)) }), altHeld && jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "absolute inset-y-0 pointer-events-none", style: TIMELINE_INSET_STYLE, children: gaps.map((gap) => jsxRuntimeExports.jsx(DeltaIndicator, { leftFrac: gap.leftFrac, rightFrac: gap.rightFrac, label: formatDurationPrecise(gap.gapMs), rowIndex: gap.rowIndex }, gap.rowIndex)) })] });
87453
+ )) }), hover != null && jsxRuntimeExports.jsx("div", { className: "absolute inset-y-0 pointer-events-none z-10", style: TIMELINE_INSET_STYLE, children: jsxRuntimeExports.jsx("div", { className: "absolute top-0 bottom-0 w-px bg-gray-alpha-500", style: { left: `${hover.fraction * 100}%` } }) }), jsxRuntimeExports.jsx("div", { style: { transform: `translateY(${start2 * ROW_HEIGHT_PX}px)` }, children: spans.slice(start2, end).map((span) => jsxRuntimeExports.jsx(TimelineBar, { span, viewStart, viewDuration, containerWidth: timelineWidth, isSelected: selectedId === span.spanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelect, onRevealTime }, span.spanId)) }), altHeld && anchorIndex < 0 && jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "absolute inset-y-0 pointer-events-none", style: TIMELINE_INSET_STYLE, children: gapMeasurements.map((gap) => jsxRuntimeExports.jsx(DeltaMeasureLine, { ...gap, timelineWidth }, gap.anchorRowIndex)) }), measurement && jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "absolute inset-y-0 pointer-events-none z-20", style: TIMELINE_INSET_STYLE, children: jsxRuntimeExports.jsx(DeltaMeasureLine, { ...measurement, timelineWidth }) })] });
87383
87454
  }
87384
87455
  const CANVAS_PAD_Y_PX = 6;
87385
87456
  const MIN_LINE_HEIGHT_PX = 1.5;
@@ -87661,10 +87732,10 @@ const Minimap = reactExports.memo(function Minimap2({ spans, root: root2, viewpo
87661
87732
  const SPLIT_PANE_START_ID = "trace-split-start";
87662
87733
  function SplitPane({ children: children2, className, startHeader, endHeader, scrollContainerRef }) {
87663
87734
  const parts = reactExports.Children.toArray(children2);
87664
- if (parts.length !== 2) {
87665
- throw new Error("SplitPane expects exactly two children");
87735
+ if (parts.length !== 3) {
87736
+ throw new Error("SplitPane expects exactly three children");
87666
87737
  }
87667
- const [start2, end] = parts;
87738
+ const [start2, end, endOverlay] = parts;
87668
87739
  const [startPx, setStartPx] = reactExports.useState(DEFAULT_START_PX);
87669
87740
  const containerRef = reactExports.useRef(null);
87670
87741
  const startRef = reactExports.useRef(null);
@@ -87687,7 +87758,7 @@ function SplitPane({ children: children2, className, startHeader, endHeader, scr
87687
87758
  const effectiveStartPx = containerWidth > 0 ? Math.max(MIN_PX, Math.min(containerWidth - MIN_PX - GUTTER_PX, startPx)) : startPx;
87688
87759
  const colTemplate = paneColTemplate(effectiveStartPx);
87689
87760
  const maxStartPx = Math.max(MIN_PX, containerWidth > 0 ? containerWidth - MIN_PX - GUTTER_PX : startPx);
87690
- return jsxRuntimeExports.jsxs("div", { className: cn$4("flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: "grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { ref: startRef, id: SPLIT_PANE_START_ID, className: "min-w-0", children: start2 }), jsxRuntimeExports.jsxs("div", { className: "relative z-20 isolate flex shrink-0 justify-center", children: [jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }), jsxRuntimeExports.jsx(DraggableBorder, { element: startRef, position: "right", onWidthChange: handleWidthChange, onReset: handleReset, "aria-label": "Resize event list", "aria-controls": SPLIT_PANE_START_ID, "aria-valuemin": MIN_PX, "aria-valuemax": maxStartPx, "aria-valuenow": Math.min(Math.max(Math.round(effectiveStartPx), MIN_PX), maxStartPx) })] }), end] })] });
87761
+ return jsxRuntimeExports.jsxs("div", { className: cn$4("relative flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: "grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { ref: startRef, id: SPLIT_PANE_START_ID, className: "min-w-0", children: start2 }), jsxRuntimeExports.jsxs("div", { className: "relative z-20 isolate flex shrink-0 justify-center", children: [jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }), jsxRuntimeExports.jsx(DraggableBorder, { element: startRef, position: "right", onWidthChange: handleWidthChange, onReset: handleReset, "aria-label": "Resize event list", "aria-controls": SPLIT_PANE_START_ID, "aria-valuemin": MIN_PX, "aria-valuemax": maxStartPx, "aria-valuenow": Math.min(Math.max(Math.round(effectiveStartPx), MIN_PX), maxStartPx) })] }), end] }), jsxRuntimeExports.jsxs("div", { className: "pointer-events-none absolute inset-x-0 bottom-3 z-[5] grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", {}), jsxRuntimeExports.jsx("div", {}), jsxRuntimeExports.jsx("div", { className: "flex min-w-0 items-center justify-between gap-3 pl-4 pr-3", children: endOverlay })] })] });
87691
87762
  }
87692
87763
  const hint$1 = "_hint_1dmsq_3";
87693
87764
  const styles$1 = {
@@ -87738,7 +87809,7 @@ function TraceShortcutHelper({ hasMultipleSpans, reducedMotion }) {
87738
87809
  }
87739
87810
  setVisible(false);
87740
87811
  };
87741
- return jsxRuntimeExports.jsxs("div", { className: "group sticky bottom-3 z-10 ml-4 mb-3 hidden h-8 w-fit items-center gap-1 text-xs leading-none text-gray-900 @min-[480px]:flex", children: [jsxRuntimeExports.jsx("span", { "aria-live": "polite", "aria-atomic": "true", className: "inline-flex items-center whitespace-nowrap", children: reducedMotion ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx("span", { className: `inline-flex items-center ${styles$1.hint}`, children: index2 === 0 ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx(NavHint, {}) }, index2) }), jsxRuntimeExports.jsx("button", { type: "button", className: "inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100 motion-reduce:transition-none", onClick: dismiss, "aria-label": "Dismiss trace shortcuts helper", children: jsxRuntimeExports.jsx(X$3, { className: "h-3 w-3" }) })] });
87812
+ return jsxRuntimeExports.jsxs("div", { className: "group pointer-events-auto hidden h-8 w-fit items-center gap-1 text-xs leading-none text-gray-900 @min-[480px]:flex", children: [jsxRuntimeExports.jsx("span", { "aria-live": "polite", "aria-atomic": "true", className: "inline-flex items-center whitespace-nowrap", children: reducedMotion ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx("span", { className: `inline-flex items-center ${styles$1.hint}`, children: index2 === 0 ? jsxRuntimeExports.jsx(AltHint, {}) : jsxRuntimeExports.jsx(NavHint, {}) }, index2) }), jsxRuntimeExports.jsx("button", { type: "button", className: "inline-flex h-5 w-5 items-center justify-center rounded text-muted-foreground opacity-0 transition-opacity hover:bg-accent hover:text-foreground group-hover:opacity-100 focus-visible:opacity-100 motion-reduce:transition-none", onClick: dismiss, "aria-label": "Dismiss trace shortcuts helper", children: jsxRuntimeExports.jsx(X$3, { className: "h-3 w-3" }) })] });
87742
87813
  }
87743
87814
  const MIN_VIEWPORT_MS = 1e-3;
87744
87815
  const ZOOM_DEBOUNCE_MS = 150;
@@ -87964,14 +88035,14 @@ function NewTraceViewerContent({ trace: trace2, onLoadMore, hasMore, isLoadingMo
87964
88035
  };
87965
88036
  }, [handleClearActiveSpan]);
87966
88037
  const timelineRef = reactExports.useRef(null);
87967
- const [hoverFraction, setHoverFraction] = reactExports.useState(null);
88038
+ const [hover, setHover] = reactExports.useState(null);
87968
88039
  const hoverInfo2 = reactExports.useMemo(() => {
87969
- if (hoverFraction == null)
88040
+ if (hover == null)
87970
88041
  return null;
87971
- const absTime = viewport.start + hoverFraction * viewDuration;
88042
+ const absTime = viewport.start + hover.fraction * viewDuration;
87972
88043
  const offset2 = absTime - root2.startTime;
87973
- return { fraction: hoverFraction, label: formatDurationPrecise(offset2) };
87974
- }, [hoverFraction, viewport.start, viewDuration, root2.startTime]);
88044
+ return { fraction: hover.fraction, label: formatDurationPrecise(offset2) };
88045
+ }, [hover, viewport.start, viewDuration, root2.startTime]);
87975
88046
  const handleTimelineMouseMove = reactExports.useCallback((e) => {
87976
88047
  const el = timelineRef.current;
87977
88048
  if (!el)
@@ -87981,10 +88052,13 @@ function NewTraceViewerContent({ trace: trace2, onLoadMore, hasMore, isLoadingMo
87981
88052
  if (contentWidth <= 0)
87982
88053
  return;
87983
88054
  const fraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
87984
- setHoverFraction(fraction);
88055
+ setHover({
88056
+ fraction,
88057
+ rowIndex: Math.floor((e.clientY - rect.top) / ROW_HEIGHT_PX)
88058
+ });
87985
88059
  }, []);
87986
88060
  const handleTimelineMouseLeave = reactExports.useCallback(() => {
87987
- setHoverFraction(null);
88061
+ setHover(null);
87988
88062
  }, []);
87989
88063
  reactExports.useEffect(() => {
87990
88064
  const el = timelineRef.current;
@@ -88026,13 +88100,13 @@ function NewTraceViewerContent({ trace: trace2, onLoadMore, hasMore, isLoadingMo
88026
88100
  el.addEventListener("wheel", onWheel, { passive: false });
88027
88101
  return () => el.removeEventListener("wheel", onWheel);
88028
88102
  }, [root2.duration, setViewport, clampToRoot]);
88029
- return jsxRuntimeExports.jsxs("div", { ref: paneRootRef, "data-pane": "pane-root", className: "relative flex w-full h-full max-h-full", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "flex-1 min-w-0 grid grid-rows-[auto_1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsx(Minimap, { spans: trace2.spans, root: root2, viewport, minViewportMs: MIN_VIEWPORT_MS, onViewportChange: setViewport, onAnimateTo: animateTo }), jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
88103
+ return jsxRuntimeExports.jsxs("div", { ref: paneRootRef, "data-pane": "pane-root", className: "relative flex w-full h-full max-h-full", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "@container flex-1 min-w-0 grid grid-rows-[auto_1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsx(Minimap, { spans: trace2.spans, root: root2, viewport, minViewportMs: MIN_VIEWPORT_MS, onViewportChange: setViewport, onAnimateTo: animateTo }), jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
88030
88104
  if (e.key === "Escape" && searchQuery) {
88031
88105
  e.preventDefault();
88032
88106
  e.stopPropagation();
88033
88107
  setSearchQuery("");
88034
88108
  }
88035
- }, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(""), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "search", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo: hoverInfo2 }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace2.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsxs("div", { ref: timelineRef, id: "trace-timeline", className: "@container block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: [jsxRuntimeExports.jsx(Timeline, { spans: trace2.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, onRevealTime: handleRevealTime, hoverFraction, altHeld }), jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace2.spans.length > 1, reducedMotion })] })] }), jsxRuntimeExports.jsxs("div", { className: "absolute right-3 bottom-3 z-[5] flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, disabled: isAtMinZoom, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, disabled: isAtMaxZoom, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx(TraceDetailPanel, { containerRef: paneRootRef, onNavigateToSpan: navigateToSpan, onClose: handleClearActiveSpan })] });
88109
+ }, placeholder: "Search spans...", "aria-label": "Search spans", className: "flex-1 min-w-0 bg-transparent text-sm text-gray-1000 placeholder:text-gray-800 outline-none" }), searchQuery && jsxRuntimeExports.jsx("button", { type: "button", "aria-label": "Clear search", onClick: () => setSearchQuery(""), className: "-mr-2 hidden h-full max-w-full shrink-0 cursor-pointer items-center rounded-r-md border-0 bg-transparent px-2.5 font-inherit text-base text-gray-900 no-underline transition-colors duration-150 ease-in hover:text-gray-1000 focus-visible:-outline-offset-1 focus-visible:outline focus-visible:outline-2 focus-visible:outline-[var(--ds-focus-color)] min-[961px]:flex", children: jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "search", children: "Esc" }) })] }), endHeader: jsxRuntimeExports.jsx(TimelineHeader, { markers: timeMarkers, hoverInfo: hoverInfo2 }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace2.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, id: "trace-timeline", className: "@container block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace2.spans, viewStart: viewport.start, viewEnd: viewport.end, markers: timeMarkers, selectedId: activeSpanId, searchResult, onSelect: handleSelectSpan, onRevealTime: handleRevealTime, hover, altHeld }) }), jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace2.spans.length > 1, reducedMotion }), jsxRuntimeExports.jsxs("div", { className: "pointer-events-auto flex items-center border border-gray-alpha-400 rounded-md bg-background-100 shadow-sm overflow-hidden divide-x divide-gray-alpha-400", children: [jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomOut, disabled: isAtMinZoom, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, disabled: isAtMaxZoom, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] })] })] }), jsxRuntimeExports.jsx(TraceDetailPanel, { containerRef: paneRootRef, onNavigateToSpan: navigateToSpan, onClose: handleClearActiveSpan })] });
88036
88110
  }
88037
88111
  const NewTraceViewer = ({ run: run2, events: events2, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
88038
88112
  const trace2 = reactExports.useMemo(() => {
@@ -92029,166 +92103,35 @@ const encryption = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
92029
92103
  encrypt: encrypt$1,
92030
92104
  importKey
92031
92105
  }, Symbol.toStringTag, { value: "Module" }));
92032
- const version$1 = "5.0.0-beta.35";
92033
- function assertWorldSupportsRuntimeProtocol(world) {
92034
- if (world.specVersion === SPEC_VERSION_CURRENT) {
92035
- return;
92036
- }
92037
- const supportedVersion = world.specVersion ?? "none";
92038
- throw new WorkflowRuntimeError(`This Workflow runtime requires a World with matching spec version ${SPEC_VERSION_CURRENT}, but the configured World declares spec version ${supportedVersion}. Install a World package version compatible with the current Workflow runtime.`);
92039
- }
92040
- const WorldCacheKey = Symbol.for("@workflow/world//cache");
92041
- const WorldCachePromiseKey = Symbol.for("@workflow/world//cachePromise");
92042
- const GetWorldFnKey$1 = Symbol.for("@workflow/world//getWorldFn");
92043
- async function getWorldLazy() {
92044
- const g2 = globalThis;
92045
- if (g2[WorldCacheKey]) {
92046
- assertWorldSupportsRuntimeProtocol(g2[WorldCacheKey]);
92047
- return g2[WorldCacheKey];
92048
- }
92049
- if (g2[WorldCachePromiseKey]) {
92050
- g2[WorldCacheKey] = await g2[WorldCachePromiseKey];
92051
- assertWorldSupportsRuntimeProtocol(g2[WorldCacheKey]);
92052
- return g2[WorldCacheKey];
92053
- }
92054
- const getWorldFn = g2[GetWorldFnKey$1];
92055
- if (getWorldFn) {
92056
- const world = await getWorldFn();
92057
- assertWorldSupportsRuntimeProtocol(world);
92058
- return world;
92059
- }
92060
- throw new Error("Workflow world runtime was not initialized. Import from the host workflow entrypoints (`workflow`, `workflow/api`, or `workflow/runtime`) so @workflow/core/runtime/world-init can register getWorld before getWorldLazy() is used.");
92061
- }
92062
- const DEFAULT_HEALTH_CHECK_TIMEOUT = 3e4;
92063
- const SAFE_WORKFLOW_NAME_PATTERN = /^[a-zA-Z0-9_\-./@]+$/;
92064
- function getWorkflowQueueName(workflowName, namespace2) {
92065
- if (!SAFE_WORKFLOW_NAME_PATTERN.test(workflowName)) {
92066
- throw new Error(`Invalid workflow name "${workflowName}": must only contain alphanumeric characters, underscores, hyphens, dots, forward slashes, or at signs`);
92067
- }
92068
- const prefix = getQueueTopicPrefix("workflow", resolveQueueNamespace(namespace2));
92069
- return `${prefix}${workflowName}`;
92070
- }
92071
- const generateId = monotonicFactory();
92072
- function getHealthCheckStreamName(correlationId) {
92073
- return `__health_check__${correlationId}`;
92074
- }
92075
- function generateHealthCheckRunId(correlationId) {
92076
- return `wrun_hc_${correlationId}`;
92077
- }
92078
- const HEALTH_CHECK_POLL_INTERVAL = 100;
92079
- const HEALTH_CHECK_READ_TIMEOUT = 500;
92080
- function withDeadline(promise2, ms2) {
92081
- let timer2;
92082
- return Promise.race([
92083
- promise2,
92084
- new Promise((_2, reject) => {
92085
- timer2 = setTimeout(() => reject(new Error(`Operation timed out after ${ms2}ms`)), ms2);
92086
- })
92087
- ]).finally(() => clearTimeout(timer2));
92088
- }
92089
- async function readStreamWithTimeout(reader, readTimeout) {
92090
- const chunks = [];
92091
- let done = false;
92092
- let timedOut = false;
92093
- while (!done && !timedOut) {
92094
- const readPromise = reader.read();
92095
- const timeoutPromise = new Promise((resolve2) => setTimeout(() => {
92096
- timedOut = true;
92097
- resolve2({ done: true, value: void 0 });
92098
- }, readTimeout));
92099
- const result = await Promise.race([readPromise, timeoutPromise]);
92100
- done = result.done;
92101
- if (result.value)
92102
- chunks.push(result.value);
92103
- }
92104
- return { chunks, timedOut };
92105
- }
92106
- function parseHealthCheckResponse(chunks) {
92107
- if (chunks.length === 0)
92108
- return null;
92109
- const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
92110
- const combined = new Uint8Array(totalLength);
92111
- let offset2 = 0;
92112
- for (const chunk of chunks) {
92113
- combined.set(chunk, offset2);
92114
- offset2 += chunk.length;
92115
- }
92116
- const responseText = new TextDecoder().decode(combined);
92117
- let response2;
92118
- try {
92119
- response2 = JSON.parse(responseText);
92120
- } catch {
92121
- if (responseText.length > 0) {
92122
- return { healthy: true };
92123
- }
92124
- return null;
92125
- }
92126
- if (typeof response2 !== "object" || response2 === null || !("healthy" in response2) || typeof response2.healthy !== "boolean") {
92127
- return null;
92128
- }
92129
- const r2 = response2;
92130
- const parsed = {
92131
- healthy: r2.healthy
92132
- };
92133
- if (typeof r2.specVersion === "number") {
92134
- parsed.specVersion = r2.specVersion;
92135
- }
92136
- if (typeof r2.workflowCoreVersion === "string") {
92137
- parsed.workflowCoreVersion = r2.workflowCoreVersion;
92138
- }
92139
- return parsed;
92140
- }
92141
- async function healthCheck(world, endpoint, options) {
92142
- var _a3;
92143
- const timeout2 = (options == null ? void 0 : options.timeout) ?? DEFAULT_HEALTH_CHECK_TIMEOUT;
92144
- const correlationId = ((_a3 = world.createRunId) == null ? void 0 : _a3.call(world)) ?? generateId();
92145
- const streamName = getHealthCheckStreamName(correlationId);
92146
- const queueName = `${getQueueTopicPrefix(endpoint, resolveQueueNamespace(options == null ? void 0 : options.namespace))}health_check`;
92147
- const startTime = Date.now();
92148
- try {
92149
- await world.queue(queueName, { __healthCheck: true, correlationId }, {
92150
- // Use JSON transport so the health check works against both
92151
- // old (JSON-only) and new (dual) deployments.
92152
- specVersion: SPEC_VERSION_LEGACY,
92153
- deploymentId: options == null ? void 0 : options.deploymentId
92154
- });
92155
- while (Date.now() - startTime < timeout2) {
92156
- try {
92157
- const remainingMs = timeout2 - (Date.now() - startTime);
92158
- const stream = await withDeadline(world.streams.get(generateHealthCheckRunId(correlationId), streamName), remainingMs);
92159
- const reader = stream.getReader();
92160
- const { chunks, timedOut } = await readStreamWithTimeout(reader, HEALTH_CHECK_READ_TIMEOUT);
92161
- if (timedOut) {
92162
- try {
92163
- reader.cancel();
92164
- } catch {
92165
- }
92166
- await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
92167
- continue;
92168
- }
92169
- const response2 = parseHealthCheckResponse(chunks);
92170
- if (response2) {
92171
- return {
92172
- ...response2,
92173
- latencyMs: Date.now() - startTime
92174
- };
92175
- }
92176
- await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
92177
- } catch {
92178
- await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
92179
- }
92180
- }
92181
- return {
92182
- healthy: false,
92183
- error: `Health check timed out after ${timeout2}ms`
92184
- };
92185
- } catch (error2) {
92186
- return {
92187
- healthy: false,
92188
- error: error2 instanceof Error ? error2.message : String(error2)
92189
- };
92190
- }
92191
- }
92106
+ const STABLE_ULID = Symbol.for("WORKFLOW_STABLE_ULID");
92107
+ const STREAM_NAME_SYMBOL = Symbol.for("WORKFLOW_STREAM_NAME");
92108
+ const STREAM_TYPE_SYMBOL = Symbol.for("WORKFLOW_STREAM_TYPE");
92109
+ const STREAM_FRAMING_SYMBOL = Symbol.for("WORKFLOW_STREAM_FRAMING");
92110
+ const STREAM_SERVER_RUN_ID_SYMBOL = Symbol.for("WORKFLOW_STREAM_SERVER_RUN_ID");
92111
+ const STREAM_SERVER_DEPLOYMENT_ID_SYMBOL = Symbol.for("WORKFLOW_STREAM_SERVER_DEPLOYMENT_ID");
92112
+ const STREAM_WRITE_BATCH_SYMBOL = Symbol.for("WORKFLOW_STREAM_WRITE_BATCH");
92113
+ const BODY_INIT_SYMBOL = Symbol.for("BODY_INIT");
92114
+ const WEBHOOK_RESPONSE_WRITABLE = Symbol.for("WEBHOOK_RESPONSE_WRITABLE");
92115
+ const WORKFLOW_CLASS_REGISTRY = Symbol.for("workflow-class-registry");
92116
+ const ABORT_STREAM_NAME = Symbol.for("WORKFLOW_ABORT_STREAM_NAME");
92117
+ const ABORT_HOOK_TOKEN = Symbol.for("WORKFLOW_ABORT_HOOK_TOKEN");
92118
+ const ABORT_LISTENER_ATTACHED = Symbol.for("WORKFLOW_ABORT_LISTENER_ATTACHED");
92119
+ const ABORT_READER_CANCEL = Symbol.for("WORKFLOW_ABORT_READER_CANCEL");
92120
+ const MAX_INFLIGHT_CHUNKS = 1e3;
92121
+ const getMaxInflightChunks = () => envNumber("WORKFLOW_STREAM_MAX_INFLIGHT_CHUNKS", MAX_INFLIGHT_CHUNKS, {
92122
+ integer: true,
92123
+ min: 1
92124
+ });
92125
+ const MAX_CHUNKS_PER_BATCH = 1e3;
92126
+ const getMaxChunksPerBatch = () => envNumber("WORKFLOW_STREAM_MAX_CHUNKS_PER_BATCH", MAX_CHUNKS_PER_BATCH, {
92127
+ integer: true,
92128
+ min: 1
92129
+ });
92130
+ const MAX_BYTES_PER_BATCH = 1024 * 1024;
92131
+ const getMaxBytesPerBatch = () => envNumber("WORKFLOW_STREAM_MAX_BYTES_PER_BATCH", MAX_BYTES_PER_BATCH, {
92132
+ integer: true,
92133
+ min: 1
92134
+ });
92192
92135
  const LOCK_POLL_INTERVAL_MS = 10;
92193
92136
  const getLockPollIntervalMs = () => envNumber("WORKFLOW_LOCK_POLL_INTERVAL_MS", LOCK_POLL_INTERVAL_MS, {
92194
92137
  integer: true,
@@ -92275,7 +92218,11 @@ function pollReadableLock(readable2, state) {
92275
92218
  }, getLockPollIntervalMs());
92276
92219
  state.readablePollingInterval = intervalId;
92277
92220
  }
92278
- async function flushablePipe(source, sink, state) {
92221
+ function flushablePipe(source, sink, state) {
92222
+ const batchWrite = sink[STREAM_WRITE_BATCH_SYMBOL];
92223
+ return typeof batchWrite === "function" ? flushablePipeCoalescing(source, sink, state, batchWrite) : flushablePipePerChunk(source, sink, state);
92224
+ }
92225
+ async function flushablePipePerChunk(source, sink, state) {
92279
92226
  const reader = source.getReader();
92280
92227
  const writer = sink.getWriter();
92281
92228
  let cancelReason;
@@ -92324,6 +92271,124 @@ async function flushablePipe(source, sink, state) {
92324
92271
  writer.releaseLock();
92325
92272
  }
92326
92273
  }
92274
+ function wake$1(ctx, which) {
92275
+ const resolve2 = ctx[which];
92276
+ if (resolve2) {
92277
+ ctx[which] = null;
92278
+ resolve2();
92279
+ }
92280
+ }
92281
+ function nextBatchSize(ctx) {
92282
+ let count2 = 0;
92283
+ let bytes = 0;
92284
+ for (const chunk of ctx.queue) {
92285
+ if (count2 >= ctx.maxChunksPerBatch)
92286
+ break;
92287
+ if (count2 > 0 && bytes + chunk.byteLength > ctx.maxBytesPerBatch)
92288
+ break;
92289
+ count2++;
92290
+ bytes += chunk.byteLength;
92291
+ }
92292
+ return count2;
92293
+ }
92294
+ async function drainBatches(ctx) {
92295
+ while (true) {
92296
+ if (ctx.queue.length === 0) {
92297
+ if (ctx.sourceDone)
92298
+ return;
92299
+ await new Promise((resolve2) => {
92300
+ ctx.wakeConsumer = resolve2;
92301
+ });
92302
+ continue;
92303
+ }
92304
+ const count2 = nextBatchSize(ctx);
92305
+ const batch = ctx.queue.slice(0, count2);
92306
+ ctx.queue = ctx.queue.slice(count2);
92307
+ await ctx.batchWrite(batch);
92308
+ ctx.state.pendingOps -= batch.length;
92309
+ wake$1(ctx, "wakeProducer");
92310
+ }
92311
+ }
92312
+ function readNextChunk(reader, writer, consumer) {
92313
+ return Promise.race([
92314
+ reader.read(),
92315
+ writer.closed.then(() => {
92316
+ throw new WorkflowRuntimeError("Writable stream closed prematurely");
92317
+ }),
92318
+ consumer.then(() => {
92319
+ throw new WorkflowRuntimeError("Stream consumer ended prematurely");
92320
+ }, (err) => {
92321
+ throw err;
92322
+ })
92323
+ ]);
92324
+ }
92325
+ async function awaitBackpressureRelief(ctx, consumer, maxInflight) {
92326
+ if (ctx.state.pendingOps < maxInflight)
92327
+ return;
92328
+ await Promise.race([
92329
+ new Promise((resolve2) => {
92330
+ ctx.wakeProducer = resolve2;
92331
+ }),
92332
+ consumer.then(() => void 0, () => void 0)
92333
+ ]);
92334
+ }
92335
+ async function flushablePipeCoalescing(source, sink, state, batchWrite) {
92336
+ const reader = source.getReader();
92337
+ const writer = sink.getWriter();
92338
+ const maxInflight = getMaxInflightChunks();
92339
+ let cancelReason;
92340
+ const ctx = {
92341
+ state,
92342
+ batchWrite,
92343
+ queue: [],
92344
+ sourceDone: false,
92345
+ wakeConsumer: null,
92346
+ wakeProducer: null,
92347
+ maxChunksPerBatch: getMaxChunksPerBatch(),
92348
+ maxBytesPerBatch: getMaxBytesPerBatch()
92349
+ };
92350
+ const consumer = drainBatches(ctx);
92351
+ try {
92352
+ while (!state.streamEnded) {
92353
+ const readResult = await readNextChunk(reader, writer, consumer);
92354
+ if (state.streamEnded)
92355
+ return;
92356
+ if (readResult.done) {
92357
+ ctx.sourceDone = true;
92358
+ wake$1(ctx, "wakeConsumer");
92359
+ await consumer;
92360
+ state.streamEnded = true;
92361
+ await writer.close();
92362
+ if (!state.doneResolved) {
92363
+ state.doneResolved = true;
92364
+ state.resolve();
92365
+ }
92366
+ return;
92367
+ }
92368
+ ctx.queue.push(readResult.value);
92369
+ state.pendingOps++;
92370
+ wake$1(ctx, "wakeConsumer");
92371
+ await awaitBackpressureRelief(ctx, consumer, maxInflight);
92372
+ }
92373
+ } catch (err) {
92374
+ state.streamEnded = true;
92375
+ cancelReason = err;
92376
+ ctx.sourceDone = true;
92377
+ wake$1(ctx, "wakeConsumer");
92378
+ await consumer.catch(() => {
92379
+ });
92380
+ if (!state.doneResolved) {
92381
+ state.doneResolved = true;
92382
+ state.reject(err);
92383
+ }
92384
+ throw err;
92385
+ } finally {
92386
+ reader.cancel(cancelReason).catch(() => {
92387
+ });
92388
+ reader.releaseLock();
92389
+ writer.releaseLock();
92390
+ }
92391
+ }
92327
92392
  const RegisteredStepsKey = Symbol.for("@workflow/core//registeredSteps");
92328
92393
  const globalSymbols$1 = globalThis;
92329
92394
  const registeredSteps = globalSymbols$1[RegisteredStepsKey] ?? (globalSymbols$1[RegisteredStepsKey] = /* @__PURE__ */ new Map());
@@ -92388,21 +92453,37 @@ function getStepFunction(stepId) {
92388
92453
  }
92389
92454
  return void 0;
92390
92455
  }
92456
+ function assertWorldSupportsRuntimeProtocol(world) {
92457
+ if (world.specVersion === SPEC_VERSION_CURRENT) {
92458
+ return;
92459
+ }
92460
+ const supportedVersion = world.specVersion ?? "none";
92461
+ throw new WorkflowRuntimeError(`This Workflow runtime requires a World with matching spec version ${SPEC_VERSION_CURRENT}, but the configured World declares spec version ${supportedVersion}. Install a World package version compatible with the current Workflow runtime.`);
92462
+ }
92463
+ const WorldCacheKey = Symbol.for("@workflow/world//cache");
92464
+ const WorldCachePromiseKey = Symbol.for("@workflow/world//cachePromise");
92465
+ const GetWorldFnKey$1 = Symbol.for("@workflow/world//getWorldFn");
92466
+ async function getWorldLazy() {
92467
+ const g2 = globalThis;
92468
+ if (g2[WorldCacheKey]) {
92469
+ assertWorldSupportsRuntimeProtocol(g2[WorldCacheKey]);
92470
+ return g2[WorldCacheKey];
92471
+ }
92472
+ if (g2[WorldCachePromiseKey]) {
92473
+ g2[WorldCacheKey] = await g2[WorldCachePromiseKey];
92474
+ assertWorldSupportsRuntimeProtocol(g2[WorldCacheKey]);
92475
+ return g2[WorldCacheKey];
92476
+ }
92477
+ const getWorldFn = g2[GetWorldFnKey$1];
92478
+ if (getWorldFn) {
92479
+ const world = await getWorldFn();
92480
+ assertWorldSupportsRuntimeProtocol(world);
92481
+ return world;
92482
+ }
92483
+ throw new Error("Workflow world runtime was not initialized. Import from the host workflow entrypoints (`workflow`, `workflow/api`, or `workflow/runtime`) so @workflow/core/runtime/world-init can register getWorld before getWorldLazy() is used.");
92484
+ }
92391
92485
  const WORKFLOW_SERIALIZE = Symbol.for("workflow-serialize");
92392
92486
  const WORKFLOW_DESERIALIZE = Symbol.for("workflow-deserialize");
92393
- const STABLE_ULID = Symbol.for("WORKFLOW_STABLE_ULID");
92394
- const STREAM_NAME_SYMBOL = Symbol.for("WORKFLOW_STREAM_NAME");
92395
- const STREAM_TYPE_SYMBOL = Symbol.for("WORKFLOW_STREAM_TYPE");
92396
- const STREAM_FRAMING_SYMBOL = Symbol.for("WORKFLOW_STREAM_FRAMING");
92397
- const STREAM_SERVER_RUN_ID_SYMBOL = Symbol.for("WORKFLOW_STREAM_SERVER_RUN_ID");
92398
- const STREAM_SERVER_DEPLOYMENT_ID_SYMBOL = Symbol.for("WORKFLOW_STREAM_SERVER_DEPLOYMENT_ID");
92399
- const BODY_INIT_SYMBOL = Symbol.for("BODY_INIT");
92400
- const WEBHOOK_RESPONSE_WRITABLE = Symbol.for("WEBHOOK_RESPONSE_WRITABLE");
92401
- const WORKFLOW_CLASS_REGISTRY = Symbol.for("workflow-class-registry");
92402
- const ABORT_STREAM_NAME = Symbol.for("WORKFLOW_ABORT_STREAM_NAME");
92403
- const ABORT_HOOK_TOKEN = Symbol.for("WORKFLOW_ABORT_HOOK_TOKEN");
92404
- const ABORT_LISTENER_ATTACHED = Symbol.for("WORKFLOW_ABORT_LISTENER_ATTACHED");
92405
- const ABORT_READER_CANCEL = Symbol.for("WORKFLOW_ABORT_READER_CANCEL");
92406
92487
  function getRegistry(global2 = globalThis) {
92407
92488
  const g2 = global2;
92408
92489
  let registry2 = g2[WORKFLOW_CLASS_REGISTRY];
@@ -93903,6 +93984,19 @@ class WorkflowServerWritableStream extends WritableStream {
93903
93984
  w2.reject(abortError);
93904
93985
  }
93905
93986
  });
93987
+ Object.defineProperty(this, STREAM_WRITE_BATCH_SYMBOL, {
93988
+ value: async (chunks) => {
93989
+ if (chunks.length === 0)
93990
+ return;
93991
+ if (batchStartAt === void 0)
93992
+ batchStartAt = Date.now();
93993
+ for (const chunk of chunks)
93994
+ buffer2.push(chunk);
93995
+ await flush();
93996
+ },
93997
+ enumerable: false,
93998
+ writable: false
93999
+ });
93906
94000
  }
93907
94001
  }
93908
94002
  function getAllBaseReducers(global2 = globalThis) {
@@ -94690,8 +94784,20 @@ function getStepRevivers(global2 = globalThis, ops, runId, cryptoKey, deployment
94690
94784
  AbortSignal: (value) => reviveAbortSignal(value, ops, runId)
94691
94785
  };
94692
94786
  }
94693
- async function maybeDecrypt(data, key) {
94694
- return decrypt(data, key);
94787
+ const prepareReplayPayload = async (value, key) => {
94788
+ const compressionStats = {};
94789
+ const prepared = await decompress$2(await decrypt(value, key), compressionStats);
94790
+ await recordCompression(compressionStats, "deserialize");
94791
+ return { data: prepared };
94792
+ };
94793
+ function deserializePreparedReplayPayload(prepared, global2 = globalThis, extraRevivers = {}) {
94794
+ return deserialize(prepared.data, {
94795
+ global: global2,
94796
+ extraRevivers: {
94797
+ ...getStreamAndRequestRevivers(getWorkflowRevivers(global2)),
94798
+ ...extraRevivers
94799
+ }
94800
+ });
94695
94801
  }
94696
94802
  async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
94697
94803
  if (v1Compat) {
@@ -94714,17 +94820,8 @@ async function dehydrateWorkflowArguments(value, runId, key, ops = [], global2 =
94714
94820
  throw new SerializationError(message2, { hint: hint2, cause });
94715
94821
  }
94716
94822
  }
94717
- async function hydrateWorkflowArguments(value, _runId, key, global2 = globalThis, extraRevivers = {}) {
94718
- const compressionStats = {};
94719
- const inflated = await decompress$2(await maybeDecrypt(value, key), compressionStats);
94720
- await recordCompression(compressionStats, "deserialize");
94721
- return deserialize(inflated, {
94722
- global: global2,
94723
- extraRevivers: {
94724
- ...getStreamAndRequestRevivers(getWorkflowRevivers(global2)),
94725
- ...extraRevivers
94726
- }
94727
- });
94823
+ async function hydrateWorkflowArguments(value, _runId, key, global2 = globalThis, extraRevivers = {}, prepared) {
94824
+ return deserializePreparedReplayPayload(await prepareReplayPayload(value, key), global2, extraRevivers);
94728
94825
  }
94729
94826
  async function hydrateWorkflowReturnValue(value, runId, key, ops = [], global2 = globalThis, extraRevivers = {}) {
94730
94827
  const compressionStats = {};
@@ -94796,7 +94893,7 @@ async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = g
94796
94893
  }
94797
94894
  async function hydrateRunError(value, runId, key, ops = [], global2 = globalThis, extraRevivers = {}) {
94798
94895
  const compressionStats = {};
94799
- const decrypted = await decompress$2(await maybeDecrypt(value, key), compressionStats);
94896
+ const decrypted = await decompress$2(await decrypt(value, key), compressionStats);
94800
94897
  await recordCompression(compressionStats, "deserialize");
94801
94898
  if (!(decrypted instanceof Uint8Array)) {
94802
94899
  return unflatten(decrypted, {
@@ -94845,6 +94942,137 @@ function getStreamAndRequestRevivers(allRevivers) {
94845
94942
  }
94846
94943
  return extra;
94847
94944
  }
94945
+ const version$1 = "5.0.0-beta.36";
94946
+ const DEFAULT_HEALTH_CHECK_TIMEOUT = 3e4;
94947
+ const SAFE_WORKFLOW_NAME_PATTERN = /^[a-zA-Z0-9_\-./@]+$/;
94948
+ function getWorkflowQueueName(workflowName, namespace2) {
94949
+ if (!SAFE_WORKFLOW_NAME_PATTERN.test(workflowName)) {
94950
+ throw new Error(`Invalid workflow name "${workflowName}": must only contain alphanumeric characters, underscores, hyphens, dots, forward slashes, or at signs`);
94951
+ }
94952
+ const prefix = getQueueTopicPrefix("workflow", resolveQueueNamespace(namespace2));
94953
+ return `${prefix}${workflowName}`;
94954
+ }
94955
+ const generateId = monotonicFactory();
94956
+ function getHealthCheckStreamName(correlationId) {
94957
+ return `__health_check__${correlationId}`;
94958
+ }
94959
+ function generateHealthCheckRunId(correlationId) {
94960
+ return `wrun_hc_${correlationId}`;
94961
+ }
94962
+ const HEALTH_CHECK_POLL_INTERVAL = 100;
94963
+ const HEALTH_CHECK_READ_TIMEOUT = 500;
94964
+ function withDeadline(promise2, ms2) {
94965
+ let timer2;
94966
+ return Promise.race([
94967
+ promise2,
94968
+ new Promise((_2, reject) => {
94969
+ timer2 = setTimeout(() => reject(new Error(`Operation timed out after ${ms2}ms`)), ms2);
94970
+ })
94971
+ ]).finally(() => clearTimeout(timer2));
94972
+ }
94973
+ async function readStreamWithTimeout(reader, readTimeout) {
94974
+ const chunks = [];
94975
+ let done = false;
94976
+ let timedOut = false;
94977
+ while (!done && !timedOut) {
94978
+ const readPromise = reader.read();
94979
+ const timeoutPromise = new Promise((resolve2) => setTimeout(() => {
94980
+ timedOut = true;
94981
+ resolve2({ done: true, value: void 0 });
94982
+ }, readTimeout));
94983
+ const result = await Promise.race([readPromise, timeoutPromise]);
94984
+ done = result.done;
94985
+ if (result.value)
94986
+ chunks.push(result.value);
94987
+ }
94988
+ return { chunks, timedOut };
94989
+ }
94990
+ function parseHealthCheckResponse(chunks) {
94991
+ if (chunks.length === 0)
94992
+ return null;
94993
+ const totalLength = chunks.reduce((sum, chunk) => sum + chunk.length, 0);
94994
+ const combined = new Uint8Array(totalLength);
94995
+ let offset2 = 0;
94996
+ for (const chunk of chunks) {
94997
+ combined.set(chunk, offset2);
94998
+ offset2 += chunk.length;
94999
+ }
95000
+ const responseText = new TextDecoder().decode(combined);
95001
+ let response2;
95002
+ try {
95003
+ response2 = JSON.parse(responseText);
95004
+ } catch {
95005
+ if (responseText.length > 0) {
95006
+ return { healthy: true };
95007
+ }
95008
+ return null;
95009
+ }
95010
+ if (typeof response2 !== "object" || response2 === null || !("healthy" in response2) || typeof response2.healthy !== "boolean") {
95011
+ return null;
95012
+ }
95013
+ const r2 = response2;
95014
+ const parsed = {
95015
+ healthy: r2.healthy
95016
+ };
95017
+ if (typeof r2.specVersion === "number") {
95018
+ parsed.specVersion = r2.specVersion;
95019
+ }
95020
+ if (typeof r2.workflowCoreVersion === "string") {
95021
+ parsed.workflowCoreVersion = r2.workflowCoreVersion;
95022
+ }
95023
+ return parsed;
95024
+ }
95025
+ async function healthCheck(world, endpoint, options) {
95026
+ var _a3;
95027
+ const timeout2 = (options == null ? void 0 : options.timeout) ?? DEFAULT_HEALTH_CHECK_TIMEOUT;
95028
+ const correlationId = ((_a3 = world.createRunId) == null ? void 0 : _a3.call(world)) ?? generateId();
95029
+ const streamName = getHealthCheckStreamName(correlationId);
95030
+ const queueName = `${getQueueTopicPrefix(endpoint, resolveQueueNamespace(options == null ? void 0 : options.namespace))}health_check`;
95031
+ const startTime = Date.now();
95032
+ try {
95033
+ await world.queue(queueName, { __healthCheck: true, correlationId }, {
95034
+ // Use JSON transport so the health check works against both
95035
+ // old (JSON-only) and new (dual) deployments.
95036
+ specVersion: SPEC_VERSION_LEGACY,
95037
+ deploymentId: options == null ? void 0 : options.deploymentId
95038
+ });
95039
+ while (Date.now() - startTime < timeout2) {
95040
+ try {
95041
+ const remainingMs = timeout2 - (Date.now() - startTime);
95042
+ const stream = await withDeadline(world.streams.get(generateHealthCheckRunId(correlationId), streamName), remainingMs);
95043
+ const reader = stream.getReader();
95044
+ const { chunks, timedOut } = await readStreamWithTimeout(reader, HEALTH_CHECK_READ_TIMEOUT);
95045
+ if (timedOut) {
95046
+ try {
95047
+ reader.cancel();
95048
+ } catch {
95049
+ }
95050
+ await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
95051
+ continue;
95052
+ }
95053
+ const response2 = parseHealthCheckResponse(chunks);
95054
+ if (response2) {
95055
+ return {
95056
+ ...response2,
95057
+ latencyMs: Date.now() - startTime
95058
+ };
95059
+ }
95060
+ await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
95061
+ } catch {
95062
+ await new Promise((resolve2) => setTimeout(resolve2, HEALTH_CHECK_POLL_INTERVAL));
95063
+ }
95064
+ }
95065
+ return {
95066
+ healthy: false,
95067
+ error: `Health check timed out after ${timeout2}ms`
95068
+ };
95069
+ } catch (error2) {
95070
+ return {
95071
+ healthy: false,
95072
+ error: error2 instanceof Error ? error2.message : String(error2)
95073
+ };
95074
+ }
95075
+ }
94848
95076
  function throwMissingStaticInjection() {
94849
95077
  throw new Error("Workflow target world was not statically injected. Configure a Workflow builder/framework plugin so @workflow/core/runtime/world-target is aliased to the selected world package.");
94850
95078
  }
@@ -97754,17 +97982,21 @@ function getRunCapabilities(workflowCoreVersion) {
97754
97982
  }
97755
97983
  return result;
97756
97984
  }
97757
- async function getHookByTokenWithKey(token) {
97758
- var _a3;
97985
+ async function getHookAndRun(token) {
97759
97986
  const world = await getWorldLazy();
97760
97987
  const hook = await world.hooks.getByToken(token);
97761
97988
  const run2 = await world.runs.get(hook.runId);
97762
- const rawKey = await ((_a3 = world.getEncryptionKeyForRun) == null ? void 0 : _a3.call(world, run2));
97989
+ return { hook, run: run2 };
97990
+ }
97991
+ async function getHookByTokenWithKey(token) {
97992
+ var _a3, _b2;
97993
+ const { hook, run: run2 } = await getHookAndRun(token);
97994
+ const rawKey = await ((_b2 = (_a3 = await getWorldLazy()).getEncryptionKeyForRun) == null ? void 0 : _b2.call(_a3, run2));
97763
97995
  const encryptionKey = rawKey ? await importKey(rawKey) : void 0;
97764
97996
  if (typeof hook.metadata !== "undefined") {
97765
97997
  hook.metadata = await hydrateStepArguments(hook.metadata, hook.runId, encryptionKey);
97766
97998
  }
97767
- return { hook, run: run2, encryptionKey };
97999
+ return { hook, encryptionKey };
97768
98000
  }
97769
98001
  async function getHookByToken$1(token) {
97770
98002
  const { hook } = await getHookByTokenWithKey(token);
@@ -97778,27 +98010,27 @@ async function resumeHook$2(tokenOrHook, payload, encryptionKeyOverride) {
97778
98010
  try {
97779
98011
  let hook;
97780
98012
  let workflowRun;
97781
- let encryptionKey;
97782
98013
  if (typeof tokenOrHook === "string") {
97783
- const result = await getHookByTokenWithKey(tokenOrHook);
98014
+ const result = await getHookAndRun(tokenOrHook);
97784
98015
  hook = result.hook;
97785
98016
  workflowRun = result.run;
97786
- encryptionKey = encryptionKeyOverride ?? result.encryptionKey;
97787
98017
  } else {
97788
98018
  hook = tokenOrHook;
97789
98019
  workflowRun = await world.runs.get(hook.runId);
97790
- if (encryptionKeyOverride) {
97791
- encryptionKey = encryptionKeyOverride;
97792
- } else {
97793
- const rawKey = await ((_a3 = world.getEncryptionKeyForRun) == null ? void 0 : _a3.call(world, workflowRun));
97794
- encryptionKey = rawKey ? await importKey(rawKey) : void 0;
97795
- }
97796
98020
  }
97797
98021
  span == null ? void 0 : span.setAttributes({
97798
98022
  ...HookToken(hook.token),
97799
98023
  ...HookId(hook.hookId),
97800
98024
  ...WorkflowRunId$2(hook.runId)
97801
98025
  });
98026
+ if (isTerminalWorkflowRunStatus(workflowRun.status)) {
98027
+ throw new HookNotFoundError(hook.token);
98028
+ }
98029
+ let encryptionKey = encryptionKeyOverride;
98030
+ if (!encryptionKey) {
98031
+ const rawKey = await ((_a3 = world.getEncryptionKeyForRun) == null ? void 0 : _a3.call(world, workflowRun));
98032
+ encryptionKey = rawKey ? await importKey(rawKey) : void 0;
98033
+ }
97802
98034
  const rawVersion = (_b2 = workflowRun.executionContext) == null ? void 0 : _b2.workflowCoreVersion;
97803
98035
  const capabilities = getRunCapabilities(typeof rawVersion === "string" ? rawVersion : void 0);
97804
98036
  if (!capabilities.supportedFormats.has(SerializationFormat.ENCRYPTED)) {
@@ -99066,6 +99298,20 @@ async function writeExclusive(filePath, data) {
99066
99298
  }
99067
99299
  }
99068
99300
  }
99301
+ async function promoteExclusive(stagedPath, filePath) {
99302
+ try {
99303
+ await withEnsuredDirectory(path$3.dirname(filePath), () => withWindowsRetry(() => promises.link(stagedPath, filePath)));
99304
+ return "linked";
99305
+ } catch (error2) {
99306
+ if (error2.code === "EEXIST") {
99307
+ return "exists";
99308
+ }
99309
+ if (error2.code === "ENOENT") {
99310
+ return "missing";
99311
+ }
99312
+ throw error2;
99313
+ }
99314
+ }
99069
99315
  async function listJSONFiles(dirPath) {
99070
99316
  return listFilesByExtension(dirPath, ".json");
99071
99317
  }
@@ -125339,6 +125585,98 @@ async function isHookDisposalCommitted(basedir, hookId, tag) {
125339
125585
  }
125340
125586
  return false;
125341
125587
  }
125588
+ function runTerminalMarkerPath(basedir, runId, tag) {
125589
+ const name2 = tag ? `${runId}.terminal.${tag}` : `${runId}.terminal`;
125590
+ return resolveWithinBase(basedir, ".locks", "runs", name2);
125591
+ }
125592
+ async function isRunTerminalCommitted(basedir, runId, tag) {
125593
+ const candidates = [runTerminalMarkerPath(basedir, runId)];
125594
+ if (tag) {
125595
+ candidates.push(runTerminalMarkerPath(basedir, runId, tag));
125596
+ }
125597
+ for (const markerPath of candidates) {
125598
+ try {
125599
+ await fs$1.access(markerPath);
125600
+ return true;
125601
+ } catch (error2) {
125602
+ if (error2.code !== "ENOENT") {
125603
+ throw error2;
125604
+ }
125605
+ }
125606
+ }
125607
+ return false;
125608
+ }
125609
+ function pendingHookEventDir(basedir, runId, tag) {
125610
+ const name2 = tag ? `${runId}.pending.${tag}` : `${runId}.pending`;
125611
+ return resolveWithinBase(basedir, ".locks", "runs", name2);
125612
+ }
125613
+ function pendingHookEventPath(basedir, runId, eventId, tag) {
125614
+ return path$3.join(pendingHookEventDir(basedir, runId, tag), `${eventId}.json`);
125615
+ }
125616
+ async function reapPendingHookEvents(basedir, runId, tag) {
125617
+ const dirs = [pendingHookEventDir(basedir, runId)];
125618
+ if (tag) {
125619
+ dirs.push(pendingHookEventDir(basedir, runId, tag));
125620
+ }
125621
+ for (const dir of dirs) {
125622
+ let entries;
125623
+ try {
125624
+ entries = await fs$1.readdir(dir);
125625
+ } catch (error2) {
125626
+ if (error2.code === "ENOENT") {
125627
+ continue;
125628
+ }
125629
+ throw error2;
125630
+ }
125631
+ for (const entry2 of entries) {
125632
+ try {
125633
+ await withWindowsRetry(() => fs$1.unlink(path$3.join(dir, entry2)));
125634
+ } catch (error2) {
125635
+ if (error2.code !== "ENOENT") {
125636
+ throw error2;
125637
+ }
125638
+ }
125639
+ }
125640
+ await fs$1.rmdir(dir).catch(() => {
125641
+ });
125642
+ }
125643
+ }
125644
+ async function mintRunDominantEventKey(basedir, runId, tag) {
125645
+ let files = [];
125646
+ try {
125647
+ files = await fs$1.readdir(path$3.join(basedir, "events"));
125648
+ } catch (error2) {
125649
+ if (error2.code !== "ENOENT") {
125650
+ throw error2;
125651
+ }
125652
+ }
125653
+ const prefix = `${runId}-`;
125654
+ let maxUlid = null;
125655
+ for (const file2 of files) {
125656
+ if (!file2.startsWith(prefix) || !file2.endsWith(".json")) {
125657
+ continue;
125658
+ }
125659
+ const fileId = file2.slice(0, -".json".length);
125660
+ if (!isUntagged(fileId) && !(tag && hasTag(fileId, tag))) {
125661
+ continue;
125662
+ }
125663
+ const candidate = stripTag(fileId).slice(prefix.length);
125664
+ if (!maxUlid || candidate > maxUlid) {
125665
+ maxUlid = candidate;
125666
+ }
125667
+ }
125668
+ let ts = Date.now();
125669
+ if (maxUlid) {
125670
+ try {
125671
+ const maxTs = decodeTime(maxUlid.replace(/^evnt_/, ""));
125672
+ if (ts <= maxTs) {
125673
+ ts = maxTs + 1;
125674
+ }
125675
+ } catch {
125676
+ }
125677
+ }
125678
+ return { eventId: `evnt_${monotonicUlid$1(ts)}`, createdAt: new Date(ts) };
125679
+ }
125342
125680
  function hookTokenClaimPath(basedir, token) {
125343
125681
  return path$3.join(basedir, "hooks", "tokens", `${hashToken(token)}.json`);
125344
125682
  }
@@ -125767,11 +126105,32 @@ async function deleteAllHooksForRun(basedir, runId) {
125767
126105
  await deleteHookByRunMarkerFile(basedir, marker2.fileId);
125768
126106
  }
125769
126107
  }
126108
+ async function publishLegacyHookReceived(basedir, runId, eventId, serializedEvent, eventPath, currentRun) {
126109
+ if (isTerminalWorkflowRunStatus(currentRun.status) || await isRunTerminalCommitted(basedir, runId)) {
126110
+ throw new RunExpiredError(`Workflow run "${runId}" is already in a terminal state`);
126111
+ }
126112
+ const stagedPath = pendingHookEventPath(basedir, runId, eventId);
126113
+ await writeExclusive(stagedPath, serializedEvent);
126114
+ try {
126115
+ if (await isRunTerminalCommitted(basedir, runId)) {
126116
+ throw new RunExpiredError(`Workflow run "${runId}" is already in a terminal state`);
126117
+ }
126118
+ const promoted = await promoteExclusive(stagedPath, eventPath);
126119
+ if (promoted !== "linked") {
126120
+ throw new RunExpiredError(`Workflow run "${runId}" is already in a terminal state`);
126121
+ }
126122
+ } finally {
126123
+ await fs$1.unlink(stagedPath).catch(() => {
126124
+ });
126125
+ }
126126
+ }
125770
126127
  async function handleLegacyEvent(basedir, runId, data, currentRun, params) {
125771
126128
  assertSafeEntityId("runId", runId);
125772
126129
  const resolveData = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION$1;
125773
126130
  switch (data.eventType) {
125774
126131
  case "run_cancelled": {
126132
+ await writeExclusive(runTerminalMarkerPath(basedir, runId), "");
126133
+ await reapPendingHookEvents(basedir, runId);
125775
126134
  const now2 = /* @__PURE__ */ new Date();
125776
126135
  const run2 = {
125777
126136
  runId: currentRun.runId,
@@ -125811,7 +126170,11 @@ async function handleLegacyEvent(basedir, runId, data, currentRun, params) {
125811
126170
  };
125812
126171
  const compositeKey = `${runId}-${eventId}`;
125813
126172
  const eventPath = resolveWithinBase(basedir, "events", `${compositeKey}.json`);
125814
- await writeJSON(eventPath, event);
126173
+ if (data.eventType === "hook_received") {
126174
+ await publishLegacyHookReceived(basedir, runId, eventId, JSON.stringify(event, jsonReplacer, 2), eventPath, currentRun);
126175
+ } else {
126176
+ await writeJSON(eventPath, event);
126177
+ }
125815
126178
  return { event: stripEventDataRefs(event, resolveData) };
125816
126179
  }
125817
126180
  default:
@@ -125838,15 +126201,31 @@ function withRunFileLock(key, fn2) {
125838
126201
  return task;
125839
126202
  }
125840
126203
  function createRunsStorage(basedir, tag) {
126204
+ const get2 = (async (id2, params) => {
126205
+ assertSafeEntityId("runId", id2);
126206
+ const run2 = await readJSONWithFallback(basedir, "runs", id2, WorkflowRunSchema, tag);
126207
+ if (!run2) {
126208
+ throw new WorkflowRunNotFoundError(id2);
126209
+ }
126210
+ const resolveData = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION$1;
126211
+ return filterRunData$1(run2, resolveData);
126212
+ });
125841
126213
  return {
125842
- get: (async (id2, params) => {
125843
- assertSafeEntityId("runId", id2);
125844
- const run2 = await readJSONWithFallback(basedir, "runs", id2, WorkflowRunSchema, tag);
125845
- if (!run2) {
125846
- throw new WorkflowRunNotFoundError(id2);
125847
- }
125848
- const resolveData = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION$1;
125849
- return filterRunData$1(run2, resolveData);
126214
+ get: get2,
126215
+ getMany: (async (ids, params) => {
126216
+ const uniqueIds = [...new Set(ids)];
126217
+ const runs = await Promise.all(uniqueIds.map(async (id2) => {
126218
+ try {
126219
+ return await get2(id2, params);
126220
+ } catch (error2) {
126221
+ if (error2 instanceof WorkflowRunNotFoundError) {
126222
+ return null;
126223
+ }
126224
+ throw error2;
126225
+ }
126226
+ }));
126227
+ const runById = new Map(uniqueIds.map((id2, i) => [id2, runs[i]]));
126228
+ return ids.map((id2) => runById.get(id2) ?? null);
125850
126229
  }),
125851
126230
  list: (async (params) => {
125852
126231
  var _a3, _b2, _c2;
@@ -125917,6 +126296,12 @@ function createRunsStorage(basedir, tag) {
125917
126296
  }
125918
126297
  };
125919
126298
  }
126299
+ const DEFAULT_MAX_EVENTS_PER_RUN = 25e3;
126300
+ function getMaxEventsPerRun() {
126301
+ const raw2 = process.env.WORKFLOW_MAX_EVENTS;
126302
+ const parsed = raw2 !== void 0 ? Number(raw2) : Number.NaN;
126303
+ return Number.isInteger(parsed) && parsed > 0 ? parsed : DEFAULT_MAX_EVENTS_PER_RUN;
126304
+ }
125920
126305
  const HookTokenClaimSchema = object$1({
125921
126306
  // The token-claim writer below has always persisted `hookId`, but
125922
126307
  // this read schema previously omitted it, which is the bug fixed
@@ -126252,7 +126637,8 @@ function createEventsStorage(basedir, tag) {
126252
126637
  const resolveData2 = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION$1;
126253
126638
  return {
126254
126639
  event: stripEventDataRefs(event2, resolveData2),
126255
- run: currentRun
126640
+ run: currentRun,
126641
+ ...currentRun ? { maxEvents: getMaxEventsPerRun() } : {}
126256
126642
  };
126257
126643
  }
126258
126644
  if (data.eventType === "run_started") {
@@ -126319,6 +126705,13 @@ function createEventsStorage(basedir, tag) {
126319
126705
  let wait;
126320
126706
  let stepCreatedLazily = false;
126321
126707
  let hookEntityWriteOptions;
126708
+ if (isTerminalRunEventType(data.eventType) && currentRun) {
126709
+ await writeExclusive(runTerminalMarkerPath(basedir, effectiveRunId, tag), "");
126710
+ await reapPendingHookEvents(basedir, effectiveRunId, tag);
126711
+ const dominantKey = await mintRunDominantEventKey(basedir, effectiveRunId, tag);
126712
+ eventId = dominantKey.eventId;
126713
+ event = { ...event, eventId, createdAt: dominantKey.createdAt };
126714
+ }
126322
126715
  if (data.eventType === "run_created" && "eventData" in data) {
126323
126716
  const runData = data.eventData;
126324
126717
  validateAttributeChanges(Object.entries(runData.attributes ?? {}).map(([key, value]) => ({
@@ -126352,7 +126745,7 @@ function createEventsStorage(basedir, tag) {
126352
126745
  } else if (data.eventType === "run_started") {
126353
126746
  if (currentRun) {
126354
126747
  if (currentRun.status === "running") {
126355
- return { run: currentRun };
126748
+ return { run: currentRun, maxEvents: getMaxEventsPerRun() };
126356
126749
  }
126357
126750
  run2 = await writeRunUnderLifecycleLock(basedir, effectiveRunId, tag, {
126358
126751
  runId: currentRun.runId,
@@ -126802,7 +127195,34 @@ function createEventsStorage(basedir, tag) {
126802
127195
  const compositeKey = `${effectiveRunId}-${eventId}`;
126803
127196
  const eventPath = taggedPath(basedir, "events", compositeKey, tag);
126804
127197
  const serializedEvent = JSON.stringify(event, jsonReplacer, 2);
126805
- const eventPublished = await writeExclusive(eventPath, serializedEvent);
127198
+ let eventPublished;
127199
+ if (data.eventType === "hook_received") {
127200
+ const terminalByMarker = await isRunTerminalCommitted(basedir, effectiveRunId, tag);
127201
+ const runNow = terminalByMarker ? null : await readJSONWithFallback(basedir, "runs", effectiveRunId, WorkflowRunSchema, tag);
127202
+ if (terminalByMarker || runNow && isTerminalWorkflowRunStatus(runNow.status)) {
127203
+ throw new RunExpiredError(`Workflow run "${effectiveRunId}" is already in a terminal state`);
127204
+ }
127205
+ const stagedPath = pendingHookEventPath(basedir, effectiveRunId, eventId, tag);
127206
+ const staged = await writeExclusive(stagedPath, serializedEvent);
127207
+ if (!staged) {
127208
+ throw new EntityConflictError(`Event "${eventId}" already exists for run "${effectiveRunId}"`);
127209
+ }
127210
+ try {
127211
+ if (await isRunTerminalCommitted(basedir, effectiveRunId, tag)) {
127212
+ throw new RunExpiredError(`Workflow run "${effectiveRunId}" is already in a terminal state`);
127213
+ }
127214
+ const promoted = await promoteExclusive(stagedPath, eventPath);
127215
+ if (promoted === "missing") {
127216
+ throw new RunExpiredError(`Workflow run "${effectiveRunId}" is already in a terminal state`);
127217
+ }
127218
+ eventPublished = promoted === "linked";
127219
+ } finally {
127220
+ await deleteJSON(stagedPath).catch(() => {
127221
+ });
127222
+ }
127223
+ } else {
127224
+ eventPublished = await writeExclusive(eventPath, serializedEvent);
127225
+ }
126806
127226
  if (!eventPublished) {
126807
127227
  if (data.eventType === "hook_created" && data.correlationId) {
126808
127228
  await repairHookEntityFromPersistedEvent(basedir, effectiveRunId, data.correlationId, eventId, tag);
@@ -126857,7 +127277,9 @@ function createEventsStorage(basedir, tag) {
126857
127277
  events: events2,
126858
127278
  cursor,
126859
127279
  hasMore,
126860
- ...stepCreatedLazily ? { stepCreated: true } : {}
127280
+ ...stepCreatedLazily ? { stepCreated: true } : {},
127281
+ // Per-run event ceiling (mirrors the Vercel World).
127282
+ ...run2 ? { maxEvents: getMaxEventsPerRun() } : {}
126861
127283
  };
126862
127284
  }
126863
127285
  },
@@ -127395,7 +127817,7 @@ function createWorld$1(args) {
127395
127817
  const basedir = mergedConfig.dataDir;
127396
127818
  const hooksDir = path$3.join(basedir, "hooks");
127397
127819
  const taggedHookFiles = await listTaggedFiles(hooksDir, tag);
127398
- const { HookSchema: HookSchema2 } = await import("./index-Dt3nkvmG.js");
127820
+ const { HookSchema: HookSchema2 } = await import("./index-Cnj8rNtV.js");
127399
127821
  await Promise.all(taggedHookFiles.map(async (hookFile) => {
127400
127822
  const hook = await readJSON(path$3.join(hooksDir, hookFile), HookSchema2);
127401
127823
  if (hook == null ? void 0 : hook.token) {
@@ -127578,8 +128000,8 @@ function requireGetVercelOidcToken() {
127578
128000
  }
127579
128001
  try {
127580
128002
  const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
127581
- await import("./token-util-DHXhfd_v.js").then((n) => n.t),
127582
- await import("./token-BaQZqFlF.js").then((n) => n.t)
128003
+ await import("./token-util-D94FNaX0.js").then((n) => n.t),
128004
+ await import("./token-CYc8-6E0.js").then((n) => n.t)
127583
128005
  ]);
127584
128006
  if (!token || isExpired(getTokenPayload(token), options == null ? void 0 : options.expirationBufferMs)) {
127585
128007
  await refreshToken(options);
@@ -128145,6 +128567,7 @@ var distExports = requireDist();
128145
128567
  let _dispatcher;
128146
128568
  let _eventsDispatcher;
128147
128569
  let _streamDispatcher;
128570
+ let _streamCloseDispatcher;
128148
128571
  const BASE_AGENT_OPTIONS = {
128149
128572
  connections: 8,
128150
128573
  keepAliveTimeout: 1e4,
@@ -128179,6 +128602,11 @@ const STREAM_RETRY_OPTIONS = {
128179
128602
  methods: ["PUT"],
128180
128603
  statusCodes: [429]
128181
128604
  };
128605
+ const STREAM_CLOSE_RETRY_OPTIONS = {
128606
+ retryAfter: true,
128607
+ methods: ["PUT"],
128608
+ statusCodes: [429, 500, 502, 503, 504]
128609
+ };
128182
128610
  function getDispatcher(config2) {
128183
128611
  return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultDispatcher();
128184
128612
  }
@@ -128188,6 +128616,9 @@ function getEventsDispatcher(config2) {
128188
128616
  function getStreamDispatcher(config2) {
128189
128617
  return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultStreamDispatcher();
128190
128618
  }
128619
+ function getStreamCloseDispatcher(config2) {
128620
+ return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultStreamCloseDispatcher();
128621
+ }
128191
128622
  function makeRetryDispatcher(agentOptions, retryOptions) {
128192
128623
  return new undiciExports.RetryAgent(new undiciExports.Agent(agentOptions), retryOptions);
128193
128624
  }
@@ -128203,6 +128634,10 @@ function getDefaultStreamDispatcher() {
128203
128634
  _streamDispatcher ?? (_streamDispatcher = makeRetryDispatcher(EVENTS_AGENT_OPTIONS, STREAM_RETRY_OPTIONS));
128204
128635
  return _streamDispatcher;
128205
128636
  }
128637
+ function getDefaultStreamCloseDispatcher() {
128638
+ _streamCloseDispatcher ?? (_streamCloseDispatcher = makeRetryDispatcher(EVENTS_AGENT_OPTIONS, STREAM_CLOSE_RETRY_OPTIONS));
128639
+ return _streamCloseDispatcher;
128640
+ }
128206
128641
  let otelApiPromise$1 = null;
128207
128642
  async function getOtelApi$1() {
128208
128643
  if (!otelApiPromise$1) {
@@ -128476,7 +128911,7 @@ async function instrumentedFetch(opts) {
128476
128911
  return response2;
128477
128912
  });
128478
128913
  }
128479
- const version = "5.0.0-beta.31";
128914
+ const version = "5.0.0-beta.32";
128480
128915
  const IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
128481
128916
  const MAX_BODY_PARSE_RETRIES = 2;
128482
128917
  const BODY_PARSE_RETRY_BASE_MS = 100;
@@ -128517,6 +128952,7 @@ const DEFAULT_RESOLVE_DATA_OPTION = "all";
128517
128952
  function deserializeError(obj) {
128518
128953
  return obj;
128519
128954
  }
128955
+ const joinUserAgentProducts = (...products) => products.filter(Boolean).join(" ");
128520
128956
  const getUserAgent = () => {
128521
128957
  const deploymentId = process.env.VERCEL_DEPLOYMENT_ID;
128522
128958
  if (deploymentId) {
@@ -128536,7 +128972,7 @@ const getHttpUrl = (config2) => {
128536
128972
  const getHeaders = (config2, options) => {
128537
128973
  const projectConfig = config2 == null ? void 0 : config2.projectConfig;
128538
128974
  const headers2 = new Headers(config2 == null ? void 0 : config2.headers);
128539
- headers2.set("User-Agent", getUserAgent());
128975
+ headers2.set("User-Agent", joinUserAgentProducts(getUserAgent(), headers2.get("User-Agent")));
128540
128976
  const testLimitOverrides = getTestLimitOverridesHeader();
128541
128977
  if (testLimitOverrides) {
128542
128978
  headers2.set(TEST_LIMIT_OVERRIDES_HEADER, testLimitOverrides);
@@ -128580,7 +129016,7 @@ async function getHttpConfig(config2) {
128580
129016
  }
128581
129017
  return { baseUrl, headers: headers2, usingProxy };
128582
129018
  }
128583
- async function makeRequest({ endpoint, options = {}, config: config2 = {}, schema, data, onResponse }) {
129019
+ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schema, data, onResponse, retryConnectTimeout = false }) {
128584
129020
  const method = options.method || "GET";
128585
129021
  const { baseUrl, headers: headers2 } = await getHttpConfig(config2);
128586
129022
  const url2 = `${baseUrl}${endpoint}`;
@@ -128598,7 +129034,7 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
128598
129034
  headers2.set("Content-Type", "application/cbor");
128599
129035
  body2 = encode$1(data);
128600
129036
  }
128601
- const canRetryBody = IDEMPOTENT_METHODS.has(method.toUpperCase());
129037
+ const canRetryRead = IDEMPOTENT_METHODS.has(method.toUpperCase());
128602
129038
  let parseResult;
128603
129039
  let responseDiagnostics = "";
128604
129040
  for (let attempt = 0; ; attempt++) {
@@ -128627,6 +129063,10 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
128627
129063
  }
128628
129064
  const transportCode = getTransientTransportCode(error2);
128629
129065
  if (transportCode) {
129066
+ if (retryConnectTimeout && canRetryRead && transportCode === "UND_ERR_CONNECT_TIMEOUT" && attempt === 0) {
129067
+ await new Promise((resolve2) => setTimeout(resolve2, BODY_PARSE_RETRY_BASE_MS));
129068
+ continue;
129069
+ }
128630
129070
  const transportError = new WorkflowWorldError(`${method} ${endpoint} transport failure after ${elapsed}ms (${transportCode})`, { url: url2, code: "TRANSPORT", cause: error2 });
128631
129071
  span == null ? void 0 : span.setAttributes({ ...ErrorType("TRANSPORT") });
128632
129072
  (_b2 = span == null ? void 0 : span.recordException) == null ? void 0 : _b2.call(span, transportError);
@@ -128671,7 +129111,7 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
128671
129111
  });
128672
129112
  break;
128673
129113
  } catch (error2) {
128674
- if (canRetryBody && attempt < MAX_BODY_PARSE_RETRIES) {
129114
+ if (canRetryRead && attempt < MAX_BODY_PARSE_RETRIES) {
128675
129115
  const backoffMs = BODY_PARSE_RETRY_BASE_MS * 2 ** attempt;
128676
129116
  span == null ? void 0 : span.setAttributes({
128677
129117
  ...ErrorType("PARSE_ERROR_RETRYING")
@@ -134110,9 +134550,11 @@ function createQueue$1(config2) {
134110
134550
  // with jitter so an outage or poison message cannot hot-loop or
134111
134551
  // redrive in lockstep. Workflow handlers are event-sourced and must
134112
134552
  // remain idempotent because queue retries can happen close together.
134113
- retry: (_error, { deliveryCount }) => ({
134114
- afterSeconds: getHandlerErrorRetryAfterSeconds(deliveryCount)
134115
- })
134553
+ retry: (error2, { messageId, deliveryCount }) => {
134554
+ const afterSeconds = getHandlerErrorRetryAfterSeconds(deliveryCount);
134555
+ console.error(`[workflow] Queue handler failed for message "${messageId}" on delivery attempt ${deliveryCount}; retrying in ${afterSeconds}s:`, error2);
134556
+ return { afterSeconds };
134557
+ }
134116
134558
  });
134117
134559
  return async (req) => {
134118
134560
  const rawId = req.headers.get("x-vercel-id");
@@ -134480,6 +134922,9 @@ function buildPostFrameMeta(input) {
134480
134922
  meta2.retryAfter = input.retryAfter;
134481
134923
  if (input.hookToken !== void 0)
134482
134924
  meta2.hookToken = input.hookToken;
134925
+ if (input.hookTokenRetentionUntil !== void 0) {
134926
+ meta2.hookTokenRetentionUntil = input.hookTokenRetentionUntil;
134927
+ }
134483
134928
  if (input.hookIsWebhook !== void 0)
134484
134929
  meta2.hookIsWebhook = input.hookIsWebhook;
134485
134930
  if (input.hookIsSystem !== void 0)
@@ -134653,9 +135098,17 @@ async function getEventsByCorrelationIdV4(correlationId, params = {}, config2) {
134653
135098
  return consumeListFrameStream(url2, headers2, config2, "listEventsByCorrelationId");
134654
135099
  }
134655
135100
  const FORMAT_PREFIX_LENGTH = 4;
135101
+ const DEVALUE_FORMAT_PREFIX = "devl";
135102
+ const ENCRYPTED_FORMAT_PREFIX = "encr";
134656
135103
  const GZIP_FORMAT_PREFIX = "gzip";
134657
135104
  const ZSTD_FORMAT_PREFIX = "zstd";
134658
135105
  const formatDecoder = new TextDecoder();
135106
+ const SERIALIZED_DATA_FORMAT_PREFIXES = /* @__PURE__ */ new Set([
135107
+ DEVALUE_FORMAT_PREFIX,
135108
+ ENCRYPTED_FORMAT_PREFIX,
135109
+ GZIP_FORMAT_PREFIX,
135110
+ ZSTD_FORMAT_PREFIX
135111
+ ]);
134659
135112
  function getNodeZlib() {
134660
135113
  var _a3, _b2;
134661
135114
  try {
@@ -134670,6 +135123,10 @@ function peekFormatPrefix(value) {
134670
135123
  }
134671
135124
  return formatDecoder.decode(value.subarray(0, FORMAT_PREFIX_LENGTH));
134672
135125
  }
135126
+ function hasSerializedDataFormatPrefix(value) {
135127
+ const format2 = peekFormatPrefix(value);
135128
+ return format2 !== null && SERIALIZED_DATA_FORMAT_PREFIXES.has(format2);
135129
+ }
134673
135130
  function decompress(format2, payload) {
134674
135131
  const zlib = getNodeZlib();
134675
135132
  const decompress2 = format2 === ZSTD_FORMAT_PREFIX ? zlib == null ? void 0 : zlib.zstdDecompressSync : zlib == null ? void 0 : zlib.gunzipSync;
@@ -134817,6 +135274,7 @@ async function getWorkflowRun(id2, params, config2) {
134817
135274
  endpoint,
134818
135275
  options: { method: "GET" },
134819
135276
  config: config2,
135277
+ retryConnectTimeout: true,
134820
135278
  schema: remoteRefBehavior === "lazy" ? WorkflowRunWireWithRefsSchema : WorkflowRunWireSchema
134821
135279
  });
134822
135280
  return filterRunData(run2, resolveData);
@@ -134827,6 +135285,21 @@ async function getWorkflowRun(id2, params, config2) {
134827
135285
  throw error2;
134828
135286
  }
134829
135287
  }
135288
+ async function getWorkflowRuns(ids, params, config2) {
135289
+ const uniqueIds = [...new Set(ids)];
135290
+ const runs = await Promise.all(uniqueIds.map(async (id2) => {
135291
+ try {
135292
+ return await getWorkflowRun(id2, params, config2);
135293
+ } catch (error2) {
135294
+ if (error2 instanceof WorkflowRunNotFoundError) {
135295
+ return null;
135296
+ }
135297
+ throw error2;
135298
+ }
135299
+ }));
135300
+ const runById = new Map(uniqueIds.map((id2, i) => [id2, runs[i]]));
135301
+ return ids.map((id2) => runById.get(id2) ?? null);
135302
+ }
134830
135303
  async function cancelWorkflowRunV1(id2, params, config2) {
134831
135304
  const resolveData = (params == null ? void 0 : params.resolveData) ?? DEFAULT_RESOLVE_DATA_OPTION;
134832
135305
  const remoteRefBehavior = resolveData === "none" ? "lazy" : "resolve";
@@ -134961,6 +135434,11 @@ const eventsNeedingResolve = /* @__PURE__ */ new Set([
134961
135434
  "step_started"
134962
135435
  // runtime reads result.step (checks attempt, state)
134963
135436
  ]);
135437
+ const legacyStructuredErrorEventTypes = /* @__PURE__ */ new Set([
135438
+ "run_failed",
135439
+ "step_failed",
135440
+ "step_retrying"
135441
+ ]);
134964
135442
  function splitEventDataForV4(data) {
134965
135443
  var _a3;
134966
135444
  const eventData = data.eventData ?? {};
@@ -134995,6 +135473,9 @@ function splitEventDataForV4(data) {
134995
135473
  if (typeof eventData.token === "string") {
134996
135474
  meta2.hookToken = eventData.token;
134997
135475
  }
135476
+ if (eventData.tokenRetentionUntil instanceof Date) {
135477
+ meta2.hookTokenRetentionUntil = eventData.tokenRetentionUntil;
135478
+ }
134998
135479
  if (typeof eventData.isWebhook === "boolean") {
134999
135480
  meta2.hookIsWebhook = eventData.isWebhook;
135000
135481
  }
@@ -135070,13 +135551,24 @@ function coerceEventDates(raw2) {
135070
135551
  function coerceNormalizedEvent(raw2) {
135071
135552
  return coerceEventDates(normalizeEventData(raw2));
135072
135553
  }
135554
+ function decodeLegacyStructuredError(payload) {
135555
+ if (hasSerializedDataFormatPrefix(payload)) {
135556
+ return payload;
135557
+ }
135558
+ try {
135559
+ const parsed = StructuredErrorSchema.safeParse(decode$1(payload.slice()));
135560
+ return parsed.success ? parsed.data : payload;
135561
+ } catch {
135562
+ return payload;
135563
+ }
135564
+ }
135073
135565
  function buildEventFromV4(decoded, payloadBody, resolveData) {
135074
135566
  const eventData = decoded.eventData ?? {};
135075
135567
  if (payloadBody.byteLength > 0) {
135076
135568
  const payloadField = getEventDataPayloadField(decoded.eventType);
135077
135569
  const normalizedPayload = normalizeSerializedData(payloadBody);
135078
135570
  if (payloadField && normalizedPayload instanceof Uint8Array) {
135079
- eventData[payloadField] = normalizedPayload;
135571
+ eventData[payloadField] = legacyStructuredErrorEventTypes.has(decoded.eventType) ? decodeLegacyStructuredError(normalizedPayload) : normalizedPayload;
135080
135572
  }
135081
135573
  }
135082
135574
  const raw2 = {
@@ -135200,7 +135692,9 @@ async function createWorkflowRunEventInner(id2, data, params, config2) {
135200
135692
  // Lazy step start: thread the server's "I created the step on this call"
135201
135693
  // signal through so the owned-inline runtime path can gate body execution
135202
135694
  // on it. Absent from older servers → undefined → safe default.
135203
- ...body2.stepCreated ? { stepCreated: true } : {}
135695
+ ...body2.stepCreated ? { stepCreated: true } : {},
135696
+ // Server-supplied per-run event ceiling; absent from older servers.
135697
+ ...typeof body2.maxEvents === "number" ? { maxEvents: body2.maxEvents } : {}
135204
135698
  };
135205
135699
  }
135206
135700
  function filterHookData(hook, resolveData) {
@@ -135274,6 +135768,7 @@ function createStorage(config2) {
135274
135768
  // Storage interface with namespaced methods
135275
135769
  runs: {
135276
135770
  get: ((id2, params) => getWorkflowRun(id2, params, config2)),
135771
+ getMany: ((ids, params) => getWorkflowRuns(ids, params, config2)),
135277
135772
  list: ((params) => listWorkflowRuns(params, config2)),
135278
135773
  experimentalSetAttributes: (runId, changes, options) => experimentalSetAttributes(runId, changes, options, config2)
135279
135774
  },
@@ -135425,7 +135920,11 @@ function createStreamer(config2) {
135425
135920
  method: "PUT",
135426
135921
  url: url2.toString(),
135427
135922
  headers: httpConfig.headers,
135428
- dispatcher: getStreamDispatcher(config2),
135923
+ // Close is idempotent (unlike chunk appends), so its dispatcher
135924
+ // retries 5xx — required by the server's close-barrier protocol,
135925
+ // which surfaces transient reconciliation states as retriable
135926
+ // 503s with the stream left durably closing.
135927
+ dispatcher: getStreamCloseDispatcher(config2),
135429
135928
  timeoutMs: null,
135430
135929
  logLabel: url2.pathname,
135431
135930
  spanName: "workflow.stream.write",
@@ -135519,6 +136018,17 @@ function createWorld(config2) {
135519
136018
  // at least it — workflow-server declared spec-5 support in
135520
136019
  // vercel/workflow-server#520.
135521
136020
  specVersion: SPEC_VERSION_SUPPORTS_COMPRESSION,
136021
+ capabilities: {
136022
+ // workflow-server enforces the `stateUpdatedAt` optimistic-concurrency
136023
+ // guard: creations carrying a stale snapshot are rejected with 412
136024
+ // (PreconditionFailedError) when the run's outside-event marker is
136025
+ // newer. See vercel/workflow-server#484.
136026
+ preconditionGuard: true,
136027
+ // Vercel Queues supports maxConcurrency-limited consumers, which
136028
+ // WORKFLOW_SEQUENTIAL_REPLAYS=1 uses for per-run `maxConcurrency: 1`
136029
+ // flow topics (see queue.ts and @workflow/builders).
136030
+ maxConcurrency: true
136031
+ },
135522
136032
  // On Vercel the platform fails the function invocation when the
135523
136033
  // process exits non-zero, and VQS redelivers the queue message via a
135524
136034
  // fresh invocation. The core runtime uses this to decide whether
@@ -158639,7 +159149,7 @@ const route4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
158639
159149
  __proto__: null,
158640
159150
  loader
158641
159151
  }, Symbol.toStringTag, { value: "Module" }));
158642
- const serverManifest = { "entry": { "module": "/assets/entry.client-Q4eUIqMI.js", "imports": ["/assets/index-Q81MFBxC.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": true, "module": "/assets/root-DfwDd0Zj.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/mermaid-3ZIDBTTL-g3vDTGSb.js", "/assets/arrow-up-right-B9knAxIp.js"], "css": ["/assets/root-CQggqXow.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/home": { "id": "routes/home", "parentId": "root", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/home-BasVp7zv.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/workflow-graph-viewer-VUIB71kS.js", "/assets/mermaid-3ZIDBTTL-g3vDTGSb.js", "/assets/index-STTN0-2V.js"], "css": ["/assets/workflow-graph-viewer-DnlNuQQH.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/run-detail": { "id": "routes/run-detail", "parentId": "root", "path": "run/:runId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/run-detail-BGMnsQO5.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/workflow-graph-viewer-VUIB71kS.js", "/assets/mermaid-3ZIDBTTL-g3vDTGSb.js", "/assets/arrow-up-right-B9knAxIp.js", "/assets/encryption-CLVP4klT.js", "/assets/index-STTN0-2V.js"], "css": ["/assets/run-detail-CWoGxu_0.css", "/assets/workflow-graph-viewer-DnlNuQQH.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.rpc": { "id": "routes/api.rpc", "parentId": "root", "path": "api/rpc", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.rpc-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.stream.$streamId": { "id": "routes/api.stream.$streamId", "parentId": "root", "path": "api/stream/:streamId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.stream._streamId-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 } }, "url": "/assets/manifest-47657566.js", "version": "47657566", "sri": void 0 };
159152
+ const serverManifest = { "entry": { "module": "/assets/entry.client-Q4eUIqMI.js", "imports": ["/assets/index-Q81MFBxC.js"], "css": [] }, "routes": { "root": { "id": "root", "parentId": void 0, "path": "", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": true, "module": "/assets/root-BPK1T9Ck.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/mermaid-3ZIDBTTL-C_EWPx9a.js", "/assets/arrow-up-right-Dv3gGqIf.js"], "css": ["/assets/root-15oK726f.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/home": { "id": "routes/home", "parentId": "root", "path": void 0, "index": true, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/home-0OfTSXd1.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/workflow-graph-viewer-DrfqsDRu.js", "/assets/mermaid-3ZIDBTTL-C_EWPx9a.js", "/assets/index-STTN0-2V.js"], "css": ["/assets/workflow-graph-viewer-DnlNuQQH.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/run-detail": { "id": "routes/run-detail", "parentId": "root", "path": "run/:runId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": false, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": true, "hasErrorBoundary": false, "module": "/assets/run-detail-CrqNzQ_y.js", "imports": ["/assets/index-Q81MFBxC.js", "/assets/workflow-graph-viewer-DrfqsDRu.js", "/assets/mermaid-3ZIDBTTL-C_EWPx9a.js", "/assets/arrow-up-right-Dv3gGqIf.js", "/assets/encryption-CLVP4klT.js", "/assets/index-STTN0-2V.js"], "css": ["/assets/run-detail-CWoGxu_0.css", "/assets/workflow-graph-viewer-DnlNuQQH.css", "/assets/mermaid-3ZIDBTTL-DDxQhcP4.css"], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.rpc": { "id": "routes/api.rpc", "parentId": "root", "path": "api/rpc", "index": void 0, "caseSensitive": void 0, "hasAction": true, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.rpc-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 }, "routes/api.stream.$streamId": { "id": "routes/api.stream.$streamId", "parentId": "root", "path": "api/stream/:streamId", "index": void 0, "caseSensitive": void 0, "hasAction": false, "hasLoader": true, "hasClientAction": false, "hasClientLoader": false, "hasClientMiddleware": false, "hasDefaultExport": false, "hasErrorBoundary": false, "module": "/assets/api.stream._streamId-l0sNRNKZ.js", "imports": [], "css": [], "clientActionModule": void 0, "clientLoaderModule": void 0, "clientMiddlewareModule": void 0, "hydrateFallbackModule": void 0 } }, "url": "/assets/manifest-485c4078.js", "version": "485c4078", "sri": void 0 };
158643
159153
  const assetsBuildDirectory = "build/client";
158644
159154
  const basename = "/";
158645
159155
  const future = { "unstable_optimizeDeps": false, "unstable_subResourceIntegrity": false, "unstable_trailingSlashAwareDataRequests": false, "unstable_previewServerPrerendering": false, "v8_middleware": false, "v8_splitRouteModules": false, "v8_viteEnvironmentApi": false };
@@ -158708,7 +159218,7 @@ const serverBuild = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineP
158708
159218
  ssr
158709
159219
  }, Symbol.toStringTag, { value: "Module" }));
158710
159220
  export {
158711
- WAIT_EVENT_TYPES as $,
159221
+ ValidQueueName as $,
158712
159222
  ATTRIBUTE_KEY_MAX_LENGTH as A,
158713
159223
  BaseEventSchema as B,
158714
159224
  CHILD_ENTITY_CREATION_EVENT_TYPES as C,
@@ -158728,56 +159238,57 @@ export {
158728
159238
  QueuePayloadSchema as Q,
158729
159239
  RESERVED_ATTRIBUTE_KEY_PREFIX as R,
158730
159240
  SPEC_VERSION_CURRENT as S,
158731
- TERMINAL_RUN_EVENT_TYPES as T,
158732
- TERMINAL_STEP_EVENT_TYPES as U,
158733
- TERMINAL_STEP_STATUSES as V,
158734
- TERMINAL_WORKFLOW_RUN_STATUSES as W,
158735
- TerminalRunEventTypeSchema as X,
158736
- TerminalStepStatusSchema as Y,
158737
- TerminalWorkflowRunStatusSchema as Z,
158738
- ValidQueueName as _,
159241
+ StructuredErrorSchema as T,
159242
+ TERMINAL_RUN_EVENT_TYPES as U,
159243
+ TERMINAL_STEP_EVENT_TYPES as V,
159244
+ TERMINAL_STEP_STATUSES as W,
159245
+ TERMINAL_WORKFLOW_RUN_STATUSES as X,
159246
+ TerminalRunEventTypeSchema as Y,
159247
+ TerminalStepStatusSchema as Z,
159248
+ TerminalWorkflowRunStatusSchema as _,
158739
159249
  ATTRIBUTE_MAX_PER_RUN as a,
158740
- WaitSchema as a0,
158741
- WaitStatusSchema as a1,
158742
- WorkflowInvokePayloadSchema as a2,
158743
- WorkflowRunBaseSchema as a3,
158744
- WorkflowRunSchema as a4,
158745
- WorkflowRunStatusSchema as a5,
158746
- applyAttributeChanges as a6,
158747
- envNumber as a7,
158748
- getEventDataPayloadField as a8,
158749
- getEventDataRefFields as a9,
158750
- Qe as aA,
158751
- registerZstdDecoder as aB,
158752
- requireTokenUtil as aC,
158753
- requireTokenError as aD,
158754
- serverBuild as aE,
158755
- getQueueTopicPrefix as aa,
158756
- isChildEntityCreationEvent as ab,
158757
- isChildEntityCreationEventType as ac,
158758
- isHookEventRequiringExistence as ad,
158759
- isHookLifecycleEventType as ae,
158760
- isLegacySpecVersion as af,
158761
- isStepEventType as ag,
158762
- isTerminalRunEventType as ah,
158763
- isTerminalStepEventType as ai,
158764
- isTerminalStepStatus as aj,
158765
- isTerminalWorkflowRunStatus as ak,
158766
- isWaitEventType as al,
158767
- parseQueueName as am,
158768
- reenqueueActiveRuns as an,
158769
- requiresNewerWorld as ao,
158770
- resolveQueueNamespace as ap,
158771
- stripEventDataRefs as aq,
158772
- ulidToDate as ar,
158773
- validateAttributeChanges as as,
158774
- validateAttributeKey as at,
158775
- validateAttributeValue as au,
158776
- validateUlidTimestamp as av,
158777
- workflowRunIdSchema as aw,
158778
- R as ax,
158779
- Ks as ay,
158780
- jsxRuntimeExports as az,
159250
+ WAIT_EVENT_TYPES as a0,
159251
+ WaitSchema as a1,
159252
+ WaitStatusSchema as a2,
159253
+ WorkflowInvokePayloadSchema as a3,
159254
+ WorkflowRunBaseSchema as a4,
159255
+ WorkflowRunSchema as a5,
159256
+ WorkflowRunStatusSchema as a6,
159257
+ applyAttributeChanges as a7,
159258
+ envNumber as a8,
159259
+ getEventDataPayloadField as a9,
159260
+ jsxRuntimeExports as aA,
159261
+ Qe as aB,
159262
+ registerZstdDecoder as aC,
159263
+ requireTokenUtil as aD,
159264
+ requireTokenError as aE,
159265
+ serverBuild as aF,
159266
+ getEventDataRefFields as aa,
159267
+ getQueueTopicPrefix as ab,
159268
+ isChildEntityCreationEvent as ac,
159269
+ isChildEntityCreationEventType as ad,
159270
+ isHookEventRequiringExistence as ae,
159271
+ isHookLifecycleEventType as af,
159272
+ isLegacySpecVersion as ag,
159273
+ isStepEventType as ah,
159274
+ isTerminalRunEventType as ai,
159275
+ isTerminalStepEventType as aj,
159276
+ isTerminalStepStatus as ak,
159277
+ isTerminalWorkflowRunStatus as al,
159278
+ isWaitEventType as am,
159279
+ parseQueueName as an,
159280
+ reenqueueActiveRuns as ao,
159281
+ requiresNewerWorld as ap,
159282
+ resolveQueueNamespace as aq,
159283
+ stripEventDataRefs as ar,
159284
+ ulidToDate as as,
159285
+ validateAttributeChanges as at,
159286
+ validateAttributeKey as au,
159287
+ validateAttributeValue as av,
159288
+ validateUlidTimestamp as aw,
159289
+ workflowRunIdSchema as ax,
159290
+ R as ay,
159291
+ Ks as az,
158781
159292
  ATTRIBUTE_VALUE_MAX_BYTES as b,
158782
159293
  AnalyticsAttributeKeySchema as c,
158783
159294
  AnalyticsEventSchema as d,