@workflow/web 5.0.0-beta.24 → 5.0.0-beta.26

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 (25) hide show
  1. package/build/client/assets/{highlighted-body-B3W2YXNL-pQbU-Oll.js → highlighted-body-B3W2YXNL-QrddlyZu.js} +1 -1
  2. package/build/client/assets/{home-Dz43xne_.js → home-BNApVOct.js} +2 -2
  3. package/build/client/assets/{manifest-e1cf8511.js → manifest-379f050f.js} +1 -1
  4. package/build/client/assets/{mermaid-3ZIDBTTL-C_xy8SxZ.js → mermaid-3ZIDBTTL-Cg-Mp5Kj.js} +218 -100
  5. package/build/client/assets/{root-BlFmfRST.js → root-BsPxYsbK.js} +1 -1
  6. package/build/client/assets/root-F_dqJDC7.css +1 -0
  7. package/build/client/assets/{run-detail-BzGs1YV_.js → run-detail-sr7StYc6.js} +359 -355
  8. package/build/client/assets/server-build-DVBDkRDS.css +1 -0
  9. package/build/client/assets/{workflow-graph-viewer-BlDVZ5AU.js → workflow-graph-viewer-CcCwLmnF.js} +1 -1
  10. package/build/client/assets/{zstd-browser-decoder-Biv4GTD9.js → zstd-browser-decoder-OOeWOMJw.js} +1 -1
  11. package/build/server/assets/{app-1p4IhK-Q.js → app-DQ35jFT1.js} +5 -1
  12. package/build/server/assets/{highlighted-body-B3W2YXNL-BlH6gm7c.js → highlighted-body-B3W2YXNL-DUlvgLoF.js} +6 -2
  13. package/build/server/assets/{index-C7C6cDW5.js → index-BafExO0s.js} +4 -0
  14. package/build/server/assets/{index-BOfd00Ok.js → index-BgRt1-Z6.js} +7 -3
  15. package/build/server/assets/{index-B8YoYr9f.js → index-DIXsjgfZ.js} +4 -0
  16. package/build/server/assets/{index-meg9qk8y.js → index-Dq5jTBN4.js} +4 -0
  17. package/build/server/assets/{mermaid-3ZIDBTTL-4IS2FONM.js → mermaid-3ZIDBTTL-BdnRYE9a.js} +6 -2
  18. package/build/server/assets/{server-build-CpnmV4F1.js → server-build-0CazaFkH.js} +1290 -797
  19. package/build/server/assets/{token-fPsafoXW.js → token-DK_R23fr.js} +6 -2
  20. package/build/server/assets/{token-util-MV-dKCwg.js → token-util-CaJAmsYa.js} +6 -2
  21. package/build/server/assets/{zstd-browser-decoder-embi2ab_.js → zstd-browser-decoder-pCjqxVHM.js} +7 -3
  22. package/build/server/index.js +5 -1
  23. package/package.json +5 -5
  24. package/build/client/assets/root-61NXpLSs.css +0 -1
  25. package/build/client/assets/server-build-B8TvrR_Z.css +0 -1
@@ -14,7 +14,11 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
14
14
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
15
15
  var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
16
16
  var _a2, _b, _c, _d, _listeners, _onabort, _reader, _root, _hasMagic, _uflag, _parts, _parent, _parentIndex, _negs, _filledNegs, _options, _toString, _emptyExt, _AST_instances, fillNegs_fn, _AST_static, parseAST_fn, canAdoptWithSpace_fn, canAdopt_fn, canAdoptType_fn, adoptWithSpace_fn, adopt_fn, canUsurpType_fn, canUsurp_fn, usurp_fn, flatten_fn, partsToRegExp_fn, parseGlob_fn, _Minimatch_instances, matchGlobstar_fn, matchGlobStarBodySections_fn, matchOne_fn, _worldPromise, _Run_instances, lazyWorldPromise_get, _encryptionKeyPromise, _resilientStart, getEncryptionKey_fn, getEncryptionKeyLazily_fn, pollReturnValue_fn;
17
- import { a as requireReact, S as ServerRouter, c as createReadableStreamFromReadable, r as reactExports, g as getDefaultExportFromCjs, R as React, b as ReactExports, w as withComponentProps, d as withErrorBoundaryProps, M as Meta, L as Links, e as ScrollRestoration, f as Scripts, O as Outlet, u as useNavigate, h as useSearchParams, i as Link$1, j as useRouteError, k as isRouteErrorResponse, l as useLocation, m as useParams } from "./app-1p4IhK-Q.js";
17
+ import { createRequire as __wkfCreateRequire } from "node:module";
18
+ if (typeof require === "undefined") {
19
+ globalThis.require = __wkfCreateRequire(import.meta.url);
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-DQ35jFT1.js";
18
22
  import require$$0$4, { PassThrough } from "node:stream";
19
23
  import require$$0 from "util";
20
24
  import require$$1 from "crypto";
@@ -30043,6 +30047,54 @@ const getDefaultConfig = () => {
30043
30047
  orderSensitiveModifiers: ["*", "**", "after", "backdrop", "before", "details-content", "file", "first-letter", "first-line", "marker", "placeholder", "selection"]
30044
30048
  };
30045
30049
  };
30050
+ const mergeConfigs = (baseConfig, {
30051
+ cacheSize,
30052
+ prefix,
30053
+ experimentalParseClassName,
30054
+ extend: extend2 = {},
30055
+ override = {}
30056
+ }) => {
30057
+ overrideProperty(baseConfig, "cacheSize", cacheSize);
30058
+ overrideProperty(baseConfig, "prefix", prefix);
30059
+ overrideProperty(baseConfig, "experimentalParseClassName", experimentalParseClassName);
30060
+ overrideConfigProperties(baseConfig.theme, override.theme);
30061
+ overrideConfigProperties(baseConfig.classGroups, override.classGroups);
30062
+ overrideConfigProperties(baseConfig.conflictingClassGroups, override.conflictingClassGroups);
30063
+ overrideConfigProperties(baseConfig.conflictingClassGroupModifiers, override.conflictingClassGroupModifiers);
30064
+ overrideProperty(baseConfig, "orderSensitiveModifiers", override.orderSensitiveModifiers);
30065
+ mergeConfigProperties(baseConfig.theme, extend2.theme);
30066
+ mergeConfigProperties(baseConfig.classGroups, extend2.classGroups);
30067
+ mergeConfigProperties(baseConfig.conflictingClassGroups, extend2.conflictingClassGroups);
30068
+ mergeConfigProperties(baseConfig.conflictingClassGroupModifiers, extend2.conflictingClassGroupModifiers);
30069
+ mergeArrayProperties(baseConfig, extend2, "orderSensitiveModifiers");
30070
+ return baseConfig;
30071
+ };
30072
+ const overrideProperty = (baseObject, overrideKey, overrideValue) => {
30073
+ if (overrideValue !== void 0) {
30074
+ baseObject[overrideKey] = overrideValue;
30075
+ }
30076
+ };
30077
+ const overrideConfigProperties = (baseObject, overrideObject) => {
30078
+ if (overrideObject) {
30079
+ for (const key in overrideObject) {
30080
+ overrideProperty(baseObject, key, overrideObject[key]);
30081
+ }
30082
+ }
30083
+ };
30084
+ const mergeConfigProperties = (baseObject, mergeObject) => {
30085
+ if (mergeObject) {
30086
+ for (const key in mergeObject) {
30087
+ mergeArrayProperties(baseObject, mergeObject, key);
30088
+ }
30089
+ }
30090
+ };
30091
+ const mergeArrayProperties = (baseObject, mergeObject, key) => {
30092
+ const mergeValue = mergeObject[key];
30093
+ if (mergeValue !== void 0) {
30094
+ baseObject[key] = baseObject[key] ? baseObject[key].concat(mergeValue) : mergeValue;
30095
+ }
30096
+ };
30097
+ const extendTailwindMerge = (configExtension, ...createConfig) => typeof configExtension === "function" ? createTailwindMerge(getDefaultConfig, configExtension, ...createConfig) : createTailwindMerge(() => mergeConfigs(getDefaultConfig(), configExtension), ...createConfig);
30046
30098
  const twMerge = /* @__PURE__ */ createTailwindMerge(getDefaultConfig);
30047
30099
  function parseName(tag, name2) {
30048
30100
  if (typeof name2 !== "string") {
@@ -30707,102 +30759,78 @@ const __iconNode = [
30707
30759
  ["line", { x1: "8", x2: "14", y1: "11", y2: "11", key: "durymu" }]
30708
30760
  ];
30709
30761
  const ZoomOut = createLucideIcon("zoom-out", __iconNode);
30710
- function cn$4(...inputs) {
30711
- return twMerge(clsx(inputs));
30712
- }
30713
- const MS_IN_SECOND = 1e3;
30714
- const MS_IN_MINUTE = 60 * MS_IN_SECOND;
30715
- const MS_IN_HOUR = 60 * MS_IN_MINUTE;
30716
- const MS_IN_DAY = 24 * MS_IN_HOUR;
30717
- function formatDuration(ms2, compact = false) {
30718
- if (ms2 === 0) {
30719
- return "0s";
30720
- }
30721
- if (ms2 < MS_IN_SECOND) {
30722
- const roundedMs2 = Math.round(ms2);
30723
- return roundedMs2 < MS_IN_SECOND ? `${roundedMs2}ms` : "1s";
30724
- }
30725
- const roundedMs = Math.round(ms2 / MS_IN_SECOND) * MS_IN_SECOND;
30726
- if (roundedMs < MS_IN_MINUTE) {
30727
- return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;
30728
- }
30729
- if (compact) {
30730
- if (roundedMs < MS_IN_HOUR) {
30731
- const m3 = Math.floor(roundedMs / MS_IN_MINUTE);
30732
- const s2 = Math.floor(roundedMs % MS_IN_MINUTE / MS_IN_SECOND);
30733
- return s2 > 0 ? `${m3}m ${s2}s` : `${m3}m`;
30734
- }
30735
- const h2 = Math.floor(roundedMs / MS_IN_HOUR);
30736
- const m2 = Math.floor(roundedMs % MS_IN_HOUR / MS_IN_MINUTE);
30737
- return m2 > 0 ? `${h2}h ${m2}m` : `${h2}h`;
30738
- }
30739
- const days = Math.floor(roundedMs / MS_IN_DAY);
30740
- const hours = Math.floor(roundedMs % MS_IN_DAY / MS_IN_HOUR);
30741
- const minutes = Math.floor(roundedMs % MS_IN_HOUR / MS_IN_MINUTE);
30742
- const seconds = Math.floor(roundedMs % MS_IN_MINUTE / MS_IN_SECOND);
30743
- const parts = [];
30744
- if (days > 0) {
30745
- parts.push(`${days}d`);
30746
- }
30747
- if (hours > 0) {
30748
- parts.push(`${hours}h`);
30749
- }
30750
- if (minutes > 0) {
30751
- parts.push(`${minutes}m`);
30752
- }
30753
- parts.push(`${seconds}s`);
30754
- return parts.join(" ");
30755
- }
30756
- const preciseSecondsFormatter = new Intl.NumberFormat(void 0, {
30757
- minimumFractionDigits: 2,
30758
- maximumFractionDigits: 2
30759
- });
30760
- function formatDurationPrecise(ms2) {
30761
- if (ms2 === 0) {
30762
- return "0s";
30763
- }
30764
- if (ms2 < MS_IN_SECOND) {
30765
- const roundedMs = Math.round(ms2);
30766
- if (roundedMs < MS_IN_SECOND) {
30767
- return `${roundedMs}ms`;
30762
+ const twMergeConfig = {
30763
+ extend: {
30764
+ classGroups: {
30765
+ "text-heading": [
30766
+ {
30767
+ "text-heading": [
30768
+ "72",
30769
+ "64",
30770
+ "56",
30771
+ "48",
30772
+ "40",
30773
+ "32",
30774
+ "24",
30775
+ "20",
30776
+ "16",
30777
+ "14"
30778
+ ]
30779
+ }
30780
+ ],
30781
+ "text-button": [
30782
+ {
30783
+ "text-button": ["16", "14", "12"]
30784
+ }
30785
+ ],
30786
+ "text-label": [
30787
+ {
30788
+ "text-label": [
30789
+ "20",
30790
+ "18",
30791
+ "16",
30792
+ "14",
30793
+ "14-mono",
30794
+ "13",
30795
+ "13-mono",
30796
+ "12",
30797
+ "12-mono"
30798
+ ]
30799
+ }
30800
+ ],
30801
+ "text-copy": [
30802
+ {
30803
+ "text-copy": ["24", "20", "18", "16", "14", "13", "13-mono"]
30804
+ }
30805
+ ],
30806
+ material: [
30807
+ {
30808
+ material: [
30809
+ "base",
30810
+ "small",
30811
+ "medium",
30812
+ "large",
30813
+ "tooltip",
30814
+ "menu",
30815
+ "modal",
30816
+ "fullscreen"
30817
+ ]
30818
+ }
30819
+ ]
30820
+ },
30821
+ // Make each category conflict with itself, so e.g. text-heading-32 overrides text-heading-24
30822
+ conflictingClassGroups: {
30823
+ "text-heading": ["text-heading"],
30824
+ "text-button": ["text-button"],
30825
+ "text-label": ["text-label"],
30826
+ "text-copy": ["text-copy"],
30827
+ material: ["material"]
30768
30828
  }
30769
30829
  }
30770
- const normalizedMs = Math.round(ms2 / 10) * 10;
30771
- if (normalizedMs < MS_IN_MINUTE) {
30772
- return `${preciseSecondsFormatter.format(normalizedMs / MS_IN_SECOND)}s`;
30773
- }
30774
- const days = Math.floor(normalizedMs / MS_IN_DAY);
30775
- const hours = Math.floor(normalizedMs % MS_IN_DAY / MS_IN_HOUR);
30776
- const minutes = Math.floor(normalizedMs % MS_IN_HOUR / MS_IN_MINUTE);
30777
- const seconds = normalizedMs % MS_IN_MINUTE / MS_IN_SECOND;
30778
- const parts = [];
30779
- if (days > 0) {
30780
- parts.push(`${days}d`);
30781
- }
30782
- if (hours > 0) {
30783
- parts.push(`${hours}h`);
30784
- }
30785
- if (minutes > 0) {
30786
- parts.push(`${minutes}m`);
30787
- }
30788
- parts.push(`${preciseSecondsFormatter.format(seconds)}s`);
30789
- return parts.join(" ");
30790
- }
30791
- function isDoStreamStep(stepName) {
30792
- return stepName.endsWith("//doStreamStep");
30793
- }
30794
- function extractConversation(stepInput) {
30795
- if (!Array.isArray(stepInput) || stepInput.length === 0) {
30796
- return null;
30797
- }
30798
- const firstArg = stepInput[0];
30799
- if (!Array.isArray(firstArg)) {
30800
- return null;
30801
- }
30802
- if (!firstArg.every((msg) => msg && typeof msg === "object" && "role" in msg)) {
30803
- return null;
30804
- }
30805
- return firstArg;
30830
+ };
30831
+ const customTwMerge = extendTailwindMerge(twMergeConfig);
30832
+ function cn$4(...classes) {
30833
+ return customTwMerge(clsx(...classes));
30806
30834
  }
30807
30835
  function ErrorCard({ title, className, details = "Unknown error" }) {
30808
30836
  const [isExpanded, setIsExpanded] = reactExports.useState(false);
@@ -49884,7 +49912,7 @@ function replaceEncryptedAndExpiredWithMarkers(resource) {
49884
49912
  async function hydrateResourceIOWithKey(resource, key) {
49885
49913
  const { hydrateDataWithKey: hydrateDataWithKey2 } = await Promise.resolve().then(() => serializationFormat);
49886
49914
  const { importKey: importKey2 } = await Promise.resolve().then(() => encryption);
49887
- const { ensureZstdDecoderRegistered } = await import("./zstd-browser-decoder-embi2ab_.js");
49915
+ const { ensureZstdDecoderRegistered } = await import("./zstd-browser-decoder-pCjqxVHM.js");
49888
49916
  ensureZstdDecoderRegistered();
49889
49917
  const cryptoKey = await importKey2(key);
49890
49918
  const revivers = getRevivers();
@@ -51026,6 +51054,100 @@ const ToastContext = reactExports.createContext(defaultAdapter);
51026
51054
  function useToast() {
51027
51055
  return reactExports.useContext(ToastContext);
51028
51056
  }
51057
+ const MS_IN_SECOND = 1e3;
51058
+ const MS_IN_MINUTE = 60 * MS_IN_SECOND;
51059
+ const MS_IN_HOUR = 60 * MS_IN_MINUTE;
51060
+ const MS_IN_DAY = 24 * MS_IN_HOUR;
51061
+ function formatDuration(ms2, compact = false) {
51062
+ if (ms2 === 0) {
51063
+ return "0s";
51064
+ }
51065
+ if (ms2 < MS_IN_SECOND) {
51066
+ const roundedMs2 = Math.round(ms2);
51067
+ return roundedMs2 < MS_IN_SECOND ? `${roundedMs2}ms` : "1s";
51068
+ }
51069
+ const roundedMs = Math.round(ms2 / MS_IN_SECOND) * MS_IN_SECOND;
51070
+ if (roundedMs < MS_IN_MINUTE) {
51071
+ return `${Math.floor(roundedMs / MS_IN_SECOND)}s`;
51072
+ }
51073
+ if (compact) {
51074
+ if (roundedMs < MS_IN_HOUR) {
51075
+ const m3 = Math.floor(roundedMs / MS_IN_MINUTE);
51076
+ const s2 = Math.floor(roundedMs % MS_IN_MINUTE / MS_IN_SECOND);
51077
+ return s2 > 0 ? `${m3}m ${s2}s` : `${m3}m`;
51078
+ }
51079
+ const h2 = Math.floor(roundedMs / MS_IN_HOUR);
51080
+ const m2 = Math.floor(roundedMs % MS_IN_HOUR / MS_IN_MINUTE);
51081
+ return m2 > 0 ? `${h2}h ${m2}m` : `${h2}h`;
51082
+ }
51083
+ const days = Math.floor(roundedMs / MS_IN_DAY);
51084
+ const hours = Math.floor(roundedMs % MS_IN_DAY / MS_IN_HOUR);
51085
+ const minutes = Math.floor(roundedMs % MS_IN_HOUR / MS_IN_MINUTE);
51086
+ const seconds = Math.floor(roundedMs % MS_IN_MINUTE / MS_IN_SECOND);
51087
+ const parts = [];
51088
+ if (days > 0) {
51089
+ parts.push(`${days}d`);
51090
+ }
51091
+ if (hours > 0) {
51092
+ parts.push(`${hours}h`);
51093
+ }
51094
+ if (minutes > 0) {
51095
+ parts.push(`${minutes}m`);
51096
+ }
51097
+ parts.push(`${seconds}s`);
51098
+ return parts.join(" ");
51099
+ }
51100
+ const preciseSecondsFormatter = new Intl.NumberFormat(void 0, {
51101
+ minimumFractionDigits: 2,
51102
+ maximumFractionDigits: 2
51103
+ });
51104
+ function formatDurationPrecise(ms2) {
51105
+ if (ms2 === 0) {
51106
+ return "0s";
51107
+ }
51108
+ if (ms2 < MS_IN_SECOND) {
51109
+ const roundedMs = Math.round(ms2);
51110
+ if (roundedMs < MS_IN_SECOND) {
51111
+ return `${roundedMs}ms`;
51112
+ }
51113
+ }
51114
+ const normalizedMs = Math.round(ms2 / 10) * 10;
51115
+ if (normalizedMs < MS_IN_MINUTE) {
51116
+ return `${preciseSecondsFormatter.format(normalizedMs / MS_IN_SECOND)}s`;
51117
+ }
51118
+ const days = Math.floor(normalizedMs / MS_IN_DAY);
51119
+ const hours = Math.floor(normalizedMs % MS_IN_DAY / MS_IN_HOUR);
51120
+ const minutes = Math.floor(normalizedMs % MS_IN_HOUR / MS_IN_MINUTE);
51121
+ const seconds = normalizedMs % MS_IN_MINUTE / MS_IN_SECOND;
51122
+ const parts = [];
51123
+ if (days > 0) {
51124
+ parts.push(`${days}d`);
51125
+ }
51126
+ if (hours > 0) {
51127
+ parts.push(`${hours}h`);
51128
+ }
51129
+ if (minutes > 0) {
51130
+ parts.push(`${minutes}m`);
51131
+ }
51132
+ parts.push(`${preciseSecondsFormatter.format(seconds)}s`);
51133
+ return parts.join(" ");
51134
+ }
51135
+ function isDoStreamStep(stepName) {
51136
+ return stepName.endsWith("//doStreamStep");
51137
+ }
51138
+ function extractConversation(stepInput) {
51139
+ if (!Array.isArray(stepInput) || stepInput.length === 0) {
51140
+ return null;
51141
+ }
51142
+ const firstArg = stepInput[0];
51143
+ if (!Array.isArray(firstArg)) {
51144
+ return null;
51145
+ }
51146
+ if (!firstArg.every((msg) => msg && typeof msg === "object" && "role" in msg)) {
51147
+ return null;
51148
+ }
51149
+ return firstArg;
51150
+ }
51029
51151
  function CopyButton({ copyText, ariaLabel, className }) {
51030
51152
  const [copied, setCopied] = reactExports.useState(false);
51031
51153
  const timeoutRef = reactExports.useRef(null);
@@ -52777,6 +52899,18 @@ function formatEventTime(date2) {
52777
52899
  hour12: false
52778
52900
  }) + "." + date2.getMilliseconds().toString().padStart(3, "0");
52779
52901
  }
52902
+ function parseEventDate(value) {
52903
+ if (value == null)
52904
+ return null;
52905
+ const date2 = value instanceof Date ? value : new Date(String(value));
52906
+ return Number.isNaN(date2.getTime()) ? null : date2;
52907
+ }
52908
+ function getEffectiveEventDate$1(event) {
52909
+ return parseEventDate(event.occurredAt) ?? new Date(event.createdAt);
52910
+ }
52911
+ function getEffectiveEventTime(event) {
52912
+ return getEffectiveEventDate$1(event).getTime();
52913
+ }
52780
52914
  function formatEventType(eventType) {
52781
52915
  return eventType.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
52782
52916
  }
@@ -52817,13 +52951,13 @@ function buildNameMaps(events2, run2) {
52817
52951
  return { correlationNameMap, workflowName };
52818
52952
  }
52819
52953
  function buildDurationMap(events2) {
52820
- const chronological = [...events2].sort((a2, b2) => new Date(a2.createdAt).getTime() - new Date(b2.createdAt).getTime());
52954
+ const chronological = [...events2].sort((a2, b2) => getEffectiveEventTime(a2) - getEffectiveEventTime(b2));
52821
52955
  const createdTimes = /* @__PURE__ */ new Map();
52822
52956
  const firstStartedTimes = /* @__PURE__ */ new Map();
52823
52957
  const startedTimes = /* @__PURE__ */ new Map();
52824
52958
  const durations = /* @__PURE__ */ new Map();
52825
52959
  for (const event of chronological) {
52826
- const ts = new Date(event.createdAt).getTime();
52960
+ const ts = getEffectiveEventTime(event);
52827
52961
  const key = event.correlationId ?? "__run__";
52828
52962
  const type = event.eventType;
52829
52963
  if (type === "step_created" || type === "run_created") {
@@ -53046,7 +53180,7 @@ const SORT_OPTIONS = [
53046
53180
  { value: "desc", label: "Newest" },
53047
53181
  { value: "asc", label: "Oldest" }
53048
53182
  ];
53049
- function RowsSkeleton() {
53183
+ function RowsSkeleton({ showSeparateEventOccurrenceTimestamps = false }) {
53050
53184
  return jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-hidden", children: Array.from({ length: 16 }, (_2, i) => jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0", style: { height: 40 }, children: [jsxRuntimeExports.jsxs("div", { className: "relative flex-shrink-0 self-stretch flex items-center", style: { width: GUTTER_WIDTH }, children: [jsxRuntimeExports.jsx("div", { style: {
53051
53185
  position: "absolute",
53052
53186
  left: 8,
@@ -53058,9 +53192,9 @@ function RowsSkeleton() {
53058
53192
  height: i % 4 === 0 ? 8 : 6,
53059
53193
  borderRadius: "50%",
53060
53194
  marginLeft: i % 4 === 0 ? 5 : 6
53061
- } })] }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0 flex items-center justify-center", children: jsxRuntimeExports.jsx(Skeleton$2, { className: "w-5 h-5", style: { borderRadius: 4 } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsxs("div", { className: "min-w-0 px-4 flex items-center gap-1.5", style: { flex: "2 1 0%" }, children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "flex-shrink-0", style: { width: 6, height: 6, borderRadius: "50%" } }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "60%" } })] }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "50%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "75%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "75%" } }) })] }, i)) });
53195
+ } })] }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0 flex items-center justify-center", children: jsxRuntimeExports.jsx(Skeleton$2, { className: "w-5 h-5", style: { borderRadius: 4 } }) }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "70%" } }) }), jsxRuntimeExports.jsxs("div", { className: "min-w-0 px-4 flex items-center gap-1.5", style: { flex: "2 1 0%" }, children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "flex-shrink-0", style: { width: 6, height: 6, borderRadius: "50%" } }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "60%" } })] }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "50%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "75%" } }) }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "75%" } }) })] }, i)) });
53062
53196
  }
