@workflow/web 5.0.0-beta.27 → 5.0.0-beta.29

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 (30) hide show
  1. package/build/client/assets/arrow-up-right-nUJMbeWN.js +15 -0
  2. package/build/client/assets/{encryption-BQTnudEZ.js → encryption-CLVP4klT.js} +2 -2
  3. package/build/client/assets/{entry.client-DOJDY_4b.js → entry.client-Q4eUIqMI.js} +25 -25
  4. package/build/client/assets/{highlighted-body-B3W2YXNL-B-EF8R0t.js → highlighted-body-B3W2YXNL-_4bJAUnT.js} +2 -2
  5. package/build/client/assets/{home-DQkixJk4.js → home-W4Ja_rr1.js} +1698 -234
  6. package/build/client/assets/{index-C7C6cDW5.js → index-HqNj_XIX.js} +10 -10
  7. package/build/client/assets/{index-BXZSIDEp.js → index-Q81MFBxC.js} +22 -22
  8. package/build/client/assets/{index-ConSkUmc.js → index-STTN0-2V.js} +1 -1
  9. package/build/client/assets/manifest-56b6d9e0.js +1 -0
  10. package/build/client/assets/{mermaid-3ZIDBTTL-aixonSAh.js → mermaid-3ZIDBTTL-BfwKRFTU.js} +404 -77
  11. package/build/client/assets/{root-CsCdj08f.js → root-DOkL1_-J.js} +5 -15
  12. package/build/client/assets/root-okIQN2A_.css +1 -0
  13. package/build/client/assets/{run-detail-CCsVqid_.js → run-detail-CRleiBxx.js} +116 -195
  14. package/build/client/assets/server-build-H39y96IB.css +1 -0
  15. package/build/client/assets/{workflow-graph-viewer-BlPvo_5I.js → workflow-graph-viewer-CvsdACR5.js} +224 -199
  16. package/build/client/assets/{zstd-browser-decoder-RyHgsNO3.js → zstd-browser-decoder-bX851D8O.js} +3 -3
  17. package/build/server/assets/{app-kYNGZFkW.js → app-jsOjV9W7.js} +43 -43
  18. package/build/server/assets/{highlighted-body-B3W2YXNL-D1QWoqJB.js → highlighted-body-B3W2YXNL-DpTmbI4L.js} +4 -4
  19. package/build/server/assets/{index-BafExO0s.js → index-BfLBLRRi.js} +10 -10
  20. package/build/server/assets/{index-fWQcXKhC.js → index-CJPCT6Jd.js} +5 -5
  21. package/build/server/assets/{mermaid-3ZIDBTTL-BOh-zwwU.js → mermaid-3ZIDBTTL-Dl6hRpcE.js} +4 -4
  22. package/build/server/assets/{server-build-B21fZEey.js → server-build-BRxoSdNU.js} +39298 -37117
  23. package/build/server/assets/{token-DmIqmbeU.js → token-BqP-cpRD.js} +2 -2
  24. package/build/server/assets/{token-util-D4JYdrFc.js → token-util-DaPlIe_a.js} +2 -2
  25. package/build/server/assets/{zstd-browser-decoder-DgO7NCG6.js → zstd-browser-decoder-Cyb8--z9.js} +5 -5
  26. package/build/server/index.js +1 -1
  27. package/package.json +10 -8
  28. package/build/client/assets/manifest-ce6dd06d.js +0 -1
  29. package/build/client/assets/root-BlaSucTH.css +0 -1
  30. package/build/client/assets/server-build-DPrKlhgf.css +0 -1
