@mastra/playground-ui 7.0.0-beta.7 → 7.0.0-beta.9

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 (33) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/index.cjs.js +836 -422
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +837 -424
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/components/ui/elements/buttons/button.d.ts +1 -0
  7. package/dist/src/components/ui/elements/buttons/combined-buttons.d.ts +6 -0
  8. package/dist/src/components/ui/elements/buttons/index.d.ts +1 -0
  9. package/dist/src/components/ui/elements/form-fields/search-field.d.ts +4 -1
  10. package/dist/src/components/ui/elements/side-dialog/side-dialog-top.d.ts +1 -2
  11. package/dist/src/domains/configuration/components/playground-config-guard.d.ts +1 -0
  12. package/dist/src/domains/configuration/context/studio-config-context.d.ts +2 -1
  13. package/dist/src/domains/configuration/hooks/use-mastra-instance-status.d.ts +4 -0
  14. package/dist/src/domains/configuration/index.d.ts +1 -0
  15. package/dist/src/domains/observability/components/helpers.d.ts +1 -3
  16. package/dist/src/domains/observability/components/index.d.ts +1 -1
  17. package/dist/src/domains/observability/components/shared.d.ts +2 -5
  18. package/dist/src/domains/observability/components/span-dialog.d.ts +4 -2
  19. package/dist/src/domains/observability/components/span-scoring.d.ts +4 -1
  20. package/dist/src/domains/observability/components/span-tabs.d.ts +4 -2
  21. package/dist/src/domains/observability/components/span-type-icon.d.ts +6 -0
  22. package/dist/src/domains/observability/components/timeline-expand-col.d.ts +13 -0
  23. package/dist/src/domains/observability/components/timeline-name-col.d.ts +16 -0
  24. package/dist/src/domains/observability/components/timeline-structure-sign.d.ts +7 -0
  25. package/dist/src/domains/observability/components/timeline-timing-col.d.ts +12 -0
  26. package/dist/src/domains/observability/components/trace-dialog.d.ts +4 -1
  27. package/dist/src/domains/observability/components/trace-timeline-span.d.ts +6 -1
  28. package/dist/src/domains/observability/components/trace-timeline-tools.d.ts +12 -0
  29. package/dist/src/domains/observability/components/trace-timeline.d.ts +5 -1
  30. package/dist/src/domains/observability/types.d.ts +13 -0
  31. package/dist/src/domains/observability/utils/get-descendant-ids.d.ts +2 -0
  32. package/package.json +8 -8
  33. package/dist/src/domains/observability/components/trace-timeline-legend.d.ts +0 -6
package/dist/index.cjs.js CHANGED
@@ -6304,13 +6304,6 @@ const StringField = ({ inputProps, error, field, id }) => {
6304
6304
 
6305
6305
  const NumberField = ({ inputProps, error, field, id }) => {
6306
6306
  const { key, ...props } = inputProps;
6307
- React.useEffect(() => {
6308
- if (field.default !== void 0) {
6309
- props.onChange({
6310
- target: { value: Number(field.default), name: inputProps.name }
6311
- });
6312
- }
6313
- }, [field.default]);
6314
6307
  return /* @__PURE__ */ jsxRuntime.jsx(
6315
6308
  Input,
6316
6309
  {
@@ -8584,7 +8577,7 @@ const WorkflowCard = ({ header, children, footer }) => {
8584
8577
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: header }),
8585
8578
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: cn("text-icon3 transition-transform -rotate-90", expanded && "rotate-0") }) })
8586
8579
  ] }),
8587
- children && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t-sm border-border1", children }),
8580
+ children && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t-sm border-border1 max-h-[400px] overflow-y-auto", children }),
8588
8581
  footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1 px-2 border-t-sm border-border1", children: footer })
8589
8582
  ] });
8590
8583
  };
@@ -8703,7 +8696,7 @@ function WorkflowTrigger({
8703
8696
  const workflowActivePaths = streamResultToUse?.steps ?? {};
8704
8697
  const hasWorkflowActivePaths = Object.values(workflowActivePaths).length > 0;
8705
8698
  const doneStatuses = ["success", "failed", "canceled"];
8706
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full pt-3 pb-12", children: [
8699
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full pt-3 pb-12 overflow-y-auto", children: [
8707
8700
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 px-5 pb-5 border-b-sm border-border1", children: [
8708
8701
  isSuspendedSteps && isStreamingWorkflow && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-2 px-5 flex items-center gap-2 bg-surface5 -mx-5 -mt-5 border-b-sm border-border1", children: [
8709
8702
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin text-icon6" }) }),
@@ -12795,19 +12788,31 @@ const AgentMetadataWrapper = ({ children }) => {
12795
12788
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 overflow-y-auto h-full px-5", children });
12796
12789
  };
12797
12790
 
12798
- function SearchField(props) {
12799
- return /* @__PURE__ */ jsxRuntime.jsx(
12800
- InputField,
12801
- {
12802
- labelIsHidden: true,
12803
- ...props,
12804
- className: "[&>input]:pl-[2.5rem]",
12805
- style: {
12806
- background: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' fill='gray' viewBox='0 0 24 24'><path d='M21 20l-5.6-5.6a7 7 0 1 0-1.4 1.4L20 21zM4 10a6 6 0 1 1 12 0 6 6 0 0 1-12 0z'/></svg>") no-repeat 8px center`,
12807
- backgroundSize: "1.5rem 1.5rem"
12791
+ function SearchField({ onReset, ...props }) {
12792
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
12793
+ /* @__PURE__ */ jsxRuntime.jsx(
12794
+ InputField,
12795
+ {
12796
+ labelIsHidden: true,
12797
+ ...props,
12798
+ className: "[&>input]:pl-[2.5rem]",
12799
+ style: {
12800
+ background: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' fill='gray' viewBox='0 0 24 24'><path d='M21 20l-5.6-5.6a7 7 0 1 0-1.4 1.4L20 21zM4 10a6 6 0 1 1 12 0 6 6 0 0 1-12 0z'/></svg>") no-repeat 8px center`,
12801
+ backgroundSize: "1.5rem 1.5rem",
12802
+ paddingRight: onReset ? "3rem" : void 0
12803
+ }
12808
12804
  }
12809
- }
12810
- );
12805
+ ),
12806
+ onReset && props.value && /* @__PURE__ */ jsxRuntime.jsx(
12807
+ "button",
12808
+ {
12809
+ type: "button",
12810
+ onClick: onReset,
12811
+ className: cn("absolute top-1/2 right-2 -translate-y-1/2 p-1", "[&:hover>svg]:text-icon5"),
12812
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, { className: "text-icon3 w-[1rem] h-[1rem]" })
12813
+ }
12814
+ )
12815
+ ] });
12811
12816
  }
12812
12817
 