53063
- function EventRow$1({ event, index: index2, isFirst, isLast, isExpanded, onToggleExpand, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData, onCacheEventData, encryptionKey, onEncryptedDataDetected, suppressGroupDimming = false }) {
53197
+ function EventRow$1({ event, index: index2, isFirst, isLast, isExpanded, onToggleExpand, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData, onCacheEventData, encryptionKey, onEncryptedDataDetected, suppressGroupDimming = false, showSeparateEventOccurrenceTimestamps = false }) {
53064
53198
  const [isLoading, setIsLoading] = reactExports.useState(false);
53065
53199
  const [loadedEventData, setLoadedEventData] = reactExports.useState(cachedEventData);
53066
53200
  const [loadError, setLoadError] = reactExports.useState(null);
@@ -53073,6 +53207,8 @@ function EventRow$1({ event, index: index2, isFirst, isLast, isExpanded, onToggl
53073
53207
  const rowGroupKey = isRunLevel(event.eventType) ? "__run__" : event.correlationId ?? void 0;
53074
53208
  const statusDotColor = getStatusDotColor(event.eventType);
53075
53209
  const createdAt = new Date(event.createdAt);
53210
+ const occurredAt = parseEventDate(event.occurredAt);
53211
+ const displayedCreatedAt = showSeparateEventOccurrenceTimestamps ? createdAt : getEffectiveEventDate$1(event);
53076
53212
  const hasExistingEventData = "eventData" in event && event.eventData != null;
53077
53213
  const isRun = isRunLevel(event.eventType);
53078
53214
  const eventName2 = isRun ? workflowName ?? "-" : event.correlationId ? correlationNameMap.get(event.correlationId) ?? "-" : "-";
@@ -53176,7 +53312,7 @@ function EventRow$1({ event, index: index2, isFirst, isLast, isExpanded, onToggl
53176
53312
  }, children: jsxRuntimeExports.jsx(ChevronRight, { className: "h-3 w-3 transition-transform", style: {
53177
53313
  color: "var(--ds-gray-900)",
53178
53314
  transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)"
53179
- } }) }), jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(TimestampTooltip, { date: createdAt, children: jsxRuntimeExports.jsx("span", { children: formatEventTime(createdAt) }) }) }), jsxRuntimeExports.jsx("div", { className: "font-medium min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5", style: { color: "var(--ds-gray-900)" }, children: [jsxRuntimeExports.jsxs("span", { style: {
53315
+ } }) }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: occurredAt ? jsxRuntimeExports.jsx(TimestampTooltip, { date: occurredAt, children: jsxRuntimeExports.jsx("span", { children: formatEventTime(occurredAt) }) }) : "-" }), jsxRuntimeExports.jsx("div", { className: "tabular-nums min-w-0 px-4", style: { color: "var(--ds-gray-900)", flex: "2 1 0%" }, children: jsxRuntimeExports.jsx(TimestampTooltip, { date: displayedCreatedAt, children: jsxRuntimeExports.jsx("span", { children: formatEventTime(displayedCreatedAt) }) }) }), jsxRuntimeExports.jsx("div", { className: "font-medium min-w-0 px-4", style: { flex: "2 1 0%" }, children: jsxRuntimeExports.jsxs("span", { className: "inline-flex items-center gap-1.5", style: { color: "var(--ds-gray-900)" }, children: [jsxRuntimeExports.jsxs("span", { style: {
53180
53316
  position: "relative",
53181
53317
  display: "inline-flex",
53182
53318
  width: 6,
@@ -53205,7 +53341,7 @@ function EventRow$1({ event, index: index2, isFirst, isLast, isExpanded, onToggl
53205
53341
  color: "var(--ds-red-900)"
53206
53342
  }, children: loadError }) : isLoading || loadedEventData === null && !hasAttemptedLoad && event.correlationId ? jsxRuntimeExports.jsxs("div", { className: "flex flex-col gap-2 p-3", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "75%" } }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "50%" } }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3", style: { width: "60%" } })] }) : jsxRuntimeExports.jsx("div", { className: "p-2 text-xs", style: { color: "var(--ds-gray-900)" }, children: "No data" })] })] })] });
53207
53343
  }
53208
- function EventListViewInner({ events: events2, run: run2, onLoadEventData, hasMoreEvents = false, isLoadingMoreEvents = false, onLoadMoreEvents, encryptionKey, isLoading = false, sortOrder: sortOrderProp, onSortOrderChange, onDecrypt, isDecrypting = false, hasEncryptedData: hasEncryptedDataProp = false, onExactIdSearch }) {
53344
+ function EventListViewInner({ events: events2, run: run2, onLoadEventData, hasMoreEvents = false, isLoadingMoreEvents = false, onLoadMoreEvents, encryptionKey, isLoading = false, sortOrder: sortOrderProp, onSortOrderChange, onDecrypt, isDecrypting = false, hasEncryptedData: hasEncryptedDataProp = false, onExactIdSearch, showSeparateEventOccurrenceTimestamps = false }) {
53209
53345
  const toast2 = useToast();
53210
53346
  const [internalSortOrder, setInternalSortOrder] = reactExports.useState("asc");
53211
53347
  const effectiveSortOrder = sortOrderProp ?? internalSortOrder;
@@ -53231,7 +53367,7 @@ function EventListViewInner({ events: events2, run: run2, onLoadEventData, hasMo
53231
53367
  if (sourceEvents.length === 0)
53232
53368
  return [];
53233
53369
  const dir = effectiveSortOrder === "desc" ? -1 : 1;
53234
- return [...sourceEvents].sort((a2, b2) => dir * (new Date(a2.createdAt).getTime() - new Date(b2.createdAt).getTime()));
53370
+ return [...sourceEvents].sort((a2, b2) => dir * (getEffectiveEventTime(a2) - getEffectiveEventTime(b2)));
53235
53371
  }, [events2, effectiveSortOrder, isExactSearchActive, searchResults]);
53236
53372
  const hasEncryptedInlineData = reactExports.useMemo(() => {
53237
53373
  const sourceEvents = isExactSearchActive ? searchResults : events2;
@@ -53459,14 +53595,14 @@ function EventListViewInner({ events: events2, run: run2, onLoadEventData, hasMo
53459
53595
  borderColor: "var(--ds-gray-alpha-200)",
53460
53596
  color: "var(--ds-gray-900)",
53461
53597
  backgroundColor: "var(--ds-background-100)"
53462
- }, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Time" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Event Type" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Name" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Event ID" })] }), isRefetching || searchLoading ? jsxRuntimeExports.jsx(RowsSkeleton, {}) : sortedEvents2.length === 0 ? jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-sm", style: { color: "var(--ds-gray-700)" }, children: searchNotFound && searchQuery.trim() ? `No events found for ${searchQuery.trim()}` : searchError ? searchError : parsedSearchId && searchQuery.trim() && !onExactIdSearch ? "Exact ID search is unavailable in this view." : "No events found" }) : jsxRuntimeExports.jsx(Yr, { ref: virtuosoRef, totalCount: sortedEvents2.length, overscan: 20, defaultItemHeight: 40, endReached: () => {
53598
+ }, children: [jsxRuntimeExports.jsx("div", { className: "flex-shrink-0", style: { width: GUTTER_WIDTH } }), jsxRuntimeExports.jsx("div", { className: "w-5 flex-shrink-0" }), showSeparateEventOccurrenceTimestamps && jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Occurred" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Created" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Event Type" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "2 1 0%" }, children: "Name" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Correlation ID" }), jsxRuntimeExports.jsx("div", { className: "min-w-0 px-4", style: { flex: "3 1 0%" }, children: "Event ID" })] }), isRefetching || searchLoading ? jsxRuntimeExports.jsx(RowsSkeleton, { showSeparateEventOccurrenceTimestamps }) : sortedEvents2.length === 0 ? jsxRuntimeExports.jsx("div", { className: "flex flex-1 items-center justify-center px-6 text-center text-sm", style: { color: "var(--ds-gray-700)" }, children: searchNotFound && searchQuery.trim() ? `No events found for ${searchQuery.trim()}` : searchError ? searchError : parsedSearchId && searchQuery.trim() && !onExactIdSearch ? "Exact ID search is unavailable in this view." : "No events found" }) : jsxRuntimeExports.jsx(Yr, { ref: virtuosoRef, totalCount: sortedEvents2.length, overscan: 20, defaultItemHeight: 40, endReached: () => {
53463
53599
  if (isExactSearchActive || !hasMoreEvents || isLoadingMoreEvents) {
53464
53600
  return;
53465
53601
  }
53466
53602
  void (onLoadMoreEvents == null ? void 0 : onLoadMoreEvents());
53467
53603
  }, itemContent: (index2) => {
53468
53604
  const ev = sortedEvents2[index2];
53469
- return jsxRuntimeExports.jsx(EventRow$1, { event: ev, index: index2, isFirst: index2 === 0, isLast: index2 === sortedEvents2.length - 1, isExpanded: expandedEventIds.has(ev.eventId), onToggleExpand: toggleEventExpanded, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData: eventDataCacheRef.current.get(ev.eventId) ?? null, onCacheEventData: cacheEventData, encryptionKey, onEncryptedDataDetected: handleEncryptedDataDetected, suppressGroupDimming: isExactSearchActive });
53605
+ return jsxRuntimeExports.jsx(EventRow$1, { event: ev, index: index2, isFirst: index2 === 0, isLast: index2 === sortedEvents2.length - 1, isExpanded: expandedEventIds.has(ev.eventId), onToggleExpand: toggleEventExpanded, activeGroupKey, selectedGroupKey, selectedGroupRange, correlationNameMap, workflowName, durationMap, onSelectGroup, onHoverGroup, onLoadEventData, cachedEventData: eventDataCacheRef.current.get(ev.eventId) ?? null, onCacheEventData: cacheEventData, encryptionKey, onEncryptedDataDetected: handleEncryptedDataDetected, suppressGroupDimming: isExactSearchActive, showSeparateEventOccurrenceTimestamps });
53470
53606
  }, style: { flex: 1, minHeight: 0 } }), jsxRuntimeExports.jsxs("div", { className: "relative flex-shrink-0 flex items-center h-10 border-t px-4 text-xs", style: {
53471
53607
  borderColor: "var(--ds-gray-alpha-200)",
53472
53608
  color: "var(--ds-gray-900)",
@@ -53728,6 +53864,22 @@ function HookResolveModalWrapper({ hookActions }) {
53728
53864
  const { selectedHook, closeResolveModal, handleResolve, isResolving } = hookActions;
53729
53865
  return jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: selectedHook !== null, onClose: closeResolveModal, onSubmit: handleResolve, isSubmitting: isResolving });
53730
53866
  }
53867
+ const COL_TEMPLATE = "340px 1px minmax(50px, 1fr)";
53868
+ const ROWS = [
53869
+ { id: "r0", name: 62, off: 0, bar: 72 },
53870
+ { id: "r1", name: 78, off: 6, bar: 48 },
53871
+ { id: "r2", name: 50, off: 10, bar: 55 },
53872
+ { id: "r3", name: 84, off: 18, bar: 30 },
53873
+ { id: "r4", name: 45, off: 18, bar: 42 },
53874
+ { id: "r5", name: 66, off: 34, bar: 38 },
53875
+ { id: "r6", name: 55, off: 41, bar: 25 },
53876
+ { id: "r7", name: 40, off: 50, bar: 30 }
53877
+ ];
53878
+ const HEADER_MARKERS = ["m0", "m1", "m2", "m3"];
53879
+ const HeaderDivider = () => jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }) });
53880
+ function TraceViewerSkeleton() {
53881
+ return jsxRuntimeExports.jsxs("output", { "aria-busy": "true", "aria-label": "Loading trace", className: "flex flex-col w-full h-full min-h-0 bg-background-100", children: [jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Loading trace…" }), jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsxs("div", { className: "h-10 min-h-10 flex items-center border-b border-gray-alpha-400 pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "w-3.5 h-3.5 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5 w-40" })] }), jsxRuntimeExports.jsx(HeaderDivider, {}), jsxRuntimeExports.jsx("div", { className: "h-10 min-h-10 flex items-end border-b border-gray-alpha-400 px-4 pb-1 gap-2", children: jsxRuntimeExports.jsx("div", { className: "relative flex-1 flex items-end justify-between", children: HEADER_MARKERS.map((id2) => jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5 w-9" }, id2)) }) })] }), jsxRuntimeExports.jsxs("div", { className: "grid flex-1 min-h-0 overflow-hidden", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx("ul", { className: "block divide-y divide-gray-alpha-400 border-b border-gray-alpha-400", children: ROWS.map((row) => jsxRuntimeExports.jsxs("li", { className: "h-10 flex items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "w-4 h-4 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5", style: { width: `${row.name}%` } })] }), jsxRuntimeExports.jsx(Skeleton$2, { className: "ml-2 h-3.5 w-10 shrink-0" })] }, row.id)) }) }), jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }), jsxRuntimeExports.jsx("div", { className: "relative min-h-0", children: ROWS.map((row) => jsxRuntimeExports.jsx("div", { className: "relative h-10", children: jsxRuntimeExports.jsx("div", { className: "absolute inset-x-4 inset-y-0", children: jsxRuntimeExports.jsx(Skeleton$2, { className: "absolute top-1/2 -translate-y-1/2 h-6 rounded-[0.25rem]", style: { left: `${row.off}%`, width: `${row.bar}%` } }) }) }, row.id)) })] })] });
53882
+ }
53731
53883
  function shouldShowVerticalLine(eventType) {
53732
53884
  if (eventType === "hook_created" || eventType === "hook_received" || eventType === "hook_disposed") {
53733
53885
  return true;
@@ -53783,24 +53935,17 @@ const MARKER_EVENT_TYPES = /* @__PURE__ */ new Set([
53783
53935
  "wait_completed",
53784
53936
  "attr_set"
53785
53937
  ]);
53786
- const findEventByType = (events2, eventTypes) => {
53787
- for (const eventType of eventTypes) {
53788
- const event = events2.find((e) => e.eventType === eventType);
53789
- if (event)
53790
- return event;
53791
- }
53792
- return void 0;
53793
- };
53794
- const withOccurredAt = (entity, occurredAt) => {
53795
- if (!occurredAt || entity.occurredAt != null) {
53796
- return entity;
53797
- }
53798
- return { ...entity, occurredAt };
53938
+ const getEventTimestamp = (event) => {
53939
+ const value = (event == null ? void 0 : event.occurredAt) ?? (event == null ? void 0 : event.createdAt);
53940
+ if (!value)
53941
+ return void 0;
53942
+ const date2 = value instanceof Date ? value : new Date(value);
53943
+ return Number.isNaN(date2.getTime()) ? void 0 : date2;
53799
53944
  };
53800
- function convertEventsToSpanEvents(events2, filterTypes = true) {
53945
+ function convertEventsToSpanEvents(events2, filterTypes = true, options = {}) {
53801
53946
  return events2.filter((event) => filterTypes ? MARKER_EVENT_TYPES.has(event.eventType) : true).map((event) => ({
53802
53947
  name: event.eventType,
53803
- timestamp: dateToOtelTime(event.createdAt),
53948
+ timestamp: dateToOtelTime(options.preferOccurredAt ? getEventTimestamp(event) ?? event.createdAt : event.createdAt),
53804
53949
  attributes: {
53805
53950
  eventId: event.eventId,
53806
53951
  correlationId: event.correlationId,
@@ -53817,13 +53962,13 @@ const waitEventsToWaitEntity = (events2) => {
53817
53962
  return null;
53818
53963
  }
53819
53964
  const completedEvent = events2.find((event) => event.eventType === "wait_completed");
53820
- return withOccurredAt({
53965
+ return {
53821
53966
  waitId: startEvent.correlationId,
53822
53967
  runId: startEvent.runId,
53823
- createdAt: startEvent.createdAt,
53968
+ createdAt: getEventTimestamp(startEvent) ?? startEvent.createdAt,
53824
53969
  resumeAt: ((_a3 = startEvent.eventData) == null ? void 0 : _a3.resumeAt) ? new Date(startEvent.eventData.resumeAt) : void 0,
53825
- completedAt: completedEvent == null ? void 0 : completedEvent.createdAt
53826
- }, startEvent.occurredAt);
53970
+ completedAt: getEventTimestamp(completedEvent)
53971
+ };
53827
53972
  };
53828
53973
  function waitToSpan(events2, maxEndTime, fallbackEndTime = maxEndTime) {
53829
53974
  const wait = waitEventsToWaitEntity(events2);
@@ -53879,16 +54024,16 @@ const stepEventsToStepEntity = (events2) => {
53879
54024
  status = "running";
53880
54025
  attempt += 1;
53881
54026
  if (!startedAt)
53882
- startedAt = e.createdAt;
54027
+ startedAt = getEventTimestamp(e) ?? e.createdAt;
53883
54028
  completedAt = void 0;
53884
54029
  break;
53885
54030
  case "step_completed":
53886
54031
  status = "completed";
53887
- completedAt = e.createdAt;
54032
+ completedAt = getEventTimestamp(e) ?? e.createdAt;
53888
54033
  break;
53889
54034
  case "step_failed":
53890
54035
  status = "failed";
53891
- completedAt = e.createdAt;
54036
+ completedAt = getEventTimestamp(e) ?? e.createdAt;
53892
54037
  break;
53893
54038
  case "step_retrying":
53894
54039
  status = "pending";
@@ -53899,19 +54044,18 @@ const stepEventsToStepEntity = (events2) => {
53899
54044
  if (attempt === 0)
53900
54045
  attempt = 1;
53901
54046
  const lastEvent = events2[events2.length - 1];
53902
- const occurrenceEvent = findEventByType(events2, ["step_created", "step_started"]) ?? anchorEvent;
53903
- return withOccurredAt({
54047
+ return {
53904
54048
  stepId: anchorEvent.correlationId ?? "",
53905
54049
  runId: anchorEvent.runId,
53906
54050
  stepName: ((_a3 = createdEvent == null ? void 0 : createdEvent.eventData) == null ? void 0 : _a3.stepName) ?? "",
53907
54051
  status,
53908
54052
  attempt,
53909
- createdAt: anchorEvent.createdAt,
53910
- updatedAt: (lastEvent == null ? void 0 : lastEvent.createdAt) ?? anchorEvent.createdAt,
54053
+ createdAt: getEventTimestamp(anchorEvent) ?? anchorEvent.createdAt,
54054
+ updatedAt: getEventTimestamp(lastEvent) ?? (lastEvent == null ? void 0 : lastEvent.createdAt) ?? anchorEvent.createdAt,
53911
54055
  startedAt,
53912
54056
  completedAt,
53913
54057
  specVersion: anchorEvent.specVersion
53914
- }, occurrenceEvent.occurredAt);
54058
+ };
53915
54059
  };
53916
54060
  function stepToSpan(stepEvents, maxEndTime) {
53917
54061
  const step = stepEventsToStepEntity(stepEvents);
@@ -53924,13 +54068,20 @@ function stepToSpan(stepEvents, maxEndTime) {
53924
54068
  data: step
53925
54069
  };
53926
54070
  const resource = "step";
53927
- const endTime = new Date(step.completedAt ?? maxEndTime);
53928
- const events2 = convertEventsToSpanEvents(stepEvents, false);
53929
- const spanStartTime = new Date(step.createdAt);
54071
+ const events2 = convertEventsToSpanEvents(stepEvents, false, {
54072
+ preferOccurredAt: true
54073
+ });
54074
+ const spanStartEvent = stepEvents.find((event) => event.eventType === "step_created") ?? stepEvents[0];
54075
+ const spanStartTime = getEventTimestamp(spanStartEvent) ?? new Date(step.createdAt);
53930
54076
  let activeStartTime = step.startedAt ? new Date(step.startedAt) : void 0;
53931
54077
  const firstStartEvent = stepEvents.find((event) => event.eventType === "step_started");
53932
54078
  if (firstStartEvent) {
53933
- activeStartTime = new Date(firstStartEvent.createdAt);
54079
+ activeStartTime = getEventTimestamp(firstStartEvent) ?? new Date(firstStartEvent.createdAt);
54080
+ }
54081
+ let endTime = new Date(maxEndTime);
54082
+ if (step.completedAt) {
54083
+ const completedEvent = stepEvents.slice().reverse().find((event) => event.eventType === "step_completed" || event.eventType === "step_failed");
54084
+ endTime = getEventTimestamp(completedEvent) ?? new Date(step.completedAt);
53934
54085
  }
53935
54086
  return {
53936
54087
  spanId: String(step.stepId),
@@ -53952,7 +54103,7 @@ function stepToSpan(stepEvents, maxEndTime) {
53952
54103
  };
53953
54104
  }
53954
54105
  const hookEventsToHookEntity = (events2) => {
53955
- var _a3, _b2;
54106
+ var _a3;
53956
54107
  const createdEvent = events2.find((event) => event.eventType === "hook_created");
53957
54108
  if (!createdEvent) {
53958
54109
  return null;
@@ -53960,15 +54111,15 @@ const hookEventsToHookEntity = (events2) => {
53960
54111
  const receivedEvents = events2.filter((event) => event.eventType === "hook_received");
53961
54112
  const disposedEvents = events2.filter((event) => event.eventType === "hook_disposed");
53962
54113
  const lastReceivedEvent = receivedEvents.at(-1);
53963
- return withOccurredAt({
54114
+ return {
53964
54115
  hookId: createdEvent.correlationId,
53965
54116
  runId: createdEvent.runId,
53966
54117
  token: (_a3 = createdEvent.eventData) == null ? void 0 : _a3.token,
53967
- createdAt: createdEvent.createdAt,
54118
+ createdAt: getEventTimestamp(createdEvent) ?? createdEvent.createdAt,
53968
54119
  receivedCount: receivedEvents.length,
53969
- lastReceivedAt: (lastReceivedEvent == null ? void 0 : lastReceivedEvent.createdAt) || void 0,
53970
- disposedAt: ((_b2 = disposedEvents.at(-1)) == null ? void 0 : _b2.createdAt) || void 0
53971
- }, createdEvent.occurredAt);
54120
+ lastReceivedAt: getEventTimestamp(lastReceivedEvent),
54121
+ disposedAt: getEventTimestamp(disposedEvents.at(-1))
54122
+ };
53972
54123
  };
53973
54124
  function hookToSpan(hookEvents, maxEndTime) {
53974
54125
  const hook = hookEventsToHookEntity(hookEvents);
@@ -54000,19 +54151,26 @@ function hookToSpan(hookEvents, maxEndTime) {
54000
54151
  function runToSpan(run2, runEvents, nowTime) {
54001
54152
  var _a3;
54002
54153
  const now2 = nowTime ?? /* @__PURE__ */ new Date();
54154
+ const runCreatedEvent = runEvents.find((event) => event.eventType === "run_created");
54155
+ const runStartedEvent = runEvents.find((event) => event.eventType === "run_started");
54156
+ const terminalEvent = runEvents.slice().reverse().find((event) => event.eventType === "run_completed" || event.eventType === "run_failed" || event.eventType === "run_cancelled");
54157
+ const spanStartTime = getEventTimestamp(runCreatedEvent) ?? new Date(run2.createdAt);
54158
+ const activeStartTime = getEventTimestamp(runStartedEvent) ?? (run2.startedAt ? new Date(run2.startedAt) : void 0);
54159
+ const completedAt = getEventTimestamp(terminalEvent) ?? run2.completedAt ?? void 0;
54160
+ const endTime = completedAt ?? now2;
54003
54161
  const { input: _i, output: _o2, error: _e2, ...runIdentity } = run2;
54004
- const occurrenceEvent = findEventByType(runEvents, [
54005
- "run_created",
54006
- "run_started"
54007
- ]);
54008
54162
  const attributes = {
54009
54163
  resource: "run",
54010
- data: withOccurredAt(runIdentity, occurrenceEvent == null ? void 0 : occurrenceEvent.occurredAt)
54164
+ data: {
54165
+ ...runIdentity,
54166
+ createdAt: spanStartTime,
54167
+ startedAt: activeStartTime,
54168
+ completedAt
54169
+ }
54011
54170
  };
54012
- const spanStartTime = new Date(run2.createdAt);
54013
- const activeStartTime = run2.startedAt ? new Date(run2.startedAt) : void 0;
54014
- const endTime = run2.completedAt ?? now2;
54015
- const events2 = convertEventsToSpanEvents(runEvents, false);
54171
+ const events2 = convertEventsToSpanEvents(runEvents, false, {
54172
+ preferOccurredAt: true
54173
+ });
54016
54174
  return {
54017
54175
  spanId: String(run2.runId),
54018
54176
  name: String(((_a3 = parseWorkflowName(run2.workflowName)) == null ? void 0 : _a3.shortName) ?? "?"),
@@ -54082,7 +54240,7 @@ function groupEventsByCorrelation(events2) {
54082
54240
  function computeLatestKnownTime(events2, run2) {
54083
54241
  let latest = new Date(run2.createdAt).getTime();
54084
54242
  for (const event of events2) {
54085
- const t = new Date(event.createdAt).getTime();
54243
+ const t = (getEventTimestamp(event) ?? new Date(event.createdAt)).getTime();
54086
54244
  if (t > latest)
54087
54245
  latest = t;
54088
54246
  }
@@ -82645,7 +82803,7 @@ var tn = f("block", "before:content-[counter(line)]", "before:inline-block", "be
82645
82803
  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 });
82646
82804
  var Se = reactExports.createContext({ code: "" }), de = () => reactExports.useContext(Se);
82647
82805
  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 }) });
82648
- var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-BlH6gm7c.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
82806
+ var cn$1 = /\n+$/, dn = reactExports.lazy(() => import("./highlighted-body-B3W2YXNL-DUlvgLoF.js").then((e) => ({ default: e.HighlightedCodeBlockBody }))), rt = ({ code: e, language: t, className: o, children: n, isIncomplete: s2 = false, ...r2 }) => {
82649
82807
  let i = reactExports.useMemo(() => e.replace(cn$1, ""), [e]), c = reactExports.useMemo(() => ({ bg: "transparent", fg: "inherit", tokens: i.split(`
82650
82808
  `).map((a2) => [{ content: a2, color: "inherit", bgColor: "transparent", htmlStyle: {}, offset: 0 }]) }), [i]);
82651
82809
  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 }) })] }) });
@@ -82967,7 +83125,7 @@ var Dt = ({ children: e, className: t, onDownload: o, onError: n }) => {
82967
83125
  }, []), 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] });
82968
83126
  };
82969
83127
  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 }) })] });