@@ -1,8 +1,9 @@
1
- import { r as reactExports, j as jsxRuntimeExports, f as reactDomExports, G as ReactDOM, B as useNavigate, C as useSearchParams, A as Link, w as withComponentProps, H as useParams } from "./index-BXZSIDEp.js";
2
- import { o as Check, M as Copy, C as CircleAlert, N as parseStepName, y as parseWorkflowName, O as ErrorCard, Q as format, Z as Zap, S as Send, R as ResolveHookModal, n as ChevronUp, X, L as ErrorBoundary, U as Circle, u as unwrapOrThrow, W as WorkflowWebAPIError, G as unwrapServerActionResult, V as useEscapeKeydown, q as composeEventHandlers, Y as useCallbackRef, _ as useLayoutEffect2, p as useControllableState, $ as useId, a0 as createContext2, s as Presence, v as createContextScope, k as hideOthers, l as ReactRemoveScroll, a1 as useFocusGuards, a2 as LAYOUT, a3 as wakeUpRun, r as resumeHook, A as Alert, c as AlertTitle, d as AlertDescription, a as Skeleton$1, a4 as RunActionsButtons, z as StatusBadge, e as CopyableText, b as RelativeTime, T as Tabs, I as TabsList, J as TabsTrigger, K as TabsContent, w as cancelRun, a5 as recreateRun } from "./workflow-graph-viewer-BlPvo_5I.js";
3
- import { c as createLucideIcon, W as cn, X as DataInspector, Y as DecryptClickContext, Z as Button, $ as Spinner, a0 as Lock, a1 as CollapsibleRoot, a2 as CollapsibleTrigger, a3 as CollapsibleContent, M as cva, a4 as RESERVED_ATTRIBUTE_KEY_PREFIX, a5 as ContextCardProvider, h as useToast, a6 as Skeleton, a7 as Yr, a8 as isEncryptedMarker, C as ChevronRight, a9 as TimestampTooltip, aa as formatDuration, ab as _r, ac as RunClickContext, ad as StreamClickContext, ae as Collapsible, af as isExpiredMarker, ag as isDoStreamStep, ah as extractConversation, ai as hasEncryptedFields, aj as getEventDataRefFields, ak as useSidebarDataOptional, al as clsx, am as useActiveSpan, an as useSidebarData, ao as Tooltip, ap as TooltipTrigger, aq as IconButton, ar as TooltipContent, H as ChevronDown, as as useRowWindow, at as isSpanDimmedBySearch, au as ROW_HEIGHT_PX, av as getSpanDurationMs, aw as formatDurationPrecise, ax as TooltipProvider, ay as ActiveSpanProvider, az as useReducedMotion, aA as searchSpans, aB as computeRootBounds, aC as computeTimeMarkers, aD as getHighResInMs, aE as scrollRowIntoView, aF as TIMELINE_PADDING_PX, aG as Timeline, aH as TimelineHeader, aI as SidebarDataProvider, aJ as fetchHook, l as fetchEvents, aK as hydrateResourceIOAsync, J as fetchRun, aL as fetchStep, aM as hydrateResourceIO, aN as fetchStreams, aO as Slot, I as useComposedRefs, aP as Slottable, e as cn$1, aQ as buttonVariants, aR as fetchEvent, aS as fetchEventsByCorrelationId, aT as isEncryptedData, aU as hydrateData, aV as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, aW as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, aX as getEncryptionKeyForRun, t as toast, L as LoaderCircle, aY as StreamViewer } from "./mermaid-3ZIDBTTL-aixonSAh.js";
4
- import { decrypt, importKey } from "./encryption-BQTnudEZ.js";
5
- import "./index-ConSkUmc.js";
1
+ import { r as reactExports, j as jsxRuntimeExports, p as reactDomExports, G as ReactDOM, d as useNavigate, e as useSearchParams, c as Link, w as withComponentProps, H as useParams } from "./index-Q81MFBxC.js";
2
+ import { C as Check, a as Copy, d as CircleAlert, U as parseStepName, G as parseWorkflowName, V as ErrorCard, Y as format, Z as Zap, S as Send, R as ResolveHookModal, t as ChevronUp, X, Q as ErrorBoundary, _ as Circle, u as unwrapOrThrow, W as WorkflowWebAPIError, K as unwrapServerActionResult, $ as useEscapeKeydown, w as composeEventHandlers, a0 as useCallbackRef, a1 as useLayoutEffect2, v as useControllableState, a2 as useId, a3 as createContext2, x as Presence, z as createContextScope, p as hideOthers, q as ReactRemoveScroll, a4 as useFocusGuards, a5 as LAYOUT, a6 as wakeUpRun, n as resumeHook, A as Alert, e as AlertTitle, g as getErrorTitle, h as AlertDescription, i as getErrorMessage, b as Skeleton$1, a7 as RunActionsButtons, H as StatusBadge, j as CopyableText, c as RelativeTime, T as Tabs, M as TabsList, N as TabsTrigger, O as TabsContent, B as cancelRun, a8 as recreateRun } from "./workflow-graph-viewer-CvsdACR5.js";
3
+ import { c as createLucideIcon, W as cn, X as DataInspector, Y as DecryptClickContext, Z as Button, $ as Spinner, a0 as Lock, a1 as CollapsibleRoot, a2 as CollapsibleTrigger, a3 as CollapsibleContent, M as cva, a4 as RESERVED_ATTRIBUTE_KEY_PREFIX, a5 as ContextCardProvider, h as useToast, a6 as Skeleton, a7 as Yr, a8 as isEncryptedMarker, C as ChevronRight, a9 as TimestampTooltip, aa as formatDuration, ab as _r, ac as RunClickContext, ad as StreamClickContext, ae as Collapsible, af as isExpiredMarker, ag as isDoStreamStep, ah as extractConversation, ai as hasEncryptedFields, aj as getEventDataRefFields, ak as useSidebarDataOptional, al as clsx, am as useActiveSpan, an as useSidebarData, ao as Tooltip, ap as TooltipTrigger, aq as IconButton, ar as TooltipContent, H as ChevronDown, as as useRowWindow, at as isSpanDimmedBySearch, au as ROW_HEIGHT_PX, av as getSpanDurationMs, aw as isSpanErrored, ax as formatDurationPrecise, ay as TooltipProvider, az as ActiveSpanProvider, aA as useReducedMotion, aB as searchSpans, aC as computeRootBounds, aD as computeTimeMarkers, aE as clampViewportToRoot, aF as getHighResInMs, aG as scrollRowIntoView, aH as TIMELINE_PADDING_PX, aI as Minimap, aJ as Timeline, aK as TimelineHeader, aL as wheelZoomScaleFactor, aM as wheelDeltaToPixels, aN as SidebarDataProvider, aO as fetchHook, l as fetchEvents, aP as hydrateResourceIOAsync, J as fetchRun, aQ as fetchStep, aR as hydrateResourceIO, aS as fetchStreams, aT as Slot, I as useComposedRefs, aU as Slottable, e as cn$1, aV as buttonVariants, aW as fetchEvent, aX as fetchEventsByCorrelationId, aY as isEncryptedData, aZ as hydrateData, a_ as getWebRevivers, T as Tooltip$1, a as TooltipTrigger$1, b as TooltipContent$1, a$ as LIVE_UPDATE_INTERVAL_MS$1, u as useServerConfig, b0 as getEncryptionKeyForRun, t as toast, L as LoaderCircle, b1 as StreamViewer } from "./mermaid-3ZIDBTTL-BfwKRFTU.js";
4
+ import { A as ArrowUpRight } from "./arrow-up-right-nUJMbeWN.js";
5
+ import { decrypt, importKey } from "./encryption-CLVP4klT.js";
6
+ import "./index-STTN0-2V.js";
6
7
  /**
7
8
  * @license lucide-react v0.575.0 - ISC
8
9
  *
@@ -431,7 +432,7 @@ function CopyableDataBlock({ data }) {
431
432
  function isReservedAttributeKey(key) {
432
433
  return key.startsWith(RESERVED_ATTRIBUTE_KEY_PREFIX);
433
434
  }
434
- const rowValueVariants = cva("max-w-[60%] truncate text-right text-copy-13 text-gray-1000", {
435
+ const rowValueVariants = cva("min-w-0 flex-1 truncate text-right text-copy-13 text-gray-1000", {
435
436
  variants: {
436
437
  variant: {
437
438
  default: "",
@@ -442,7 +443,7 @@ const rowValueVariants = cva("max-w-[60%] truncate text-right text-copy-13 text-
442
443
  variant: "default"
443
444
  }
444
445
  });
445
- const rowCopyValueVariants = cva("flex min-w-0 max-w-[60%] items-center justify-end gap-1 text-copy-13 text-gray-1000", {
446
+ const rowCopyValueVariants = cva("flex min-w-0 flex-1 items-center justify-end gap-1 text-copy-13 text-gray-1000", {
446
447
  variants: {
447
448
  variant: {
448
449
  default: "",
@@ -453,9 +454,9 @@ const rowCopyValueVariants = cva("flex min-w-0 max-w-[60%] items-center justify-
453
454
  variant: "default"
454
455
  }
455
456
  });
456
- function DetailKeyValueRowBase({ label, value, copyText, removed = false, variant }) {
457
+ function DetailKeyValueRowBase({ label, value, copyText, href, removed = false, variant }) {
457
458
  const stringValue = typeof value === "string" ? value : void 0;
458
- return jsxRuntimeExports.jsxs("div", { className: "px-1.5 hover:bg-gray-100 flex justify-between gap-3 -mx-1.5 py-0.5 rounded items-center", children: [jsxRuntimeExports.jsx("span", { className: "flex min-w-0 items-center gap-1.5 truncate text-label-13 text-gray-900", children: label }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-copy-13 italic text-gray-700", children: "removed" }) : copyText ? jsxRuntimeExports.jsxs("div", { className: cn(rowCopyValueVariants({ variant })), title: copyText, children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: copyText, className: cn(rowValueVariants({ variant, className: "text-right" })), style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(CopyButton, { copyText, ariaLabel: `Copy ${label}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: cn(rowValueVariants({ variant })), title: stringValue, children: value })] });
459
+ return jsxRuntimeExports.jsxs("div", { className: "px-1.5 hover:bg-gray-100 flex justify-between gap-3 -mx-1.5 py-0.5 rounded items-center", children: [jsxRuntimeExports.jsx("span", { className: "flex min-w-0 items-center gap-1.5 truncate text-label-13 text-gray-900", children: label }), removed ? jsxRuntimeExports.jsx("span", { className: "shrink-0 text-copy-13 italic text-gray-700", children: "removed" }) : copyText ? jsxRuntimeExports.jsxs("div", { className: cn(rowCopyValueVariants({ variant })), title: copyText, children: [href ? jsxRuntimeExports.jsxs("a", { href, target: "_blank", rel: "noreferrer", className: cn(rowValueVariants({ variant }), "flex min-w-0 items-center gap-0.5 hover:underline"), children: [jsxRuntimeExports.jsx(MiddleTruncate, { value: copyText, className: "min-w-0 text-right", style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(ArrowUpRight, { "aria-hidden": true, className: "h-3 w-3 shrink-0" })] }) : jsxRuntimeExports.jsx(MiddleTruncate, { value: copyText, className: cn(rowValueVariants({ variant, className: "text-right" })), style: { gridTemplateColumns: "minmax(0, 1fr)" } }), jsxRuntimeExports.jsx(CopyButton, { copyText, ariaLabel: `Copy ${label}`, className: "shrink-0 -mr-1" })] }) : jsxRuntimeExports.jsx("span", { className: cn(rowValueVariants({ variant })), title: stringValue, children: href ? jsxRuntimeExports.jsx("a", { href, target: "_blank", rel: "noreferrer", className: "hover:underline", children: value }) : value })] });
459
460
  }
460
461
  function DetailKeyValueRow(props) {
461
462
  return jsxRuntimeExports.jsx(DetailKeyValueRowBase, { ...props });
@@ -912,6 +913,12 @@ function PayloadBlock({ data, eventType }) {
912
913
  if (eventType === "attr_set") {
913
914
  return jsxRuntimeExports.jsx(AttrSetEventBlock, { data: cleaned });
914
915
  }
916
+ if (eventType === "run_cancelled") {
917
+ const cancelReason = cleaned != null && typeof cleaned === "object" && typeof cleaned.cancelReason === "string" ? cleaned.cancelReason : null;
918
+ if (cancelReason) {
919
+ return jsxRuntimeExports.jsxs("div", { className: "p-2 text-xs", style: { color: "var(--ds-gray-1000)" }, children: [jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-gray-900)" }, children: "Reason: " }), jsxRuntimeExports.jsx("span", { className: "whitespace-pre-wrap break-words", children: cancelReason })] });
920
+ }
921
+ }
915
922
  return jsxRuntimeExports.jsxs("div", { className: "relative group/payload", children: [jsxRuntimeExports.jsx("div", { className: "overflow-x-auto p-2 text-[11px]", style: { color: "var(--ds-gray-1000)" }, children: jsxRuntimeExports.jsx(DataInspector, { data: cleaned, expandLevel: 2 }) }), jsxRuntimeExports.jsx("button", { type: "button", onClick: handleCopy, className: "absolute bottom-2 right-2 opacity-0 group-hover/payload:opacity-100 transition-opacity flex items-center gap-1 px-2 py-1 rounded-md text-xs hover:bg-[var(--ds-gray-alpha-200)]", style: { ...BUTTON_RESET_STYLE, color: "var(--ds-gray-700)" }, "aria-label": "Copy payload", children: copied ? jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Check, { className: "h-3 w-3", style: { color: "var(--ds-green-700)" } }), jsxRuntimeExports.jsx("span", { style: { color: "var(--ds-green-700)" }, children: "Copied" })] }) : jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Copy, { className: "h-3 w-3" }), jsxRuntimeExports.jsx("span", { children: "Copy" })] }) })] });
916
923
  }
917
924
  const SORT_OPTIONS = [
@@ -1370,7 +1377,11 @@ const ROWS = [
1370
1377
  const HEADER_MARKERS = ["m0", "m1", "m2", "m3"];
1371
1378
  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" }) });
1372
1379
  function TraceViewerSkeleton() {
1373
- 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, { className: "w-3.5 h-3.5 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { 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((id) => jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5 w-9" }, id)) }) })] }), 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, { className: "w-4 h-4 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5", style: { width: `${row.name}%` } })] }), jsxRuntimeExports.jsx(Skeleton, { 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, { className: "absolute top-1/2 -translate-y-1/2 h-6 rounded-[0.25rem]", style: { left: `${row.off}%`, width: `${row.bar}%` } }) }) }, row.id)) })] })] });
1380
+ 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.jsx("div", { className: "relative h-10 min-h-10 shrink-0 border-b border-gray-alpha-400", children: jsxRuntimeExports.jsx("div", { className: "absolute inset-x-4 top-[6px]", children: ROWS.map((row, index) => jsxRuntimeExports.jsx(Skeleton, { className: "absolute h-[3px] rounded-full", style: {
1381
+ left: `${row.off}%`,
1382
+ width: `${row.bar}%`,
1383
+ top: index * 3.5
1384
+ } }, row.id)) }) }), 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, { className: "w-3.5 h-3.5 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { 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((id) => jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5 w-9" }, id)) }) })] }), 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, { className: "w-4 h-4 shrink-0 rounded-sm" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-3.5", style: { width: `${row.name}%` } })] }), jsxRuntimeExports.jsx(Skeleton, { 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, { className: "absolute top-1/2 -translate-y-1/2 h-6 rounded-[0.25rem]", style: { left: `${row.off}%`, width: `${row.bar}%` } }) }) }, row.id)) })] })] });
1374
1385
  }
1375
1386
  function shouldShowVerticalLine(eventType) {
1376
1387
  if (eventType === "hook_created" || eventType === "hook_received" || eventType === "hook_disposed") {
@@ -1931,9 +1942,9 @@ const conversationTabs = [
1931
1942
  { id: "conversation", label: "Conversation" },
1932
1943
  { id: "json", label: "Raw JSON" }
1933
1944
  ];
1934
- function ConversationWithTabs({ conversation, args }) {
1945
+ function ConversationWithTabs({ conversation, args, defaultOpen, onOpenChange }) {
1935
1946
  const [activeTab, setActiveTab] = reactExports.useState("conversation");
1936
- return jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: jsxRuntimeExports.jsx(TabbedContainer, { tabs: conversationTabs, activeTab, onTabChange: setActiveTab, ariaLabel: "Conversation view", children: activeTab === "conversation" ? jsxRuntimeExports.jsx(ConversationView, { messages: conversation }) : jsxRuntimeExports.jsx("div", { className: "p-3", children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }) }) });
1947
+ return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen, onOpenChange, children: jsxRuntimeExports.jsx(TabbedContainer, { tabs: conversationTabs, activeTab, onTabChange: setActiveTab, ariaLabel: "Conversation view", children: activeTab === "conversation" ? jsxRuntimeExports.jsx(ConversationView, { messages: conversation }) : jsxRuntimeExports.jsx("div", { className: "p-3", children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }) }) });
1937
1948
  }
1938
1949
  function EncryptedFieldBlock() {
1939
1950
  return jsxRuntimeExports.jsx(EncryptedDataBlock, {});
@@ -2135,7 +2146,7 @@ const attributeToDisplayFn = {
2135
2146
  },
2136
2147
  input: (value, context) => {
2137
2148
  if (isEncryptedMarker(value)) {
2138
- return jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2149
+ return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2139
2150
  }
2140
2151
  if (isExpiredMarker(value))
2141
2152
  return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
@@ -2147,28 +2158,28 @@ const attributeToDisplayFn = {
2147
2158
  if ((context == null ? void 0 : context.stepName) && isDoStreamStep(context.stepName)) {
2148
2159
  const conversation = extractConversation(args);
2149
2160
  if (conversation && conversation.length > 0) {
2150
- return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "This Value", children: JsonBlock(thisVal) })] });
2161
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(ConversationWithTabs, { conversation, args, defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "This Value", children: JsonBlock(thisVal) })] });
2151
2162
  }
2152
2163
  }
2153
2164
  if (!hasArgs && !hasClosureVars && !hasThisVal) {
2154
2165
  return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
2155
2166
  }
2156
- return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "Context", children: JsonBlock(thisVal) })] });
2167
+ return jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: Array.isArray(args) ? args.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(args) }), hasClosureVars && jsxRuntimeExports.jsx(Collapsible, { label: "Closure Variables", children: JsonBlock(closureVars) }), hasThisVal && jsxRuntimeExports.jsx(Collapsible, { label: "Context", children: JsonBlock(thisVal) })] });
2157
2168
  }
2158
2169
  if (!hasDisplayContent(value)) {
2159
2170
  return jsxRuntimeExports.jsx(Collapsible, { label: "Input (no data)", disabled: true });
2160
2171
  }
2161
- return jsxRuntimeExports.jsx(Collapsible, { label: "Input", children: Array.isArray(value) ? value.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(value) });
2172
+ return jsxRuntimeExports.jsx(Collapsible, { label: "Input", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: Array.isArray(value) ? value.map((v, i) => jsxRuntimeExports.jsx("div", { className: "mt-2 first:mt-0", children: JsonBlock(v) }, i)) : JsonBlock(value) });
2162
2173
  },
2163
- output: (value) => {
2174
+ output: (value, context) => {
2164
2175
  if (isEncryptedMarker(value)) {
2165
- return jsxRuntimeExports.jsx(Collapsible, { label: "Output", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2176
+ return jsxRuntimeExports.jsx(Collapsible, { label: "Output", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2166
2177
  }
2167
2178
  if (!hasDisplayContent(value))
2168
2179
  return null;
2169
2180
  if (isExpiredMarker(value))
2170
2181
  return jsxRuntimeExports.jsx(ExpiredFieldBlock, {});
2171
- return jsxRuntimeExports.jsx(Collapsible, { label: "Output", children: JsonBlock(value) });
2182
+ return jsxRuntimeExports.jsx(Collapsible, { label: "Output", defaultOpen: context == null ? void 0 : context.sectionOpen, onOpenChange: context == null ? void 0 : context.onSectionOpenChange, children: JsonBlock(value) });
2172
2183
  },
2173
2184
  error: (value) => {
2174
2185
  if (isEncryptedMarker(value)) {
@@ -2227,13 +2238,21 @@ const copyableBasicAttributes = /* @__PURE__ */ new Set([
2227
2238
  "deploymentId",
2228
2239
  "moduleSpecifier"
2229
2240
  ]);