12813
12818
  function InputField({
@@ -13297,7 +13302,7 @@ function SideDialogRoot({
13297
13302
  }
13298
13303
 
13299
13304
  const Button = React.forwardRef(
13300
- ({ className, variant = "outline", ...props }, ref) => {
13305
+ ({ className, variant = "outline", isFaded, ...props }, ref) => {
13301
13306
  return /* @__PURE__ */ jsxRuntime.jsx(
13302
13307
  "button",
13303
13308
  {
@@ -13313,7 +13318,8 @@ const Button = React.forwardRef(
13313
13318
  "bg-ui-primaryBtnBg text-ui-primaryBtnText hover:bg-surface6 leading-[0] font-semibold": variant === "primary",
13314
13319
  "min-h-[2rem]": variant === "ghost",
13315
13320
  "min-h-[2.5rem]": variant !== "ghost",
13316
- "border-[rgba(255,255,255,0.15)]": variant === "outline"
13321
+ "border-[rgba(255,255,255,0.15)]": variant === "outline",
13322
+ "opacity-40": isFaded
13317
13323
  }
13318
13324
  ),
13319
13325
  ...props
@@ -13323,6 +13329,21 @@ const Button = React.forwardRef(
13323
13329
  );
13324
13330
  Button.displayName = "Button";
13325
13331
 
13332
+ const CombinedButtons = ({ className, children }) => {
13333
+ return /* @__PURE__ */ jsxRuntime.jsx(
13334
+ "div",
13335
+ {
13336
+ className: cn(
13337
+ "flex items-center text-[0.75rem] border border-border1 rounded-lg overflow-hidden",
13338
+ "[&>button]:border-0 [&>button:not(:first-child)]:border-l [&>button:not(:first-child)]:border-border1",
13339
+ "[&>button]:rounded-none [&>button:first-child]:rounded-l-lg [&>button:last-child]:rounded-r-lg",
13340
+ className
13341
+ ),
13342
+ children
13343
+ }
13344
+ );
13345
+ };
13346
+
13326
13347
  function MainContentLayout({
13327
13348
  children,
13328
13349
  className,
@@ -13496,16 +13517,13 @@ function SideDialogHeader({ children, className }) {
13496
13517
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex justify-between items-center pb-[1rem]", className), children });
13497
13518
  }
13498
13519
 
13499
- function SideDialogTop({ children, withTopSeparator, className }) {
13520
+ function SideDialogTop({ children, className }) {
13500
13521
  return /* @__PURE__ */ jsxRuntime.jsx(
13501
13522
  "div",
13502
13523
  {
13503
13524
  className: cn(
13504
13525
  `flex h-[3.5rem] items-center text-icon5 text-[.875rem] pl-[1.5rem] relative gap-[1rem]`,
13505
13526
  '[&:after]:content-[""] [&:after]:absolute [&:after]:left-[1.5rem] [&:after]:right-[1.5rem] [&:after]:bottom-0 [&:after]:border-b [&:after]:border-border1',
13506
- {
13507
- '[&:before]:content-[""] [&:before]:absolute [&:before]:left-[1.5rem] [&:before]:right-[1.5rem] [&:before]:top-0 [&:before]:border-t [&:before]:border-border1': withTopSeparator
13508
- },
13509
13527
  className
13510
13528
  ),
13511
13529
  children
@@ -17729,7 +17747,8 @@ const formatHierarchicalSpans = (spans) => {
17729
17747
  latency: endDate ? endDate.getTime() - startDate.getTime() : 0,
17730
17748
  startTime: startDate.toISOString(),
17731
17749
  endTime: endDate ? endDate.toISOString() : void 0,
17732
- spans: []
17750
+ spans: [],
17751
+ parentSpanId: spanRecord.parentSpanId
17733
17752
  };
17734
17753
  spanMap.set(spanRecord.spanId, uiSpan);
17735
17754
  });
@@ -17768,198 +17787,410 @@ const formatHierarchicalSpans = (spans) => {
17768
17787
  return sortedRootSpans;
17769
17788
  };
17770
17789
 
17771
- const spanTypePrefixes = ["agent", "workflow", "llm", "tool"];
17790
+ const spanTypePrefixes = ["agent", "workflow", "model", "tool", "other"];
17772
17791
  function getSpanTypeUi(type) {
17773
17792
  const typePrefix = type?.toLowerCase().split("_")[0];
17774
17793
  const spanTypeToUiElements = {
17775
17794
  agent: {
17776
17795
  icon: /* @__PURE__ */ jsxRuntime.jsx(AgentIcon, {}),
17777
17796
  color: "oklch(0.75 0.15 250)",
17778
- label: "Agent"
17797
+ label: "Agent",
17798
+ bgColor: "bg-oklch(0.75 0.15 250 / 0.1)",
17799
+ typePrefix: "agent"
17779
17800
  },
17780
17801
  workflow: {
17781
17802
  icon: /* @__PURE__ */ jsxRuntime.jsx(WorkflowIcon, {}),
17782
17803
  color: "oklch(0.75 0.15 200)",
17783
- label: "Workflow"
17804
+ label: "Workflow",
17805
+ bgColor: "bg-oklch(0.75 0.15 200 / 0.1)",
17806
+ typePrefix: "workflow"
17784
17807
  },
17785
- llm: {
17808
+ model: {
17786
17809
  icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BrainIcon, {}),
17787
17810
  color: "oklch(0.75 0.15 320)",
17788
- label: "LLM"
17811
+ label: "Model",
17812
+ bgColor: "bg-oklch(0.75 0.15 320 / 0.1)",
17813
+ typePrefix: "model"
17789
17814
  },
17790
17815
  tool: {
17791
17816
  icon: /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, {}),
17792
17817
  color: "oklch(0.75 0.15 100)",
17793
- label: "Tool"
17818
+ label: "Tool",
17819
+ bgColor: "bg-oklch(0.75 0.15 100 / 0.1)",
17820
+ typePrefix: "tool"
17794
17821
  }
17795
17822
  };
17796
17823
  if (typePrefix in spanTypeToUiElements) {
17797
17824
  return spanTypeToUiElements[typePrefix];
17825
+ } else {
17826
+ return {
17827
+ typePrefix: "other"
17828
+ };
17798
17829
  }
17799
- return null;
17800
17830
  }
17801
17831
 
17802
- function TraceTimelineSpan({
17832
+ function getSpanDescendantIds(span) {
17833
+ if (!span.spans || span.spans.length === 0) {
17834
+ return [];
17835
+ }
17836
+ const descendantIds = [];
17837
+ span.spans.forEach((childSpan) => {
17838
+ descendantIds.push(childSpan.id);
17839
+ descendantIds.push(...getSpanDescendantIds(childSpan));
17840
+ });
17841
+ return descendantIds;
17842
+ }
17843
+
17844
+ function TimelineStructureSign({
17845
+ isLastChild,
17846
+ hasChildren = false,
17847
+ expanded = false
17848
+ }) {
17849
+ return /* @__PURE__ */ jsxRuntime.jsx(
17850
+ "div",
17851
+ {
17852
+ className: cn(
17853
+ "w-[3rem] h-[2.8rem] relative opacity-100",
17854
+ 'after:content-[""] after:absolute after:left-[-1px] after:top-0 after:bottom-0 after:w-[0px] after:border-l-[1px] after:border-icon3 after:border-dashed ',
17855
+ 'before:content-[""] before:absolute before:left-0 before:top-[50%] before:w-full before:h-[0px] before:border-b-[1px] before:border-icon3 before:border-dashed',
17856
+ "[&_svg]:transition-all",
17857
+ "[&:hover_svg]:text-yellow-500 [&:hover_svg]:scale-[1.3] [&:hover_svg]:opacity-100",
17858
+ {
17859
+ "after:bottom-[50%]": isLastChild
17860
+ }
17861
+ ),
17862
+ children: hasChildren && /* @__PURE__ */ jsxRuntime.jsx(
17863
+ "span",
17864
+ {
17865
+ className: cn(
17866
+ "flex absolute left-[50%] top-[50%] translate-y-[-50%] translate-x-[-50%] items-center justify-center bg-surface2 p-[0.25rem]",
17867
+ "[&>svg]:shrink-0 [&>svg]:opacity-60 [&>svg]:w-[0.8rem] [&>svg]:h-[0.8rem]"
17868
+ ),
17869
+ children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleChevronUpIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleChevronDownIcon, {})
17870
+ }
17871
+ )
17872
+ }
17873
+ );
17874
+ }
17875
+
17876
+ function SpanTypeIcon({ icon, color }) {
17877
+ return /* @__PURE__ */ jsxRuntime.jsx(
17878
+ "span",
17879
+ {
17880
+ className: cn(
17881
+ "flex w-[1.1rem] h-[1.1rem] shrink-0 rounded-md items-center justify-center",
17882
+ "[&>svg]:w-[.9rem] [&>svg]:h-[.9rem] [&>svg]:text-surface2"
17883
+ ),
17884
+ style: { backgroundColor: color },
17885
+ children: icon
17886
+ }
17887
+ );
17888
+ }
17889
+
17890
+ function TimelineNameCol({
17803
17891
  span,
17892
+ spanUI,
17893
+ isFaded,
17804
17894
  depth = 0,
17805
17895
  onSpanClick,
17806
17896
  selectedSpanId,
17807
17897
  isLastChild,
17898
+ hasChildren,
17899
+ isRootSpan,
17900
+ isExpanded,
17901
+ toggleChildren
17902
+ }) {
17903
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17904
+ "div",
17905
+ {
17906
+ "aria-label": `View details for span ${span.name}`,
17907
+ className: cn(
17908
+ "rounded-md transition-colors flex opacity-80 min-h-[3rem] items-center rounded-l-lg",
17909
+ "mt-[1rem] xl:mt-0",
17910
+ {
17911
+ "opacity-30 [&:hover]:opacity-60": isFaded,
17912
+ "bg-surface4": selectedSpanId === span.id
17913
+ }
17914
+ ),
17915
+ style: { paddingLeft: `${depth * 1.5}rem` },
17916
+ children: [
17917
+ !isRootSpan && /* @__PURE__ */ jsxRuntime.jsx(
17918
+ "button",
17919
+ {
17920
+ onClick: () => toggleChildren?.(),
17921
+ disabled: !hasChildren,
17922
+ className: cn({
17923
+ "cursor-default": !hasChildren,
17924
+ "cursor-pointer": hasChildren
17925
+ }),
17926
+ children: /* @__PURE__ */ jsxRuntime.jsx(TimelineStructureSign, { isLastChild, hasChildren: Boolean(hasChildren), expanded: isExpanded })
17927
+ }
17928
+ ),
17929
+ /* @__PURE__ */ jsxRuntime.jsxs(
17930
+ "button",
17931
+ {
17932
+ onClick: () => onSpanClick?.(span.id),
17933
+ className: cn(
17934
+ "text-[0.875rem] flex items-center text-left break-all gap-[0.5rem] text-white w-full rounded-lg h-full px-3 py-2 transition-colors",
17935
+ "[&>svg]:transition-all [&>svg]:shrink-0 [&>svg]:opacity-0 [&>svg]:w-[1em] [&>svg]:h-[1em] [&>svg]:ml-auto",
17936
+ "hover:bg-surface4 [&:hover>svg]:opacity-60"
17937
+ ),
17938
+ children: [
17939
+ spanUI?.icon && /* @__PURE__ */ jsxRuntime.jsx(SpanTypeIcon, { icon: spanUI.icon, color: spanUI.color ? spanUI.color : void 0 }),
17940
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("p-0 px-1 rounded-md"), children: span.name }),
17941
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, {})
17942
+ ]
17943
+ }
17944
+ )
17945
+ ]
17946
+ }
17947
+ );
17948
+ }
17949
+
17950
+ function TimelineExpandCol({
17951
+ isSelected,
17952
+ isFaded,
17953
+ isExpanded,
17954
+ toggleChildren,
17955
+ expandAllDescendants,
17956
+ totalDescendants = 0,
17957
+ allDescendantsExpanded,
17958
+ numOfChildren
17959
+ }) {
17960
+ return /* @__PURE__ */ jsxRuntime.jsx(
17961
+ "div",
17962
+ {
17963
+ className: cn("flex items-center justify-end h-full px-3", {
17964
+ "opacity-30 [&:hover]:opacity-60": isFaded,
17965
+ "bg-surface4": isSelected
17966
+ }),
17967
+ children: numOfChildren && numOfChildren > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-1", children: [
17968
+ /* @__PURE__ */ jsxRuntime.jsxs(ExpandButton, { onClick: () => toggleChildren?.(), children: [
17969
+ allDescendantsExpanded ? totalDescendants : numOfChildren,
17970
+ " ",
17971
+ isExpanded ? allDescendantsExpanded ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsUpIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUpIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, {})
17972
+ ] }),
17973
+ totalDescendants > numOfChildren && !allDescendantsExpanded && /* @__PURE__ */ jsxRuntime.jsxs(ExpandButton, { onClick: () => expandAllDescendants?.(), children: [
17974
+ totalDescendants,
17975
+ " ",
17976
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsDownIcon, {})
17977
+ ] })
17978
+ ] }) : null
17979
+ }
17980
+ );
17981
+ }
17982
+ function ExpandButton({ onClick, children, className }) {
17983
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { onClick, className: cn("h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx(
17984
+ "div",
17985
+ {
17986
+ className: cn(
17987
+ "flex items-center gap-[0.1rem] text-[0.75rem] text-icon5 border border-border1 pl-2 pr-1 rounded-lg transition-all",
17988
+ "hover:text-yellow-500",
17989
+ "[&>svg]:shrink-0 [&>svg]:opacity-80 [&>svg]:w-[1rem] [&>svg]:h-[1rem] [&>svg]:transition-all"
17990
+ ),
17991
+ children
17992
+ }
17993
+ ) });
17994
+ }
17995
+
17996
+ function TimelineTimingCol({
17997
+ span,
17998
+ selectedSpanId,
17999
+ isFaded,
17808
18000
  overallLatency,
17809
18001
  overallStartTime,
17810
- overallEndTime
18002
+ color
17811
18003
  }) {
17812
18004
  const { Link } = useLinkComponent();
17813
- const [isHovered, setIsHovered] = React.useState(false);
17814
- const hasChildren = span.spans && span.spans.length > 0;
17815
- const isRootSpan = depth === 0;
17816
18005
  const percentageSpanLatency = overallLatency ? Math.ceil(span.latency / overallLatency * 100) : 0;
17817
18006
  const overallStartTimeDate = overallStartTime ? new Date(overallStartTime) : null;
17818
18007
  const spanStartTimeDate = span.startTime ? new Date(span.startTime) : null;
17819
18008
  const spanStartTimeShift = spanStartTimeDate && overallStartTimeDate ? spanStartTimeDate.getTime() - overallStartTimeDate.getTime() : 0;
17820
18009
  const percentageSpanStartTime = overallLatency && Math.floor(spanStartTimeShift / overallLatency * 100);
17821
- const spanUI = getSpanTypeUi(span?.type);
17822
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17823
- /* @__PURE__ */ jsxRuntime.jsx(
17824
- "button",
18010
+ return /* @__PURE__ */ jsxRuntime.jsxs(HoverCard__namespace.Root, { openDelay: 250, children: [
18011
+ /* @__PURE__ */ jsxRuntime.jsxs(
18012
+ HoverCard__namespace.Trigger,
17825
18013
  {
17826
- onClick: () => onSpanClick?.(span.id),
17827
- onMouseEnter: () => setIsHovered(true),
17828
- onMouseLeave: () => setIsHovered(false),
17829
- type: "button",
17830
- "aria-label": `View details for span ${span.name}`,
17831
18014
  className: cn(
17832
- "rounded-md transition-colors cursor-pointer flex py-[0.5rem] opacity-80 min-h-[3.5rem]",
17833
- "mt-[1rem] xl:mt-0",
18015
+ "h-[3rem] p-[0.5rem] grid grid-cols-[1fr_auto] gap-4 items-center cursor-help pr-3 rounded-r-lg col-span-2 xl:col-span-1",
18016
+ "[&:hover>div]:bg-surface5",
17834
18017
  {
17835
- "bg-icon1/30 text-white": selectedSpanId === span.id,
17836
- "bg-icon1/10 opacity-100": isHovered
18018
+ "opacity-30 [&:hover]:opacity-60": isFaded,
18019
+ "bg-surface4": selectedSpanId === span.id
17837
18020
  }
17838
18021
  ),
17839
- style: { paddingLeft: `${depth * 1.4}rem` },
17840
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[1rem] w-full", children: [
17841
- !isRootSpan && /* @__PURE__ */ jsxRuntime.jsx(TreePositionMark, { isLastChild, hasChildren: Boolean(hasChildren) }),
17842
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-[0.875rem] flex items-center text-left break-all gap-[0.5rem] text-[#fff] w-full"), children: [
17843
- spanUI?.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0", style: { color: spanUI?.color }, children: spanUI?.icon }),
17844
- span.name
18022
+ children: [
18023
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full p-[0.6rem] rounded-lg bg-surface4 transition-colors duration-[1s]"), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full h-[0.4rem] rounded-sm", children: /* @__PURE__ */ jsxRuntime.jsx(
18024
+ "div",
18025
+ {
18026
+ className: cn("bg-icon1 absolute rounded-sm h-[0.4rem] top-0"),
18027
+ style: {
18028
+ width: percentageSpanLatency ? `${percentageSpanLatency}%` : "2px",
18029
+ left: `${percentageSpanStartTime || 0}%`,
18030
+ backgroundColor: color
18031
+ }
18032
+ }
18033
+ ) }) }),
18034
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex justify-end text-icon3 text-[0.75rem]"), children: [
18035
+ (span.latency / 1e3).toFixed(3),
18036
+ " s"
17845
18037
  ] })
17846
- ] })
18038
+ ]
17847
18039
  }