82970
- var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-4IS2FONM.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
83128
+ var Jn = reactExports.lazy(() => import("./mermaid-3ZIDBTTL-BdnRYE9a.js").then((e) => ({ default: e.Mermaid }))), Kn = /language-([^\s]+)/;
82971
83129
  function ke(e, t) {
82972
83130
  if (!(e != null && e.position || t != null && t.position)) return true;
82973
83131
  if (!(e != null && e.position && (t != null && t.position))) return false;
@@ -83666,7 +83824,7 @@ const getModuleSpecifierFromName = (value) => {
83666
83824
  }
83667
83825
  return raw2;
83668
83826
  };
83669
- const parseDateValue = (value) => {
83827
+ const parseDateValue$1 = (value) => {
83670
83828
  if (value == null) {
83671
83829
  return null;
83672
83830
  }
@@ -83681,14 +83839,14 @@ const parseDateValue = (value) => {
83681
83839
  };
83682
83840
  const formatLocalMillisecondTime = (date2) => format(date2, "MMM dd HH:mm:ss.SS OO").toUpperCase();
83683
83841
  const localMillisecondTimeOrNull = (value) => {
83684
- const date2 = parseDateValue(value);
83842
+ const date2 = parseDateValue$1(value);
83685
83843
  if (!date2) {
83686
83844
  return null;
83687
83845
  }
83688
83846
  return formatLocalMillisecondTime(date2);
83689
83847
  };
83690
83848
  const timestampWithTooltipOrNull = (value) => {
83691
- const date2 = parseDateValue(value);
83849
+ const date2 = parseDateValue$1(value);
83692
83850
  if (!date2)
83693
83851
  return null;
83694
83852
  return jsxRuntimeExports.jsx(TimestampTooltip, { date: date2, children: jsxRuntimeExports.jsx("span", { children: formatLocalMillisecondTime(date2) }) });
@@ -83895,8 +84053,8 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error: error2, expir
83895
84053
  return present;
83896
84054
  if (resource === "sleep")
83897
84055
  return present;
83898
- const loadingDefaults = ["input", "output"];
83899
- for (const key of loadingDefaults) {
84056
+ const loadingPlaceholders = ["input", "output"];
84057
+ for (const key of loadingPlaceholders) {
83900
84058
  if (!present.includes(key)) {
83901
84059
  present.push(key);
83902
84060
  }
@@ -83961,7 +84119,23 @@ const DATA_EVENT_TYPES = /* @__PURE__ */ new Set([
83961
84119
  "wait_completed",
83962
84120
  "attr_set"
83963
84121
  ]);
83964
- function EventItem({ event, onLoadEventData, encryptionKey }) {
84122
+ const parseDateValue = (value) => {
84123
+ if (value == null)
84124
+ return null;
84125
+ const date2 = value instanceof Date ? value : new Date(String(value));
84126
+ return Number.isNaN(date2.getTime()) ? null : date2;
84127
+ };
84128
+ const getEffectiveEventDate = (event) => parseDateValue(event.occurredAt) ?? new Date(event.createdAt);
84129
+ const formatEventTimestamp = (date2) => date2.toLocaleString(void 0, {
84130
+ month: "short",
84131
+ day: "numeric",
84132
+ hour: "numeric",
84133
+ minute: "numeric",
84134
+ second: "numeric",
84135
+ fractionalSecondDigits: 3,
84136
+ timeZoneName: "short"
84137
+ });
84138
+ function EventItem({ event, onLoadEventData, encryptionKey, showSeparateEventOccurrenceTimestamps = false }) {
83965
84139
  const [loadedData, setLoadedData] = reactExports.useState(null);
83966
84140
  const [isLoading, setIsLoading] = reactExports.useState(false);
83967
84141
  const [loadError, setLoadError] = reactExports.useState(null);
@@ -84002,16 +84176,18 @@ function EventItem({ event, onLoadEventData, encryptionKey }) {
84002
84176
  void loadEventData({ force: true });
84003
84177
  }, [encryptionKey, loadEventData]);
84004
84178
  const createdAt = new Date(event.createdAt);
84005
- const createdAtTime = createdAt.toLocaleTimeString(void 0, {
84179
+ const occurredAt = parseDateValue(event.occurredAt);
84180
+ const displayedCreatedAt = showSeparateEventOccurrenceTimestamps ? createdAt : getEffectiveEventDate(event);
84181
+ const displayedCreatedAtTime = displayedCreatedAt.toLocaleTimeString(void 0, {
84006
84182
  hour: "numeric",
84007
84183
  minute: "numeric",
84008
84184
  second: "numeric"
84009
84185
  });
84010
84186
  const displayPayload = isLoading ? loadedData : mergedDisplay;
84011
- return jsxRuntimeExports.jsxs(DetailCard, { variant: "card", summaryClassName: "px-3 py-2", summary: jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [jsxRuntimeExports.jsx("span", { className: "text-gray-1000 text-label-12 font-mono", children: event.eventType }), jsxRuntimeExports.jsx("span", { className: "shrink-0 text-label-13 text-gray-900", children: createdAtTime })] }), onToggle: canHaveData ? (open) => {
84187
+ return jsxRuntimeExports.jsxs(DetailCard, { variant: "card", summaryClassName: "px-3 py-2", summary: jsxRuntimeExports.jsxs("div", { className: "flex w-full items-center justify-between gap-3", children: [jsxRuntimeExports.jsx("span", { className: "text-gray-1000 text-label-12 font-mono", children: event.eventType }), jsxRuntimeExports.jsx("span", { className: "shrink-0 text-label-13 text-gray-900", children: displayedCreatedAtTime })] }), onToggle: canHaveData ? (open) => {
84012
84188
  if (open)
84013
84189
  handleExpand();
84014
- } : void 0, children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col bg-background-200 [&:has(+_*)]:border-b [&:has(+_*)]:border-gray-alpha-400", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Event ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.eventId })] }), event.correlationId && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Correlation ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.correlationId })] })] }), isLoading && jsxRuntimeExports.jsxs("div", { className: "p-3", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayPayload != null && jsxRuntimeExports.jsx("div", { className: "[&>div]:border-none [&>div]:rounded-none", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayPayload }) })] });
84190
+ } : void 0, children: [jsxRuntimeExports.jsxs("div", { className: "flex flex-col bg-background-200 [&:has(+_*)]:border-b [&:has(+_*)]:border-gray-alpha-400", children: [showSeparateEventOccurrenceTimestamps && occurredAt && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Occurred" }), jsxRuntimeExports.jsx(TimestampTooltip, { date: occurredAt, children: jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: formatEventTimestamp(occurredAt) }) })] }), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Event ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.eventId })] }), event.correlationId && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 py-2 px-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-12 text-gray-900", children: "Correlation ID" }), jsxRuntimeExports.jsx("span", { className: "max-w-[70%] truncate text-right text-label-12 font-mono", children: event.correlationId })] })] }), isLoading && jsxRuntimeExports.jsxs("div", { className: "p-3", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-4 w-[35%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[90%]" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "mt-2 h-4 w-[75%]" })] }), loadError && jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load event data", details: loadError, className: "mt-2" }), displayPayload != null && jsxRuntimeExports.jsx("div", { className: "[&>div]:border-none [&>div]:rounded-none", children: jsxRuntimeExports.jsx(EventDataBlock, { eventType: event.eventType, data: displayPayload }) })] });
84015
84191
  }
84016
84192
  function hasOnlyExpiredFields(data, eventType) {
84017
84193
  if (data === null || typeof data !== "object" || Array.isArray(data)) {
@@ -84047,13 +84223,13 @@ function EventDataBlock({ eventType, data }) {
84047
84223
  }
84048
84224
  return jsxRuntimeExports.jsx(CopyableDataBlock, { data });
84049
84225
  }
84050
- function EventsList({ events: events2, isLoading = false, error: error2, onLoadEventData, onStreamClick, onRunClick, encryptionKey }) {
84051
- const sortedEvents2 = reactExports.useMemo(() => [...events2].sort((a2, b2) => new Date(a2.createdAt).getTime() - new Date(b2.createdAt).getTime()), [events2]);
84226
+ function EventsList({ events: events2, isLoading = false, error: error2, onLoadEventData, onStreamClick, onRunClick, encryptionKey, showSeparateEventOccurrenceTimestamps = false }) {
84227
+ const sortedEvents2 = reactExports.useMemo(() => [...events2].sort((a2, b2) => getEffectiveEventDate(a2).getTime() - getEffectiveEventDate(b2).getTime()), [events2]);
84052
84228
  const hasEvents = sortedEvents2.length > 0 && !error2;
84053
84229
  if (!hasEvents && !isLoading) {
84054
84230
  return jsxRuntimeExports.jsx(DetailCard, { summary: "Events", disabled: true });
84055
84231
  }
84056
- return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsx(DetailCard, { summary: "Events", contentClassName: "mb-0", defaultOpen: true, children: isLoading ? jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: [0, 1, 2].map((i) => jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 bg-background-200 px-4 py-2", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-4 w-32 rounded" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3 w-16 rounded" })] }, i)) }) : jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: sortedEvents2.map((event) => jsxRuntimeExports.jsx(EventItem, { event, onLoadEventData, encryptionKey }, event.eventId)) }) }) }) });
84232
+ return jsxRuntimeExports.jsx(RunClickContext.Provider, { value: onRunClick, children: jsxRuntimeExports.jsx(StreamClickContext.Provider, { value: onStreamClick, children: jsxRuntimeExports.jsx(DetailCard, { summary: "Events", contentClassName: "mb-0", defaultOpen: true, children: isLoading ? jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: [0, 1, 2].map((i) => jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 bg-background-200 px-4 py-2", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "h-4 w-32 rounded" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3 w-16 rounded" })] }, i)) }) : jsxRuntimeExports.jsx("div", { className: "flex flex-col -mx-4", children: sortedEvents2.map((event) => jsxRuntimeExports.jsx(EventItem, { event, onLoadEventData, encryptionKey, showSeparateEventOccurrenceTimestamps }, event.eventId)) }) }) }) });
84057
84233
  }
84058
84234
  const SidebarDataContext = reactExports.createContext(null);
84059
84235
  SidebarDataContext.displayName = "SidebarDataContext";
@@ -84071,6 +84247,43 @@ function useSidebarDataOptional() {
84071
84247
  return reactExports.useContext(SidebarDataContext);
84072
84248
  }
84073
84249
  const hasField = (value, key) => key in value;
84250
+ const RESOURCES_WITH_FETCHED_DETAIL = /* @__PURE__ */ new Set(["run", "step", "sleep"]);
84251
+ function resourceNeedsFetchedDetail(resource) {
84252
+ return resource !== void 0 && RESOURCES_WITH_FETCHED_DETAIL.has(resource);
84253
+ }
84254
+ function deriveSpanDetailView(args) {
84255
+ const { resource, resourceId, inlineData, fetchedDetail, fetchedError } = args;
84256
+ const matchedDetail = spanDetailMatchesSelection(fetchedDetail, resource, resourceId) ? fetchedDetail : null;
84257
+ const displayData = mergeSpanDetail(inlineData, matchedDetail);
84258
+ if (!resource || !resourceId) {
84259
+ return { status: "idle", displayData, detail: null, error: void 0 };
84260
+ }
84261
+ if (fetchedError) {
84262
+ return {
84263
+ status: "error",
84264
+ displayData,
84265
+ detail: matchedDetail,
84266
+ error: fetchedError
84267
+ };
84268
+ }
84269
+ if (!resourceNeedsFetchedDetail(resource)) {
84270
+ return {
84271
+ status: "ready",
84272
+ displayData,
84273
+ detail: matchedDetail,
84274
+ error: void 0
84275
+ };
84276
+ }
84277
+ if (matchedDetail !== null) {
84278
+ return {
84279
+ status: "ready",
84280
+ displayData,
84281
+ detail: matchedDetail,
84282
+ error: void 0
84283
+ };
84284
+ }
84285
+ return { status: "loading", displayData, detail: null, error: void 0 };
84286
+ }
84074
84287
  function spanDetailMatchesSelection(detail, resource, resourceId) {
84075
84288
  if (!detail || typeof detail !== "object" || !resource || !resourceId) {
84076
84289
  return false;
@@ -84103,16 +84316,88 @@ function mergeSpanDetail(spanData, detail) {
84103
84316
  }
84104
84317
  return merged;
84105
84318
  }
84106
- function isStep(data) {
84107
- return data !== null && typeof data === "object" && "stepId" in data;
84319
+ function deriveSpanSelection(selectedSpan) {
84320
+ if (!selectedSpan)
84321
+ return null;
84322
+ const { resource, data } = selectedSpan;
84323
+ if (resource === "step" && data && typeof data === "object" && "stepId" in data) {
84324
+ const step = data;
84325
+ return { resource: "step", resourceId: step.stepId, runId: step.runId };
84326
+ }
84327
+ if (resource === "run" && data && typeof data === "object" && "runId" in data) {
84328
+ return { resource: "run", resourceId: data.runId };
84329
+ }
84330
+ if (resource === "hook" && data && typeof data === "object" && "hookId" in data) {
84331
+ return { resource: "hook", resourceId: data.hookId };
84332
+ }
84333
+ if (resource === "sleep") {
84334
+ if (!selectedSpan.spanId)
84335
+ return null;
84336
+ const waitData = data;
84337
+ return {
84338
+ resource: "sleep",
84339
+ resourceId: selectedSpan.spanId,
84340
+ runId: waitData == null ? void 0 : waitData.runId
84341
+ };
84342
+ }
84343
+ return null;
84108
84344
  }
84109
- function isWorkflowRun(data) {
84110
- return data !== null && typeof data === "object" && "runId" in data;
84345
+ function useSelectedSpanDetail(selectedSpan, fetchSpanDetail) {
84346
+ const selection2 = reactExports.useMemo(() => deriveSpanSelection(selectedSpan), [selectedSpan]);
84347
+ const resource = selection2 == null ? void 0 : selection2.resource;
84348
+ const resourceId = selection2 == null ? void 0 : selection2.resourceId;
84349
+ const runId = selection2 == null ? void 0 : selection2.runId;
84350
+ const selectionKey = resource && resourceId ? `${resource}:${resourceId}` : null;
84351
+ const needsFetch = resourceNeedsFetchedDetail(resource);
84352
+ const [fetched, setFetched] = reactExports.useState({ detail: null, error: null, errorKey: null });
84353
+ const tokenRef = reactExports.useRef(0);
84354
+ const selectionRef = reactExports.useRef(selection2);
84355
+ selectionRef.current = selection2;
84356
+ reactExports.useEffect(() => {
84357
+ if (!selectionKey || !needsFetch) {
84358
+ return;
84359
+ }
84360
+ const activeSelection = selectionRef.current;
84361
+ if (!activeSelection) {
84362
+ return;
84363
+ }
84364
+ const token = ++tokenRef.current;
84365
+ fetchSpanDetail(activeSelection).then((detail) => {
84366
+ if (tokenRef.current !== token)
84367
+ return;
84368
+ setFetched({ detail, error: null, errorKey: null });
84369
+ }).catch((err) => {
84370
+ if (tokenRef.current !== token)
84371
+ return;
84372
+ setFetched({
84373
+ detail: null,
84374
+ error: err instanceof Error ? err : new Error(String(err)),
84375
+ errorKey: selectionKey
84376
+ });
84377
+ });
84378
+ }, [selectionKey, runId, needsFetch, fetchSpanDetail]);
84379
+ const scopedError = fetched.errorKey === selectionKey ? fetched.error : null;
84380
+ const view = reactExports.useMemo(() => deriveSpanDetailView({
84381
+ resource,
84382
+ resourceId,
84383
+ inlineData: selectedSpan == null ? void 0 : selectedSpan.data,
84384
+ fetchedDetail: fetched.detail,
84385
+ fetchedError: scopedError
84386
+ }), [resource, resourceId, selectedSpan == null ? void 0 : selectedSpan.data, fetched.detail, scopedError]);
84387
+ return {
84388
+ status: view.status,
84389
+ resource,
84390
+ resourceId,
84391
+ runId,
84392
+ displayData: view.displayData,
84393
+ detail: view.detail,
84394
+ error: view.error
84395
+ };
84111
84396
  }
84112
84397
  function isHook(data) {
84113
84398
  return data !== null && typeof data === "object" && "hookId" in data;
84114
84399
  }
84115
- function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, spanDetailData, spanDetailError, spanDetailLoading, onSpanSelect, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan }) {
84400
+ function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, fetchSpanDetail, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan, showSeparateEventOccurrenceTimestamps = false }) {
84116
84401
  const toast2 = useToast();
84117
84402
  const [stoppingSleep, setStoppingSleep] = reactExports.useState(false);
84118
84403
  const [showResolveHookModal, setShowResolveHookModal] = reactExports.useState(false);
@@ -84123,41 +84408,8 @@ function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, spanDetailDat
84123
84408
  const data = selectedSpan == null ? void 0 : selectedSpan.data;
84124
84409
  const rawEvents = selectedSpan == null ? void 0 : selectedSpan.rawEvents;
84125
84410
  const rawEventsLength = (rawEvents == null ? void 0 : rawEvents.length) ?? 0;
84126
- const { resource, resourceId, runId } = reactExports.useMemo(() => {
84127
- if (!selectedSpan) {
84128
- return { resource: void 0, resourceId: void 0, runId: void 0 };
84129
- }
84130
- const res = selectedSpan.resource;
84131
- if (res === "step" && isStep(data)) {
84132
- return { resource: "step", resourceId: data.stepId, runId: data.runId };
84133
- }
84134
- if (res === "run" && isWorkflowRun(data)) {
84135
- return { resource: "run", resourceId: data.runId, runId: void 0 };
84136
- }
84137
- if (res === "hook" && isHook(data)) {
84138
- return { resource: "hook", resourceId: data.hookId, runId: void 0 };
84139
- }
84140
- if (res === "sleep") {
84141
- const waitData = data;
84142
- return {
84143
- resource: "sleep",
84144
- resourceId: selectedSpan.spanId,
84145
- runId: waitData == null ? void 0 : waitData.runId
84146
- };
84147
- }
84148
- return { resource: void 0, resourceId: void 0, runId: void 0 };
84149
- }, [selectedSpan, data]);
84150
- const onSpanSelectRef = reactExports.useRef(onSpanSelect);
84151
- onSpanSelectRef.current = onSpanSelect;
84152
- reactExports.useEffect(() => {
84153
- if (resource && resourceId && ["run", "step", "hook", "sleep"].includes(resource)) {
84154
- onSpanSelectRef.current({
84155
- resource,
84156
- resourceId,
84157
- runId
84158
- });
84159
- }
84160
- }, [resource, resourceId, runId]);
84411
+ const { status, resource, resourceId, displayData, detail: matchedSpanDetailData, error: error2 } = useSelectedSpanDetail(selectedSpan, fetchSpanDetail);
84412
+ const loading = status === "loading";
84161
84413
  const canWakeUp = reactExports.useMemo(() => {
84162
84414
  if (resource !== "sleep" || !rawEvents)
84163
84415
  return false;
@@ -84190,9 +84442,6 @@ function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, spanDetailDat
84190
84442
  run2.status,
84191
84443
  resolvedHookIds
84192
84444
  ]);
84193
- const error2 = spanDetailError ?? void 0;
84194
- const loading = spanDetailLoading ?? false;
84195
- const matchedSpanDetailData = reactExports.useMemo(() => spanDetailMatchesSelection(spanDetailData, resource, resourceId) ? spanDetailData : null, [spanDetailData, resource, resourceId]);
84196
84445
  const hookToken = reactExports.useMemo(() => {
84197
84446
  if (resource !== "hook" || !resourceId)
84198
84447
  return void 0;
@@ -84277,7 +84526,6 @@ function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, spanDetailDat
84277
84526
  setResolvingHook(false);
84278
84527
  }
84279
84528
  }, [onResolveHook, hookToken, resolvingHook, matchedSpanDetailData, data]);
84280
- const displayData = reactExports.useMemo(() => mergeSpanDetail(data, matchedSpanDetailData), [data, matchedSpanDetailData]);
84281
84529
  const moduleSpecifier = reactExports.useMemo(() => {
84282
84530
  const displayRecord = displayData;
84283
84531
  const displayStepName = displayRecord.stepName;
@@ -84306,7 +84554,7 @@ function EntityDetailPanel({ run: run2, onStreamClick, onRunClick, spanDetailDat
84306
84554
  }, children: [jsxRuntimeExports.jsx(Zap, { className: "h-4 w-4" }), stoppingSleep ? "Waking up..." : "Wake Up Sleep"] }), resource === "hook" && canResolveHook && jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setShowResolveHookModal(true), disabled: resolvingHook, className: clsx("flex items-center justify-center gap-2 rounded-md px-3 py-2 text-sm font-medium", "disabled:opacity-50 disabled:cursor-not-allowed transition-colors", resolvingHook ? "opacity-50 cursor-not-allowed" : "cursor-pointer"), style: {
84307
84555
  background: "var(--ds-gray-1000)",
84308
84556
  color: "var(--ds-background-100)"
84309
- }, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run2.expiredAt, isLoading: loading, error: error2 ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }), rawEvents && jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, onStreamClick, onRunClick, encryptionKey })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
84557
+ }, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run2.expiredAt, isLoading: loading, error: error2 ?? void 0, onStreamClick, onRunClick, onDecrypt, isDecrypting, resource }), rawEvents && jsxRuntimeExports.jsx(EventsList, { events: rawEvents, onLoadEventData, onStreamClick, onRunClick, encryptionKey, showSeparateEventOccurrenceTimestamps })] }) }), jsxRuntimeExports.jsx(ResolveHookModal, { isOpen: showResolveHookModal, onClose: () => setShowResolveHookModal(false), onSubmit: handleResolveHook, isSubmitting: resolvingHook })] });
84310
84558
  }