2241
+ const loadingSectionLabels = {
2242
+ input: "Input",
2243
+ output: "Output",
2244
+ eventData: "Event Data"
2245
+ };
2230
2246
  const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }) => {
2231
2247
  const decryptCtx = reactExports.useContext(DecryptClickContext);
2232
- const isExpandableLoadingTarget = attribute === "input" || attribute === "output" || attribute === "eventData";
2233
- if (isLoading && isExpandableLoadingTarget && !hasDisplayContent(value)) {
2234
- const label = attribute === "eventData" ? "Event Data" : attribute === "output" ? "Output" : "Input";
2248
+ const sectionOpenRef = reactExports.useRef(false);
2249
+ const handleSectionOpenChange = reactExports.useCallback((open) => {
2250
+ sectionOpenRef.current = open;
2251
+ }, []);
2252
+ const label = loadingSectionLabels[attribute];
2253
+ if (isLoading && label && !hasDisplayContent(value)) {
2235
2254
  if (decryptCtx == null ? void 0 : decryptCtx.hasEncryptedData) {
2236
- return jsxRuntimeExports.jsx(Collapsible, { label, defaultOpen: attribute === "eventData", children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2255
+ return jsxRuntimeExports.jsx(Collapsible, { label, defaultOpen: attribute === "eventData" || sectionOpenRef.current, onOpenChange: handleSectionOpenChange, children: jsxRuntimeExports.jsx(EncryptedFieldBlock, {}) });
2237
2256
  }
2238
2257
  return jsxRuntimeExports.jsx(Collapsible, { label });
2239
2258
  }
@@ -2241,7 +2260,11 @@ const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }
2241
2260
  if (!displayFn) {
2242
2261
  return null;
2243
2262
  }
2244
- const displayValue = displayFn(value, context);
2263
+ const displayValue = displayFn(value, {
2264
+ ...context,
2265
+ sectionOpen: sectionOpenRef.current,
2266
+ onSectionOpenChange: handleSectionOpenChange
2267
+ });
2245
2268
  if (!displayValue) {
2246
2269
  return null;
2247
2270
  }
@@ -2253,7 +2276,7 @@ const AttributeBlock = ({ attribute, value, isLoading, inline = false, context }
2253
2276
  }
2254
2277
  return jsxRuntimeExports.jsxs("div", { className: "relative", children: [typeof isLoading === "boolean" && isLoading && jsxRuntimeExports.jsx("div", { className: "absolute top-9 right-4", children: jsxRuntimeExports.jsx("div", { className: "animate-spin rounded-full h-4 w-4 border-b-2", style: { borderColor: "var(--ds-gray-900)" } }) }), jsxRuntimeExports.jsxs("div", { className: "my-2 flex flex-col gap-0", children: [jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-1000 font-medium first-letter:uppercase", children: attribute }), jsxRuntimeExports.jsx("span", { className: "text-xs", style: { color: "var(--ds-gray-1000)" }, children: displayValue })] }, attribute)] });
2255
2278
  };
2256
- const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
2279
+ const AttributePanel = ({ data, moduleSpecifier, moduleSourceUrl, isLoading, error, expiredAt, onStreamClick, onRunClick, onDecrypt, isDecrypting = false, resource }) => {
2257
2280
  const displayData = reactExports.useMemo(() => {
2258
2281
  const result = { ...data };
2259
2282
  const execCtx = data.executionContext;
@@ -2326,7 +2349,7 @@ const AttributePanel = ({ data, moduleSpecifier, isLoading, error, expiredAt, on
2326
2349
  const displayValue = (_a = attributeToDisplayFn[attribute]) == null ? void 0 : _a.call(attributeToDisplayFn, displayData[attribute]);
2327
2350
  const isCopyableBasicAttribute = copyableBasicAttributes.has(attribute) && typeof displayValue === "string";
2328
2351
  const label = getAttributeDisplayName(attribute);
2329
- return jsxRuntimeExports.jsx(DetailMonoKeyValueRow, { label, value: displayValue, copyText: isCopyableBasicAttribute ? displayValue : void 0 }, attribute);
2352
+ return jsxRuntimeExports.jsx(DetailMonoKeyValueRow, { label, value: displayValue, copyText: isCopyableBasicAttribute ? displayValue : void 0, href: attribute === "moduleSpecifier" ? moduleSourceUrl : void 0 }, attribute);
2330
2353
  }), isLoading && resource === "sleep" && !displayData.resumeAt && jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-3 py-0.5", children: [jsxRuntimeExports.jsx("span", { className: "text-label-13 text-gray-900", children: "Resume" }), jsxRuntimeExports.jsx(Skeleton, { className: "h-4 w-[55%]" })] })] }) })] }), error ? jsxRuntimeExports.jsx(ErrorCard, { title: "Failed to load resource details", details: error.message, className: "my-4" }) : hasExpired ? jsxRuntimeExports.jsx(ExpiredDataMessage, {}) : resolvedAttributes.length > 0 ? resolvedAttributes.map((attribute) => jsxRuntimeExports.jsx(AttributeBlock, { isLoading, attribute, value: displayData[attribute], context: displayContext }, attribute)) : null] }) }) }) });
2331
2354
  };
2332
2355
  const ERROR_EVENT_TYPES = /* @__PURE__ */ new Set(["step_failed", "step_retrying"]);
@@ -2607,7 +2630,7 @@ function useSelectedSpanDetail(selectedSpan, fetchSpanDetail) {
2607
2630
  function isHook(data) {
2608
2631
  return data !== null && typeof data === "object" && "hookId" in data;
2609
2632
  }
2610
- function EntityDetailPanel({ run, onStreamClick, onRunClick, fetchSpanDetail, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan, showSeparateEventOccurrenceTimestamps = false }) {
2633
+ function EntityDetailPanel({ run, onStreamClick, onRunClick, fetchSpanDetail, onWakeUpSleep, onLoadEventData, onResolveHook, encryptionKey, onDecrypt, isDecrypting = false, selectedSpan, showSeparateEventOccurrenceTimestamps = false, getModuleSourceUrl }) {
2611
2634
  const toast2 = useToast();
2612
2635
  const [stoppingSleep, setStoppingSleep] = reactExports.useState(false);
2613
2636
  const [showResolveHookModal, setShowResolveHookModal] = reactExports.useState(false);
@@ -2751,6 +2774,18 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, fetchSpanDetail, on
2751
2774
  }
2752
2775
  return void 0;
2753
2776
  }, [displayData, run.workflowName]);
2777
+ const moduleSourceUrl = reactExports.useMemo(() => {
2778
+ if (!getModuleSourceUrl || !moduleSpecifier)
2779
+ return void 0;
2780
+ const parsed = parseStepName(moduleSpecifier) ?? parseWorkflowName(moduleSpecifier);
2781
+ if (!parsed)
2782
+ return void 0;
2783
+ const dataDeploymentId = displayData.deploymentId;
2784
+ return getModuleSourceUrl({
2785
+ moduleSpecifier: parsed.moduleSpecifier,
2786
+ deploymentId: typeof dataDeploymentId === "string" ? dataDeploymentId : run.deploymentId
2787
+ });
2788
+ }, [getModuleSourceUrl, moduleSpecifier, displayData, run.deploymentId]);
2754
2789
  if (!selectedSpan || !resource || !resourceId) {
2755
2790
  return null;
2756
2791
  }
@@ -2764,7 +2799,7 @@ function EntityDetailPanel({ run, onStreamClick, onRunClick, fetchSpanDetail, on
2764
2799
  }, 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: {
2765
2800
  background: "var(--ds-gray-1000)",
2766
2801
  color: "var(--ds-background-100)"
2767
- }, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, expiredAt: run.expiredAt, isLoading: loading, error: error ?? 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 })] });
2802
+ }, children: [jsxRuntimeExports.jsx(Send, { className: "h-4 w-4" }), "Resolve Hook"] })] })] }), jsxRuntimeExports.jsx(AttributePanel, { data: displayData, moduleSpecifier, moduleSourceUrl, expiredAt: run.expiredAt, isLoading: loading, error: error ?? 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 })] });
2768
2803
  }