17848
18040
  ),
17849
- /* @__PURE__ */ jsxRuntime.jsxs(HoverCard__namespace.Root, { openDelay: 250, children: [
17850
- /* @__PURE__ */ jsxRuntime.jsxs(
17851
- HoverCard__namespace.Trigger,
17852
- {
17853
- className: cn(
17854
- "rounded-md transition-colors content-center cursor-help grid min-h-[3.5rem] opacity-80 px-[2.5rem] items-center relative",
17855
- "bg-surface2 xl:bg-surface3",
17856
- 'xl:last-of-type:before:content-[""] last-of-type:before:absolute last-of-type:before:bottom-[-1rem] last-of-type:before:h-[1rem] last-of-type:before:w-full last-of-type:before:bg-surface3',
17857
- 'xl:first-of-type:before:content-[""] first-of-type:before:absolute first-of-type:before:top-[-1rem] first-of-type:before:h-[1rem] first-of-type:before:w-full first-of-type:before:bg-surface3',
18041
+ /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
18042
+ HoverCard__namespace.Content,
18043
+ {
18044
+ className: "z-[100] w-auto max-w-[25rem] rounded-md bg-[#222] p-[.5rem] px-[1rem] pr-[1.5rem] text-[.75rem] text-icon5 text-center border border-border1",
18045
+ sideOffset: 5,
18046
+ side: "top",
18047
+ children: [
18048
+ /* @__PURE__ */ jsxRuntime.jsxs(
18049
+ "div",
17858
18050
  {
17859
- "bg-icon1/10 xl:bg-icon1/10 opacity-100": isHovered
18051
+ className: cn(
18052
+ "text-[0.875rem] flex items-center gap-[0.5rem] mb-[1rem]",
18053
+ "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0 [&>svg]:opacity-50"
18054
+ ),
18055
+ children: [
18056
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TimerIcon, {}),
18057
+ " Span Timing"
18058
+ ]
17860
18059
  }
17861
18060
  ),
17862
- onMouseEnter: () => setIsHovered(true),
17863
- onMouseLeave: () => setIsHovered(false),
17864
- children: [
17865
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-left text-[0.75rem] relative w-full h-[1.4rem] min-w-[6rem]", children: /* @__PURE__ */ jsxRuntime.jsxs(
17866
- "span",
17867
- {
17868
- className: cn(
17869
- "absolute flex pt-[0.1rem] items-center gap-[0.5rem] text-icon5",
17870
- "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0 [&>svg]:opacity-50 mb-[0.1em] [&>svg]:mb-[0.1rem]"
17871
- ),
17872
- style: { width: `${percentageSpanLatency}%`, left: `${percentageSpanStartTime}%` },
17873
- children: [
17874
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRight, {}),
17875
- /* @__PURE__ */ jsxRuntime.jsxs(
17876
- "span",
17877
- {
17878
- style: {
17879
- transform: percentageSpanStartTime && percentageSpanStartTime > 70 ? "translateX(calc((100% + 2rem) * -1))" : "none"
17880
- },
17881
- children: [
17882
- (span.latency / 1e3).toFixed(3),
17883
- " s"
17884
- ]
17885
- }
17886
- )
17887
- ]
17888
- }
17889
- ) }),
17890
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full bg-surface5 h-[3px] ", children: /* @__PURE__ */ jsxRuntime.jsx(
17891
- "div",
17892
- {
17893
- className: cn("bg-icon1 h-full absolute rounded-full"),
17894
- style: {
17895
- width: percentageSpanLatency ? `${percentageSpanLatency}%` : "2px",
17896
- left: `${percentageSpanStartTime}%`,
17897
- backgroundColor: spanUI?.color
18061
+ /* @__PURE__ */ jsxRuntime.jsx(
18062
+ KeyValueList,
18063
+ {
18064
+ className: " [&>dd]:text-[0.875rem] [&>dt]:text-[0.875rem] [&>dt]:min-h-0 [&>dd]:min-h-0",
18065
+ data: [
18066
+ {
18067
+ key: "Latency",
18068
+ label: "Latency",
18069
+ value: `${span.latency} ms`,
18070
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightIcon, {})
18071
+ },
18072
+ {
18073
+ key: "startTime",
18074
+ label: "Started at",
18075
+ value: span.startTime ? format.format(new Date(span.startTime), "hh:mm:ss:SSS a") : "-",
18076
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronFirstIcon, {})
18077
+ },
18078
+ {
18079
+ key: "endTime",
18080
+ label: "Ended at",
18081
+ value: span.endTime ? format.format(new Date(span.endTime), "hh:mm:ss:SSS a") : "-",
18082
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLastIcon, {})
18083
+ },
18084
+ {
18085
+ key: "startShift",
18086
+ label: "Start Shift",
18087
+ value: `${spanStartTimeShift}ms`,
18088
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRightIcon, {})
17898
18089
  }
17899
- }
17900
- ) })
17901
- ]
17902
- }
17903
- ),
17904
- /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
17905
- HoverCard__namespace.Content,
17906
- {
17907
- className: "z-[100] w-auto max-w-[25rem] rounded-md bg-[#222] p-[.5rem] px-[1rem] pr-[1.5rem] text-[.75rem] text-icon5 text-center border border-border1",
17908
- sideOffset: 5,
17909
- side: "top",
17910
- children: [
17911
- /* @__PURE__ */ jsxRuntime.jsxs(
17912
- "div",
17913
- {
17914
- className: cn(
17915
- "text-[0.875rem] flex items-center gap-[0.5rem] mb-[1rem]",
17916
- "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0 [&>svg]:opacity-50"
17917
- ),
17918
- children: [
17919
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TimerIcon, {}),
17920
- " Span Timing"
17921
- ]
17922
- }
17923
- ),
17924
- /* @__PURE__ */ jsxRuntime.jsx(
17925
- KeyValueList,
17926
- {
17927
- className: " [&>dd]:text-[0.875rem] [&>dt]:text-[0.875rem] [&>dt]:min-h-0 [&>dd]:min-h-0",
17928
- data: [
17929
- {
17930
- key: "Latency",
17931
- label: "Latency",
17932
- value: `${span.latency} ms`,
17933
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightIcon, {})
17934
- },
17935
- {
17936
- key: "startTime",
17937
- label: "Started at",
17938
- value: span.startTime ? format.format(new Date(span.startTime), "hh:mm:ss:SSS a") : "-",
17939
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronFirstIcon, {})
17940
- },
17941
- {
17942
- key: "endTime",
17943
- label: "Ended at",
17944
- value: span.endTime ? format.format(new Date(span.endTime), "hh:mm:ss:SSS a") : "-",
17945
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLastIcon, {})
17946
- },
17947
- {
17948
- key: "startShift",
17949
- label: "Start Shift",
17950
- value: `${spanStartTimeShift}ms`,
17951
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRightIcon, {})
17952
- }
17953
- ],
17954
- LinkComponent: Link
17955
- }
17956
- ),
17957
- /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Arrow, { className: "fill-surface5" })
17958
- ]
17959
- }
17960
- ) })
17961
- ] }),
17962
- hasChildren && span.spans?.map((childSpan, idx, array) => {
18090
+ ],
18091
+ LinkComponent: Link
18092
+ }
18093
+ ),
18094
+ /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Arrow, { className: "fill-surface5" })
18095
+ ]
18096
+ }
18097
+ ) })
18098
+ ] });
18099
+ }
18100
+
18101
+ function TraceTimelineSpan({
18102
+ span,
18103
+ depth = 0,
18104
+ onSpanClick,
18105
+ selectedSpanId,
18106
+ isLastChild,
18107
+ overallLatency,
18108
+ overallStartTime,
18109
+ overallEndTime,
18110
+ fadedTypes,
18111
+ searchPhrase,
18112
+ featuredSpanIds,
18113
+ expandedSpanIds,
18114
+ setExpandedSpanIds
18115
+ }) {
18116
+ const hasChildren = span.spans && span.spans.length > 0;
18117
+ const numOfChildren = span.spans ? span.spans.length : 0;
18118
+ const allDescendantIds = getSpanDescendantIds(span);
18119
+ const totalDescendants = allDescendantIds.length;
18120
+ const isRootSpan = depth === 0;
18121
+ const spanUI = getSpanTypeUi(span?.type);
18122
+ const isExpanded = expandedSpanIds ? expandedSpanIds.includes(span.id) : false;
18123
+ const isFadedBySearch = featuredSpanIds && featuredSpanIds.length > 0 ? !featuredSpanIds.includes(span.id) : false;
18124
+ const isFadedByType = fadedTypes && fadedTypes.length > 0 ? fadedTypes.includes(spanUI?.typePrefix || "") : false;
18125
+ const isFaded = isFadedByType || isFadedBySearch;
18126
+ React.useEffect(() => {
18127
+ isRootSpan && setExpandedSpanIds?.([span.id]);
18128
+ }, [isRootSpan, span.id, setExpandedSpanIds]);
18129
+ React.useEffect(() => {
18130
+ if (!featuredSpanIds || !span.spans || span.spans.length === 0) return;
18131
+ const hasFeaturedChildren = span.spans.some((childSpan) => featuredSpanIds.includes(childSpan.id));
18132
+ if (!isExpanded && hasFeaturedChildren) {
18133
+ toggleChildren();
18134
+ }
18135
+ }, [featuredSpanIds, span.spans, span.id, isExpanded, setExpandedSpanIds, expandedSpanIds]);
18136
+ const toggleChildren = () => {
18137
+ if (!setExpandedSpanIds || !expandedSpanIds) return;
18138
+ if (isExpanded) {
18139
+ const idsToRemove = [span.id, ...allDescendantIds];
18140
+ setExpandedSpanIds(expandedSpanIds.filter((id) => !idsToRemove.includes(id)));
18141
+ } else {
18142
+ setExpandedSpanIds([...expandedSpanIds, span.id]);
18143
+ }
18144
+ };
18145
+ const expandAllDescendants = () => {
18146
+ if (!setExpandedSpanIds || !expandedSpanIds) return;
18147
+ setExpandedSpanIds([...expandedSpanIds, span.id, ...allDescendantIds]);
18148
+ };
18149
+ const allDescendantsExpanded = allDescendantIds.every((id) => expandedSpanIds?.includes(id));
18150
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18151
+ /* @__PURE__ */ jsxRuntime.jsx(
18152
+ TimelineNameCol,
18153
+ {
18154
+ span,
18155
+ spanUI,
18156
+ isFaded,
18157
+ depth,
18158
+ onSpanClick,
18159
+ selectedSpanId,
18160
+ isLastChild,
18161
+ hasChildren,
18162
+ isRootSpan,
18163
+ isExpanded,
18164
+ toggleChildren
18165
+ }
18166
+ ),
18167
+ /* @__PURE__ */ jsxRuntime.jsx(
18168
+ TimelineExpandCol,
18169
+ {
18170
+ isSelected: selectedSpanId === span.id,
18171
+ isFaded,
18172
+ isExpanded,
18173
+ toggleChildren,
18174
+ expandAllDescendants,
18175
+ expandedSpanIds,
18176
+ totalDescendants,
18177
+ allDescendantsExpanded,
18178
+ numOfChildren
18179
+ }
18180
+ ),
18181
+ /* @__PURE__ */ jsxRuntime.jsx(
18182
+ TimelineTimingCol,
18183
+ {
18184
+ span,
18185
+ selectedSpanId,
18186
+ isFaded,
18187
+ overallLatency,
18188
+ overallStartTime,
18189
+ overallEndTime,
18190
+ color: spanUI?.color
18191
+ }
18192
+ ),
18193
+ hasChildren && isExpanded && span.spans?.map((childSpan, idx, array) => {
17963
18194
  const isLastChild2 = idx === array.length - 1;
17964
18195
  return /* @__PURE__ */ jsxRuntime.jsx(
17965
18196
  TraceTimelineSpan,
@@ -17970,31 +18201,29 @@ function TraceTimelineSpan({
17970
18201
  selectedSpanId,
17971
18202
  isLastChild: isLastChild2,
17972
18203
  overallLatency,
17973
- overallStartTime
18204
+ overallStartTime,
18205
+ fadedTypes,
18206
+ searchPhrase,
18207
+ expandedSpanIds,
18208
+ setExpandedSpanIds,
18209
+ featuredSpanIds
17974
18210
  },
17975
18211
  childSpan.id
17976
18212
  );
17977
18213
  })
17978
18214
  ] });