84311
84559
  const MAP_HEIGHT = 56;
84312
84560
  const TIMELINE_PADDING = 8;
@@ -85573,6 +85821,41 @@ function StreamViewer({ streamId: _streamId, chunks, isLive, error: error2, isLo
85573
85821
  color: "var(--ds-gray-600)"
85574
85822
  }, children: isLive ? "Waiting for stream data..." : "Stream is empty" }) : jsxRuntimeExports.jsx(Yr, { ref: virtuosoRef, totalCount: chunks.length, overscan: 10, endReached: () => onScrollEnd == null ? void 0 : onScrollEnd(), itemContent: (index2) => jsxRuntimeExports.jsx("div", { style: { paddingBottom: 8 }, children: jsxRuntimeExports.jsx(ChunkRow, { chunk: chunks[index2], index: index2 }) }), style: { flex: 1, minHeight: 0 } }) })] });
85575
85823
  }
85824
+ function useIntersectionObserver(elementRef, { threshold = 0, rootRef, rootMargin = "0%", freezeOnceVisible = false } = {}) {
85825
+ const [entry2, setEntry] = reactExports.useState();
85826
+ const frozen = (entry2 == null ? void 0 : entry2.isIntersecting) && freezeOnceVisible;
85827
+ reactExports.useEffect(() => {
85828
+ const node2 = elementRef == null ? void 0 : elementRef.current;
85829
+ const hasIOSupport = !!window.IntersectionObserver;
85830
+ if (!hasIOSupport || frozen || !node2)
85831
+ return;
85832
+ const updateEntry = ([entry3]) => {
85833
+ setEntry(entry3);
85834
+ };
85835
+ const observer = new IntersectionObserver(updateEntry, {
85836
+ threshold,
85837
+ root: (rootRef == null ? void 0 : rootRef.current) ?? null,
85838
+ rootMargin
85839
+ });
85840
+ observer.observe(node2);
85841
+ return () => observer.disconnect();
85842
+ }, [elementRef, threshold, rootRef, rootMargin, frozen]);
85843
+ return entry2;
85844
+ }
85845
+ function useLoadMoreOnScroll(loadMore, { hasMore, isLoadingMore, rootRef, rootMargin = "400px" }) {
85846
+ const sentinelRef = reactExports.useRef(null);
85847
+ const entry2 = useIntersectionObserver(sentinelRef, { rootRef, rootMargin });
85848
+ const loadMoreRef = reactExports.useRef(loadMore);
85849
+ reactExports.useEffect(() => {
85850
+ loadMoreRef.current = loadMore;
85851
+ }, [loadMore]);
85852
+ reactExports.useEffect(() => {
85853
+ if ((entry2 == null ? void 0 : entry2.isIntersecting) && hasMore && !isLoadingMore) {
85854
+ loadMoreRef.current();
85855
+ }
85856
+ }, [entry2 == null ? void 0 : entry2.isIntersecting, hasMore, isLoadingMore]);
85857
+ return sentinelRef;
85858
+ }
85576
85859
  const iconButtonVariants = cva([
85577
85860
  "m-0 inline-flex shrink-0 appearance-none items-center justify-center border-0 bg-transparent p-0 align-baseline font-inherit no-underline [background:none] [-webkit-appearance:none] [-webkit-tap-highlight-color:transparent]",
85578
85861
  "transition-colors duration-150 ease-in-out",
@@ -85616,57 +85899,6 @@ const kbdVariants = cva("inline-flex items-center justify-center rounded px-1 te
85616
85899
  function Kbd({ children: children2, className, variant, size: size2, ...props }) {
85617
85900
  return jsxRuntimeExports.jsx("kbd", { className: cn$4(kbdVariants({ variant, size: size2, className })), ...props, children: children2 });
85618
85901
  }
85619
- const COL_TEMPLATE = "340px 1px minmax(50px, 1fr)";
85620
- const ROWS = [
85621
- { id: "r0", name: 62, off: 0, bar: 72 },
85622
- { id: "r1", name: 78, off: 6, bar: 48 },
85623
- { id: "r2", name: 50, off: 10, bar: 55 },
85624
- { id: "r3", name: 84, off: 18, bar: 30 },
85625
- { id: "r4", name: 45, off: 18, bar: 42 },
85626
- { id: "r5", name: 66, off: 34, bar: 38 },
85627
- { id: "r6", name: 55, off: 41, bar: 25 },
85628
- { id: "r7", name: 40, off: 50, bar: 30 }
85629
- ];
85630
- const HEADER_MARKERS = ["m0", "m1", "m2", "m3"];
85631
- const HeaderDivider = () => jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }) });
85632
- function TraceViewerSkeleton() {
85633
- return jsxRuntimeExports.jsxs("output", { "aria-busy": "true", "aria-label": "Loading trace", className: "flex flex-col w-full h-full min-h-0 bg-background-100", children: [jsxRuntimeExports.jsx("span", { className: "sr-only", children: "Loading trace…" }), jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsxs("div", { className: "h-10 min-h-10 flex items-center border-b border-gray-alpha-400 pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "w-3.5 h-3.5 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5 w-40" })] }), jsxRuntimeExports.jsx(HeaderDivider, {}), jsxRuntimeExports.jsx("div", { className: "h-10 min-h-10 flex items-end border-b border-gray-alpha-400 px-4 pb-1 gap-2", children: jsxRuntimeExports.jsx("div", { className: "relative flex-1 flex items-end justify-between", children: HEADER_MARKERS.map((id2) => jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5 w-9" }, id2)) }) })] }), jsxRuntimeExports.jsxs("div", { className: "grid flex-1 min-h-0 overflow-hidden", style: { gridTemplateColumns: COL_TEMPLATE }, children: [jsxRuntimeExports.jsx("div", { className: "block overflow-visible", children: jsxRuntimeExports.jsx("ul", { className: "block divide-y divide-gray-alpha-400 border-b border-gray-alpha-400", children: ROWS.map((row) => jsxRuntimeExports.jsxs("li", { className: "h-10 flex items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsx(Skeleton$2, { className: "w-4 h-4 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton$2, { className: "h-3.5", style: { width: `${row.name}%` } })] }), jsxRuntimeExports.jsx(Skeleton$2, { className: "ml-2 h-3.5 w-10 shrink-0" })] }, row.id)) }) }), jsxRuntimeExports.jsx("span", { "aria-hidden": true, className: "h-full w-px bg-gray-alpha-400" }), jsxRuntimeExports.jsx("div", { className: "relative min-h-0", children: ROWS.map((row) => jsxRuntimeExports.jsx("div", { className: "relative h-10", children: jsxRuntimeExports.jsx("div", { className: "absolute inset-x-4 inset-y-0", children: jsxRuntimeExports.jsx(Skeleton$2, { className: "absolute top-1/2 -translate-y-1/2 h-6 rounded-[0.25rem]", style: { left: `${row.off}%`, width: `${row.bar}%` } }) }) }, row.id)) })] })] });
85634
- }
85635
- function useIntersectionObserver(elementRef, { threshold = 0, rootRef, rootMargin = "0%", freezeOnceVisible = false } = {}) {
85636
- const [entry2, setEntry] = reactExports.useState();
85637
- const frozen = (entry2 == null ? void 0 : entry2.isIntersecting) && freezeOnceVisible;
85638
- reactExports.useEffect(() => {
85639
- const node2 = elementRef == null ? void 0 : elementRef.current;
85640
- const hasIOSupport = !!window.IntersectionObserver;
85641
- if (!hasIOSupport || frozen || !node2)
85642
- return;
85643
- const updateEntry = ([entry3]) => {
85644
- setEntry(entry3);
85645
- };
85646
- const observer = new IntersectionObserver(updateEntry, {
85647
- threshold,
85648
- root: (rootRef == null ? void 0 : rootRef.current) ?? null,
85649
- rootMargin
85650
- });
85651
- observer.observe(node2);
85652
- return () => observer.disconnect();
85653
- }, [elementRef, threshold, rootRef, rootMargin, frozen]);
85654
- return entry2;
85655
- }
85656
- function useLoadMoreOnScroll(loadMore, { hasMore, isLoadingMore, rootRef, rootMargin = "400px" }) {
85657
- const sentinelRef = reactExports.useRef(null);
85658
- const entry2 = useIntersectionObserver(sentinelRef, { rootRef, rootMargin });
85659
- const loadMoreRef = reactExports.useRef(loadMore);
85660
- reactExports.useEffect(() => {
85661
- loadMoreRef.current = loadMore;
85662
- }, [loadMore]);
85663
- reactExports.useEffect(() => {
85664
- if ((entry2 == null ? void 0 : entry2.isIntersecting) && hasMore && !isLoadingMore) {
85665
- loadMoreRef.current();
85666
- }
85667
- }, [entry2 == null ? void 0 : entry2.isIntersecting, hasMore, isLoadingMore]);
85668
- return sentinelRef;
85669
- }
85670
85902
  const TooltipProvider = Provider$2;
85671
85903
  const Tooltip$1 = Root3$1;
85672
85904
  const TooltipTrigger$1 = Trigger$4;
@@ -86252,57 +86484,6 @@ const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
86252
86484
  paddingBottom: (spans.length - end) * ROW_HEIGHT_PX
86253
86485
  }, children: spans.slice(start2, end).map((span) => jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelectSpan }, span.spanId)) });
86254
86486
  };
86255
- const hint$1 = "_hint_1dmsq_3";
86256
- const styles$2 = {
86257
- hint: hint$1
86258
- };
86259
- const DISMISSALS_KEY = "workflow-step-shortcut-helper-dismissals";
86260
- const DISMISSAL_LIMIT = 3;
86261
- const HINT_ROTATION_MS = 8e3;
86262
- function getAltKeyLabel() {
86263
- if (typeof navigator === "undefined")
86264
- return "Alt";
86265
- return navigator.platform.toLowerCase().includes("mac") ? "Option" : "Alt";
86266
- }
86267
- function readDismissals() {
86268
- try {
86269
- const dismissals = Number.parseInt(window.localStorage.getItem(DISMISSALS_KEY) ?? "0", 10);
86270
- return Number.isNaN(dismissals) ? 0 : dismissals;
86271
- } catch {
86272
- return 0;
86273
- }
86274
- }
86275
- function AltHint() {
86276
- return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Hold", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mx-1", children: getAltKeyLabel() }), "to see delta between spans"] });
86277
- }
86278
- function NavHint() {
86279
- return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Use", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "ml-1", children: "J" }), jsxRuntimeExports.jsx("span", { className: "mx-1", children: "/" }), jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mr-1", children: "K" }), "to move between spans"] });
86280
- }
86281
- function TraceShortcutHelper({ hasMultipleSpans, reducedMotion }) {
86282
- const [visible, setVisible] = reactExports.useState(false);
86283
- const [index2, setIndex] = reactExports.useState(0);
86284
- reactExports.useEffect(() => {
86285
- setVisible(readDismissals() < DISMISSAL_LIMIT);
86286
- }, []);
86287
- reactExports.useEffect(() => {
86288
- if (reducedMotion)
86289
- return;
86290
- const id2 = setInterval(() => {
86291
- setIndex((i) => i === 0 ? 1 : 0);
86292
- }, HINT_ROTATION_MS);
86293
- return () => clearInterval(id2);
86294
- }, [reducedMotion]);
86295
- if (!visible || !hasMultipleSpans)
86296
- return null;
86297
- const dismiss = () => {
86298
- try {
86299
- window.localStorage.setItem(DISMISSALS_KEY, String(readDismissals() + 1));
86300
- } catch {
86301
- }
86302
- setVisible(false);
86303
- };
86304
- return jsxRuntimeExports.jsxs("div", { className: "group absolute bottom-3 left-1/2 z-10 hidden h-8 max-w-[calc(100%-2rem)] -translate-x-1/2 items-center gap-1 text-xs leading-none text-gray-900 md:inline-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$2.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" }) })] });
86305
- }
86306
86487
  const GUTTER_PX = 1;
86307
86488
  const MIN_PX = 50;
86308
86489
  const DEFAULT_START_PX = 340;
@@ -86443,11 +86624,11 @@ function OffscreenMarkerIndicator({ direction, count: count2, targetMs, onReveal
86443
86624
  return jsxRuntimeExports.jsx("button", { type: "button", "aria-label": label, title: label, onClick: (e) => {
86444
86625
  e.stopPropagation();
86445
86626
  onReveal == null ? void 0 : onReveal(targetMs);
86446
- }, className: cn$4("pointer-events-auto absolute top-1/2 z-20 flex h-6 -translate-y-1/2 cursor-pointer items-center rounded-[0.25rem] border border-gray-alpha-400 bg-background-100 shadow-sm hover:bg-gray-100", direction === "right" ? "right-0 pl-1.5" : "left-0 pr-1.5"), children: direction === "left" ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [chevron, tick] }) : jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [tick, chevron] }) });
86627
+ }, className: cn$4("pointer-events-auto absolute top-1/2 z-20 flex h-6 -translate-y-1/2 cursor-pointer items-center rounded-[0.25rem] border border-gray-alpha-400 bg-background-100 hover:bg-gray-100", direction === "right" ? "right-0 pl-1.5" : "left-0 pr-1.5"), children: direction === "left" ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [chevron, tick] }) : jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [tick, chevron] }) });
86447
86628
  }
86448
86629
  const runningStripes = "_runningStripes_1ii0z_1";
86449
86630
  const pendingStripes = "_pendingStripes_1ii0z_2";
86450
- const styles$1 = {
86631
+ const styles$2 = {
86451
86632
  runningStripes,
86452
86633
  pendingStripes
86453
86634
  };
@@ -86476,7 +86657,7 @@ const STRIPED_SEGMENT_STATUSES = /* @__PURE__ */ new Set([
86476
86657
  "received"
86477
86658
  ]);
86478
86659
  function AnimatedStripes({ status }) {
86479
- return jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: status === "pending" ? styles$1.pendingStripes : styles$1.runningStripes });
86660
+ return jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: status === "pending" ? styles$2.pendingStripes : styles$2.runningStripes });
86480
86661
  }
86481
86662
  function computeBarGeometry(startMs, endMs, viewStart, viewEnd, containerWidth) {
86482
86663
  const viewDuration = viewEnd - viewStart;
@@ -86640,6 +86821,57 @@ function Timeline({ spans, viewStart, viewEnd, markers: markers2, selectedId, se
86640
86821
  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
86641
86822
  )) }), 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: formatDuration(gap.gapMs, true), rowIndex: gap.rowIndex }, gap.rowIndex)) })] });
86642
86823
  }
86824
+ const hint$1 = "_hint_1dmsq_3";
86825
+ const styles$1 = {
86826
+ hint: hint$1
86827
+ };
86828
+ const DISMISSALS_KEY = "workflow-step-shortcut-helper-dismissals";
86829
+ const DISMISSAL_LIMIT = 3;
86830
+ const HINT_ROTATION_MS = 8e3;
86831
+ function getAltKeyLabel() {
86832
+ if (typeof navigator === "undefined")
86833
+ return "Alt";
86834
+ return navigator.platform.toLowerCase().includes("mac") ? "Option" : "Alt";
86835
+ }
86836
+ function readDismissals() {
86837
+ try {
86838
+ const dismissals = Number.parseInt(window.localStorage.getItem(DISMISSALS_KEY) ?? "0", 10);
86839
+ return Number.isNaN(dismissals) ? 0 : dismissals;
86840
+ } catch {
86841
+ return 0;
86842
+ }
86843
+ }
86844
+ function AltHint() {
86845
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Hold", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mx-1", children: getAltKeyLabel() }), "to see delta between spans"] });
86846
+ }
86847
+ function NavHint() {
86848
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: ["Use", jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "ml-1", children: "J" }), jsxRuntimeExports.jsx("span", { className: "mx-1", children: "/" }), jsxRuntimeExports.jsx(Kbd, { variant: "outline", size: "compact", className: "mr-1", children: "K" }), "to move between spans"] });
86849
+ }
86850
+ function TraceShortcutHelper({ hasMultipleSpans, reducedMotion }) {
86851
+ const [visible, setVisible] = reactExports.useState(false);
86852
+ const [index2, setIndex] = reactExports.useState(0);
86853
+ reactExports.useEffect(() => {
86854
+ setVisible(readDismissals() < DISMISSAL_LIMIT);
86855
+ }, []);
86856
+ reactExports.useEffect(() => {
86857
+ if (reducedMotion)
86858
+ return;
86859
+ const id2 = setInterval(() => {
86860
+ setIndex((i) => i === 0 ? 1 : 0);
86861
+ }, HINT_ROTATION_MS);
86862
+ return () => clearInterval(id2);
86863
+ }, [reducedMotion]);
86864
+ if (!visible || !hasMultipleSpans)
86865
+ return null;
86866
+ const dismiss = () => {
86867
+ try {
86868
+ window.localStorage.setItem(DISMISSALS_KEY, String(readDismissals() + 1));
86869
+ } catch {
86870
+ }
86871
+ setVisible(false);
86872
+ };
86873
+ return jsxRuntimeExports.jsxs("div", { className: "group absolute bottom-3 left-1/2 z-10 hidden h-8 max-w-[calc(100%-2rem)] -translate-x-1/2 items-center gap-1 text-xs leading-none text-gray-900 md:inline-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" }) })] });
86874
+ }
86643
86875
  const ActiveSpanContext = reactExports.createContext(null);