2769
2804
  function useIntersectionObserver(elementRef, { threshold = 0, rootRef, rootMargin = "0%", freezeOnceVisible = false } = {}) {
2770
2805
  const [entry, setEntry] = reactExports.useState();
@@ -3070,7 +3105,7 @@ function TraceDetailPanel({ containerRef, onNavigateToSpan, onClose }) {
3070
3105
  }, [selectedSpan == null ? void 0 : selectedSpan.data, selectedSpan == null ? void 0 : selectedSpan.resource]);
3071
3106
  if (!activeSpan)
3072
3107
  return null;
3073
- return jsxRuntimeExports.jsxs("aside", { ref: asideRef, id: DETAIL_PANEL_ID, className: "relative flex flex-col h-full max-h-full shrink-0 bg-background-100 border-l border-gray-alpha-400", style: { width: panelWidth }, children: [jsxRuntimeExports.jsx(DraggableBorder, { element: asideRef, position: "left", onWidthChange: handleResize, onReset: () => handleResize(PANEL_DEFAULT_WIDTH), "aria-label": "Resize span details panel", "aria-controls": DETAIL_PANEL_ID, "aria-valuemin": PANEL_MIN_WIDTH, "aria-valuemax": panelMaxWidth, "aria-valuenow": Math.min(Math.max(Math.round(panelWidth), PANEL_MIN_WIDTH), panelMaxWidth) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 py-[7.5px]", 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, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrev, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNext, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { 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: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { 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 }) }) })] });
3108
+ return jsxRuntimeExports.jsxs("aside", { ref: asideRef, id: DETAIL_PANEL_ID, className: "relative flex flex-col h-full max-h-full shrink-0 bg-background-100 border-l border-gray-alpha-400", style: { width: panelWidth }, children: [jsxRuntimeExports.jsx(DraggableBorder, { element: asideRef, position: "left", onWidthChange: handleResize, onReset: () => handleResize(PANEL_DEFAULT_WIDTH), "aria-label": "Resize span details panel", "aria-controls": DETAIL_PANEL_ID, "aria-valuemin": PANEL_MIN_WIDTH, "aria-valuemax": panelMaxWidth, "aria-valuenow": Math.min(Math.max(Math.round(panelWidth), PANEL_MIN_WIDTH), panelMaxWidth) }), jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-between gap-2 shrink-0 px-4 py-[7.5px]", 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, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate up", "aria-keyshortcuts": "K", onClick: handleSelectPrev, disabled: !prevSpanId, children: jsxRuntimeExports.jsx(ChevronUp, { className: "w-4 h-4" }) }) }), prevSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { children: ["Navigate up", jsxRuntimeExports.jsx(Kbd, { children: "K" })] }) : null] }), jsxRuntimeExports.jsxs(Tooltip, { children: [jsxRuntimeExports.jsx(TooltipTrigger, { asChild: true, children: jsxRuntimeExports.jsx(IconButton, { "aria-label": "Navigate down", "aria-keyshortcuts": "J", onClick: handleSelectNext, disabled: !nextSpanId, children: jsxRuntimeExports.jsx(ChevronDown, { className: "w-4 h-4" }) }) }), nextSpanId ? jsxRuntimeExports.jsxs(TooltipContent, { 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: onClose, children: jsxRuntimeExports.jsx(X, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx("div", { className: "flex-1 overflow-y-auto", children: jsxRuntimeExports.jsx(ErrorBoundary, { 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, getModuleSourceUrl: sidebar.getModuleSourceUrl }) }) })] });
3074
3109
  }