17979
18215
  }
17980
- function TreePositionMark({ isLastChild, hasChildren = false }) {
17981
- return /* @__PURE__ */ jsxRuntime.jsx(
17982
- "div",
17983
- {
17984
- className: cn(
17985
- "w-[1.5rem] h-[2.2rem] relative opacity-50 ",
17986
- 'after:content-[""] after:absolute after:left-0 after:top-0 after:bottom-0 after:w-[0px] after:border-r-[0.5px] after:border-white after:border-dashed',
17987
- 'before:content-[""] before:absolute before:left-0 before:top-[50%] before:w-full before:h-[0px] before:border-b-[0.5px] before:border-white before:border-dashed',
17988
- {
17989
- "after:bottom-[50%]": isLastChild
17990
- }
17991
- ),
17992
- children: hasChildren && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -right-[1px] top-[50%] bottom-0 w-[0px] border-r-[0.5px] border-white border-dashed" })
17993
- }
17994
- );
17995
- }
17996
18216
 
17997
- function TraceTimeline({ hierarchicalSpans = [], onSpanClick, selectedSpanId, isLoading }) {
18217
+ function TraceTimeline({
18218
+ hierarchicalSpans = [],
18219
+ onSpanClick,
18220
+ selectedSpanId,
18221
+ isLoading,
18222
+ fadedTypes,
18223
+ expandedSpanIds,
18224
+ setExpandedSpanIds,
18225
+ featuredSpanIds
18226
+ }) {
17998
18227
  const overallLatency = hierarchicalSpans?.[0]?.latency || 0;
17999
18228
  const overallStartTime = hierarchicalSpans?.[0]?.startTime || "";
18000
18229
  const overallEndTime = hierarchicalSpans?.[0]?.endTime || "";
@@ -18013,10 +18242,13 @@ function TraceTimeline({ hierarchicalSpans = [], onSpanClick, selectedSpanId, is
18013
18242
  ) : /* @__PURE__ */ jsxRuntime.jsx(
18014
18243
  "div",
18015
18244
  {
18016
- className: cn("grid items-start content-start gap-y-[2px] overflow-hidden", "xl:gap-x-[1rem] xl:py-[1rem]", {
18017
- "xl:grid-cols-[3fr_auto]": !overallEndTime,
18018
- "xl:grid-cols-[3fr_2fr]": overallEndTime
18019
- }),
18245
+ className: cn(
18246
+ "grid items-start content-start gap-y-[2px] overflow-hidden grid-cols-[1fr_auto] xl:py-[1rem]",
18247
+ {
18248
+ "xl:grid-cols-[1fr_auto_auto]": !overallEndTime,
18249
+ "xl:grid-cols-[2fr_auto_1fr]": overallEndTime
18250
+ }
18251
+ ),
18020
18252
  children: hierarchicalSpans?.map((span) => /* @__PURE__ */ jsxRuntime.jsx(
18021
18253
  TraceTimelineSpan,
18022
18254
  {
@@ -18025,7 +18257,11 @@ function TraceTimeline({ hierarchicalSpans = [], onSpanClick, selectedSpanId, is
18025
18257
  selectedSpanId,
18026
18258
  overallLatency,
18027
18259
  overallStartTime,
18028
- overallEndTime
18260
+ overallEndTime,
18261
+ fadedTypes,
18262
+ featuredSpanIds,
18263
+ expandedSpanIds,
18264
+ setExpandedSpanIds
18029
18265
  },
18030
18266
  span.id
18031
18267
  ))
@@ -18033,19 +18269,235 @@ function TraceTimeline({ hierarchicalSpans = [], onSpanClick, selectedSpanId, is
18033
18269
  ) });
18034
18270
  }
18035
18271
 
18036
- function TraceTimelineLegend({ spans = [] }) {
18037
- const activeSpanTypes = spanTypePrefixes.filter(
18038
- (typePrefix) => spans.some((span) => span?.spanType?.startsWith(typePrefix))
18039
- );
18040
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex justify-start gap-[2rem] mb-2 text-[0.75rem] opacity-90"), children: activeSpanTypes.map((item) => {
18041
- const spanUI = getSpanTypeUi(item);
18042
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-[.5rem]"), children: [
18043
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("[&>svg]:w-[1.2em] [&>svg]:h-[1.2em]"), style: { color: spanUI?.color }, children: spanUI?.icon && spanUI.icon }),
18044
- spanUI?.label
18045
- ] }, item);
18046
- }) });
18272
+ function TraceTimelineTools({
18273
+ spans = [],
18274
+ fadedTypes,
18275
+ onLegendClick,
18276
+ onLegendReset,
18277
+ onSearchPhraseChange,
18278
+ traceId
18279
+ }) {
18280
+ const [localSearchPhrase, setLocalSearchPhrase] = React.useState("");
18281
+ React.useEffect(() => {
18282
+ setLocalSearchPhrase("");
18283
+ }, [traceId]);
18284
+ const usedSpanTypes = spanTypePrefixes.filter((typePrefix) => spans.some((span) => span?.spanType?.startsWith(typePrefix))) || [];
18285
+ const hasOtherSpanTypes = spans.some((span) => {
18286
+ const isKnownType = spanTypePrefixes.some((typePrefix) => span?.spanType?.startsWith(typePrefix));
18287
+ return !isKnownType;
18288
+ });
18289
+ const handleToggle = (type) => {
18290
+ onLegendClick?.(type);
18291
+ };
18292
+ React.useEffect(() => {
18293
+ handleSearchPhraseChange(localSearchPhrase);
18294
+ }, [localSearchPhrase, onSearchPhraseChange]);
18295
+ const handleSearchPhraseChange = useDebounce.useThrottledCallback((value) => {
18296
+ onSearchPhraseChange?.(value);
18297
+ }, 1e3);
18298
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-3 items-center justify-between", children: [
18299
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(
18300
+ SearchField,
18301
+ {
18302
+ value: localSearchPhrase,
18303
+ onChange: (e) => {
18304
+ setLocalSearchPhrase(e.target.value);
18305
+ },
18306
+ label: "Find span by name",
18307
+ placeholder: "Look for span name",
18308
+ onReset: () => setLocalSearchPhrase("")
18309
+ }
18310
+ ) }),
18311
+ /* @__PURE__ */ jsxRuntime.jsxs(CombinedButtons, { children: [
18312
+ usedSpanTypes.map((item, idx) => {
18313
+ const spanUI = getSpanTypeUi(item);
18314
+ const isFaded = fadedTypes?.includes(item);
18315
+ return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs(
18316
+ Button,
18317
+ {
18318
+ onClick: () => handleToggle(item),
18319
+ isFaded,
18320
+ style: { color: !isFaded ? spanUI?.color : void 0, backgroundColor: spanUI?.bgColor },
18321
+ children: [
18322
+ spanUI?.icon && spanUI.icon,
18323
+ spanUI?.label
18324
+ ]
18325
+ }
18326
+ ) }, item);
18327
+ }),
18328
+ hasOtherSpanTypes && /* @__PURE__ */ jsxRuntime.jsxs(
18329
+ Button,
18330
+ {
18331
+ onClick: () => handleToggle("other"),
18332
+ isFaded: fadedTypes?.includes("other"),
18333
+ style: { color: !fadedTypes?.includes("other") ? void 0 : void 0, backgroundColor: void 0 },
18334
+ children: [
18335
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashedIcon, {}),
18336
+ "Other"
18337
+ ]
18338
+ }
18339
+ ),
18340
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onLegendReset, disabled: fadedTypes?.length === 0, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}) })
18341
+ ] })
18342
+ ] });
18047
18343
  }