86644
86876
  ActiveSpanContext.displayName = "ActiveSpanContext";
86645
86877
  function ActiveSpanProvider({ spans, children: children2 }) {
@@ -87093,7 +87325,7 @@ function NewTraceViewerContent({ trace: trace2, onLoadMore, hasMore, isLoadingMo
87093
87325
  e.stopPropagation();
87094
87326
  setSearchQuery("");
87095
87327
  }
87096
- }, 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, className: "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.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, "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, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [jsxRuntimeExports.jsxs(Tooltip$1, { children: [jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent$1, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip$1, { children: [jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent$1, { children: ["Navigate down", jsxRuntimeExports.jsx(Kbd, { children: "J" })] }) : null] }), jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: handleClearActiveSpan, children: jsxRuntimeExports.jsx(X$3, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary$1, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, spanDetailData: sidebar.spanDetailData, spanDetailError: sidebar.spanDetailError, spanDetailLoading: sidebar.spanDetailLoading, onSpanSelect: sidebar.onSpanSelect, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan }) }) })] }) : null, jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace2.spans.length > 1, reducedMotion })] });
87328
+ }, 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, className: "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.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, "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, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), activeSpan ? jsxRuntimeExports.jsxs("aside", { className: "flex flex-col h-full max-h-full bg-background-100 border-l border-gray-alpha-400 overflow-auto", children: [jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 pt-3 pb-3", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 font-medium text-gray-1000 truncate block", children: selectedSpanName }), jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-0.5 shrink-0", children: [jsxRuntimeExports.jsxs(Tooltip$1, { children: [jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrevSpan, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent$1, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip$1, { children: [jsxRuntimeExports.jsx(TooltipTrigger$1, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNextSpan, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent$1, { children: ["Navigate down", jsxRuntimeExports.jsx(Kbd, { children: "J" })] }) : null] }), jsxRuntimeExports.jsx("div", { "aria-hidden": true, className: "w-px h-4 bg-gray-alpha-400 mx-1" }), jsxRuntimeExports.jsx(IconButton, { "aria-label": "Close span details", "aria-keyshortcuts": "Escape", onClick: handleClearActiveSpan, children: jsxRuntimeExports.jsx(X$3, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary$1, { children: jsxRuntimeExports.jsx(EntityDetailPanel, { run: sidebar.run, onStreamClick: sidebar.onStreamClick, onRunClick: sidebar.onRunClick, fetchSpanDetail: sidebar.fetchSpanDetail, onWakeUpSleep: sidebar.onWakeUpSleep, onLoadEventData: sidebar.onLoadEventData, onResolveHook: sidebar.onResolveHook, encryptionKey: sidebar.encryptionKey, onDecrypt: sidebar.onDecrypt, isDecrypting: sidebar.isDecrypting, selectedSpan, showSeparateEventOccurrenceTimestamps: sidebar.showSeparateEventOccurrenceTimestamps }) }) })] }) : null, jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace2.spans.length > 1, reducedMotion })] });
87097
87329
  }
87098
87330
  const NewTraceViewer = ({ run: run2, events: events2, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
87099
87331
  const trace2 = reactExports.useMemo(() => {
@@ -90466,6 +90698,19 @@ if (typeof globalThis !== "undefined") {
90466
90698
  });
90467
90699
  }
90468
90700
  }
90701
+ const RETRYABLE_WORLD_ERROR_CODES = /* @__PURE__ */ new Set(["TRANSPORT", "TIMEOUT"]);
90702
+ function isRetryableWorldError(err) {
90703
+ if (ThrottleError.is(err)) {
90704
+ return true;
90705
+ }
90706
+ if (!WorkflowWorldError.is(err)) {
90707
+ return false;
90708
+ }
90709
+ if (err.status !== void 0 && err.status >= 500) {
90710
+ return true;
90711
+ }
90712
+ return err.code !== void 0 && RETRYABLE_WORLD_ERROR_CODES.has(err.code);
90713
+ }
90469
90714
  const colorEnabled = (() => {
90470
90715
  var _a3;
90471
90716
  const p2 = globalThis.process;
@@ -90790,7 +91035,7 @@ async function deserializeTraceCarrier(traceCarrier) {
90790
91035
  }
90791
91036
  const OtelApi = once$1(async () => {
90792
91037
  try {
90793
- return await import("./index-meg9qk8y.js");
91038
+ return await import("./index-Dq5jTBN4.js");
90794
91039
  } catch {
90795
91040
  runtimeLogger.info("OpenTelemetry not available, tracing will be disabled");
90796
91041
  return null;
@@ -91006,7 +91251,7 @@ const encryption = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePr
91006
91251
  encrypt: encrypt$1,
91007
91252
  importKey
91008
91253
  }, Symbol.toStringTag, { value: "Module" }));
91009
- const version$1 = "5.0.0-beta.24";
91254
+ const version$1 = "5.0.0-beta.26";
91010
91255
  const WorldCacheKey = Symbol.for("@workflow/world//cache");
91011
91256
  const WorldCachePromiseKey = Symbol.for("@workflow/world//cachePromise");
91012
91257
  const GetWorldFnKey$1 = Symbol.for("@workflow/world//getWorldFn");
@@ -92620,7 +92865,16 @@ function createReconnectingFramedStream(runId, name2, startIndex) {
92620
92865
  }
92621
92866
  const STREAM_FLUSH_INTERVAL_MS = 10;
92622
92867
  class WorkflowServerWritableStream extends WritableStream {
92623
- constructor(runId, name2) {
92868
+ /**
92869
+ * @param runReadyBarrier Turbo mode only: a promise that resolves once the
92870
+ * backgrounded `run_started` has landed. When the step body runs
92871
+ * optimistically (before `run_started` is durable), the first chunk write to
92872
+ * a brand-new stream would otherwise reach the World before the run exists
92873
+ * and be rejected as run-not-found. Awaiting this once before the first
92874
+ * flush/close orders the write after the run's creation. `undefined` outside
92875
+ * turbo and on the await path, where the run was already durable.
92876
+ */
92877
+ constructor(runId, name2, runReadyBarrier) {
92624
92878
  if (typeof runId !== "string") {
92625
92879
  throw new WorkflowRuntimeError(`"runId" must be a string, got "${typeof runId}"`);
92626
92880
  }
@@ -92628,6 +92882,16 @@ class WorkflowServerWritableStream extends WritableStream {
92628
92882
  throw new WorkflowRuntimeError(`"name" is required, got "${name2}"`);
92629
92883
  }
92630
92884
  const worldPromise = getWorldLazy();
92885
+ let pendingRunReady = runReadyBarrier;
92886
+ const ensureRunReady = async () => {
92887
+ if (pendingRunReady) {
92888
+ try {
92889
+ await pendingRunReady;
92890
+ } catch {
92891
+ }
92892
+ pendingRunReady = void 0;
92893
+ }
92894
+ };
92631
92895
  let buffer2 = [];
92632
92896
  let flushTimer = null;
92633
92897
  let flushPromise = null;
@@ -92639,6 +92903,7 @@ class WorkflowServerWritableStream extends WritableStream {
92639
92903
  }
92640
92904
  if (buffer2.length === 0)
92641
92905
  return;
92906
+ await ensureRunReady();
92642
92907
  const chunksToFlush = buffer2.slice();
92643
92908
  const world = await worldPromise;
92644
92909
  if (resolvedFlushIntervalMs === void 0) {
@@ -92688,6 +92953,7 @@ class WorkflowServerWritableStream extends WritableStream {
92688
92953
  flushPromise = null;
92689
92954
  }
92690
92955
  await flush();
92956
+ await ensureRunReady();
92691
92957
  const world = await worldPromise;
92692
92958
  await world.streams.close(runId, name2);
92693
92959
  },
@@ -92803,7 +93069,7 @@ function attachAbortListenerOnce(signal, streamName, runId, cryptoKey, ops) {
92803
93069
  })());
92804
93070
  }, { once: true });
92805
93071
  }
92806
- function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false) {
93072
+ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
92807
93073
  return {
92808
93074
  ...getAllBaseReducers(global2),
92809
93075
  ReadableStream: (value) => {
@@ -92817,7 +93083,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
92817
93083
  const streamId = (global2[STABLE_ULID] || defaultUlid)();
92818
93084
  const name2 = `strm_${streamId}`;
92819
93085
  const type = getStreamType(value);
92820
- const writable = new WorkflowServerWritableStream(runId, name2);
93086
+ const writable = new WorkflowServerWritableStream(runId, name2, runReadyBarrier);
92821
93087
  if (type === "bytes") {
92822
93088
  if (framedByteStreams) {
92823
93089
  ops.push(value.pipeThrough(getByteFramingStream()).pipeTo(writable));
@@ -92825,7 +93091,7 @@ function getExternalReducers(global2 = globalThis, ops, runId, cryptoKey, framed
92825
93091
  ops.push(value.pipeTo(writable));
92826
93092
  }
92827
93093
  } else {
92828
- ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams), cryptoKey)).pipeTo(writable));
93094
+ ops.push(value.pipeThrough(getSerializeStream(getExternalReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
92829
93095
  }
92830
93096
  const s2 = { name: name2 };
92831
93097
  if (type)
@@ -92935,7 +93201,7 @@ function getWorkflowReducers(global2 = globalThis) {
92935
93201
  }
92936
93202
  };
92937
93203
  }
92938
- function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false) {
93204
+ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByteStreams = false, runReadyBarrier) {
92939
93205
  return {
92940
93206
  ...getAllBaseReducers(global2),
92941
93207
  ReadableStream: (value) => {
@@ -92954,7 +93220,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
92954
93220
  name2 = `strm_${streamId}`;
92955
93221
  type = getStreamType(value);
92956
93222
  framing = type === "bytes" && framedByteStreams ? "framed-v1" : framing;
92957
- const writable = new WorkflowServerWritableStream(runId, name2);
93223
+ const writable = new WorkflowServerWritableStream(runId, name2, runReadyBarrier);
92958
93224
  if (type === "bytes") {
92959
93225
  if (framing === "framed-v1") {
92960
93226
  ops.push(value.pipeThrough(getByteFramingStream()).pipeTo(writable));
@@ -92962,7 +93228,7 @@ function getStepReducers(global2 = globalThis, ops, runId, cryptoKey, framedByte
92962
93228
  ops.push(value.pipeTo(writable));
92963
93229
  }
92964
93230
  } else {
92965
- ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams), cryptoKey)).pipeTo(writable));
93231
+ ops.push(value.pipeThrough(getSerializeStream(getStepReducers(global2, ops, runId, cryptoKey, framedByteStreams, runReadyBarrier), cryptoKey)).pipeTo(writable));
92966
93232
  }
92967
93233
  }
92968
93234
  const s2 = { name: name2 };
@@ -93568,16 +93834,16 @@ async function hydrateStepArguments(value, runId, key, ops = [], global2 = globa
93568
93834
  await recordCompression(compressionStats, "deserialize");
93569
93835
  return result;
93570
93836
  }
93571
- async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false) {
93837
+ async function dehydrateStepReturnValue(value, runId, key, ops = [], global2 = globalThis, v1Compat = false, framedByteStreams = false, compression = false, runReadyBarrier) {
93572
93838
  if (v1Compat) {
93573
- const str = stringify$2(value, getStepReducers(global2, ops, runId, key, framedByteStreams));
93839
+ const str = stringify$2(value, getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier));
93574
93840
  return revive(str);
93575
93841
  }
93576
93842
  try {
93577
93843
  const compressionStats = {};
93578
93844
  const result = await serialize(value, key, {
93579
93845
  global: global2,
93580
- extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams)),
93846
+ extraReducers: getStreamAndRequestReducers(getStepReducers(global2, ops, runId, key, framedByteStreams, runReadyBarrier)),
93581
93847
  compression,
93582
93848
  compressionStats
93583
93849
  });