3075
3110
  const WorkflowIcon = () => {
3076
3111
  return jsxRuntimeExports.jsx("svg", { "data-testid": "geist-icon", height: "16", strokeLinejoin: "round", style: { color: "currentColor" }, viewBox: "0 0 16 16", width: "16", children: jsxRuntimeExports.jsx("path", { d: "M5.75 7L6.4209 7.33594L4.85254 10.4717C5.38789 10.771 5.75 11.3431 5.75 12V14C5.75 14.9665 4.96648 15.75 4 15.75H2C1.03352 15.75 0.25 14.9665 0.25 14V12C0.25 11.0335 1.03352 10.25 2 10.25H3.28711L5.0791 6.66504L5.75 7ZM14 10.25C14.9665 10.25 15.75 11.0335 15.75 12V14C15.75 14.9665 14.9665 15.75 14 15.75H12C11.1185 15.75 10.3909 15.098 10.2695 14.25H7V12.75H10.25V12C10.25 11.0335 11.0335 10.25 12 10.25H14ZM2 11.75C1.86192 11.75 1.75 11.8619 1.75 12V14C1.75 14.1381 1.86192 14.25 2 14.25H4C4.13808 14.25 4.25 14.1381 4.25 14V12C4.25 11.8619 4.13808 11.75 4 11.75H2ZM12 11.75C11.8619 11.75 11.75 11.8619 11.75 12V14C11.75 14.1381 11.8619 14.25 12 14.25H14C14.1381 14.25 14.25 14.1381 14.25 14V12C14.25 11.8619 14.1381 11.75 14 11.75H12ZM9 0.25C9.96649 0.25 10.75 1.03351 10.75 2V4C10.75 4.44642 10.5808 4.85197 10.3057 5.16113L12.2041 8.6416L10.8877 9.36035L8.91895 5.75H7C6.03351 5.75 5.25 4.96649 5.25 4V2C5.25 1.03351 6.03351 0.25 7 0.25H9ZM7 1.75C6.86193 1.75 6.75 1.86193 6.75 2V4C6.75 4.13807 6.86193 4.25 7 4.25H9C9.13807 4.25 9.25 4.13807 9.25 4V2C9.25 1.86193 9.13807 1.75 9 1.75H7Z", fill: "currentColor" }) });
@@ -3103,21 +3138,20 @@ function getEventStyle(resource, isErrored) {
3103
3138
  };
3104
3139
  }