18048
18344
 
18345
+ function useTraceInfo(trace) {
18346
+ const { paths } = useLinkComponent();
18347
+ if (!trace) {
18348
+ return [];
18349
+ }
18350
+ const agentsLink = paths.agentsLink();
18351
+ const workflowsLink = paths.workflowsLink();
18352
+ const agentLink = paths.agentLink(trace?.metadata?.resourceId);
18353
+ const workflowLink = paths.workflowLink(trace?.attributes?.workflowId);
18354
+ return [
18355
+ {
18356
+ key: "entityId",
18357
+ label: "Entity Id",
18358
+ value: [
18359
+ {
18360
+ id: trace?.metadata?.resourceId,
18361
+ name: trace?.attributes?.agentId || trace?.attributes?.workflowId || "-",
18362
+ path: trace?.attributes?.agentId ? agentLink : trace?.attributes?.workflowId ? workflowLink : void 0
18363
+ }
18364
+ ]
18365
+ },
18366
+ {
18367
+ key: "entityType",
18368
+ label: "Entity Type",
18369
+ value: [
18370
+ {
18371
+ id: trace?.attributes?.agentId || trace?.attributes?.workflowId,
18372
+ name: trace?.attributes?.agentId ? "Agent" : trace?.attributes?.workflowId ? "Workflow" : "-",
18373
+ path: trace?.attributes?.agentId ? agentsLink : trace?.attributes?.workflowId ? workflowsLink : void 0
18374
+ }
18375
+ ]
18376
+ },
18377
+ {
18378
+ key: "status",
18379
+ label: "Status",
18380
+ value: trace?.attributes?.status || "-"
18381
+ },
18382
+ {
18383
+ key: "startedAt",
18384
+ label: "Started at",
18385
+ value: trace?.startedAt ? dateFns.format(new Date(trace?.startedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18386
+ },
18387
+ {
18388
+ key: "endedAt",
18389
+ label: "Ended at",
18390
+ value: trace?.endedAt ? dateFns.format(new Date(trace?.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18391
+ }
18392
+ ];
18393
+ }
18394
+ function getSpanInfo({ span }) {
18395
+ if (!span) {
18396
+ return [];
18397
+ }
18398
+ const baseInfo = [
18399
+ {
18400
+ key: "spanType",
18401
+ label: "Span Type",
18402
+ value: span?.spanType
18403
+ },
18404
+ {
18405
+ key: "startedAt",
18406
+ label: "Started At",
18407
+ value: span?.startedAt ? dateFns.format(new Date(span.startedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18408
+ },
18409
+ {
18410
+ key: "endedAt",
18411
+ label: "Ended At",
18412
+ value: span?.endedAt ? dateFns.format(new Date(span.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18413
+ }
18414
+ ];
18415
+ if (span?.attributes?.finishReason) {
18416
+ baseInfo.push({
18417
+ key: "finishReason",
18418
+ label: "Finish Reason",
18419
+ value: span.attributes.finishReason
18420
+ });
18421
+ }
18422
+ return baseInfo;
18423
+ }
18424
+
18425
+ const TabsRoot = ({
18426
+ children,
18427
+ defaultTab,
18428
+ value,
18429
+ onValueChange,
18430
+ className
18431
+ }) => {
18432
+ const [internalTab, setInternalTab] = React.useState(defaultTab);
18433
+ const isControlled = value !== void 0 && onValueChange !== void 0;
18434
+ const currentTab = isControlled ? value : internalTab;
18435
+ const handleTabChange = (newValue) => {
18436
+ const typedValue = newValue;
18437
+ if (isControlled) {
18438
+ onValueChange(typedValue);
18439
+ } else {
18440
+ setInternalTab(typedValue);
18441
+ }
18442
+ };
18443
+ return /* @__PURE__ */ jsxRuntime.jsx(
18444
+ TabsPrimitive__namespace.Root,
18445
+ {
18446
+ value: currentTab,
18447
+ onValueChange: handleTabChange,
18448
+ className: cn("grid gap-8 overflow-y-auto", className),
18449
+ children
18450
+ }
18451
+ );
18452
+ };
18453
+
18454
+ const TabList = ({ children, variant = "default", className }) => {
18455
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full overflow-x-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx(
18456
+ TabsPrimitive__namespace.List,
18457
+ {
18458
+ className: cn(
18459
+ "flex items-center",
18460
+ {
18461
+ // variant: default
18462
+ "text-[0.9375rem]": variant === "default",
18463
+ "[&>button]:py-[0.5rem] [&>button]:px-[1.5rem] [&>button]:font-normal [&>button]:text-icon3 [&>button]:flex-1 [&>button]:border-b [&>button]:border-border1": variant === "default",
18464
+ "[&>button[data-state=active]]:text-icon5 [&>button[data-state=active]]:transition-colors [&>button[data-state=active]]:duration-200 [&>button[data-state=active]]:border-icon3": variant === "default",
18465
+ // variant: buttons
18466
+ "border border-border1 flex justify-stretch rounded-md overflow-hidden text-[0.875rem] min-h-[2.5rem]": variant === "buttons",
18467
+ "[&>button]:flex-1 [&>button]:py-[0.5rem] [&>button]:px-[1rem] [&>button]:text-icon3": variant === "buttons",
18468
+ "[&>button[data-state=active]]:text-icon5 [&>button[data-state=active]]:bg-[#222]": variant === "buttons"
18469
+ },
18470
+ className
18471
+ ),
18472
+ children
18473
+ }
18474
+ ) });
18475
+ };
18476
+
18477
+ const Tab = ({ children, value, onClick, className }) => {
18478
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Trigger, { value, className: cn("hover:text-icon5", className), onClick, children });
18479
+ };
18480
+
18481
+ const TabContent = ({ children, value, className }) => {
18482
+ return /* @__PURE__ */ jsxRuntime.jsx(
18483
+ TabsPrimitive__namespace.Content,
18484
+ {
18485
+ value,
18486
+ className: cn(
18487
+ "grid overflow-y-auto ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:none",
18488
+ className
18489
+ ),
18490
+ children
18491
+ }
18492
+ );
18493
+ };
18494
+
18495
+ const Tabs = Object.assign(TabsRoot, {
18496
+ List: TabList,
18497
+ Tab,
18498
+ Content: TabContent
18499
+ });
18500
+
18049
18501
  function TraceSpanUsage({ traceUsage, traceSpans = [], spanUsage, className }) {
18050
18502
  if (!traceUsage && !spanUsage) {
18051
18503
  console.warn("No usage data available");
@@ -18208,169 +18660,6 @@ function TraceSpanUsage({ traceUsage, traceSpans = [], spanUsage, className }) {
18208
18660
  )) });
18209
18661
  }
18210
18662
 
18211
- function useTraceInfo(trace) {
18212
- const { paths } = useLinkComponent();
18213
- if (!trace) {
18214
- return [];
18215
- }
18216
- const agentsLink = paths.agentsLink();
18217
- const workflowsLink = paths.workflowsLink();
18218
- const agentLink = paths.agentLink(trace?.metadata?.resourceId);
18219
- const workflowLink = paths.workflowLink(trace?.attributes?.workflowId);
18220
- return [
18221
- {
18222
- key: "entityId",
18223
- label: "Entity Id",
18224
- value: [
18225
- {
18226
- id: trace?.metadata?.resourceId,
18227
- name: trace?.attributes?.agentId || trace?.attributes?.workflowId || "-",
18228
- path: trace?.attributes?.agentId ? agentLink : trace?.attributes?.workflowId ? workflowLink : void 0
18229
- }
18230
- ]
18231
- },
18232
- {
18233
- key: "entityType",
18234
- label: "Entity Type",
18235
- value: [
18236
- {
18237
- id: trace?.attributes?.agentId || trace?.attributes?.workflowId,
18238
- name: trace?.attributes?.agentId ? "Agent" : trace?.attributes?.workflowId ? "Workflow" : "-",
18239
- path: trace?.attributes?.agentId ? agentsLink : trace?.attributes?.workflowId ? workflowsLink : void 0
18240
- }
18241
- ]
18242
- },
18243
- {
18244
- key: "status",
18245
- label: "Status",
18246
- value: trace?.attributes?.status || "-"
18247
- },
18248
- {
18249
- key: "startedAt",
18250
- label: "Started at",
18251
- value: trace?.startedAt ? dateFns.format(new Date(trace?.startedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18252
- },
18253
- {
18254
- key: "endedAt",
18255
- label: "Ended at",
18256
- value: trace?.endedAt ? dateFns.format(new Date(trace?.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18257
- }
18258
- ];
18259
- }
18260
- function getSpanInfo({ span, withTraceId = true, withSpanId = true }) {
18261
- if (!span) {
18262
- return [];
18263
- }
18264
- const baseInfo = [
18265
- {
18266
- key: "spanType",
18267
- label: "Span Type",
18268
- value: span?.spanType
18269
- },
18270
- {
18271
- key: "startedAt",
18272
- label: "Started At",
18273
- value: span?.startedAt ? dateFns.format(new Date(span.startedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18274
- },
18275
- {
18276
- key: "endedAt",
18277
- label: "Ended At",
18278
- value: span?.endedAt ? dateFns.format(new Date(span.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18279
- }
18280
- ];
18281
- if (span?.attributes?.finishReason) {
18282
- baseInfo.push({
18283
- key: "finishReason",
18284
- label: "Finish Reason",
18285
- value: span.attributes.finishReason
18286
- });
18287
- }
18288
- if (withSpanId) {
18289
- baseInfo.unshift({
18290
- key: "spanId",
18291
- label: "#",
18292
- value: span?.spanId
18293
- });
18294
- }
18295
- return baseInfo;
18296
- }
18297
-
18298
- const TabsRoot = ({
18299
- children,
18300
- defaultTab,
18301
- value,
18302
- onValueChange,
18303
- className
18304
- }) => {
18305
- const [internalTab, setInternalTab] = React.useState(defaultTab);
18306
- const isControlled = value !== void 0 && onValueChange !== void 0;
18307
- const currentTab = isControlled ? value : internalTab;
18308
- const handleTabChange = (newValue) => {
18309
- const typedValue = newValue;
18310
- if (isControlled) {
18311
- onValueChange(typedValue);
18312
- } else {
18313
- setInternalTab(typedValue);
18314
- }
18315
- };
18316
- return /* @__PURE__ */ jsxRuntime.jsx(
18317
- TabsPrimitive__namespace.Root,
18318
- {
18319
- value: currentTab,
18320
- onValueChange: handleTabChange,
18321
- className: cn("grid gap-[3rem] overflow-y-auto", className),
18322
- children
18323
- }
18324
- );
18325
- };
18326
-
18327
- const TabList = ({ children, variant = "default", className }) => {
18328
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full overflow-x-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx(
18329
- TabsPrimitive__namespace.List,
18330
- {
18331
- className: cn(
18332
- "flex items-center",
18333
- {
18334
- // variant: default
18335
- "text-[0.9375rem]": variant === "default",
18336
- "[&>button]:py-[0.5rem] [&>button]:px-[1.5rem] [&>button]:font-normal [&>button]:text-icon3 [&>button]:flex-1 [&>button]:border-b [&>button]:border-border1": variant === "default",
18337
- "[&>button[data-state=active]]:text-icon5 [&>button[data-state=active]]:transition-colors [&>button[data-state=active]]:duration-200 [&>button[data-state=active]]:border-icon3": variant === "default",
18338
- // variant: buttons
18339
- "border border-border1 flex justify-stretch rounded-md overflow-hidden text-[0.875rem] min-h-[2.5rem]": variant === "buttons",
18340
- "[&>button]:flex-1 [&>button]:py-[0.5rem] [&>button]:px-[1rem] [&>button]:text-icon3": variant === "buttons",
18341
- "[&>button[data-state=active]]:text-icon5 [&>button[data-state=active]]:bg-[#222]": variant === "buttons"
18342
- },
18343
- className
18344
- ),
18345
- children
18346
- }
18347
- ) });
18348
- };
18349
-
18350
- const Tab = ({ children, value, onClick, className }) => {
18351
- return /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Trigger, { value, className: cn("hover:text-icon5", className), onClick, children });
18352
- };
18353
-
18354
- const TabContent = ({ children, value, className }) => {
18355
- return /* @__PURE__ */ jsxRuntime.jsx(
18356
- TabsPrimitive__namespace.Content,
18357
- {
18358
- value,
18359
- className: cn(
18360
- "grid overflow-y-auto ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:none",
18361
- className
18362
- ),
18363
- children
18364
- }
18365
- );
18366
- };
18367
-
18368
- const Tabs = Object.assign(TabsRoot, {
18369
- List: TabList,
18370
- Tab,
18371
- Content: TabContent
18372
- });
18373
-
18374
18663
  function isTokenLimitExceeded(span) {
18375
18664
  return span?.attributes?.finishReason === "length";
18376
18665
  }
@@ -18447,7 +18736,9 @@ function SpanTabs({
18447
18736
  spanInfo = [],
18448
18737
  defaultActiveTab = "details",
18449
18738
  initialScoreId,
18450
- computeTraceLink
18739
+ computeTraceLink,
18740
+ scorers,
18741
+ isLoadingScorers
18451
18742
  }) {
18452
18743
  const { Link } = useLinkComponent();
18453
18744
  let entityType;
@@ -18481,7 +18772,9 @@ function SpanTabs({
18481
18772
  traceId: trace?.traceId,
18482
18773
  isTopLevelSpan: span?.parentSpanId === null,
18483
18774
  spanId: span?.spanId,
18484
- entityType
18775
+ entityType,
18776
+ scorers,
18777
+ isLoadingScorers
18485
18778
  }
18486
18779
  )
18487
18780
  ] }),
@@ -18521,7 +18814,9 @@ function SpanDialog({
18521
18814
  spanInfo = [],
18522
18815
  defaultActiveTab = "details",
18523
18816
  initialScoreId,
18524
- computeTraceLink
18817
+ computeTraceLink,
18818
+ scorers,
18819
+ isLoadingScorers
18525
18820
  }) {
18526
18821
  return /* @__PURE__ */ jsxRuntime.jsxs(
18527
18822
  SideDialog,
@@ -18574,7 +18869,9 @@ function SpanDialog({
18574
18869
  spanInfo,
18575
18870
  defaultActiveTab,
18576
18871
  initialScoreId,
18577
- computeTraceLink
18872
+ computeTraceLink,
18873
+ scorers,
18874
+ isLoadingScorers
18578
18875
  }
18579
18876
  )
18580
18877
  ] })
@@ -18592,12 +18889,12 @@ function TraceDialog({
18592
18889
  onNext,
18593
18890
  onPrevious,
18594
18891
  isLoadingSpans,
18595
- computeAgentsLink,
18596
- computeWorkflowsLink,
18597
18892
  computeTraceLink,
18598
18893
  initialSpanId,
18599
18894
  initialSpanTab,
18600
- initialScoreId
18895
+ initialScoreId,
18896
+ scorers,
18897
+ isLoadingScorers
18601
18898
  }) {
18602
18899
  const { Link, navigate } = useLinkComponent();
18603
18900
  const [dialogIsOpen, setDialogIsOpen] = React.useState(Boolean(initialSpanId));
@@ -18607,6 +18904,19 @@ function TraceDialog({
18607
18904
  const selectedSpan = traceSpans.find((span) => span.spanId === selectedSpanId);
18608
18905
  const traceInfo = useTraceInfo(traceDetails);
18609
18906
  const [spanScoresPage, setSpanScoresPage] = React.useState(0);
18907
+ const [searchPhrase, setSearchPhrase] = React.useState("");
18908
+ const [fadedSpanTypes, setFadedSpanTypes] = React.useState([]);
18909
+ const [featuredSpanIds, setFeaturedSpanIds] = React.useState([]);
18910
+ const [expandedSpanIds, setExpandedSpanIds] = React.useState([]);
18911
+ React.useEffect(() => {
18912
+ if (searchPhrase.trim() === "") {
18913
+ setFeaturedSpanIds([]);
18914
+ return;
18915
+ }
18916
+ const lowerCaseSearch = searchPhrase.toLowerCase();
18917
+ const newFeaturedSpanIds = traceSpans.filter((span) => span.name.toLowerCase().includes(lowerCaseSearch)).map((span) => span.spanId);
18918
+ setFeaturedSpanIds(newFeaturedSpanIds);
18919
+ }, [searchPhrase]);
18610
18920
  React.useEffect(() => {
18611
18921
  if (initialSpanId) {
18612
18922
  setSelectedSpanId(initialSpanId);
@@ -18641,9 +18951,13 @@ function TraceDialog({
18641
18951
  page: spanScoresPage
18642
18952
  });
18643
18953
  const handleSpanClick = (id) => {
18644
- setSelectedSpanId(id);
18645
- setSpanDialogDefaultTab("details");
18646
- setDialogIsOpen(true);
18954
+ if (selectedSpanId === id) {
18955
+ setSelectedSpanId(void 0);
18956
+ } else {
18957
+ setSelectedSpanId(id);
18958
+ setSpanDialogDefaultTab("details");
18959
+ setDialogIsOpen(true);
18960
+ }
18647
18961
  };
18648
18962
  const handleToScoring = () => {
18649
18963
  setSelectedSpanId(hierarchicalSpans[0]?.id);
@@ -18664,9 +18978,53 @@ function TraceDialog({
18664
18978
  );
18665
18979
  }
18666
18980
  };
18667
- const selectedSpanInfo = getSpanInfo({ span: selectedSpan, withTraceId: !combinedView, withSpanId: combinedView });
18668
- const toNextSpan = getToNextEntryFn({ entries: flatSpans, id: selectedSpanId, update: setSelectedSpanId });
18669
- const toPreviousSpan = getToPreviousEntryFn({ entries: flatSpans, id: selectedSpanId, update: setSelectedSpanId });
18981
+ const handleLegendClick = (type) => {
18982
+ setFadedSpanTypes((prev) => {
18983
+ if (prev.includes(type)) {
18984
+ return prev.filter((t) => t !== type);
18985
+ } else {
18986
+ return [...prev, type];
18987
+ }
18988
+ });
18989
+ };
18990
+ const handleLegendReset = () => {
18991
+ setFadedSpanTypes([]);
18992
+ };
18993
+ const selectedSpanInfo = getSpanInfo({ span: selectedSpan });
18994
+ const getVisibleSpans = () => {
18995
+ const visibleSpans = [];
18996
+ const collectVisibleSpans = (spans, parentId) => {
18997
+ spans.forEach((span) => {
18998
+ const isVisible = !parentId || parentId === null || expandedSpanIds.includes(parentId);
18999
+ if (isVisible) {
19000
+ visibleSpans.push(span);
19001
+ if (expandedSpanIds.includes(span.id) && span.spans) {
19002
+ collectVisibleSpans(span.spans, span.id);
19003
+ }
19004
+ }
19005
+ });
19006
+ };
19007
+ collectVisibleSpans(hierarchicalSpans);
19008
+ return visibleSpans;
19009
+ };
19010
+ const toNextSpan = () => {
19011
+ if (!selectedSpanId) return void 0;
19012
+ const visibleSpans = getVisibleSpans();
19013
+ const currentIndex = visibleSpans.findIndex((span) => span.id === selectedSpanId);
19014
+ if (currentIndex >= 0 && currentIndex < visibleSpans.length - 1) {
19015
+ return () => setSelectedSpanId(visibleSpans[currentIndex + 1].id);
19016
+ }
19017
+ return void 0;
19018
+ };
19019
+ const toPreviousSpan = () => {
19020
+ if (!selectedSpanId) return void 0;
19021
+ const visibleSpans = getVisibleSpans();
19022
+ const currentIndex = visibleSpans.findIndex((span) => span.id === selectedSpanId);
19023
+ if (currentIndex > 0) {
19024
+ return () => setSelectedSpanId(visibleSpans[currentIndex - 1].id);
19025
+ }
19026
+ return void 0;
19027
+ };
18670
19028
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18671
19029
  /* @__PURE__ */ jsxRuntime.jsxs(
18672
19030
  SideDialog,
@@ -18728,57 +19086,66 @@ function TraceDialog({
18728
19086
  ] })
18729
19087
  ] }),
18730
19088
  /* @__PURE__ */ jsxRuntime.jsxs(Section, { children: [
18731
- /* @__PURE__ */ jsxRuntime.jsxs(Section.Header, { children: [
18732
- /* @__PURE__ */ jsxRuntime.jsxs(Section.Heading, { children: [
18733
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTreeIcon, {}),
18734
- " Timeline"
18735
- ] }),
18736
- /* @__PURE__ */ jsxRuntime.jsx(TraceTimelineLegend, { spans: traceSpans })
18737
- ] }),
19089
+ /* @__PURE__ */ jsxRuntime.jsx(Section.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(Section.Heading, { children: [
19090
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTreeIcon, {}),
19091
+ " Timeline"
19092
+ ] }) }),
19093
+ /* @__PURE__ */ jsxRuntime.jsx(
19094
+ TraceTimelineTools,
19095
+ {
19096
+ spans: traceSpans,
19097
+ fadedTypes: fadedSpanTypes,
19098
+ onLegendClick: handleLegendClick,
19099
+ onLegendReset: handleLegendReset,
19100
+ searchPhrase,
19101
+ onSearchPhraseChange: setSearchPhrase,
19102
+ traceId
19103
+ }
19104
+ ),
18738
19105
  /* @__PURE__ */ jsxRuntime.jsx(
18739
19106
  TraceTimeline,
18740
19107
  {
18741
19108
  hierarchicalSpans,
18742
19109
  onSpanClick: handleSpanClick,
18743
19110
  selectedSpanId,
18744
- isLoading: isLoadingSpans
19111
+ isLoading: isLoadingSpans,
19112
+ fadedTypes: fadedSpanTypes,
19113
+ expandedSpanIds,
19114
+ setExpandedSpanIds,
19115
+ featuredSpanIds
18745
19116
  }
18746
19117
  )
18747
19118
  ] })
18748
19119
  ] })
18749
19120
  ] }),