@@ -93936,6 +94202,9 @@ function stripTag(fileId) {
93936
94202
  function hasTag(fileId, tag) {
93937
94203
  return fileId.endsWith(`.${tag}`);
93938
94204
  }
94205
+ function isUntagged(fileId) {
94206
+ return !TAG_PATTERN.test(fileId);
94207
+ }
93939
94208
  function taggedPath(basedir, entityDir, fileId, tag) {
93940
94209
  assertSafeEntityId("fileId", fileId);
93941
94210
  if (tag !== void 0)
@@ -94362,7 +94631,7 @@ async function initDataDir(dataDir) {
94362
94631
  let otelApiPromise$1 = null;
94363
94632
  async function getOtelApi$1() {
94364
94633
  if (!otelApiPromise$1) {
94365
- otelApiPromise$1 = import("./index-meg9qk8y.js").catch(() => null);
94634
+ otelApiPromise$1 = import("./index-Dq5jTBN4.js").catch(() => null);
94366
94635
  }
94367
94636
  return otelApiPromise$1;
94368
94637
  }
@@ -120174,34 +120443,54 @@ function createQueue$2(config2) {
120174
120443
  await semaphore.acquire();
120175
120444
  }
120176
120445
  const MAX_LOCAL_SAFETY_LIMIT = 256;
120446
+ let delivery = 0;
120177
120447
  try {
120178
- for (let attempt = 0; attempt < MAX_LOCAL_SAFETY_LIMIT; attempt++) {
120448
+ for (let loop = 0; loop < MAX_LOCAL_SAFETY_LIMIT; loop++) {
120179
120449
  const headers2 = {
120180
120450
  ...opts == null ? void 0 : opts.headers,
120181
120451
  "content-type": "application/json",
120182
120452
  "x-vqs-queue-name": queueName,
120183
120453
  "x-vqs-message-id": messageId,
120184
- "x-vqs-message-attempt": String(attempt + 1)
120454
+ "x-vqs-message-attempt": String(delivery + 1)
120185
120455
  };
120186
120456
  const directHandler = directHandlers.get(prefix);
120187
120457
  let response2;
120188
- if (directHandler) {
120189
- const req = new Request(`http://localhost/.well-known/workflow/v1/${pathname}`, {
120190
- method: "POST",
120191
- headers: headers2,
120192
- body: body2
120193
- });
120194
- response2 = await directHandler(req);
120195
- } else {
120196
- const baseUrl = await resolveBaseUrl$1(config2);
120197
- response2 = await fetch(`${baseUrl}/.well-known/workflow/v1/${pathname}`, {
120198
- method: "POST",
120199
- duplex: "half",
120200
- dispatcher: httpAgent,
120201
- headers: headers2,
120202
- body: body2
120458
+ try {
120459
+ if (directHandler) {
120460
+ const req = new Request(`http://localhost/.well-known/workflow/v1/${pathname}`, {
120461
+ method: "POST",
120462
+ headers: headers2,
120463
+ body: body2
120464
+ });
120465
+ response2 = await directHandler(req);
120466
+ } else {
120467
+ const baseUrl = await resolveBaseUrl$1(config2);
120468
+ response2 = await fetch(`${baseUrl}/.well-known/workflow/v1/${pathname}`, {
120469
+ method: "POST",
120470
+ duplex: "half",
120471
+ dispatcher: httpAgent,
120472
+ headers: headers2,
120473
+ body: body2
120474
+ });
120475
+ }
120476
+ } catch (err) {
120477
+ const name2 = err == null ? void 0 : err.name;
120478
+ if (closeSignal.aborted || name2 === "AbortError" || name2 === "ResponseAborted") {
120479
+ return;
120480
+ }
120481
+ if (isDetachedArrayBufferQueueError(err))
120482
+ throw err;
120483
+ console.error(`[world-local] Queue delivery failed at the transport (loop ${loop + 1}), retrying`, {
120484
+ queueName,
120485
+ messageId,
120486
+ ...runId && { runId },
120487
+ ...stepId && { stepId },
120488
+ error: String(err)
120203
120489
  });
120490
+ await setTimeout$1(5e3, void 0, { signal: closeSignal });
120491
+ continue;
120204
120492
  }
120493
+ delivery++;
120205
120494
  const text2 = await response2.text();
120206
120495
  if (response2.ok) {
120207
120496
  try {
@@ -120219,7 +120508,7 @@ function createQueue$2(config2) {
120219
120508
  }
120220
120509
  return;
120221
120510
  }
120222
- console.error(`[world-local] Queue message failed (attempt ${attempt + 1}, HTTP ${response2.status})`, {
120511
+ console.error(`[world-local] Queue message failed (attempt ${delivery}, HTTP ${response2.status})`, {
120223
120512
  queueName,
120224
120513
  messageId,
120225
120514
  ...runId && { runId },
@@ -121930,13 +122219,14 @@ function createLocalWorld(args) {
121930
122219
  if (!recoverActiveRuns) {
121931
122220
  return;
121932
122221
  }
121933
- const recoveryRuns = tag ? {
122222
+ const fileIdFilter = tag ? (fileId) => hasTag(fileId, tag) : isUntagged;
122223
+ const recoveryRuns = {
121934
122224
  ...storage.runs,
121935
122225
  list: ((params) => storage.runs.list({
121936
122226
  ...params,
121937
- fileIdFilter: (fileId) => hasTag(fileId, tag)
122227
+ fileIdFilter
121938
122228
  }))
121939
- } : storage.runs;
122229
+ };
121940
122230
  await reenqueueActiveRuns(recoveryRuns, queue.queue, "world-local");
121941
122231
  },
121942
122232
  async close() {
@@ -121947,7 +122237,7 @@ function createLocalWorld(args) {
121947
122237
  const basedir = mergedConfig.dataDir;
121948
122238
  const hooksDir = path$3.join(basedir, "hooks");
121949
122239
  const taggedHookFiles = await listTaggedFiles(hooksDir, tag);
121950
- const { HookSchema: HookSchema2 } = await import("./index-BOfd00Ok.js");
122240
+ const { HookSchema: HookSchema2 } = await import("./index-BgRt1-Z6.js");
121951
122241
  await Promise.all(taggedHookFiles.map(async (hookFile) => {
121952
122242
  const hook = await readJSON(path$3.join(hooksDir, hookFile), HookSchema2);
121953
122243
  if (hook == null ? void 0 : hook.token) {
@@ -121982,6 +122272,67 @@ function createLocalWorld(args) {
121982
122272
  }
121983
122273
  };
121984
122274
  }
122275
+ let _dispatcher;
122276
+ let _eventsDispatcher;
122277
+ let _streamDispatcher;
122278
+ const BASE_AGENT_OPTIONS = {
122279
+ connections: 8,
122280
+ keepAliveTimeout: 1e4,
122281
+ // HTTP/1.1 pipelining is disabled (pipelining: 1) because it causes
122282
+ // head-of-line blocking that deadlocks the webhook respondWith mechanism.
122283
+ pipelining: 1
122284
+ };
122285
+ const DEFAULT_AGENT_OPTIONS = {
122286
+ ...BASE_AGENT_OPTIONS,
122287
+ allowH2: false
122288
+ };
122289
+ const EVENTS_AGENT_OPTIONS = {
122290
+ ...BASE_AGENT_OPTIONS,
122291
+ allowH2: true
122292
+ };
122293
+ const RETRY_AGENT_OPTIONS = {
122294
+ // Observe Retry-After header if received
122295
+ retryAfter: true,
122296
+ // Retry 5xx in-process (genuine transient blips recover fast), but NOT 429.
122297
+ // The Vercel firewall issues a challenge as a 429: our server-to-server
122298
+ // client cannot solve a challenge, so in-process retries just re-trigger it
122299
+ // ~5× per request and amplify load against an already-overloaded firewall
122300
+ // during an incident. Letting 429 pass through surfaces it immediately to
122301
+ // makeRequest — which maps it to a ThrottleError carrying the
122302
+ // `x-vercel-mitigated` / `x-vercel-id` headers — and the queue does the
122303
+ // (backed-off) retry instead. This is the long-standing "let 429s pass
122304
+ // through" intent. (undici default is [500, 502, 503, 504, 429].)
122305
+ statusCodes: [500, 502, 503, 504]
122306
+ };
122307
+ const STREAM_RETRY_OPTIONS = {
122308
+ retryAfter: true,
122309
+ methods: ["PUT"],
122310
+ statusCodes: [429]
122311
+ };
122312
+ function getDispatcher(config2) {
122313
+ return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultDispatcher();
122314
+ }
122315
+ function getEventsDispatcher(config2) {
122316
+ return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultEventsDispatcher();
122317
+ }
122318
+ function getStreamDispatcher(config2) {
122319
+ return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultStreamDispatcher();
122320
+ }
122321
+ function makeRetryDispatcher(agentOptions, retryOptions) {
122322
+ return new undiciExports.RetryAgent(new undiciExports.Agent(agentOptions), retryOptions);
122323
+ }
122324
+ function getDefaultDispatcher() {
122325
+ _dispatcher ?? (_dispatcher = makeRetryDispatcher(DEFAULT_AGENT_OPTIONS, RETRY_AGENT_OPTIONS));
122326
+ return _dispatcher;
122327
+ }
122328
+ function getDefaultEventsDispatcher() {
122329
+ _eventsDispatcher ?? (_eventsDispatcher = makeRetryDispatcher(EVENTS_AGENT_OPTIONS, RETRY_AGENT_OPTIONS));
122330
+ return _eventsDispatcher;
122331
+ }
122332
+ function getDefaultStreamDispatcher() {
122333
+ _streamDispatcher ?? (_streamDispatcher = makeRetryDispatcher(EVENTS_AGENT_OPTIONS, STREAM_RETRY_OPTIONS));
122334
+ return _streamDispatcher;
122335
+ }
121985
122336
  var getContext_1;
121986
122337
  var hasRequiredGetContext;
121987
122338
  function requireGetContext() {
@@ -122100,8 +122451,8 @@ function requireGetVercelOidcToken() {
122100
122451
  }
122101
122452
  try {
122102
122453
  const [{ getTokenPayload, isExpired }, { refreshToken }] = await Promise.all([
122103
- await import("./token-util-MV-dKCwg.js").then((n) => n.t),
122104
- await import("./token-fPsafoXW.js").then((n) => n.t)
122454
+ await import("./token-util-CaJAmsYa.js").then((n) => n.t),
122455
+ await import("./token-DK_R23fr.js").then((n) => n.t)
122105
122456
  ]);
122106
122457
  if (!token || isExpired(getTokenPayload(token), options == null ? void 0 : options.expirationBufferMs)) {
122107
122458
  await refreshToken(options);
@@ -122664,32 +123015,218 @@ function requireDist() {
122664
123015
  return dist;
122665
123016
  }
122666
123017
  var distExports = requireDist();
122667
- let _dispatcher;
122668
- function getDispatcher(config2) {
122669
- return (config2 == null ? void 0 : config2.dispatcher) ?? getDefaultDispatcher();
123018
+ let otelApiPromise = null;
123019
+ async function getOtelApi() {
123020
+ if (!otelApiPromise) {
123021
+ otelApiPromise = import("./index-Dq5jTBN4.js").catch(() => null);
123022
+ }
123023
+ return otelApiPromise;
122670
123024
  }
122671
- function getDefaultDispatcher() {
122672
- if (!_dispatcher) {
122673
- _dispatcher = new undiciExports.RetryAgent(new undiciExports.Agent({
122674
- connections: 8,
122675
- keepAliveTimeout: 1e4,
122676
- // H2 is specifically incompatible with SvelteKit on Vercel prod. Everything else
122677
- // runs fine.
122678
- // TODO: Investigate/fix the failure on SvelteKit so we can re-enable H2.
122679
- allowH2: false,
122680
- // HTTP/1.1 pipelining is disabled (pipelining: 1) because it causes
122681
- // head-of-line blocking that deadlocks the webhook respondWith mechanism.
122682
- pipelining: 1
122683
- }), {
122684
- // Observe Retry-After header if received
122685
- retryAfter: true
122686
- // By default, we observe re-try headers, and also separately
122687
- // re-try on these status codes: 429 / 500 / 502 / 503 / 504.
122688
- // TODO: We might want to let 429s pass through, so that we can do
122689
- // runtime retry-after handling through the queue.
122690
- });
123025
+ let tracerPromise = null;
123026
+ async function getTracer() {
123027
+ if (!tracerPromise) {
123028
+ tracerPromise = getOtelApi().then((otel) => otel ? otel.trace.getTracer("workflow") : null);
122691
123029
  }
122692
- return _dispatcher;
123030
+ return tracerPromise;
123031
+ }
123032
+ async function trace(spanName2, ...args) {
123033
+ const [tracer, otel] = await Promise.all([getTracer(), getOtelApi()]);
123034
+ const { fn: fn2, opts } = typeof args[0] === "function" ? { fn: args[0], opts: {} } : { fn: args[1], opts: args[0] };
123035
+ if (!fn2)
123036
+ throw new Error("Function to trace must be provided");
123037
+ if (!tracer || !otel) {
123038
+ return await fn2();
123039
+ }
123040
+ return tracer.startActiveSpan(spanName2, opts, async (span) => {
123041
+ try {
123042
+ const result = await fn2(span);
123043
+ span.setStatus({ code: otel.SpanStatusCode.OK });
123044
+ return result;
123045
+ } catch (e) {
123046
+ span.setStatus({
123047
+ code: otel.SpanStatusCode.ERROR,
123048
+ message: e.message
123049
+ });
123050
+ throw e;
123051
+ } finally {
123052
+ span.end();
123053
+ }
123054
+ });
123055
+ }
123056
+ async function getSpanKind(field) {
123057
+ const otel = await getOtelApi();
123058
+ if (!otel)
123059
+ return void 0;
123060
+ return otel.SpanKind[field];
123061
+ }
123062
+ async function injectTraceContextIntoHeaders(headers2) {
123063
+ const otel = await getOtelApi();
123064
+ if (!otel)
123065
+ return;
123066
+ const carrier = {};
123067
+ otel.propagation.inject(otel.context.active(), carrier);
123068
+ for (const [key, value] of Object.entries(carrier)) {
123069
+ headers2.set(key, value);
123070
+ }
123071
+ }
123072
+ function SemanticConvention(...names) {
123073
+ return (value) => Object.fromEntries(names.map((name2) => [name2, value]));
123074
+ }
123075
+ const HttpRequestMethod = SemanticConvention("http.request.method");
123076
+ const UrlFull = SemanticConvention("url.full");
123077
+ const ServerAddress = SemanticConvention("server.address");
123078
+ const ServerPort = SemanticConvention("server.port");
123079
+ const HttpResponseStatusCode = SemanticConvention("http.response.status_code");
123080
+ const ErrorType = SemanticConvention("error.type");
123081
+ const WorldParseFormat = SemanticConvention("workflow.world.parse.format");
123082
+ const PeerService = SemanticConvention("peer.service");
123083
+ const RpcSystem = SemanticConvention("rpc.system");
123084
+ const RpcService = SemanticConvention("rpc.service");
123085
+ const RpcMethod = SemanticConvention("rpc.method");
123086
+ const WorkflowRunId = SemanticConvention("workflow.run.id");
123087
+ const StepId = SemanticConvention("step.id");
123088
+ const REQUEST_TIMEOUT_MS = 6e4;
123089
+ const HTTP_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
123090
+ const DIAGNOSTIC_HEADERS = [
123091
+ "x-vercel-id",
123092
+ "x-vercel-error",
123093
+ "x-vercel-mitigated"
123094
+ ];
123095
+ function getVercelDiagnostics(headers2) {
123096
+ return DIAGNOSTIC_HEADERS.flatMap((header) => {
123097
+ const value = headers2.get(header);
123098
+ return value ? [`${header}=${value}`] : [];
123099
+ });
123100
+ }
123101
+ function formatVercelDiagnostics(headers2) {
123102
+ const diagnostics2 = getVercelDiagnostics(headers2);
123103
+ return diagnostics2.length > 0 ? ` (${diagnostics2.join("; ")})` : "";
123104
+ }
123105
+ function httpLog(method, label, response2, ms2) {
123106
+ if (!HTTP_DEBUG_ENABLED)
123107
+ return;
123108
+ const diagnostics2 = getVercelDiagnostics(response2.headers);
123109
+ const suffix = diagnostics2.length > 0 ? `; ${diagnostics2.join("; ")}` : "";
123110
+ console.debug(`[workflow:world-vercel:http] ${method} ${label} -> ${response2.status} (${ms2}ms${suffix})`);
123111
+ }
123112
+ function logCurlRepro(method, url2, headers2) {
123113
+ if (!process.env.DEBUG)
123114
+ return;
123115
+ const stringifiedHeaders = Array.from(headers2.entries()).filter(([key]) => key.toLowerCase() !== "authorization").map(([key, value]) => `-H "${key}: ${value}"`).join(" ");
123116
+ console.error(`Failed to fetch, reproduce with:
123117
+ curl -X ${method} ${stringifiedHeaders} "${url2}"`);
123118
+ }
123119
+ function parseRetryAfter(value) {
123120
+ if (!value)
123121
+ return void 0;
123122
+ const parsed = parseInt(value, 10);
123123
+ return Number.isNaN(parsed) ? void 0 : parsed;
123124
+ }
123125
+ function errorForResponse(status, message2, opts = {}) {
123126
+ const { retryAfter, code: code2, url: url2, mitigated } = opts;
123127
+ if (status === 409)
123128
+ return new EntityConflictError(message2);
123129
+ if (status === 410)
123130
+ return new RunExpiredError(message2);
123131
+ if (status === 425)
123132
+ return new TooEarlyError(message2, { retryAfter });
123133
+ if (status === 429) {
123134
+ if (isFirewallChallenge429(status, mitigated)) {
123135
+ return new WorkflowWorldError(`${message2} (x-vercel-mitigated=challenge)`, {
123136
+ url: url2,
123137
+ status,
123138
+ code: "TRANSPORT",
123139
+ retryAfter
123140
+ });
123141
+ }
123142
+ return new ThrottleError(message2, { retryAfter });
123143
+ }
123144
+ return new WorkflowWorldError(message2, { url: url2, status, code: code2, retryAfter });
123145
+ }
123146
+ function isFirewallChallenge429(status, mitigated) {
123147
+ return status === 429 && mitigated === "challenge";
123148
+ }
123149
+ async function resolveVercelApiToken(opts) {
123150
+ return (opts == null ? void 0 : opts.token) ?? process.env.VERCEL_TOKEN ?? await distExports.getVercelOidcToken().catch(() => null);
123151
+ }
123152
+ function parseServer(url2) {
123153
+ try {
123154
+ const parsed = new URL(url2);
123155
+ return {
123156
+ serverAddress: parsed.hostname,
123157
+ serverPort: parsed.port ? parseInt(parsed.port, 10) : parsed.protocol === "https:" ? 443 : 80
123158
+ };
123159
+ } catch {
123160
+ return {};
123161
+ }
123162
+ }
123163
+ function httpClientSpanAttributes(args) {
123164
+ const { method, url: url2, peerService } = args;
123165
+ const { serverAddress, serverPort } = parseServer(url2);
123166
+ return {
123167
+ ...HttpRequestMethod(method),
123168
+ ...UrlFull(url2),
123169
+ ...serverAddress ? ServerAddress(serverAddress) : {},
123170
+ ...serverPort ? ServerPort(serverPort) : {},
123171
+ ...PeerService(peerService),
123172
+ ...RpcSystem("http"),
123173
+ ...RpcService(peerService)
123174
+ };
123175
+ }
123176
+ async function instrumentedFetch(opts) {
123177
+ const { method, url: url2, headers: headers2, body: body2, dispatcher: dispatcher2, peerService = "workflow-server", timeoutMs = REQUEST_TIMEOUT_MS, signal: callerSignal, injectTraceContext = true, cacheBust = true, logLabel, buildError } = opts;
123178
+ const label = logLabel ?? url2;
123179
+ return trace(`http ${method}`, { kind: await getSpanKind("CLIENT") }, async (span) => {
123180
+ var _a3, _b2, _c2;
123181
+ span == null ? void 0 : span.setAttributes(httpClientSpanAttributes({ method, url: url2, peerService }));
123182
+ if (injectTraceContext)
123183
+ await injectTraceContextIntoHeaders(headers2);
123184
+ if (cacheBust)
123185
+ headers2.set("X-Request-Time", Date.now().toString());
123186
+ const timeoutSignal = timeoutMs != null ? AbortSignal.timeout(timeoutMs) : void 0;
123187
+ const signal = callerSignal && timeoutSignal ? AbortSignal.any([callerSignal, timeoutSignal]) : callerSignal ?? timeoutSignal;
123188
+ const start2 = Date.now();
123189
+ let response2;
123190
+ try {
123191
+ response2 = await fetch(url2, {
123192
+ method,
123193
+ headers: headers2,
123194
+ body: body2,
123195
+ signal,
123196
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici dispatcher type doesn't match @types/node's RequestInit
123197
+ dispatcher: dispatcher2
123198
+ });
123199
+ } catch (error2) {
123200
+ const elapsed = Date.now() - start2;
123201
+ if (error2 instanceof Error && (error2.name === "TimeoutError" || error2.name === "AbortError")) {
123202
+ const timeoutError = new WorkflowWorldError(`${method} ${label} timed out after ${elapsed}ms`, { url: url2, cause: error2 });
123203
+ span == null ? void 0 : span.setAttributes({ ...ErrorType("TIMEOUT") });
123204
+ (_a3 = span == null ? void 0 : span.recordException) == null ? void 0 : _a3.call(span, timeoutError);
123205
+ throw timeoutError;
123206
+ }
123207
+ throw error2;
123208
+ }
123209
+ const ms2 = Date.now() - start2;
123210
+ httpLog(method, label, response2, ms2);
123211
+ span == null ? void 0 : span.setAttributes({ ...HttpResponseStatusCode(response2.status) });
123212
+ if (!response2.ok) {
123213
+ span == null ? void 0 : span.setAttributes({ ...ErrorType(`HTTP ${response2.status}`) });
123214
+ logCurlRepro(method, url2, headers2);
123215
+ if (buildError) {
123216
+ const error3 = await buildError(response2);
123217
+ (_b2 = span == null ? void 0 : span.recordException) == null ? void 0 : _b2.call(span, error3);
123218
+ throw error3;
123219
+ }
123220
+ const text2 = await response2.text().catch(() => "");
123221
+ const error2 = errorForResponse(response2.status, `${method} ${label} -> HTTP ${response2.status}: ${response2.statusText}${text2 ? ` ${text2}` : ""}${formatVercelDiagnostics(response2.headers)}`, {
123222
+ url: url2,
123223
+ retryAfter: parseRetryAfter(response2.headers.get("Retry-After"))
123224
+ });
123225
+ (_c2 = span == null ? void 0 : span.recordException) == null ? void 0 : _c2.call(span, error2);
123226
+ throw error2;
123227
+ }
123228
+ return response2;
123229
+ });
122693
123230
  }
122694
123231
  const KEY_BYTES = 32;
122695
123232
  async function deriveRunKey(deploymentKey, projectId, runId) {
@@ -122715,7 +123252,7 @@ async function deriveRunKey(deploymentKey, projectId, runId) {
122715
123252
  return new Uint8Array(derivedBits);
122716
123253
  }
122717
123254
  async function fetchRunKey(deploymentId, projectId, runId, options) {
122718
- const token = (options == null ? void 0 : options.token) ?? process.env.VERCEL_TOKEN ?? await distExports.getVercelOidcToken().catch(() => null);
123255
+ const token = await resolveVercelApiToken({ token: options == null ? void 0 : options.token });
122719
123256
  if (!token) {
122720
123257
  throw new Error("Cannot fetch run key: no OIDC token or VERCEL_TOKEN available");
122721
123258
  }
@@ -122723,23 +123260,25 @@ async function fetchRunKey(deploymentId, projectId, runId, options) {
122723
123260
  if (options == null ? void 0 : options.teamId) {
122724
123261
  params.set("teamId", options.teamId);
122725
123262
  }
122726
- const response2 = await fetch(`https://api.vercel.com/v1/workflow/run-key/${deploymentId}?${params}`, {
123263
+ const response2 = await instrumentedFetch({
122727
123264
  method: "GET",
122728
- headers: {
122729
- Authorization: `Bearer ${token}`
122730
- },
122731
- // @ts-expect-error -- undici dispatcher is accepted by Node.js fetch but not in @types/node's RequestInit
122732
- dispatcher: getDispatcher({ dispatcher: options == null ? void 0 : options.dispatcher })
122733
- });
122734
- if (!response2.ok) {
122735
- let body2;
122736
- try {
122737
- body2 = await response2.text();
122738
- } catch {
122739
- body2 = "<unable to read response body>";
123265
+ url: `https://api.vercel.com/v1/workflow/run-key/${deploymentId}?${params}`,
123266
+ headers: new Headers({ Authorization: `Bearer ${token}` }),
123267
+ dispatcher: getDispatcher({ dispatcher: options == null ? void 0 : options.dispatcher }),
123268
+ peerService: "vercel-api",
123269
+ // Preserve the prior no-timeout behavior for this Vercel-API call; the
123270
+ // shared RetryAgent still handles transient/5xx retries.
123271
+ timeoutMs: null,
123272
+ buildError: async (res) => {
123273
+ let body2;
123274
+ try {
123275
+ body2 = await res.text();
123276
+ } catch {
123277
+ body2 = "<unable to read response body>";
123278
+ }
123279
+ return new Error(`Failed to fetch run key for ${runId} (deployment ${deploymentId}): HTTP ${res.status} ${res.statusText}${body2 ? ` — ${body2}` : ""}`);
122740
123280
  }
122741
- throw new Error(`Failed to fetch run key for ${runId} (deployment ${deploymentId}): HTTP ${response2.status} ${response2.statusText}${body2 ? ` — ${body2}` : ""}`);
122742
- }
123281
+ });
122743
123282
  const data = await response2.json();
122744
123283
  const result = object$1({ key: string$3().nullable() }).safeParse(data);
122745
123284
  if (!result.success) {
@@ -122784,76 +123323,6 @@ function createGetEncryptionKeyForRun(projectId, teamId, token, dispatcher2) {
122784
123323
  });
122785
123324
  };
122786
123325
  }
122787
- let otelApiPromise = null;
122788
- async function getOtelApi() {
122789
- if (!otelApiPromise) {
122790
- otelApiPromise = import("./index-meg9qk8y.js").catch(() => null);
122791
- }
122792
- return otelApiPromise;
122793
- }
122794
- let tracerPromise = null;
122795
- async function getTracer() {
122796
- if (!tracerPromise) {
122797
- tracerPromise = getOtelApi().then((otel) => otel ? otel.trace.getTracer("workflow") : null);
122798
- }
122799
- return tracerPromise;
122800
- }
122801
- async function trace(spanName2, ...args) {
122802
- const [tracer, otel] = await Promise.all([getTracer(), getOtelApi()]);
122803
- const { fn: fn2, opts } = typeof args[0] === "function" ? { fn: args[0], opts: {} } : { fn: args[1], opts: args[0] };
122804
- if (!fn2)
122805
- throw new Error("Function to trace must be provided");
122806
- if (!tracer || !otel) {
122807
- return await fn2();
122808
- }
122809
- return tracer.startActiveSpan(spanName2, opts, async (span) => {
122810
- try {
122811
- const result = await fn2(span);
122812
- span.setStatus({ code: otel.SpanStatusCode.OK });
122813
- return result;
122814
- } catch (e) {
122815
- span.setStatus({
122816
- code: otel.SpanStatusCode.ERROR,
122817
- message: e.message
122818
- });
122819
- throw e;
122820
- } finally {
122821
- span.end();
122822
- }
122823
- });
122824
- }
122825
- async function getSpanKind(field) {
122826
- const otel = await getOtelApi();
122827
- if (!otel)
122828
- return void 0;
122829
- return otel.SpanKind[field];
122830
- }
122831
- async function injectTraceContextIntoHeaders(headers2) {
122832
- const otel = await getOtelApi();
122833
- if (!otel)
122834
- return;
122835
- const carrier = {};
122836
- otel.propagation.inject(otel.context.active(), carrier);
122837
- for (const [key, value] of Object.entries(carrier)) {
122838
- headers2.set(key, value);
122839
- }
122840
- }
122841
- function SemanticConvention(...names) {
122842
- return (value) => Object.fromEntries(names.map((name2) => [name2, value]));
122843
- }
122844
- const HttpRequestMethod = SemanticConvention("http.request.method");
122845
- const UrlFull = SemanticConvention("url.full");
122846
- const ServerAddress = SemanticConvention("server.address");
122847
- const ServerPort = SemanticConvention("server.port");
122848
- const HttpResponseStatusCode = SemanticConvention("http.response.status_code");
122849
- const ErrorType = SemanticConvention("error.type");
122850
- const WorldParseFormat = SemanticConvention("workflow.world.parse.format");
122851
- const PeerService = SemanticConvention("peer.service");
122852
- const RpcSystem = SemanticConvention("rpc.system");
122853
- const RpcService = SemanticConvention("rpc.service");
122854
- const RpcMethod = SemanticConvention("rpc.method");
122855
- const WorkflowRunId = SemanticConvention("workflow.run.id");
122856
- const StepId = SemanticConvention("step.id");
122857
123326
  const WORKFLOW_SERVER_SERVICE = {
122858
123327
  peerService: "workflow-server",
122859
123328
  rpcSystem: "http",
@@ -127450,29 +127919,37 @@ var QueueClient = class {
127450
127919
  setApi(this, new ApiClient({ ...options, region }));
127451
127920
  }
127452
127921
  };
127453
- const version = "5.0.0-beta.20";
127454
- const HTTP_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
127455
- function httpLog(method, endpoint, response2, ms2) {
127456
- if (HTTP_DEBUG_ENABLED) {
127457
- const responseContext = getResponseDiagnosticHeaders(response2);
127458
- const diagnosticSuffix = responseContext.length > 0 ? `; ${responseContext.join("; ")}` : "";
127459
- console.debug(`[workflow:world-vercel:http] ${method} ${endpoint} -> ${response2.status} (${ms2}ms${diagnosticSuffix})`);
127460
- }
127461
- }
127462
- function getResponseDiagnosticHeaders(response2) {
127463
- return ["x-vercel-id", "x-vercel-error"].flatMap((header) => {
127464
- const value = response2.headers.get(header);
127465
- return value ? [`${header}=${value}`] : [];
127466
- });
127467
- }
127468
- function formatResponseDiagnostics(response2) {
127469
- const headers2 = getResponseDiagnosticHeaders(response2);
127470
- return headers2.length > 0 ? ` (${headers2.join("; ")})` : "";
127471
- }
127472
- const REQUEST_TIMEOUT_MS = 6e4;
127922
+ const version = "5.0.0-beta.22";
127473
127923
  const IDEMPOTENT_METHODS = /* @__PURE__ */ new Set(["GET", "HEAD"]);
127474
127924
  const MAX_BODY_PARSE_RETRIES = 2;
127475
127925
  const BODY_PARSE_RETRY_BASE_MS = 100;
127926
+ const TRANSIENT_TRANSPORT_ERROR_CODES = /* @__PURE__ */ new Set([
127927
+ "UND_ERR_REQ_RETRY",
127928
+ "UND_ERR_SOCKET",
127929
+ "UND_ERR_CONNECT",
127930
+ "UND_ERR_CONNECT_TIMEOUT",
127931
+ "UND_ERR_HEADERS_TIMEOUT",
127932
+ "UND_ERR_BODY_TIMEOUT",
127933
+ "UND_ERR_CLOSED",
127934
+ "ECONNRESET",
127935
+ "ECONNREFUSED",
127936
+ "ENOTFOUND",
127937
+ "EAI_AGAIN",
127938
+ "EPIPE"
127939
+ ]);
127940
+ function getTransientTransportCode(error2) {
127941
+ let current = error2;
127942
+ for (let depth = 0; current != null && depth < 5; depth++) {
127943
+ if (typeof current === "object" && "code" in current) {
127944
+ const code2 = current.code;
127945
+ if (typeof code2 === "string" && TRANSIENT_TRANSPORT_ERROR_CODES.has(code2)) {
127946
+ return code2;
127947
+ }
127948
+ }
127949
+ current = current == null ? void 0 : current.cause;
127950
+ }
127951
+ return void 0;
127952
+ }
127476
127953
  const getWorkflowServerUrlOverride = () => process.env.VERCEL_WORKFLOW_SERVER_URL || "";
127477
127954
  const DEFAULT_RESOLVE_DATA_OPTION = "all";
127478
127955
  function deserializeError(obj) {
@@ -127541,26 +128018,13 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
127541
128018
  const method = options.method || "GET";
127542
128019
  const { baseUrl, headers: headers2 } = await getHttpConfig(config2);
127543
128020
  const url2 = `${baseUrl}${endpoint}`;
127544
- let serverAddress;
127545
- let serverPort;
127546
- try {
127547
- const parsedUrl = new URL(url2);
127548
- serverAddress = parsedUrl.hostname;
127549
- serverPort = parsedUrl.port ? parseInt(parsedUrl.port, 10) : parsedUrl.protocol === "https:" ? 443 : 80;
127550
- } catch {
127551
- }
127552
128021
  return trace(`http ${method}`, { kind: await getSpanKind("CLIENT") }, async (span) => {
127553
- var _a3;
127554
- span == null ? void 0 : span.setAttributes({
127555
- ...HttpRequestMethod(method),
127556
- ...UrlFull(url2),
127557
- ...serverAddress && ServerAddress(serverAddress),
127558
- ...serverPort && ServerPort(serverPort),
127559
- // Peer service for Datadog service maps
127560
- ...PeerService("workflow-server"),
127561
- ...RpcSystem("http"),
127562
- ...RpcService("workflow-server")
127563
- });
128022
+ var _a3, _b2, _c2;
128023
+ span == null ? void 0 : span.setAttributes(httpClientSpanAttributes({
128024
+ method,
128025
+ url: url2,
128026
+ peerService: "workflow-server"
128027
+ }));
127564
128028
  headers2.set("Accept", "application/cbor");
127565
128029
  await injectTraceContextIntoHeaders(headers2);
127566
128030
  let body2;
@@ -127590,61 +128054,42 @@ async function makeRequest({ endpoint, options = {}, config: config2 = {}, schem
127590
128054
  } catch (error2) {
127591
128055
  const elapsed = Date.now() - fetchStart;
127592
128056
  if (error2 instanceof Error && (error2.name === "TimeoutError" || error2.name === "AbortError")) {
127593
- const timeoutError = new WorkflowWorldError(`${method} ${endpoint} timed out after ${elapsed}ms`, { url: url2, cause: error2 });
128057
+ const timeoutError = new WorkflowWorldError(`${method} ${endpoint} timed out after ${elapsed}ms`, { url: url2, code: "TIMEOUT", cause: error2 });
127594
128058
  span == null ? void 0 : span.setAttributes({ ...ErrorType("TIMEOUT") });
127595
128059
  (_a3 = span == null ? void 0 : span.recordException) == null ? void 0 : _a3.call(span, timeoutError);
127596
128060
  throw timeoutError;
127597
128061
  }
128062
+ const transportCode = getTransientTransportCode(error2);
128063
+ if (transportCode) {
128064
+ const transportError = new WorkflowWorldError(`${method} ${endpoint} transport failure after ${elapsed}ms (${transportCode})`, { url: url2, code: "TRANSPORT", cause: error2 });
128065
+ span == null ? void 0 : span.setAttributes({ ...ErrorType("TRANSPORT") });
128066
+ (_b2 = span == null ? void 0 : span.recordException) == null ? void 0 : _b2.call(span, transportError);
128067
+ throw transportError;
128068
+ }
127598
128069
  throw error2;
127599
128070
  }
127600
128071
  const fetchMs = Date.now() - fetchStart;
127601
- responseDiagnostics = formatResponseDiagnostics(response2);
128072
+ responseDiagnostics = formatVercelDiagnostics(response2.headers);
127602
128073
  httpLog(method, endpoint, response2, fetchMs);
127603
128074
  span == null ? void 0 : span.setAttributes({
127604
128075
  ...HttpResponseStatusCode(response2.status)
127605
128076
  });
127606
128077
  if (!response2.ok) {
127607
128078
  const errorData = await parseResponseBody(response2).then((r2) => r2.data).catch(() => ({}));
127608
- if (process.env.DEBUG) {
127609
- const stringifiedHeaders = Array.from(headers2.entries()).filter(([key]) => key.toLowerCase() !== "authorization").map(([key, value]) => `-H "${key}: ${value}"`).join(" ");
127610
- console.error(`Failed to fetch, reproduce with:
127611
- curl -X ${request2.method} ${stringifiedHeaders} "${url2}"`);
127612
- }
127613
- let retryAfter;
127614
- const retryAfterHeader = response2.headers.get("Retry-After");
127615
- if (retryAfterHeader) {
127616
- const parsed = parseInt(retryAfterHeader, 10);
127617
- if (!Number.isNaN(parsed)) {
127618
- retryAfter = parsed;
127619
- }
127620
- }
128079
+ logCurlRepro(request2.method, url2, headers2);
128080
+ const retryAfter = parseRetryAfter(response2.headers.get("Retry-After"));
127621
128081
  const defaultMessage = (errorData.message || `${request2.method} ${endpoint} -> HTTP ${response2.status}: ${response2.statusText}`) + responseDiagnostics;
127622
- const throwWithTrace = (error2) => {
127623
- var _a4;
127624
- span == null ? void 0 : span.setAttributes({
127625
- ...ErrorType(errorData.code || `HTTP ${response2.status}`)
127626
- });
127627
- (_a4 = span == null ? void 0 : span.recordException) == null ? void 0 : _a4.call(span, error2);
127628
- throw error2;
127629
- };
127630
- if (response2.status === 409) {
127631
- throwWithTrace(new EntityConflictError(defaultMessage));
127632
- }
127633
- if (response2.status === 410) {
127634
- throwWithTrace(new RunExpiredError(defaultMessage));
127635
- }
127636
- if (response2.status === 425) {
127637
- throwWithTrace(new TooEarlyError(defaultMessage, { retryAfter }));
127638
- }
127639
- if (response2.status === 429) {
127640
- throwWithTrace(new ThrottleError(defaultMessage, { retryAfter }));
127641
- }
127642
- throwWithTrace(new WorkflowWorldError(defaultMessage, {
128082
+ const error2 = errorForResponse(response2.status, defaultMessage, {
127643
128083
  url: url2,
127644
- status: response2.status,
127645
128084
  code: errorData.code,
127646
- retryAfter
127647
- }));
128085
+ retryAfter,
128086
+ mitigated: response2.headers.get("x-vercel-mitigated")
128087
+ });
128088
+ span == null ? void 0 : span.setAttributes({
128089
+ ...ErrorType(errorData.code || `HTTP ${response2.status}`)
128090
+ });
128091
+ (_c2 = span == null ? void 0 : span.recordException) == null ? void 0 : _c2.call(span, error2);
128092
+ throw error2;
127648
128093
  }
127649
128094
  onResponse == null ? void 0 : onResponse(response2);
127650
128095
  try {
@@ -127793,7 +128238,7 @@ const MAX_DELAY_SECONDS = Number(
127793
128238
  // 23 hours - leave 1h buffer before 24h retention limit
127794
128239
  );
127795
128240
  const HANDLER_ERROR_RETRY_AFTER_SECONDS = 1;
127796
- const HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS = 60;
128241
+ const HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS = 900;
127797
128242
  const HANDLER_ERROR_RETRY_JITTER_RATIO = 0.25;
127798
128243
  function getHandlerErrorRetryAfterSeconds(deliveryCount) {
127799
128244
  const backoffSeconds = Math.min(Math.max(HANDLER_ERROR_RETRY_AFTER_SECONDS, 2 ** (deliveryCount - 1)), HANDLER_ERROR_MAX_RETRY_AFTER_SECONDS);
@@ -127927,28 +128372,30 @@ function createResolveLatestDeploymentId(config2) {
127927
128372
  if (!currentDeploymentId) {
127928
128373
  throw new Error("Cannot resolve latest deployment: VERCEL_DEPLOYMENT_ID environment variable is not set");
127929
128374
  }
127930
- const token = (config2 == null ? void 0 : config2.token) ?? process.env.VERCEL_TOKEN ?? await distExports.getVercelOidcToken().catch(() => null);
128375
+ const token = await resolveVercelApiToken(config2);
127931
128376
  if (!token) {
127932
128377
  throw new Error("Cannot resolve latest deployment: no OIDC token or VERCEL_TOKEN available");
127933
128378
  }
127934
128379
  const url2 = `https://api.vercel.com/v1/workflow/resolve-latest-deployment/${encodeURIComponent(currentDeploymentId)}`;
127935
- const response2 = await fetch(url2, {
128380
+ const response2 = await instrumentedFetch({
127936
128381
  method: "GET",
127937
- headers: {
127938
- Authorization: `Bearer ${token}`
127939
- },
127940
- // @ts-expect-error -- undici dispatcher is accepted by Node.js fetch but not in @types/node's RequestInit
127941
- dispatcher: getDispatcher(config2)
127942
- });
127943
- if (!response2.ok) {
127944
- let body2;
127945
- try {
127946
- body2 = await response2.text();
127947
- } catch {
127948
- body2 = "<unable to read response body>";
128382
+ url: url2,
128383
+ headers: new Headers({ Authorization: `Bearer ${token}` }),
128384
+ dispatcher: getDispatcher(config2),
128385
+ peerService: "vercel-api",
128386
+ // Preserve the prior no-timeout behavior for this Vercel-API call; the
128387
+ // shared RetryAgent still handles transient/5xx retries.
128388
+ timeoutMs: null,
128389
+ buildError: async (res) => {
128390
+ let body2;
128391
+ try {
128392
+ body2 = await res.text();
128393
+ } catch {
128394
+ body2 = "<unable to read response body>";
128395
+ }
128396
+ return new Error(`Failed to resolve latest deployment for ${currentDeploymentId}: HTTP ${res.status} ${res.statusText}${body2 ? ` — ${body2}` : ""}`);
127949
128397
  }
127950
- throw new Error(`Failed to resolve latest deployment for ${currentDeploymentId}: HTTP ${response2.status} ${response2.statusText}${body2 ? ` — ${body2}` : ""}`);
127951
- }
128398
+ });
127952
128399
  const data = await response2.json();
127953
128400
  const result = ResolveLatestDeploymentResponseSchema.safeParse(data);
127954
128401
  if (!result.success) {
@@ -127957,6 +128404,181 @@ function createResolveLatestDeploymentId(config2) {
127957
128404
  return result.data.id;
127958
128405
  };
127959
128406
  }
128407
+ const EVENT_RETRY_ELIGIBILITY = {
128408
+ // Creates: conditional create → 409 EntityConflictError if it already exists.
128409
+ run_created: {
128410
+ retryable: true,
128411
+ reason: "conditional create → 409 if exists"
128412
+ },
128413
+ step_created: {
128414
+ retryable: true,
128415
+ reason: "conditional create → 409 if exists"
128416
+ },
128417
+ wait_created: {
128418
+ retryable: true,
128419
+ reason: "conditional create → 409 if exists"
128420
+ },
128421
+ hook_created: {
128422
+ retryable: true,
128423
+ reason: "transactional token uniqueness → 409 if exists"
128424
+ },
128425
+ // Run start: early-returns if already running, writes no duplicate row.
128426
+ run_started: {
128427
+ retryable: true,
128428
+ reason: "early-returns if already running, no duplicate row"
128429
+ },
128430
+ // Terminal transitions: conditional `.where()` excludes terminal states →
128431
+ // 409 before the event row is written.
128432
+ run_completed: {
128433
+ retryable: true,
128434
+ reason: "terminal-state guard → 409, no duplicate row"
128435
+ },
128436
+ run_failed: {
128437
+ retryable: true,
128438
+ reason: "terminal-state guard → 409, no duplicate row"
128439
+ },
128440
+ run_cancelled: {
128441
+ retryable: true,
128442
+ reason: "terminal-state guard → 409, no duplicate row"
128443
+ },
128444
+ step_completed: {
128445
+ retryable: true,
128446
+ reason: "terminal-state guard → 409, no duplicate row"
128447
+ },
128448
+ step_failed: {
128449
+ retryable: true,
128450
+ reason: "terminal-state guard → 409, no duplicate row"
128451
+ },
128452
+ wait_completed: {
128453
+ retryable: true,
128454
+ reason: "waiting-state guard → 409, no duplicate row"
128455
+ },
128456
+ hook_disposed: {
128457
+ retryable: true,
128458
+ reason: "conditional delete (exists) → 409, no duplicate row"
128459
+ },
128460
+ // True idempotency via a correlationId constraint that reuses the eventId.
128461
+ attr_set: {
128462
+ retryable: true,
128463
+ reason: "correlationId constraint reuses eventId (idempotent replay)"
128464
+ },
128465
+ // NOT safe to retry — see the module comment.
128466
+ step_started: {
128467
+ retryable: false,
128468
+ reason: "unconditional attempt increment → a retry double-counts attempts"
128469
+ },
128470
+ step_retrying: {
128471
+ retryable: false,
128472
+ reason: "no duplicate guard → a retry appends a second event row"
128473
+ },
128474
+ hook_received: {
128475
+ retryable: false,
128476
+ reason: "no server guard → a retry duplicates the row / re-delivers payload"
128477
+ },
128478
+ // Server-originated; the SDK never POSTs it.
128479
+ hook_conflict: {
128480
+ retryable: false,
128481
+ reason: "server-originated; never POSTed by the SDK"
128482
+ }
128483
+ };
128484
+ const MAX_EVENT_POST_RETRIES = 2;
128485
+ const EVENT_POST_RETRY_BASE_MS = 100;
128486
+ const EVENT_POST_RETRY_JITTER_MS = 50;
128487
+ const TRANSIENT_CODES = /* @__PURE__ */ new Set([
128488
+ "ECONNRESET",
128489
+ "ECONNREFUSED",
128490
+ "ENOTFOUND",
128491
+ "ENETDOWN",
128492
+ "ENETUNREACH",
128493
+ "EHOSTDOWN",
128494
+ "EHOSTUNREACH",
128495
+ "EPIPE",
128496
+ "ETIMEDOUT",
128497
+ "UND_ERR_SOCKET",
128498
+ "UND_ERR_REQ_RETRY",
128499
+ "UND_ERR_CONNECT_TIMEOUT",
128500
+ "UND_ERR_HEADERS_TIMEOUT",
128501
+ "UND_ERR_BODY_TIMEOUT",
128502
+ // Names (undici/Node surface these on the error or its cause).
128503
+ // `TimeoutError` is our own per-request deadline (`AbortSignal.timeout` in
128504
+ // makeRequest) — a genuinely ambiguous failure worth retrying. We deliberately
128505
+ // do NOT include `AbortError`: that is how an external/caller-supplied
128506
+ // cancellation surfaces (makeRequest composes the caller's signal via
128507
+ // `AbortSignal.any`), and re-issuing a write the caller asked to cancel —
128508
+ // stalling the abort by the full backoff budget — would be wrong.
128509
+ "TimeoutError",
128510
+ "RequestRetryError"
128511
+ ]);
128512
+ function collectErrorMarkers(err, depth = 0) {
128513
+ if (depth > 5 || err === null || typeof err !== "object")
128514
+ return [];
128515
+ const markers2 = [];
128516
+ const e = err;
128517
+ if (typeof e.code === "string")
128518
+ markers2.push(e.code);
128519
+ if (typeof e.name === "string")
128520
+ markers2.push(e.name);
128521
+ if (e.cause)
128522
+ markers2.push(...collectErrorMarkers(e.cause, depth + 1));
128523
+ return markers2;
128524
+ }
128525
+ function isRetryableEventPostError(err) {
128526
+ if (EntityConflictError.is(err) || RunExpiredError.is(err) || TooEarlyError.is(err) || ThrottleError.is(err)) {
128527
+ return false;
128528
+ }
128529
+ if (WorkflowWorldError.is(err)) {
128530
+ if (err.code === "PARSE_ERROR")
128531
+ return true;
128532
+ if (typeof err.status === "number") {
128533
+ return err.status >= 500 && err.status <= 599;
128534
+ }
128535
+ }
128536
+ return collectErrorMarkers(err).some((m2) => TRANSIENT_CODES.has(m2));
128537
+ }
128538
+ const sleep$1 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
128539
+ const RETRY_DEBUG_ENABLED = typeof process !== "undefined" && typeof process.env.DEBUG === "string" && (process.env.DEBUG.includes("workflow:") || process.env.DEBUG === "*");
128540
+ function logRetry(message2, fields) {
128541
+ if (!RETRY_DEBUG_ENABLED)
128542
+ return;
128543
+ const suffix = Object.entries(fields).map(([k2, v2]) => `${k2}=${v2}`).join(" ");
128544
+ console.debug(`[workflow:world-vercel:event-retry] ${message2} ${suffix}`);
128545
+ }
128546
+ function errorMarker(err) {
128547
+ if (WorkflowWorldError.is(err)) {
128548
+ return err.code ?? (err.status != null ? `status_${err.status}` : err.name);
128549
+ }
128550
+ return collectErrorMarkers(err)[0] ?? (err instanceof Error ? err.name : "unknown");
128551
+ }
128552
+ async function withEventPostRetry(fn2, eventType) {
128553
+ var _a3;
128554
+ const retryable = ((_a3 = EVENT_RETRY_ELIGIBILITY[eventType]) == null ? void 0 : _a3.retryable) ?? false;
128555
+ for (let attempt = 0; ; attempt++) {
128556
+ try {
128557
+ return await fn2();
128558
+ } catch (err) {
128559
+ const transient = retryable && isRetryableEventPostError(err);
128560
+ if (transient && attempt < MAX_EVENT_POST_RETRIES) {
128561
+ const backoff = EVENT_POST_RETRY_BASE_MS * 2 ** attempt + Math.floor(Math.random() * EVENT_POST_RETRY_JITTER_MS);
128562
+ logRetry("retrying event POST after transient failure", {
128563
+ eventType,
128564
+ attempt: attempt + 1,
128565
+ backoffMs: backoff,
128566
+ error: errorMarker(err)
128567
+ });
128568
+ await sleep$1(backoff);
128569
+ continue;
128570
+ }
128571
+ if (transient) {
128572
+ logRetry("exhausted in-process retries; surfacing for queue redelivery", {
128573
+ eventType,
128574
+ attempts: attempt + 1,
128575
+ error: errorMarker(err)
128576
+ });
128577
+ }
128578
+ throw err;
128579
+ }
128580
+ }
128581
+ }
127960
128582
  const V4_FRAME_CONTENT_TYPE = "application/vnd.workflow.v4-frames";
127961
128583
  function encodeFrame(meta2, body2) {
127962
128584
  const metaBytes = new Uint8Array(encode(meta2));
@@ -128026,15 +128648,16 @@ async function* readerToIterator(reader) {
128026
128648
  yield value;
128027
128649
  }
128028
128650
  }
128029
- async function fetchV4(url2, init2, config2) {
128030
- init2.headers.set("X-Request-Time", Date.now().toString());
128031
- await injectTraceContextIntoHeaders(init2.headers);
128032
- return fetch(url2, {
128651
+ async function fetchV4(url2, init2, config2, opName) {
128652
+ return instrumentedFetch({
128033
128653
  method: init2.method,
128654
+ url: url2,
128034
128655
  headers: init2.headers,
128035
128656
  body: init2.body,
128036
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- undici dispatcher type doesn't match @types/node's RequestInit
128037
- dispatcher: getDispatcher(config2)
128657
+ dispatcher: getEventsDispatcher(config2),
128658
+ timeoutMs: null,
128659
+ logLabel: opName,
128660
+ buildError: async (response2) => errorFromV4Response(response2.status, headersToRecord(response2.headers), await response2.text(), opName, url2)
128038
128661
  });
128039
128662
  }
128040
128663
  function headersToRecord(headers2) {
@@ -128101,7 +128724,7 @@ function buildPostFrameMeta(input) {
128101
128724
  meta2.skipPreload = input.skipPreload;
128102
128725
  return meta2;
128103
128726
  }
128104
- function throwForErrorResponse(statusCode, responseHeaders, errorBody, opName, url2) {
128727
+ function errorFromV4Response(statusCode, responseHeaders, errorBody, opName, url2) {
128105
128728
  let message2 = `v4 ${opName} failed: HTTP ${statusCode}`;
128106
128729
  let code2;
128107
128730
  try {
@@ -128114,26 +128737,12 @@ function throwForErrorResponse(statusCode, responseHeaders, errorBody, opName, u
128114
128737
  if (errorBody)
128115
128738
  message2 += ` ${errorBody}`;
128116
128739
  }
128117
- let retryAfter;
128118
- const retryAfterHeader = readHeader(responseHeaders, "retry-after");
128119
- if (retryAfterHeader) {
128120
- const parsed = parseInt(retryAfterHeader, 10);
128121
- if (!Number.isNaN(parsed))
128122
- retryAfter = parsed;
128123
- }
128124
- if (statusCode === 409)
128125
- throw new EntityConflictError(message2);
128126
- if (statusCode === 410)
128127
- throw new RunExpiredError(message2);
128128
- if (statusCode === 425)
128129
- throw new TooEarlyError(message2, { retryAfter });
128130
- if (statusCode === 429)
128131
- throw new ThrottleError(message2, { retryAfter });
128132
- throw new WorkflowWorldError(message2, {
128133
- status: statusCode,
128740
+ const retryAfter = parseRetryAfter(readHeader(responseHeaders, "retry-after"));
128741
+ return errorForResponse(statusCode, message2, {
128742
+ retryAfter,
128134
128743
  code: code2,
128135
128744
  url: url2,
128136
- retryAfter
128745
+ mitigated: readHeader(responseHeaders, "x-vercel-mitigated")
128137
128746
  });
128138
128747
  }
128139
128748
  async function createWorkflowRunEventV4(input, config2) {
@@ -128142,11 +128751,7 @@ async function createWorkflowRunEventV4(input, config2) {
128142
128751
  headers2.set("Content-Type", "application/octet-stream");
128143
128752
  const frame2 = encodeFrame(buildPostFrameMeta(input), input.payload ?? new Uint8Array(0));
128144
128753
  const url2 = `${baseUrl}/v4/runs/${encodeURIComponent(input.runId)}/events/${encodeURIComponent(input.eventType)}`;
128145
- const response2 = await fetchV4(url2, { method: "POST", headers: headers2, body: frame2 }, config2);
128146
- if (!response2.ok) {
128147
- const errorBody = await response2.text();
128148
- throwForErrorResponse(response2.status, headersToRecord(response2.headers), errorBody, "createEvent", url2);
128149
- }
128754
+ const response2 = await fetchV4(url2, { method: "POST", headers: headers2, body: frame2 }, config2, "createEvent");
128150
128755
  const eventId = response2.headers.get(V4_RESPONSE_HEADERS.eventId);
128151
128756
  const runId = response2.headers.get(V4_RESPONSE_HEADERS.runId);
128152
128757
  const createdAt = response2.headers.get(V4_RESPONSE_HEADERS.createdAt);
@@ -128168,11 +128773,7 @@ function readHeader(responseHeaders, name2) {
128168
128773
  async function getEventV4(runId, eventId, config2) {
128169
128774
  const { baseUrl, headers: headers2 } = await getHttpConfig(config2);
128170
128775
  const url2 = `${baseUrl}/v4/runs/${encodeURIComponent(runId)}/events/${encodeURIComponent(eventId)}`;
128171
- const response2 = await fetchV4(url2, { method: "GET", headers: headers2 }, config2);
128172
- if (!response2.ok) {
128173
- const errorBody = await response2.text();
128174
- throwForErrorResponse(response2.status, headersToRecord(response2.headers), errorBody, "getEvent", url2);
128175
- }
128776
+ const response2 = await fetchV4(url2, { method: "GET", headers: headers2 }, config2, "getEvent");
128176
128777
  const contentType = response2.headers.get("content-type");
128177
128778
  if (!(contentType == null ? void 0 : contentType.startsWith(V4_FRAME_CONTENT_TYPE))) {
128178
128779
  throw new Error(`v4 getEvent: expected ${V4_FRAME_CONTENT_TYPE}, got ${contentType ?? "(none)"}`);
@@ -128184,11 +128785,7 @@ async function getEventV4(runId, eventId, config2) {
128184
128785
  throw new Error(`v4 getEvent: empty frame stream for ${eventId}`);
128185
128786
  }
128186
128787
  async function consumeListFrameStream(url2, headers2, config2, opName) {
128187
- const response2 = await fetchV4(url2, { method: "GET", headers: headers2 }, config2);
128188
- if (!response2.ok) {
128189
- const errorBody = await response2.text();
128190
- throwForErrorResponse(response2.status, headersToRecord(response2.headers), errorBody, opName, url2);
128191
- }
128788
+ const response2 = await fetchV4(url2, { method: "GET", headers: headers2 }, config2, opName);
128192
128789
  const contentType = response2.headers.get("content-type");
128193
128790
  if (!(contentType == null ? void 0 : contentType.startsWith(V4_FRAME_CONTENT_TYPE))) {
128194
128791
  throw new Error(`v4 ${opName}: expected ${V4_FRAME_CONTENT_TYPE}, got ${contentType ?? "(none)"}`);
@@ -128629,7 +129226,7 @@ async function getWorkflowRunEvents(params, config2) {
128629
129226
  }
128630
129227
  async function createWorkflowRunEvent(id2, data, params, config2) {
128631
129228
  try {
128632
- return await createWorkflowRunEventInner(id2, data, params, config2);
129229
+ return await withEventPostRetry(() => createWorkflowRunEventInner(id2, data, params, config2), data.eventType);
128633
129230
  } catch (err) {
128634
129231
  if (hookEventsRequiringExistence.has(data.eventType) && WorkflowWorldError.is(err) && err.status === 404 && data.correlationId) {
128635
129232
  throw new HookNotFoundError(data.correlationId);
@@ -128815,13 +129412,10 @@ function getStreamReadUrl(name2, runId, httpConfig) {
128815
129412
  return new URL(`${httpConfig.baseUrl}/v3/runs/${encodeURIComponent(runId)}/stream/${encodeURIComponent(name2)}`);
128816
129413
  }
128817
129414
  function createStreamRequestError(operation, url2, response2, text2) {
128818
- const context = [`PUT ${url2.origin}${url2.pathname}`];
128819
- for (const header of ["x-vercel-id", "x-vercel-error"]) {
128820
- const value = response2.headers.get(header);
128821
- if (value) {
128822
- context.push(`${header}=${value}`);
128823
- }
128824
- }
129415
+ const context = [
129416
+ `PUT ${url2.origin}${url2.pathname}`,
129417
+ ...getVercelDiagnostics(response2.headers)
129418
+ ];
128825
129419
  return new Error(`Stream ${operation} failed: HTTP ${response2.status} (${context.join("; ")}): ${text2}`);
128826
129420
  }
128827
129421
  function encodeMultiChunks(chunks) {
@@ -128864,15 +129458,17 @@ function createStreamer(config2) {
128864
129458
  const resolvedRunId = await runId;
128865
129459
  const httpConfig = await getHttpConfig(config2);
128866
129460
  const url2 = getStreamUrl(name2, resolvedRunId, httpConfig);
128867
- const response2 = await fetch(url2, {
129461
+ const response2 = await instrumentedFetch({
128868
129462
  method: "PUT",
129463
+ url: url2.toString(),
128869
129464
  body: chunk,
128870
- headers: httpConfig.headers
129465
+ headers: httpConfig.headers,
129466
+ dispatcher: getStreamDispatcher(config2),
129467
+ timeoutMs: null,
129468
+ logLabel: url2.pathname,
129469
+ buildError: async (res) => createStreamRequestError("write", url2, res, await res.text())
128871
129470
  });
128872
- const text2 = await response2.text();
128873
- if (!response2.ok) {
128874
- throw createStreamRequestError("write", url2, response2, text2);
128875
- }
129471
+ await response2.text();
128876
129472
  },
128877
129473
  async writeMulti(runId, name2, chunks) {
128878
129474
  if (chunks.length === 0)
@@ -128884,15 +129480,17 @@ function createStreamer(config2) {
128884
129480
  const batch = chunks.slice(i, i + MAX_CHUNKS_PER_REQUEST);
128885
129481
  const body2 = encodeMultiChunks(batch);
128886
129482
  const url2 = getStreamUrl(name2, resolvedRunId, httpConfig);
128887
- const response2 = await fetch(url2, {
129483
+ const response2 = await instrumentedFetch({
128888
129484
  method: "PUT",
129485
+ url: url2.toString(),
128889
129486
  body: body2,
128890
- headers: httpConfig.headers
129487
+ headers: httpConfig.headers,
129488
+ dispatcher: getStreamDispatcher(config2),
129489
+ timeoutMs: null,
129490
+ logLabel: url2.pathname,
129491
+ buildError: async (res) => createStreamRequestError("write", url2, res, await res.text())
128891
129492
  });
128892
- const text2 = await response2.text();
128893
- if (!response2.ok) {
128894
- throw createStreamRequestError("write", url2, response2, text2);
128895
- }
129493
+ await response2.text();
128896
129494
  }
128897
129495
  },
128898
129496
  async close(runId, name2) {
@@ -128900,14 +129498,16 @@ function createStreamer(config2) {
128900
129498
  const httpConfig = await getHttpConfig(config2);
128901
129499
  httpConfig.headers.set("X-Stream-Done", "true");
128902
129500
  const url2 = getStreamUrl(name2, resolvedRunId, httpConfig);
128903
- const response2 = await fetch(url2, {
129501
+ const response2 = await instrumentedFetch({
128904
129502
  method: "PUT",
128905
- headers: httpConfig.headers
129503
+ url: url2.toString(),
129504
+ headers: httpConfig.headers,
129505
+ dispatcher: getStreamDispatcher(config2),
129506
+ timeoutMs: null,
129507
+ logLabel: url2.pathname,
129508
+ buildError: async (res) => createStreamRequestError("close", url2, res, await res.text())
128906
129509
  });
128907
- const text2 = await response2.text();
128908
- if (!response2.ok) {
128909
- throw createStreamRequestError("close", url2, response2, text2);
128910
- }
129510
+ await response2.text();
128911
129511
  },
128912
129512
  async get(runId, name2, startIndex) {
128913
129513
  const httpConfig = await getHttpConfig(config2);
@@ -128915,12 +129515,15 @@ function createStreamer(config2) {
128915
129515
  if (typeof startIndex === "number") {
128916
129516
  url2.searchParams.set("startIndex", String(startIndex));
128917
129517
  }
128918
- const response2 = await fetch(url2, {
128919
- headers: httpConfig.headers
129518
+ const response2 = await instrumentedFetch({
129519
+ method: "GET",
129520
+ url: url2.toString(),
129521
+ headers: httpConfig.headers,
129522
+ dispatcher: void 0,
129523
+ timeoutMs: null,
129524
+ logLabel: url2.pathname,
129525
+ buildError: (res) => new Error(`Failed to fetch stream: ${res.status}`)
128920
129526
  });
128921
- if (!response2.ok) {
128922
- throw new Error(`Failed to fetch stream: ${response2.status}`);
128923
- }
128924
129527
  if (!response2.body) {
128925
129528
  throw new Error("No response body for stream");
128926
129529
  }
@@ -128953,12 +129556,15 @@ function createStreamer(config2) {
128953
129556
  async list(runId) {
128954
129557
  const httpConfig = await getHttpConfig(config2);
128955
129558
  const url2 = new URL(`${httpConfig.baseUrl}/v2/runs/${encodeURIComponent(runId)}/streams`);
128956
- const response2 = await fetch(url2, {
128957
- headers: httpConfig.headers
129559
+ const response2 = await instrumentedFetch({
129560
+ method: "GET",
129561
+ url: url2.toString(),
129562
+ headers: httpConfig.headers,
129563
+ dispatcher: void 0,
129564
+ timeoutMs: null,
129565
+ logLabel: url2.pathname,
129566
+ buildError: (res) => new Error(`Failed to list streams: ${res.status}`)
128958
129567
  });
128959
- if (!response2.ok) {
128960
- throw new Error(`Failed to list streams: ${response2.status}`);
128961
- }
128962
129568
  return await response2.json();
128963
129569
  }
128964
129570
  }
@@ -129072,7 +129678,7 @@ const getWorld = async () => {
129072
129678
  const GetWorldFnKey = Symbol.for("@workflow/world//getWorldFn");
129073
129679
  globalThis[GetWorldFnKey] ?? (globalThis[GetWorldFnKey] = getWorld);
129074
129680
  function waitUntil(promise2) {
129075
- void import("./index-B8YoYr9f.js").then((n) => n.i).then(({ waitUntil: waitUntil2 }) => {
129681
+ void import("./index-DIXsjgfZ.js").then((n) => n.i).then(({ waitUntil: waitUntil2 }) => {
129076
129682
  waitUntil2(promise2);
129077
129683
  });
129078
129684
  }
@@ -132047,7 +132653,7 @@ async function start$1(workflow, argsOrOptions, options) {
132047
132653
  if (runCreatedResult.status === "rejected") {
132048
132654
  const err = runCreatedResult.reason;
132049
132655
  if (EntityConflictError.is(err)) ;
132050
- else if (isRetryableStartError(err)) {
132656
+ else if (isRetryableWorldError(err)) {
132051
132657
  resilientStart = true;
132052
132658
  runtimeLogger.warn("Run creation event failed, but the run was accepted via the queue. The run_created event will be re-tried async by the runtime.", { workflowRunId: runId, error: err.message });
132053
132659
  } else {
@@ -132077,13 +132683,6 @@ async function start$1(workflow, argsOrOptions, options) {
132077
132683
  });
132078
132684
  });
132079
132685
  }
132080
- function isRetryableStartError(err) {
132081
- if (ThrottleError.is(err))
132082
- return true;
132083
- if (WorkflowWorldError.is(err) && err.status && err.status >= 500)
132084
- return true;
132085
- return false;
132086
- }
132087
132686
  const normalizeWorkflowArgs = (args) => {
132088
132687
  return Array.isArray(args) ? args : [args];
132089
132688
  };
@@ -137401,130 +138000,48 @@ async function fetchResourceWithCorrelationId(env2, resource, resourceId, option
137401
138000
  }
137402
138001
  return { data: resourceData, correlationId };
137403
138002
  }
137404
- function useWorkflowResourceData(env2, resource, resourceId, options = {}) {
137405
- const { refreshInterval = 0, runId, enabled = true, encryptionKey } = options;
137406
- const [data, setData] = reactExports.useState(
137407
- null
137408
- );
137409
- const [loading, setLoading] = reactExports.useState(enabled);
137410
- const [error2, setError] = reactExports.useState(null);
137411
- const hydrate = reactExports.useCallback(
137412
- async (resource2) => encryptionKey ? hydrateResourceIOWithKey(resource2, encryptionKey) : hydrateResourceIO(resource2),
137413
- [encryptionKey]
137414
- );
137415
- const prevSelectionRef = reactExports.useRef("");
137416
- const fetchData = reactExports.useCallback(async () => {
137417
- if (!enabled) {
137418
- setLoading(false);
137419
- return;
137420
- }
137421
- const selectionKey = `${resource}:${resourceId}`;
137422
- if (selectionKey !== prevSelectionRef.current) {
137423
- setData(null);
137424
- prevSelectionRef.current = selectionKey;
137425
- }
137426
- setError(null);
137427
- setLoading(true);
137428
- if (resource === "hook") {
137429
- try {
137430
- const { error: error22, result } = await unwrapServerActionResult(
137431
- fetchHook$1(env2, resourceId, "all")
137432
- );
137433
- if (error22) {
137434
- setError(error22);
137435
- return;
137436
- }
137437
- try {
137438
- setData(await hydrate(result));
137439
- } catch (hydrateError) {
137440
- setError(
137441
- hydrateError instanceof Error ? hydrateError : new Error(String(hydrateError))
137442
- );
137443
- }
137444
- } finally {
137445
- setLoading(false);
137446
- }
137447
- return;
137448
- }
137449
- if (resource === "sleep") {
137450
- try {
137451
- if (!runId) {
137452
- setError(new Error("runId is required for loading sleep details"));
137453
- return;
137454
- }
137455
- const { error: error22, result } = await unwrapServerActionResult(
137456
- fetchEvents$1(env2, runId, {
137457
- sortOrder: "asc",
137458
- limit: 1e3,
137459
- withData: true
137460
- })
137461
- );
137462
- if (error22) {
137463
- setError(error22);
137464
- return;
137465
- }
137466
- try {
137467
- const allEvents = result.data.map(
137468
- hydrateResourceIO
137469
- );
137470
- const waitEvents = await Promise.all(
137471
- allEvents.filter((e) => e.correlationId === resourceId).map(hydrate)
137472
- );
137473
- const data2 = waitEventsToWaitEntity(waitEvents);
137474
- if (data2 === null) {
137475
- setError(
137476
- new Error(
137477
- `Failed to load ${resource} details: missing required event data`
137478
- )
137479
- );
137480
- return;
137481
- }
137482
- setData(data2);
137483
- } catch (hydrateError) {
137484
- setError(
137485
- hydrateError instanceof Error ? hydrateError : new Error(String(hydrateError))
137486
- );
137487
- }
137488
- } finally {
137489
- setLoading(false);
137490
- }
137491
- return;
138003
+ async function fetchSpanDetailResource(env2, selection2, options = {}) {
138004
+ const { resource, resourceId, runId } = selection2;
138005
+ const { encryptionKey } = options;
138006
+ const hydrate = async (value) => encryptionKey ? hydrateResourceIOWithKey(value, encryptionKey) : hydrateResourceIO(value);
138007
+ if (resource === "hook") {
138008
+ const result = await unwrapOrThrow(fetchHook$1(env2, resourceId, "all"));
138009
+ return hydrate(result);
138010
+ }
138011
+ if (resource === "sleep") {
138012
+ if (!runId) {
138013
+ throw new WorkflowWebAPIError(
138014
+ "runId is required for loading sleep details",
138015
+ { layer: "client" }
138016
+ );
137492
138017
  }
137493
- try {
137494
- const { data: resourceData } = await fetchResourceWithCorrelationId(
137495
- env2,
137496
- resource,
137497
- resourceId,
137498
- { runId }
138018
+ const result = await unwrapOrThrow(
138019
+ fetchEvents$1(env2, runId, { sortOrder: "asc", limit: 1e3, withData: true })
138020
+ );
138021
+ const allEvents = result.data.map(
138022
+ hydrateResourceIO
138023
+ );
138024
+ const waitEvents = await Promise.all(
138025
+ allEvents.filter((e) => e.correlationId === resourceId).map(hydrate)
138026
+ );
138027
+ const data2 = waitEventsToWaitEntity(waitEvents);
138028
+ if (data2 === null) {
138029
+ throw new WorkflowWebAPIError(
138030
+ `Failed to load ${resource} details: missing required event data`,
138031
+ { layer: "client" }
137499
138032
  );
137500
- setData(await hydrate(resourceData));
137501
- } catch (error22) {
137502
- if (error22 instanceof Error) {
137503
- setError(error22);
137504
- } else {
137505
- setError(new Error(String(error22)));
137506
- }
137507
- return;
137508
- } finally {
137509
- setLoading(false);
137510
138033
  }
137511
- }, [env2, resource, resourceId, runId, enabled, hydrate]);
137512
- reactExports.useEffect(() => {
137513
- fetchData();
137514
- }, [fetchData]);
137515
- reactExports.useEffect(() => {
137516
- if (!refreshInterval || refreshInterval <= 0) {
137517
- return;
138034
+ return data2;
138035
+ }
138036
+ const { data } = await fetchResourceWithCorrelationId(
138037
+ env2,
138038
+ resource,
138039
+ resourceId,
138040
+ {
138041
+ runId
137518
138042
  }
137519
- const interval2 = setInterval(fetchData, refreshInterval);
137520
- return () => clearInterval(interval2);
137521
- }, [refreshInterval, fetchData]);
137522
- return {
137523
- data,
137524
- loading,
137525
- error: error2,
137526
- refresh: fetchData
137527
- };
138043
+ );
138044
+ return hydrate(data);
137528
138045
  }
137529
138046
  function mergeById(prev, next2, idKey) {
137530
138047
  const combined = [...prev, ...next2];
@@ -153566,30 +154083,15 @@ function RunDetailView({
153566
154083
  encryptionKey: encryptionKey ?? void 0,
153567
154084
  enabled: activeTab === "events"
153568
154085
  });
153569
- const [spanSelection, setSpanSelection] = reactExports.useState(
153570
- null
153571
- );
153572
- const {
153573
- data: spanDetailData,
153574
- loading: spanDetailLoading,
153575
- error: spanDetailError,
153576
- refresh: refreshSpanDetail
153577
- } = useWorkflowResourceData(
153578
- env2,
153579
- (spanSelection == null ? void 0 : spanSelection.resource) ?? "run",
153580
- (spanSelection == null ? void 0 : spanSelection.resourceId) ?? "",
153581
- {
153582
- runId: spanSelection == null ? void 0 : spanSelection.runId,
153583
- enabled: Boolean(
153584
- (spanSelection == null ? void 0 : spanSelection.resource) && (spanSelection == null ? void 0 : spanSelection.resourceId) && spanSelection.resource !== "hook"
153585
- ),
154086
+ const fetchSpanDetail = reactExports.useCallback(
154087
+ (selection2) => fetchSpanDetailResource(env2, selection2, {
153586
154088
  encryptionKey: encryptionKey ?? void 0
153587
- }
154089
+ }),
154090
+ [env2, encryptionKey]
153588
154091
  );
153589
154092
  const [isDecrypting, setIsDecrypting] = reactExports.useState(false);
153590
154093
  const handleDecrypt = reactExports.useCallback(async () => {
153591
154094
  if (encryptionKey) {
153592
- refreshSpanDetail();
153593
154095
  return;
153594
154096
  }
153595
154097
  setIsDecrypting(true);
@@ -153607,18 +154109,12 @@ function RunDetailView({
153607
154109
  } finally {
153608
154110
  setIsDecrypting(false);
153609
154111
  }
153610
- }, [encryptionKey, env2, runId, refreshSpanDetail]);
153611
- const handleSpanSelect = reactExports.useCallback((info) => {
153612
- setSpanSelection(info);
153613
- }, []);
154112
+ }, [encryptionKey, env2, runId]);
153614
154113
  const sidebarData = reactExports.useMemo(
153615
154114
  () => ({
153616
154115
  run: run2,
153617
154116
  events: allEvents ?? [],
153618
- spanDetailData: spanDetailData ?? null,
153619
- spanDetailError,
153620
- spanDetailLoading,
153621
- onSpanSelect: handleSpanSelect,
154117
+ fetchSpanDetail,
153622
154118
  onStreamClick: handleStreamClick,
153623
154119
  onRunClick: handleRunRefClick,
153624
154120
  onWakeUpSleep: handleWakeUpSleep,
@@ -153632,10 +154128,7 @@ function RunDetailView({
153632
154128
  [
153633
154129
  run2,
153634
154130
  allEvents,
153635
- spanDetailData,
153636
- spanDetailError,
153637
- spanDetailLoading,
153638
- handleSpanSelect,
154131
+ fetchSpanDetail,
153639
154132
  handleStreamClick,
153640
154133
  handleRunRefClick,
153641
154134
  handleWakeUpSleep,
@@ -154161,7 +154654,7 @@ const route4 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProper
154161
154654
  __proto__: null,
154162
154655
  loader
154163
154656
  }, Symbol.toStringTag, { value: "Module" }));
154164
- const serverManifest = { "entry": { "module": "/assets/entry.client-DOJDY_4b.js", "imports": ["/assets/index-BXZSIDEp.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-BlFmfRST.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/mermaid-3ZIDBTTL-C_xy8SxZ.js"], "css": ["/assets/root-61NXpLSs.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-Dz43xne_.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/workflow-graph-viewer-BlDVZ5AU.js", "/assets/mermaid-3ZIDBTTL-C_xy8SxZ.js", "/assets/index-B6-SzLmT.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-BzGs1YV_.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/workflow-graph-viewer-BlDVZ5AU.js", "/assets/mermaid-3ZIDBTTL-C_xy8SxZ.js", "/assets/encryption-g14N5vQl.js", "/assets/index-B6-SzLmT.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-e1cf8511.js", "version": "e1cf8511", "sri": void 0 };
154657
+ const serverManifest = { "entry": { "module": "/assets/entry.client-DOJDY_4b.js", "imports": ["/assets/index-BXZSIDEp.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-BsPxYsbK.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/mermaid-3ZIDBTTL-Cg-Mp5Kj.js"], "css": ["/assets/root-F_dqJDC7.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-BNApVOct.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/workflow-graph-viewer-CcCwLmnF.js", "/assets/mermaid-3ZIDBTTL-Cg-Mp5Kj.js", "/assets/index-B6-SzLmT.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-sr7StYc6.js", "imports": ["/assets/index-BXZSIDEp.js", "/assets/workflow-graph-viewer-CcCwLmnF.js", "/assets/mermaid-3ZIDBTTL-Cg-Mp5Kj.js", "/assets/encryption-g14N5vQl.js", "/assets/index-B6-SzLmT.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-379f050f.js", "version": "379f050f", "sri": void 0 };
154165
154658
  const assetsBuildDirectory = "build/client";
154166
154659
  const basename = "/";
154167
154660
  const future = { "unstable_optimizeDeps": false, "unstable_subResourceIntegrity": false, "unstable_trailingSlashAwareDataRequests": false, "unstable_previewServerPrerendering": false, "v8_middleware": false, "v8_splitRouteModules": false, "v8_viteEnvironmentApi": false };