3105
3140
  const EventRow = ({ span, isSelected, isDimmed, onSelectSpan }) => {
3106
- var _a;
3107
3141
  const durationMs = getSpanDurationMs(span);
3108
- const workflowStatus = (_a = span.attributes.data) == null ? void 0 : _a.status;
3109
- const isErrored = span.status.code === 2 || workflowStatus === "failed";
3142
+ const isErrored = isSpanErrored(span);
3110
3143
  const { icon: Icon, className: tagClassName } = getEventStyle(span.resource, isErrored);
3111
3144
  return jsxRuntimeExports.jsx("li", { className: cn("relative overflow-clip group transition-opacity", ROW_HEIGHT_CLASS, isDimmed && "opacity-35"), role: "treeitem", "aria-selected": isSelected, "aria-expanded": isSelected, "aria-level": 1, onClick: () => onSelectSpan(span.spanId), children: jsxRuntimeExports.jsx("div", { className: "h-full hover:bg-gray-100 group-aria-selected:bg-gray-100 group-aria-selected:hover:bg-gray-200", children: jsxRuntimeExports.jsxs("div", { className: "flex h-full min-w-0 items-center pl-4 pr-2", children: [jsxRuntimeExports.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-2", children: [jsxRuntimeExports.jsx("span", { className: cn("shrink-0", tagClassName), children: jsxRuntimeExports.jsx(Icon, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx("span", { className: "min-w-0 text-label-14", children: jsxRuntimeExports.jsx(MiddleTruncate, { value: span.name }) })] }), jsxRuntimeExports.jsx("div", { className: "ml-2 shrink-0", children: jsxRuntimeExports.jsx("span", { className: "text-label-14 text-gray-900 tabular-nums", children: formatDurationPrecise(durationMs) }) })] }) }) });
3112
3145
  };
3113
3146
  const EventList = ({ spans, activeSpanId, searchResult, onSelectSpan }) => {
3114
3147
  const listRef = reactExports.useRef(null);
3115
3148
  const { start, end } = useRowWindow(listRef, spans.length, ROW_HEIGHT_PX);
3116
- return jsxRuntimeExports.jsx("ul", { ref: listRef, id: "event-list", role: "tree", className: "block min-h-0 overflow-visible divide-y divide-gray-alpha-400 border-b border-gray-alpha-400", style: {
3149
+ return jsxRuntimeExports.jsx("ul", { ref: listRef, id: "event-list", role: "tree", className: "block min-h-0 overflow-visible divide-y divide-gray-400 border-b border-gray-400", style: {
3117
3150
  paddingTop: start * ROW_HEIGHT_PX,
3118
3151
  paddingBottom: (spans.length - end) * ROW_HEIGHT_PX
3119
3152
  }, children: spans.slice(start, end).map((span) => jsxRuntimeExports.jsx(EventRow, { span, isSelected: span.spanId === activeSpanId, isDimmed: isSpanDimmedBySearch(span.spanId, searchResult), onSelectSpan }, span.spanId)) });
3120
3153
  };
3154
+ const SPLIT_PANE_START_ID = "trace-split-start";
3121
3155
  function SplitPane({ children, className, startHeader, endHeader, scrollContainerRef }) {
3122
3156
  const parts = reactExports.Children.toArray(children);
3123
3157
  if (parts.length !== 2) {
@@ -3125,19 +3159,9 @@ function SplitPane({ children, className, startHeader, endHeader, scrollContaine
3125
3159
  }
3126
3160
  const [start, end] = parts;
3127
3161
  const [startPx, setStartPx] = reactExports.useState(DEFAULT_START_PX);
3128
- const [isDragging, setIsDragging] = reactExports.useState(false);
3129
3162
  const containerRef = reactExports.useRef(null);
3130
- const gutterRef = reactExports.useRef(null);
3131
- const rafRef = reactExports.useRef(null);
3132
- const pendingPx = reactExports.useRef(DEFAULT_START_PX);
3133
- const pointerIdRef = reactExports.useRef(null);
3163
+ const startRef = reactExports.useRef(null);
3134
3164
  const containerWidth = useElementWidth(containerRef);
3135
- reactExports.useEffect(() => {
3136
- return () => {
3137
- if (rafRef.current)
3138
- cancelAnimationFrame(rafRef.current);
3139
- };
3140
- }, []);
3141
3165
  const setContainerRef = reactExports.useCallback((node) => {
3142
3166
  containerRef.current = node;
3143
3167
  if (scrollContainerRef) {
@@ -3151,64 +3175,12 @@ function SplitPane({ children, className, startHeader, endHeader, scrollContaine
3151
3175
  const maxPx = el.getBoundingClientRect().width - MIN_PX - GUTTER_PX;
3152
3176
  return Math.min(maxPx, Math.max(MIN_PX, px));
3153
3177
  }, []);
3154
- reactExports.useEffect(() => {
3155
- if (!isDragging)
3156
- return;
3157
- const onPointerMove = (e) => {
3158
- if (e.pointerId !== pointerIdRef.current)
3159
- return;
3160
- const container = containerRef.current;
3161
- if (!container)
3162
- return;
3163
- const rect = container.getBoundingClientRect();
3164
- pendingPx.current = clampPx(e.clientX - rect.left);
3165
- if (!rafRef.current) {
3166
- rafRef.current = requestAnimationFrame(() => {
3167
- rafRef.current = null;
3168
- setStartPx(pendingPx.current);
3169
- });
3170
- }
3171
- };
3172
- const onPointerUp = (e) => {
3173
- if (e.pointerId !== pointerIdRef.current)
3174
- return;
3175
- const gutter2 = gutterRef.current;
3176
- if (gutter2 == null ? void 0 : gutter2.hasPointerCapture(e.pointerId)) {
3177
- gutter2.releasePointerCapture(e.pointerId);
3178
- }
3179
- if (rafRef.current) {
3180
- cancelAnimationFrame(rafRef.current);
3181
- rafRef.current = null;
3182
- }
3183
- pointerIdRef.current = null;
3184
- setIsDragging(false);
3185
- };
3186
- document.addEventListener("pointermove", onPointerMove);
3187
- document.addEventListener("pointerup", onPointerUp);
3188
- document.addEventListener("pointercancel", onPointerUp);
3189
- return () => {
3190
- document.removeEventListener("pointermove", onPointerMove);
3191
- document.removeEventListener("pointerup", onPointerUp);
3192
- document.removeEventListener("pointercancel", onPointerUp);
3193
- };
3194
- }, [isDragging, clampPx]);
3195
- const handlePointerDown = (e) => {
3196
- e.currentTarget.setPointerCapture(e.pointerId);
3197
- pointerIdRef.current = e.pointerId;
3198
- setIsDragging(true);
3199
- };
3200
- const handleLostPointerCapture = () => {
3201
- pointerIdRef.current = null;
3202
- setIsDragging(false);
3203
- if (rafRef.current) {
3204
- cancelAnimationFrame(rafRef.current);
3205
- rafRef.current = null;
3206
- }
3207
- };
3178
+ const handleWidthChange = reactExports.useCallback((next) => setStartPx(clampPx(next)), [clampPx]);
3179
+ const handleReset = reactExports.useCallback(() => setStartPx(clampPx(DEFAULT_START_PX)), [clampPx]);
3208
3180
  const effectiveStartPx = containerWidth > 0 ? Math.max(MIN_PX, Math.min(containerWidth - MIN_PX - GUTTER_PX, startPx)) : startPx;
3209
3181
  const colTemplate = paneColTemplate(effectiveStartPx);
3210
- const gutter = jsxRuntimeExports.jsx("div", { ref: gutterRef, className: "relative z-20 isolate flex shrink-0 cursor-col-resize justify-center", onPointerDown: handlePointerDown, onLostPointerCapture: handleLostPointerCapture, children: jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }) });
3211
- return jsxRuntimeExports.jsxs("div", { className: cn("flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: cn("grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", isDragging && "select-none"), style: { gridTemplateColumns: colTemplate }, children: [start, gutter, end] })] });
3182
+ const maxStartPx = Math.max(MIN_PX, containerWidth > 0 ? containerWidth - MIN_PX - GUTTER_PX : startPx);
3183
+ return jsxRuntimeExports.jsxs("div", { className: cn("flex flex-col h-full min-h-0", className), children: [jsxRuntimeExports.jsxs("div", { className: "shrink-0 grid", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { children: startHeader }), jsxRuntimeExports.jsx("div", { className: "flex justify-center", children: jsxRuntimeExports.jsx("span", { className: "h-full w-px bg-gray-alpha-400", "aria-hidden": true }) }), jsxRuntimeExports.jsx("div", { children: endHeader })] }), jsxRuntimeExports.jsxs("div", { ref: setContainerRef, className: "grid flex-1 min-h-0 overflow-x-hidden overflow-y-auto", style: { gridTemplateColumns: colTemplate }, children: [jsxRuntimeExports.jsx("div", { ref: startRef, id: SPLIT_PANE_START_ID, className: "min-w-0", children: start }), jsxRuntimeExports.jsxs("div", { className: "relative z-20 isolate flex shrink-0 justify-center", children: [jsxRuntimeExports.jsx("span", { className: "pointer-events-none relative z-10 h-full w-px shrink-0 bg-gray-alpha-400", "aria-hidden": true }), jsxRuntimeExports.jsx(DraggableBorder, { element: startRef, position: "right", onWidthChange: handleWidthChange, onReset: handleReset, "aria-label": "Resize event list", "aria-controls": SPLIT_PANE_START_ID, "aria-valuemin": MIN_PX, "aria-valuemax": maxStartPx, "aria-valuenow": Math.min(Math.max(Math.round(effectiveStartPx), MIN_PX), maxStartPx) })] }), end] })] });
3212
3184
  }
3213
3185
  const hint = "_hint_1dmsq_3";
3214
3186
  const styles = {
@@ -3285,8 +3257,8 @@ function useAnimatedViewport(initial) {
3285
3257
  const from = currentRef.current;
3286
3258
  const anim = { raf: 0, from, to: target, start: performance.now() };
3287
3259
  const tick = () => {
3288
- const t = Math.min((performance.now() - anim.start) / 150, 1);
3289
- const e = 1 - (1 - t) * (1 - t);
3260
+ const t = Math.min((performance.now() - anim.start) / 240, 1);
3261
+ const e = t < 0.5 ? 8 * t * t * t * t : 1 - (-2 * t + 2) ** 4 / 2;
3290
3262
  setViewportState({
3291
3263
  start: anim.from.start + (anim.to.start - anim.from.start) * e,
3292
3264
  end: anim.from.end + (anim.to.end - anim.from.end) * e
@@ -3363,45 +3335,26 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3363
3335
  const resetZoom = reactExports.useCallback(() => {
3364
3336
  animateTo({ start: root.startTime, end: root.startTime + root.duration });
3365
3337
  }, [animateTo, root.startTime, root.duration]);
3338
+ const clampToRoot = reactExports.useCallback((next) => clampViewportToRoot(next, root.startTime, root.endTime, MIN_VIEWPORT_MS), [root.startTime, root.endTime]);
3366
3339
  const handleRevealTime = reactExports.useCallback((timeMs) => {
3367
- const rootS = root.startTime;
3368
- const rootE = root.startTime + root.duration;
3369
3340
  const { start, end } = viewportRef.current;
3370
3341
  const duration = end - start;
3371
- let newStart = timeMs - duration / 2;
3372
- let newEnd = timeMs + duration / 2;
3373
- if (newStart < rootS) {
3374
- newStart = rootS;
3375
- newEnd = rootS + duration;
3376
- }
3377
- if (newEnd > rootE) {
3378
- newEnd = rootE;
3379
- newStart = Math.max(rootS, rootE - duration);
3380
- }
3381
- animateTo({ start: newStart, end: newEnd });
3382
- }, [animateTo, root.startTime, root.duration]);
3342
+ animateTo(clampToRoot({
3343
+ start: timeMs - duration / 2,
3344
+ end: timeMs + duration / 2
3345
+ }));
3346
+ }, [animateTo, clampToRoot]);
3383
3347
  const ZOOM_FACTOR = 0.5;
3384
3348
  const zoomBy = reactExports.useCallback((factor) => {
3385
- const rootS = root.startTime;
3386
- const rootE = root.startTime + root.duration;
3387
- const rootD = root.duration;
3388
3349
  setViewport((prev) => {
3389
- const prevDuration = prev.end - prev.start;
3390
3350
  const center = (prev.start + prev.end) / 2;
3391
- const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(rootD, prevDuration * factor));
3392
- let newStart = center - newDuration / 2;
3393
- let newEnd = center + newDuration / 2;
3394
- if (newStart < rootS) {
3395
- newStart = rootS;
3396
- newEnd = rootS + newDuration;
3397
- }
3398
- if (newEnd > rootE) {
3399
- newEnd = rootE;
3400
- newStart = Math.max(rootS, rootE - newDuration);
3401
- }
3402
- return { start: newStart, end: newEnd };
3351
+ const newDuration = Math.max(MIN_VIEWPORT_MS, (prev.end - prev.start) * factor);
3352
+ return clampToRoot({
3353
+ start: center - newDuration / 2,
3354
+ end: center + newDuration / 2
3355
+ });
3403
3356
  });
3404
- }, [setViewport, root.startTime, root.duration]);
3357
+ }, [setViewport, clampToRoot]);
3405
3358
  const zoomIn = reactExports.useCallback(() => zoomBy(ZOOM_FACTOR), [zoomBy]);
3406
3359
  const zoomOut = reactExports.useCallback(() => zoomBy(1 / ZOOM_FACTOR), [zoomBy]);
3407
3360
  const isAtMinZoom = viewDuration >= root.duration;
@@ -3413,11 +3366,8 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3413
3366
  const spanStart = getHighResInMs(span.startTime);
3414
3367
  const spanEnd = getHighResInMs(span.endTime);
3415
3368
  const spanDuration = spanEnd - spanStart;
3416
- const rootS = root.startTime;
3417
- const rootE = root.startTime + root.duration;
3418
- const rootD = root.duration;
3419
- if (spanDuration > rootD * 0.8) {
3420
- animateTo({ start: rootS, end: rootE });
3369
+ if (spanDuration > root.duration * 0.8) {
3370
+ animateTo({ start: root.startTime, end: root.endTime });
3421
3371
  return;
3422
3372
  }
3423
3373
  const padding = Math.max(spanDuration * 0.2, MIN_VIEWPORT_MS / 2);
@@ -3428,18 +3378,15 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3428
3378
  newStart = center - MIN_VIEWPORT_MS / 2;
3429
3379
  newEnd = center + MIN_VIEWPORT_MS / 2;
3430
3380
  }
3431
- if (newStart < rootS) {
3432
- const duration = newEnd - newStart;
3433
- newStart = rootS;
3434
- newEnd = Math.min(rootE, rootS + duration);
3435
- }
3436
- if (newEnd > rootE) {
3437
- const duration = newEnd - newStart;
3438
- newEnd = rootE;
3439
- newStart = Math.max(rootS, rootE - duration);
3440
- }
3441
- animateTo({ start: newStart, end: newEnd });
3442
- }, [animateTo, trace.spans, root.startTime, root.duration]);
3381
+ animateTo(clampToRoot({ start: newStart, end: newEnd }));
3382
+ }, [
3383
+ animateTo,
3384
+ trace.spans,
3385
+ root.startTime,
3386
+ root.endTime,
3387
+ root.duration,
3388
+ clampToRoot
3389
+ ]);
3443
3390
  const scrollSpanIntoView = reactExports.useCallback((spanId) => {
3444
3391
  var _a;
3445
3392
  const index = trace.spans.findIndex((s) => s.spanId === spanId);
@@ -3516,7 +3463,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3516
3463
  return null;
3517
3464
  const absTime = viewport.start + hoverFraction * viewDuration;
3518
3465
  const offset = absTime - root.startTime;
3519
- return { fraction: hoverFraction, label: formatDuration(offset, true) };
3466
+ return { fraction: hoverFraction, label: formatDurationPrecise(offset) };
3520
3467
  }, [hoverFraction, viewport.start, viewDuration, root.startTime]);
3521
3468
  const handleTimelineMouseMove = reactExports.useCallback((e) => {
3522
3469
  const el = timelineRef.current;
@@ -3534,12 +3481,7 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3534
3481
  }, []);
3535
3482
  reactExports.useEffect(() => {
3536
3483
  const el = timelineRef.current;
3537
- if (!el)
3538
- return;
3539
- const rootS = root.startTime;
3540
- const rootE = root.startTime + root.duration;
3541
- const rootD = root.duration;
3542
- if (rootD <= 0)
3484
+ if (!el || root.duration <= 0)
3543
3485
  return;
3544
3486
  const onWheel = (e) => {
3545
3487
  const isZoomGesture = e.ctrlKey || e.metaKey;
@@ -3552,59 +3494,38 @@ function NewTraceViewerContent({ trace, onLoadMore, hasMore, isLoadingMore }) {
3552
3494
  if (contentWidth <= 0)
3553
3495
  return;
3554
3496
  if (isZoomGesture) {
3555
- let dy = e.deltaY;
3556
- if (e.deltaMode === 1)
3557
- dy *= 16;
3558
3497
  const cursorFraction = Math.max(0, Math.min(1, (e.clientX - rect.left - TIMELINE_PADDING_PX) / contentWidth));
3559
- const isMouseWheel = e.deltaMode === 1 || Math.abs(e.deltaY) >= 50;
3560
- const scaleFactor = 2 ** (dy / (isMouseWheel ? 200 : 60));
3498
+ const scaleFactor = wheelZoomScaleFactor(e);
3561
3499
  setViewport((prev) => {
3562
3500
  const prevDuration = prev.end - prev.start;
3563
3501
  const cursorTime = prev.start + cursorFraction * prevDuration;
3564
- const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(rootD, prevDuration * scaleFactor));
3565
- let newStart = cursorTime - cursorFraction * newDuration;
3566
- let newEnd = newStart + newDuration;
3567
- if (newStart < rootS) {
3568
- newStart = rootS;
3569
- newEnd = rootS + newDuration;
3570
- }
3571
- if (newEnd > rootE) {
3572
- newEnd = rootE;
3573
- newStart = Math.max(rootS, rootE - newDuration);
3574
- }
3575
- return { start: newStart, end: newEnd };
3502
+ const newDuration = Math.max(MIN_VIEWPORT_MS, Math.min(root.duration, prevDuration * scaleFactor));
3503
+ return clampToRoot({
3504
+ start: cursorTime - cursorFraction * newDuration,
3505
+ end: cursorTime + (1 - cursorFraction) * newDuration
3506
+ });
3576
3507
  });
3577
3508
  } else {
3578
- let dx = e.deltaX;
3579
- if (e.deltaMode === 1)
3580
- dx *= 16;
3509
+ const dx = wheelDeltaToPixels(e.deltaX, e.deltaMode);
3581
3510
  setViewport((prev) => {
3582
- const prevDuration = prev.end - prev.start;
3583
- const panAmount = dx / contentWidth * prevDuration;
3584
- let newStart = prev.start + panAmount;
3585
- let newEnd = prev.end + panAmount;
3586
- if (newStart < rootS) {
3587
- newStart = rootS;
3588
- newEnd = rootS + prevDuration;
3589
- }
3590
- if (newEnd > rootE) {
3591
- newEnd = rootE;
3592
- newStart = Math.max(rootS, rootE - prevDuration);
3593
- }
3594
- return { start: newStart, end: newEnd };
3511
+ const panAmount = dx / contentWidth * (prev.end - prev.start);
3512
+ return clampToRoot({
3513
+ start: prev.start + panAmount,
3514
+ end: prev.end + panAmount
3515
+ });
3595
3516
  });
3596
3517
  }
3597
3518
  };
3598
3519
  el.addEventListener("wheel", onWheel, { passive: false });
3599
3520
  return () => el.removeEventListener("wheel", onWheel);
3600
- }, [root.startTime, root.duration, setViewport]);
3601
- return jsxRuntimeExports.jsxs("div", { ref: paneRootRef, "data-pane": "pane-root", className: "relative flex w-full h-full max-h-full", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "flex-1 min-w-0 grid grid-rows-[1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
3521
+ }, [root.duration, setViewport, clampToRoot]);
3522
+ return jsxRuntimeExports.jsxs("div", { ref: paneRootRef, "data-pane": "pane-root", className: "relative flex w-full h-full max-h-full", children: [jsxRuntimeExports.jsxs("div", { id: "trace-parent", className: "flex-1 min-w-0 grid grid-rows-[auto_1fr] h-full min-h-0 overflow-hidden relative bg-background-100", children: [jsxRuntimeExports.jsx(Minimap, { spans: trace.spans, root, viewport, minViewportMs: MIN_VIEWPORT_MS, onViewportChange: setViewport, onAnimateTo: animateTo }), jsxRuntimeExports.jsxs(SplitPane, { scrollContainerRef, startHeader: jsxRuntimeExports.jsxs("div", { className: "bg-background-100 border-b border-gray-alpha-400 h-10 min-h-10 flex items-center pl-4 pr-2 gap-1.5", children: [jsxRuntimeExports.jsx(Search, { className: "w-3.5 h-3.5 shrink-0 text-gray-800" }), jsxRuntimeExports.jsx("input", { id: "trace-viewer-search", name: "trace-viewer-search", type: "text", value: searchQuery, onChange: (e) => setSearchQuery(e.target.value), onKeyDown: (e) => {
3602
3523
  if (e.key === "Escape" && searchQuery) {
3603
3524
  e.preventDefault();
3604
3525
  e.stopPropagation();
3605
3526
  setSearchQuery("");
3606
3527
  }
3607
- }, 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 }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace.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: trace.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, disabled: isAtMinZoom, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, disabled: isAtMaxZoom, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx(TraceDetailPanel, { containerRef: paneRootRef, onNavigateToSpan: navigateToSpan, onClose: handleClearActiveSpan }), jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace.spans.length > 1, reducedMotion })] });
3528
+ }, 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 }), children: [jsxRuntimeExports.jsxs("div", { className: "block overflow-visible", children: [jsxRuntimeExports.jsx(EventList, { spans: trace.spans, activeSpanId, searchResult, onSelectSpan: handleSelectSpan }), jsxRuntimeExports.jsx("div", { ref: loadMoreSentinelRef, className: "flex justify-center", children: isLoadingMore ? jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-center gap-2 py-3 text-sm text-gray-800", children: [jsxRuntimeExports.jsx(Spinner, { size: 14 }), jsxRuntimeExports.jsx("span", { children: "Loading spans…" })] }) : null })] }), jsxRuntimeExports.jsx("div", { ref: timelineRef, id: "trace-timeline", className: "block min-h-0 overflow-visible relative", onDoubleClick: resetZoom, onMouseMove: handleTimelineMouseMove, onMouseLeave: handleTimelineMouseLeave, children: jsxRuntimeExports.jsx(Timeline, { spans: trace.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, disabled: isAtMinZoom, "aria-label": "Zoom out", children: jsxRuntimeExports.jsx(ZoomOut, { className: "w-4 h-4" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: resetZoom, "aria-label": "Reset zoom", children: jsxRuntimeExports.jsx(RotateCcw, { className: "w-3.5 h-3.5" }) }), jsxRuntimeExports.jsx(IconButton, { variant: "muted", size: "small", onClick: zoomIn, disabled: isAtMaxZoom, "aria-label": "Zoom in", children: jsxRuntimeExports.jsx(ZoomIn, { className: "w-4 h-4" }) })] })] }), jsxRuntimeExports.jsx(TraceDetailPanel, { containerRef: paneRootRef, onNavigateToSpan: navigateToSpan, onClose: handleClearActiveSpan }), jsxRuntimeExports.jsx(TraceShortcutHelper, { hasMultipleSpans: trace.spans.length > 1, reducedMotion })] });
3608
3529
  }
3609
3530
  const NewTraceViewer = ({ run, events, sidebarData, onLoadMore, hasMore, isLoadingMore, loading = false }) => {
3610
3531
  const trace = reactExports.useMemo(() => {
@@ -5801,8 +5722,8 @@ function RunDetailView({
5801
5722
  if (error && !runData) {
5802
5723
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(Alert, { variant: "destructive", className: "m-4", children: [
5803
5724
  /* @__PURE__ */ jsxRuntimeExports.jsx(CircleAlert, { className: "h-4 w-4" }),
5804
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: "Error loading workflow run" }),
5805
- /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: error.message })
5725
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertTitle, { children: getErrorTitle(error, "Error loading workflow run") }),
5726
+ /* @__PURE__ */ jsxRuntimeExports.jsx(AlertDescription, { children: getErrorMessage(error) })
5806
5727
  ] });
5807
5728
  }
5808
5729
  const workflowName = (_a = parseWorkflowName(run.workflowName)) == null ? void 0 : _a.shortName;