18750
- selectedSpan && combinedView && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-rows-[auto_1fr] relative overflow-y-auto", children: [
18751
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Top, { withTopSeparator: true, children: [
19121
+ selectedSpan && combinedView && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-rows-[auto_1fr] relative overflow-y-auto rounded-xl mx-[2rem] mb-[2rem] bg-surface4", children: [
19122
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Top, { children: [
18752
19123
  /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
18753
19124
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
18754
19125
  " ",
18755
19126
  getShortId(selectedSpanId)
18756
19127
  ] }),
18757
19128
  "|",
18758
- /* @__PURE__ */ jsxRuntime.jsx(SideDialog.Nav, { onNext: toNextSpan, onPrevious: toPreviousSpan }),
19129
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialog.Nav, { onNext: toNextSpan(), onPrevious: toPreviousSpan() }),
18759
19130
  /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "ml-auto mr-[2rem]", onClick: () => setCombinedView(false), children: [
18760
19131
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftIcon, {}),
18761
19132
  " ",
18762
19133
  /* @__PURE__ */ jsxRuntime.jsx(VisuallyHidden.VisuallyHidden, { children: "Switch to dialog view" })
18763
19134
  ] })
18764
19135
  ] }),
18765
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("h-full overflow-y-auto grid gap-[2rem] grid-cols-[20rem_1fr]"), children: [
18766
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto grid content-start p-[2rem] gap-[2rem]", children: [
18767
- /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Heading, { as: "h2", children: [
18768
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
18769
- " ",
19136
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("h-full overflow-y-auto pb-[2rem] pl-[2rem]"), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto pr-[2rem] pt-[2rem] h-full", children: [
19137
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Header, { children: [
19138
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialog.Heading, { children: [
19139
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
18770
19140
  selectedSpan?.name
18771
19141
  ] }),
18772
- selectedSpan?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(
18773
- TraceSpanUsage,
18774
- {
18775
- spanUsage: selectedSpan.attributes.usage,
18776
- className: "xl:grid-cols-1 xl:gap-[1rem]"
18777
- }
18778
- ),
18779
- /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: selectedSpanInfo, LinkComponent: Link })
19142
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
19143
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HashIcon, {}),
19144
+ " ",
19145
+ selectedSpanId
19146
+ ] })
18780
19147
  ] }),
18781
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto pr-[2rem] pt-[2rem] h-full", children: /* @__PURE__ */ jsxRuntime.jsx(
19148
+ /* @__PURE__ */ jsxRuntime.jsx(
18782
19149
  SpanTabs,
18783
19150
  {
18784
19151
  trace: traceDetails,
@@ -18791,8 +19158,8 @@ function TraceDialog({
18791
19158
  initialScoreId,
18792
19159
  computeTraceLink
18793
19160
  }
18794
- ) })
18795
- ] })
19161
+ )
19162
+ ] }) })
18796
19163
  ] })
18797
19164
  ]
18798
19165
  }
@@ -18812,15 +19179,16 @@ function TraceDialog({
18812
19179
  onClose: () => {
18813
19180
  navigate(computeTraceLink(traceId || ""));
18814
19181
  setDialogIsOpen(false);
18815
- setSelectedSpanId(void 0);
18816
19182
  },
18817
- onNext: toNextSpan,
18818
- onPrevious: toPreviousSpan,
19183
+ onNext: toNextSpan(),
19184
+ onPrevious: toPreviousSpan(),
18819
19185
  onViewToggle: () => setCombinedView(!combinedView),
18820
19186
  spanInfo: selectedSpanInfo,
18821
19187
  defaultActiveTab: spanDialogDefaultTab,
18822
19188
  initialScoreId,
18823
- computeTraceLink
19189
+ computeTraceLink,
19190
+ scorers,
19191
+ isLoadingScorers
18824
19192
  }
18825
19193
  )
18826
19194
  ] });
@@ -19080,8 +19448,14 @@ const useTriggerScorer = () => {
19080
19448
  });
19081
19449
  };
19082
19450
 
19083
- const SpanScoring = ({ traceId, spanId, entityType, isTopLevelSpan }) => {
19084
- const { data: scorers = {}, isLoading, error } = useScorers();
19451
+ const SpanScoring = ({
19452
+ traceId,
19453
+ spanId,
19454
+ entityType,
19455
+ isTopLevelSpan,
19456
+ scorers,
19457
+ isLoadingScorers
19458
+ }) => {
19085
19459
  const [selectedScorer, setSelectedScorer] = React.useState(null);
19086
19460
  const { mutate: triggerScorer, isPending, isSuccess } = useTriggerScorer();
19087
19461
  const [notificationIsVisible, setNotificationIsVisible] = React.useState(false);
@@ -19090,7 +19464,7 @@ const SpanScoring = ({ traceId, spanId, entityType, isTopLevelSpan }) => {
19090
19464
  setNotificationIsVisible(true);
19091
19465
  }
19092
19466
  }, [isSuccess]);
19093
- let scorerList = Object.entries(scorers).map(([key, scorer]) => ({
19467
+ let scorerList = Object.entries(scorers || {}).map(([key, scorer]) => ({
19094
19468
  id: key,
19095
19469
  name: scorer.scorer.config.name,
19096
19470
  description: scorer.scorer.config.description,
@@ -19100,7 +19474,7 @@ const SpanScoring = ({ traceId, spanId, entityType, isTopLevelSpan }) => {
19100
19474
  if (entityType !== "Agent" || !isTopLevelSpan) {
19101
19475
  scorerList = scorerList.filter((scorer) => scorer.type !== "agent");
19102
19476
  }
19103
- const isWaiting = isPending || isLoading;
19477
+ const isWaiting = isPending || isLoadingScorers;
19104
19478
  const handleStartScoring = () => {
19105
19479
  if (selectedScorer) {
19106
19480
  setNotificationIsVisible(false);
@@ -19116,11 +19490,10 @@ const SpanScoring = ({ traceId, spanId, entityType, isTopLevelSpan }) => {
19116
19490
  setNotificationIsVisible(false);
19117
19491
  };
19118
19492
  const selectedScorerDescription = scorerList.find((s) => s.name === selectedScorer)?.description || "";
19119
- if (error) {
19493
+ if (scorers === void 0 && !isLoadingScorers) {
19120
19494
  return /* @__PURE__ */ jsxRuntime.jsxs(Notification, { isVisible: true, autoDismiss: false, type: "error", children: [
19121
19495
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, {}),
19122
- " ",
19123
- error?.message ? error.message : "Failed to load scorers."
19496
+ " Failed to load scorers."
19124
19497
  ] });
19125
19498
  }
19126
19499
  if (scorerList.length === 0) {
@@ -19729,6 +20102,22 @@ function MCPServerCombobox({
19729
20102
  );
19730
20103
  }
19731
20104
 
20105
+ const getMastraInstanceStatus = async (endpoint = "http://localhost:4111") => {
20106
+ try {
20107
+ const response = await fetch(endpoint);
20108
+ return { status: response.ok ? "active" : "inactive" };
20109
+ } catch {
20110
+ return { status: "inactive" };
20111
+ }
20112
+ };
20113
+ const useMastraInstanceStatus = (endpoint = "http://localhost:4111") => {
20114
+ return reactQuery.useQuery({
20115
+ queryKey: ["mastra-instance-status", endpoint],
20116
+ queryFn: () => getMastraInstanceStatus(endpoint),
20117
+ retry: false
20118
+ });
20119
+ };
20120
+
19732
20121
  const StudioConfigContext = React.createContext({
19733
20122
  baseUrl: "",
19734
20123
  headers: {},
@@ -19740,13 +20129,16 @@ const useStudioConfig = () => {
19740
20129
  return React.useContext(StudioConfigContext);
19741
20130
  };
19742
20131
  const LOCAL_STORAGE_KEY = "mastra-studio-config";
19743
- const StudioConfigProvider = ({ children }) => {
20132
+ const StudioConfigProvider = ({ children, endpoint = "http://localhost:4111" }) => {
20133
+ const { data: instanceStatus } = useMastraInstanceStatus(endpoint);
19744
20134
  const [config, setConfig] = React.useState({
19745
20135
  baseUrl: "",
19746
20136
  headers: {},
19747
20137
  isLoading: true
19748
20138
  });
20139
+ console.log("instanceStatus", instanceStatus);
19749
20140
  React.useLayoutEffect(() => {
20141
+ if (!instanceStatus?.status) return;
19750
20142
  const storedConfig = localStorage.getItem(LOCAL_STORAGE_KEY);
19751
20143
  if (storedConfig) {
19752
20144
  const parsedConfig = JSON.parse(storedConfig);
@@ -19754,8 +20146,11 @@ const StudioConfigProvider = ({ children }) => {
19754
20146
  return setConfig({ ...parsedConfig, isLoading: false });
19755
20147
  }
19756
20148
  }
20149
+ if (instanceStatus.status === "active") {
20150
+ return setConfig((prev) => ({ ...prev, baseUrl: endpoint, isLoading: false }));
20151
+ }
19757
20152
  return setConfig({ baseUrl: "", headers: {}, isLoading: false });
19758
- }, []);
20153
+ }, [instanceStatus, endpoint]);
19759
20154
  const doSetConfig = (partialNewConfig) => {
19760
20155
  setConfig((prev) => {
19761
20156
  const nextConfig = { ...prev, ...partialNewConfig };
@@ -19837,13 +20232,14 @@ const StudioConfigForm = ({ initialConfig }) => {
19837
20232
  const handleSubmit = (e) => {
19838
20233
  e.preventDefault();
19839
20234
  const formData = new FormData(e.target);
20235
+ const url = formData.get("url");
19840
20236
  const formHeaders = {};
19841
20237
  for (let i = 0; i < headers.length; i++) {
19842
20238
  const headerName = formData.get(`headers.${i}.name`);
19843
20239
  const headerValue = formData.get(`headers.${i}.value`);
19844
20240
  formHeaders[headerName] = headerValue;
19845
20241
  }
19846
- setConfig({ headers: formHeaders });
20242
+ setConfig({ headers: formHeaders, baseUrl: url });
19847
20243
  sonner.toast.success("Configuration saved");
19848
20244
  };
19849
20245
  const handleAddHeader = (header) => {
@@ -19853,6 +20249,16 @@ const StudioConfigForm = ({ initialConfig }) => {
19853
20249
  setHeaders((prev) => prev.filter((_, i) => i !== index));
19854
20250
  };
19855
20251
  return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
20252
+ /* @__PURE__ */ jsxRuntime.jsx(
20253
+ InputField,
20254
+ {
20255
+ name: "url",
20256
+ label: "Mastra instance URL",
20257
+ placeholder: "e.g: http://localhost:4111",
20258
+ required: true,
20259
+ defaultValue: initialConfig?.baseUrl
20260
+ }
20261
+ ),
19856
20262
  /* @__PURE__ */ jsxRuntime.jsx(HeaderListForm, { headers, onAddHeader: handleAddHeader, onRemoveHeader: handleRemoveHeader }),
19857
20263
  /* @__PURE__ */ jsxRuntime.jsxs(Button$1, { type: "submit", variant: "light", className: "w-full", size: "lg", children: [
19858
20264
  /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, {}) }),
@@ -19861,6 +20267,13 @@ const StudioConfigForm = ({ initialConfig }) => {
19861
20267
  ] });
19862
20268
  };
19863
20269
 
20270
+ const PlaygroundConfigGuard = () => {
20271
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-screen w-full items-center justify-center bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md w-full mx-auto px-4 pt-4", children: [
20272
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center pb-4", children: /* @__PURE__ */ jsxRuntime.jsx(LogoWithoutText, { className: "size-32" }) }),
20273
+ /* @__PURE__ */ jsxRuntime.jsx(StudioConfigForm, {})
20274
+ ] }) });
20275
+ };
20276
+
19864
20277
  Object.defineProperty(exports, "Toaster", {
19865
20278
  enumerable: true,
19866
20279
  get: () => sonner.Toaster
@@ -19970,6 +20383,7 @@ exports.MemorySearch = MemorySearch;
19970
20383
  exports.Notification = Notification;
19971
20384
  exports.OpenAIIcon = OpenAIIcon;
19972
20385
  exports.PageHeader = PageHeader;
20386
+ exports.PlaygroundConfigGuard = PlaygroundConfigGuard;
19973
20387
  exports.PlaygroundQueryClient = PlaygroundQueryClient;
19974
20388
  exports.PlaygroundTabs = PlaygroundTabs;
19975
20389
  exports.PromptIcon = PromptIcon;
@@ -20036,8 +20450,8 @@ exports.TooltipTrigger = TooltipTrigger;
20036
20450
  exports.TraceDialog = TraceDialog;
20037
20451
  exports.TraceIcon = TraceIcon;
20038
20452
  exports.TraceTimeline = TraceTimeline;
20039
- exports.TraceTimelineLegend = TraceTimelineLegend;
20040
20453
  exports.TraceTimelineSpan = TraceTimelineSpan;
20454
+ exports.TraceTimelineTools = TraceTimelineTools;
20041
20455
  exports.TracesList = TracesList;
20042
20456
  exports.TracesTools = TracesTools;
20043
20457
  exports.TracingSettingsContext = TracingSettingsContext;