@mastra/playground-ui 6.1.0 → 6.1.1-alpha.0

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 (42) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/index.cjs.js +2950 -1185
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.css +1477 -0
  5. package/dist/index.es.js +2923 -1190
  6. package/dist/index.es.js.map +1 -1
  7. package/dist/src/components/ui/elements/buttons/button.d.ts +1 -6
  8. package/dist/src/components/ui/elements/date-time-picker/date-picker.d.ts +4 -0
  9. package/dist/src/components/ui/elements/date-time-picker/date-time-picker.d.ts +31 -0
  10. package/dist/src/components/ui/elements/date-time-picker/index.d.ts +1 -0
  11. package/dist/src/components/ui/elements/date-time-picker/time-picker.d.ts +7 -0
  12. package/dist/src/components/ui/elements/entry-list/entry-list-cell.d.ts +5 -1
  13. package/dist/src/components/ui/elements/entry-list/entry-list-item.d.ts +4 -3
  14. package/dist/src/components/ui/elements/entry-list/entry-list.d.ts +5 -3
  15. package/dist/src/components/ui/elements/headers/index.d.ts +1 -0
  16. package/dist/src/components/ui/elements/headers/page-header.d.ts +8 -0
  17. package/dist/src/components/ui/elements/index.d.ts +5 -0
  18. package/dist/src/components/ui/elements/side-dialog/index.d.ts +2 -0
  19. package/dist/src/components/ui/elements/side-dialog/side-dialog-code-section.d.ts +5 -0
  20. package/dist/src/components/ui/elements/side-dialog/side-dialog-heading.d.ts +6 -0
  21. package/dist/src/components/ui/elements/side-dialog/side-dialog-top.d.ts +2 -1
  22. package/dist/src/components/ui/elements/side-dialog/side-dialog.d.ts +3 -1
  23. package/dist/src/components/ui/elements/text/formatters/get-short-id.d.ts +1 -0
  24. package/dist/src/components/ui/elements/text/index.d.ts +2 -0
  25. package/dist/src/components/ui/elements/text/text-and-icon.d.ts +6 -0
  26. package/dist/src/domains/observability/components/helpers.d.ts +17 -0
  27. package/dist/src/domains/observability/components/index.d.ts +6 -0
  28. package/dist/src/domains/observability/components/shared.d.ts +6 -0
  29. package/dist/src/domains/observability/components/span-details.d.ts +4 -0
  30. package/dist/src/domains/observability/components/span-dialog.d.ts +13 -0
  31. package/dist/src/domains/observability/components/trace-dialog.d.ts +13 -0
  32. package/dist/src/domains/observability/components/trace-span-usage.d.ts +12 -0
  33. package/dist/src/domains/observability/components/trace-timeline-legend.d.ts +6 -0
  34. package/dist/src/domains/observability/components/trace-timeline-span.d.ts +12 -0
  35. package/dist/src/domains/observability/components/trace-timeline.d.ts +12 -0
  36. package/dist/src/domains/observability/components/traces-tools.d.ts +17 -0
  37. package/dist/src/domains/observability/index.d.ts +3 -0
  38. package/dist/src/domains/observability/types.d.ts +9 -0
  39. package/dist/src/domains/observability/utils/format-hierarchical-spans.d.ts +3 -0
  40. package/dist/src/index.d.ts +2 -0
  41. package/package.json +4 -4
  42. package/dist/src/components/ui/elements/buttons/button.stories.d.ts +0 -13
package/dist/index.cjs.js CHANGED
@@ -59,8 +59,9 @@ const AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
59
59
  const uiUtils = require('@ai-sdk/ui-utils');
60
60
  const Markdown = require('react-markdown');
61
61
  const runtimeContext = require('@mastra/core/runtime-context');
62
- const reactVisuallyHidden = require('@radix-ui/react-visually-hidden');
62
+ const VisuallyHidden = require('@radix-ui/react-visually-hidden');
63
63
  const HoverCard = require('@radix-ui/react-hover-card');
64
+ const format = require('date-fns/format');
64
65
  const reactQuery = require('@tanstack/react-query');
65
66
 
66
67
  function _interopNamespaceDefault(e) {
@@ -94,6 +95,7 @@ const SliderPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(SliderP
94
95
  const RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(RadioGroupPrimitive);
95
96
  const TabsPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TabsPrimitive);
96
97
  const AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(AlertDialogPrimitive);
98
+ const VisuallyHidden__namespace = /*#__PURE__*/_interopNamespaceDefault(VisuallyHidden);
97
99
  const HoverCard__namespace = /*#__PURE__*/_interopNamespaceDefault(HoverCard);
98
100
 
99
101
  const createMastraClient = (baseUrl, mastraClientHeaders = {}) => {
@@ -4342,7 +4344,7 @@ function CopyButton({ content, copyMessage, className }) {
4342
4344
  );
4343
4345
  }
4344
4346
 
4345
- const useCodemirrorTheme$1 = () => {
4347
+ const useCodemirrorTheme$2 = () => {
4346
4348
  return React.useMemo(
4347
4349
  () => codemirrorThemeDracula.draculaInit({
4348
4350
  settings: {
@@ -4360,7 +4362,7 @@ const useCodemirrorTheme$1 = () => {
4360
4362
  };
4361
4363
  const SyntaxHighlighter$2 = ({ data, className }) => {
4362
4364
  const formattedCode = JSON.stringify(data, null, 2);
4363
- const theme = useCodemirrorTheme$1();
4365
+ const theme = useCodemirrorTheme$2();
4364
4366
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("rounded-md bg-surface4 p-1 font-mono relative", className), children: [
4365
4367
  /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: formattedCode, className: "absolute top-2 right-2" }),
4366
4368
  /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: formattedCode, theme, extensions: [langJson.jsonLanguage] })
@@ -5611,7 +5613,7 @@ const Button$1 = ({ className, as, size = "md", variant = "default", ...props })
5611
5613
  );
5612
5614
  };
5613
5615
 
5614
- const useCodemirrorTheme = () => {
5616
+ const useCodemirrorTheme$1 = () => {
5615
5617
  return React.useMemo(
5616
5618
  () => codemirrorThemeDracula.draculaInit({
5617
5619
  settings: {
@@ -5629,12 +5631,12 @@ const useCodemirrorTheme = () => {
5629
5631
  };
5630
5632
  const SyntaxHighlighter$1 = ({ data }) => {
5631
5633
  const formattedCode = JSON.stringify(data, null, 2);
5632
- const theme = useCodemirrorTheme();
5634
+ const theme = useCodemirrorTheme$1();
5633
5635
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-md bg-[#1a1a1a] p-1 font-mono", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: formattedCode, theme, extensions: [langJson.jsonLanguage] }) });
5634
5636
  };
5635
5637
 
5636
5638
  const CodeDialogContent = ({ data }) => {
5637
- const theme = useCodemirrorTheme();
5639
+ const theme = useCodemirrorTheme$1();
5638
5640
  if (typeof data !== "string") {
5639
5641
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
5640
5642
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: JSON.stringify(data, null, 2) }) }),
@@ -5692,7 +5694,7 @@ const WorkflowRunEventForm = ({ event, runId, onSendEvent }) => {
5692
5694
  const [eventData, setEventData] = React.useState("");
5693
5695
  const [isLoading, setIsLoading] = React.useState(false);
5694
5696
  const [error, setError] = React.useState(null);
5695
- const theme = useCodemirrorTheme();
5697
+ const theme = useCodemirrorTheme$1();
5696
5698
  const { handleCopy } = useCopyToClipboard({ text: eventData });
5697
5699
  const handleSendEvent = async () => {
5698
5700
  let data;
@@ -6556,7 +6558,7 @@ const PopoverContent = React__namespace.forwardRef(({ className, align = "center
6556
6558
  ) }));
6557
6559
  PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
6558
6560
 
6559
- const DatePicker = ({
6561
+ const DatePicker$1 = ({
6560
6562
  value,
6561
6563
  setValue,
6562
6564
  children,
@@ -6722,7 +6724,7 @@ const DateField = ({ inputProps, field, error, id }) => {
6722
6724
  }
6723
6725
  }, [field]);
6724
6726
  return /* @__PURE__ */ jsxRuntime.jsx(
6725
- DatePicker,
6727
+ DatePicker$1,
6726
6728
  {
6727
6729
  id,
6728
6730
  className: error ? "border-destructive" : "",
@@ -6741,7 +6743,7 @@ const DateField = ({ inputProps, field, error, id }) => {
6741
6743
  );
6742
6744
  };
6743
6745
 
6744
- const Select = SelectPrimitive__namespace.Root;
6746
+ const Select$1 = SelectPrimitive__namespace.Root;
6745
6747
  const SelectValue = SelectPrimitive__namespace.Value;
6746
6748
  const SelectTrigger = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
6747
6749
  SelectPrimitive__namespace.Trigger,
@@ -6803,7 +6805,7 @@ SelectItem.displayName = SelectPrimitive__namespace.Item.displayName;
6803
6805
  const SelectField$1 = ({ field, inputProps, error, id, value }) => {
6804
6806
  const { key, ...props } = inputProps;
6805
6807
  return /* @__PURE__ */ jsxRuntime.jsxs(
6806
- Select,
6808
+ Select$1,
6807
6809
  {
6808
6810
  ...props,
6809
6811
  onValueChange: (value2) => {
@@ -7841,7 +7843,7 @@ const JSONInput = ({ schema, defaultValues, isSubmitLoading, submitButtonLabel,
7841
7843
  ] });
7842
7844
  };
7843
7845
  const SyntaxHighlighter = ({ data, onChange }) => {
7844
- const theme = useCodemirrorTheme$1();
7846
+ const theme = useCodemirrorTheme$2();
7845
7847
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md bg-[#1a1a1a] p-1 font-mono", children: [
7846
7848
  /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: data, className: "absolute top-2 right-2 z-10" }),
7847
7849
  /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: data, theme, extensions: [langJson.jsonLanguage], onChange })
@@ -10724,7 +10726,7 @@ const AgentAdvancedSettings = () => {
10724
10726
  const [providerOptionsValue, setProviderOptionsValue] = React.useState("");
10725
10727
  const [saved, setSaved] = React.useState(false);
10726
10728
  const [error, setError] = React.useState(null);
10727
- const theme = useCodemirrorTheme();
10729
+ const theme = useCodemirrorTheme$1();
10728
10730
  const { handleCopy } = useCopyToClipboard({ text: providerOptionsValue });
10729
10731
  const providerOptionsStr = JSON.stringify(settings?.modelSettings?.providerOptions ?? {});
10730
10732
  React.useEffect(() => {
@@ -11564,7 +11566,7 @@ const EmptyAgentsTable = () => /* @__PURE__ */ jsxRuntime.jsx("div", { className
11564
11566
  const RuntimeContext = () => {
11565
11567
  const { runtimeContext, setRuntimeContext } = usePlaygroundStore();
11566
11568
  const [runtimeContextValue, setRuntimeContextValue] = React.useState("");
11567
- const theme = useCodemirrorTheme();
11569
+ const theme = useCodemirrorTheme$1();
11568
11570
  const { handleCopy } = useCopyToClipboard({ text: runtimeContextValue });
11569
11571
  const runtimeContextStr = JSON.stringify(runtimeContext);
11570
11572
  React.useEffect(() => {
@@ -12033,7 +12035,7 @@ const AgentMetadataModelSwitcher = ({
12033
12035
  const filteredModels = allModels.filter((model2) => model2.model.includes(selectedModel));
12034
12036
  return /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
12035
12037
  /* @__PURE__ */ jsxRuntime.jsxs(
12036
- Select,
12038
+ Select$1,
12037
12039
  {
12038
12040
  value: model?.provider ?? selectedProvider,
12039
12041
  onValueChange: setSelectedProvider,
@@ -14068,7 +14070,7 @@ function InputField({
14068
14070
  ...props
14069
14071
  }) {
14070
14072
  const LabelWrapper = ({ children }) => {
14071
- return labelIsHidden ? /* @__PURE__ */ jsxRuntime.jsx(reactVisuallyHidden.VisuallyHidden, { children }) : children;
14073
+ return labelIsHidden ? /* @__PURE__ */ jsxRuntime.jsx(VisuallyHidden.VisuallyHidden, { children }) : children;
14072
14074
  };
14073
14075
  return /* @__PURE__ */ jsxRuntime.jsxs(
14074
14076
  "div",
@@ -14101,10 +14103,11 @@ function InputField({
14101
14103
  value,
14102
14104
  className: cn(
14103
14105
  "flex grow items-center cursor-pointer text-[0.875rem] text-[rgba(255,255,255,0.8)] border border-[rgba(255,255,255,0.15)] leading-none rounded-lg bg-transparent min-h-[2.5rem] px-[0.75rem] py-[0.5rem] w-full",
14106
+ "focus:outline-none focus:shadow-[inset_0_0_0_1px_#18fb6f]",
14104
14107
  "placeholder:text-icon3 placeholder:text-[.8125rem]",
14105
14108
  {
14106
14109
  "cursor-not-allowed opacity-50": disabled,
14107
- "border-red-800": error || errorMsg
14110
+ "border-red-800 focus:border-[rgba(255,255,255,0.15)]": error || errorMsg
14108
14111
  }
14109
14112
  ),
14110
14113
  "data-testid": testId,
@@ -14158,6 +14161,7 @@ function TextareaField({
14158
14161
  {
14159
14162
  className: cn(
14160
14163
  "flex w-full items-center leading-[1.6] text-[0.875rem] text-[rgba(255,255,255,0.7)] border border-[rgba(255,255,255,0.15)] rounded-lg bg-transparent py-[0.5rem] px-[0.75rem] min-h-[6rem]",
14164
+ "focus:outline-none focus:shadow-[inset_0_0_0_1px_#18fb6f]",
14161
14165
  { "cursor-not-allowed opacity-50": disabled }
14162
14166
  ),
14163
14167
  "data-testid": testId,
@@ -14171,28 +14175,32 @@ function TextareaField({
14171
14175
  );
14172
14176
  }
14173
14177
 
14174
- const Button = ({ className, as, variant = "outline", ...props }) => {
14175
- const Component = as || "button";
14176
- return /* @__PURE__ */ jsxRuntime.jsx(
14177
- Component,
14178
- {
14179
- className: cn(
14180
- "text-[.875rem] inline-flex items-center justify-center rounded-lg px-[1rem] gap-[.75rem] leading-0 border bg-transparent text-[rgba(255,255,255,0.7)]",
14181
- "[&:not(:disabled):hover]:border-[rgba(255,255,255,0.25)] [&:not(:disabled):hover]:text-[rgba(255,255,255,0.9)]",
14182
- "[&>svg]:w-[1em] [&>svg]:h-[1em] [&>svg]:mx-[-0.3em] [&>svg]:opacity-70",
14183
- className,
14184
- {
14185
- "cursor-not-allowed opacity-50": props.disabled,
14186
- "bg-ui-primaryBtnBg text-ui-primaryBtnText hover:bg-surface6 leading-[0] font-semibold": variant === "primary",
14187
- "min-h-[2rem]": variant === "ghost",
14188
- "min-h-[2.5rem]": variant !== "ghost",
14189
- "border-[rgba(255,255,255,0.15)]": variant === "outline"
14190
- }
14191
- ),
14192
- ...props
14193
- }
14194
- );
14195
- };
14178
+ const Button = React.forwardRef(
14179
+ ({ className, variant = "outline", ...props }, ref) => {
14180
+ return /* @__PURE__ */ jsxRuntime.jsx(
14181
+ "button",
14182
+ {
14183
+ ref,
14184
+ className: cn(
14185
+ "text-[.875rem] inline-flex items-center justify-center rounded-lg px-[1rem] gap-[.75rem] leading-0 border bg-transparent text-[rgba(255,255,255,0.7)] whitespace-nowrap",
14186
+ "[&:not(:disabled):hover]:border-[rgba(255,255,255,0.25)] [&:not(:disabled):hover]:text-[rgba(255,255,255,0.9)]",
14187
+ "[&>svg]:w-[1em] [&>svg]:h-[1em] [&>svg]:mx-[-0.3em] [&>svg]:opacity-70 [&>svg]:shrink-0",
14188
+ "focus:outline-none focus:shadow-[inset_0_0_0_1px_rgba(24,251,111,0.75)]",
14189
+ className,
14190
+ {
14191
+ "cursor-not-allowed opacity-50": props.disabled,
14192
+ "bg-ui-primaryBtnBg text-ui-primaryBtnText hover:bg-surface6 leading-[0] font-semibold": variant === "primary",
14193
+ "min-h-[2rem]": variant === "ghost",
14194
+ "min-h-[2.5rem]": variant !== "ghost",
14195
+ "border-[rgba(255,255,255,0.15)]": variant === "outline"
14196
+ }
14197
+ ),
14198
+ ...props
14199
+ }
14200
+ );
14201
+ }
14202
+ );
14203
+ Button.displayName = "Button";
14196
14204
 
14197
14205
  function FormActions({
14198
14206
  children,
@@ -14240,7 +14248,7 @@ function SelectField({
14240
14248
  "div",
14241
14249
  {
14242
14250
  className: cn(
14243
- "flex gap-[.5rem]",
14251
+ "flex gap-[.5rem] items-center",
14244
14252
  {
14245
14253
  "grid-rows-[auto_1fr]": label,
14246
14254
  "grid-rows-[auto_1fr_auto]": helpMsg
@@ -14252,18 +14260,19 @@ function SelectField({
14252
14260
  label,
14253
14261
  required && /* @__PURE__ */ jsxRuntime.jsx("i", { className: "text-icon2", children: "(required)" })
14254
14262
  ] }),
14255
- /* @__PURE__ */ jsxRuntime.jsxs(Select, { name, value, onValueChange, disabled, children: [
14263
+ /* @__PURE__ */ jsxRuntime.jsxs(Select$1, { name, value, onValueChange, disabled, children: [
14256
14264
  /* @__PURE__ */ jsxRuntime.jsx(
14257
14265
  SelectTrigger,
14258
14266
  {
14259
14267
  id: "select-dataset",
14260
14268
  className: cn(
14261
- "w-full border border-[rgba(255,255,255,0.15)] rounded-lg min-h-[2.5rem] min-w-[5rem] gap-[0.5rem]"
14269
+ "w-full border border-[rgba(255,255,255,0.15)] rounded-lg min-h-[2.5rem] min-w-[5rem] gap-[0.5rem]",
14270
+ "focus:outline-none focus:shadow-[inset_0_0_0_1px_rgba(24,251,111,0.75)]"
14262
14271
  ),
14263
14272
  children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder })
14264
14273
  }
14265
14274
  ),
14266
- /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.value, children: option.label }, option.label)) })
14275
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: option.value, children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "whitespace-nowrap truncate block", children: option.label }) }, option.label)) })
14267
14276
  ] }),
14268
14277
  helpMsg && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon3 text-[0.75rem]", children: helpMsg })
14269
14278
  ]
@@ -14310,7 +14319,7 @@ function SliderField({
14310
14319
  ...props,
14311
14320
  children: [
14312
14321
  /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Track, { className: "relative h-[4px] w-full grow overflow-hidden rounded-full bg-gray-600", children: /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Range, { className: "absolute h-full bg-gray-400" }) }),
14313
- /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Thumb, { className: "block h-4 w-4 rounded-full bg-gray-400 shadow transition-colors disabled:pointer-events-none disabled:opacity-50" })
14322
+ /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Thumb, { className: "block h-4 w-4 rounded-full bg-gray-400 shadow transition-colors focus:outline-none focus:bg-[#18fb6f] disabled:pointer-events-none disabled:opacity-50" })
14314
14323
  ]
14315
14324
  }
14316
14325
  ),
@@ -14390,7 +14399,7 @@ function RadioGroupField({
14390
14399
  /* @__PURE__ */ jsxRuntime.jsx(
14391
14400
  RadioGroupPrimitive__namespace.Item,
14392
14401
  {
14393
- className: "aspect-square h-4 w-4 rounded-full border border-primary text-primary disabled:cursor-not-allowed disabled:opacity-50 ",
14402
+ className: "aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 ",
14394
14403
  value: option.value,
14395
14404
  children: /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Circle, { className: "h-2.5 w-2.5 fill-current text-current" }) })
14396
14405
  }
@@ -14426,7 +14435,7 @@ function RadioGroupField({
14426
14435
  function KeyValueList({ data, LinkComponent, className, labelsAreHidden, isLoading }) {
14427
14436
  const { Link } = useLinkComponent();
14428
14437
  const LabelWrapper = ({ children }) => {
14429
- return labelsAreHidden ? /* @__PURE__ */ jsxRuntime.jsx(reactVisuallyHidden.VisuallyHidden, { children }) : children;
14438
+ return labelsAreHidden ? /* @__PURE__ */ jsxRuntime.jsx(VisuallyHidden.VisuallyHidden, { children }) : children;
14430
14439
  };
14431
14440
  if (!data || data.length === 0) {
14432
14441
  return null;
@@ -14467,7 +14476,8 @@ function KeyValueList({ data, LinkComponent, className, labelsAreHidden, isLoadi
14467
14476
  className: cn(
14468
14477
  "flex flex-wrap gap-[.5rem] py-[0.25rem] min-h-[2.25rem] text-[0.875rem] items-center text-icon5 text-wrap",
14469
14478
  "[&>a]:text-icon5 [&>a]:max-w-full [&>a]:w-auto truncate [&>a]:bg-[#222] [&>a]:transition-colors [&>a]:flex [&>a]:items-center [&>a]:gap-[0.5rem] [&>a]:pt-[0.15rem] [&>a]:pb-[0.2rem] [&>a]:px-[.5rem] [&>a]:rounded-md [&>a]:text-[0.875rem] [&>a]:min-h-[1.75rem] [&>a]:leading-0 ",
14470
- "[&>a:hover]:text-icon6 [&>a:hover]:bg-surface6"
14479
+ "[&>a:hover]:text-icon6 [&>a:hover]:bg-surface6",
14480
+ "[&>a>svg]:w-[1em] [&>a>svg]:h-[1em] [&>a>svg]:text-icon3 [&>a>svg]:ml-[-0.5em]"
14471
14481
  ),
14472
14482
  children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
14473
14483
  "span",
@@ -14477,7 +14487,11 @@ function KeyValueList({ data, LinkComponent, className, labelsAreHidden, isLoadi
14477
14487
  children: " "
14478
14488
  }
14479
14489
  ) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: isValueItemArray ? value?.map((item) => {
14480
- return item.path ? /* @__PURE__ */ jsxRuntime.jsx(RelationWrapper, { description: item.description, children: /* @__PURE__ */ jsxRuntime.jsx(Link, { href: item.path, children: item?.name }) }, item.id) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: item?.name }, item.id);
14490
+ return item.path ? /* @__PURE__ */ jsxRuntime.jsx(RelationWrapper, { description: item.description, children: /* @__PURE__ */ jsxRuntime.jsxs(Link, { href: item.path, children: [
14491
+ item?.name,
14492
+ " ",
14493
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, {})
14494
+ ] }) }, item.id) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: item?.name }, item.id);
14481
14495
  }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: value ? value : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-icon3 text-[0.75rem]", children: "n/a" }) }) })
14482
14496
  }
14483
14497
  )
@@ -14502,784 +14516,1659 @@ function RelationWrapper({ description, children }) {
14502
14516
  ] }) : children;
14503
14517
  }
14504
14518
 
14505
- function TemplatesTools({
14506
- tagOptions,
14507
- selectedTag,
14508
- providerOptions,
14509
- selectedProvider,
14510
- onTagChange,
14511
- onProviderChange,
14512
- searchTerm,
14513
- onSearchChange,
14514
- onReset,
14515
- className,
14516
- isLoading
14517
- }) {
14518
- if (isLoading) {
14519
- return /* @__PURE__ */ jsxRuntime.jsxs(
14519
+ function EntryListTextCell({ children, isLoading }) {
14520
+ const randomWidth = React.useMemo(() => {
14521
+ return Math.floor(Math.random() * (90 - 50 + 1)) + 50;
14522
+ }, []);
14523
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon4 text-[0.875rem] truncate ", children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(
14524
+ "div",
14525
+ {
14526
+ className: "bg-surface4 rounded-md animate-pulse text-transparent h-[1rem] select-none",
14527
+ style: { width: `${randomWidth}%` }
14528
+ }
14529
+ ) : children });
14530
+ }
14531
+ function EntryListStatusCell({ status }) {
14532
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex justify-center items-center w-full relative"), children: [
14533
+ status ? /* @__PURE__ */ jsxRuntime.jsx(
14520
14534
  "div",
14521
14535
  {
14522
- className: cn(
14523
- "h-[6.5rem] flex items-center gap-[2rem]",
14524
- "[&>div]:bg-surface3 [&>div]:w-[12rem] [&>div]:h-[2rem] [&>div]:animate-pulse",
14525
- className
14526
- ),
14527
- children: [
14528
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
14529
- " ",
14530
- /* @__PURE__ */ jsxRuntime.jsx("div", {}),
14531
- " ",
14532
- /* @__PURE__ */ jsxRuntime.jsx("div", {})
14533
- ]
14536
+ className: cn("w-[0.6rem] h-[0.6rem] rounded-full", {
14537
+ "bg-green-600": status === "success",
14538
+ "bg-red-700": status === "failed"
14539
+ })
14534
14540
  }
14535
- );
14541
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon2 text-[0.75rem] leading-none", children: "-" }),
14542
+ /* @__PURE__ */ jsxRuntime.jsxs(VisuallyHidden.VisuallyHidden, { children: [
14543
+ "Status: ",
14544
+ status ? status : "not provided"
14545
+ ] })
14546
+ ] });
14547
+ }
14548
+
14549
+ function getColumnTemplate(columns) {
14550
+ if (!columns || columns.length === 0) {
14551
+ return "";
14536
14552
  }
14537
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-wrap mx-auto sticky top-0 gap-[2rem] bg-surface2 py-[2rem]", className), children: [
14538
- /* @__PURE__ */ jsxRuntime.jsx(
14539
- SearchField,
14540
- {
14541
- label: "Search templates",
14542
- value: searchTerm,
14543
- onChange: (e) => onSearchChange?.(e.target.value),
14544
- placeholder: "Search Template"
14545
- }
14546
- ),
14547
- /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Filter by tag", value: selectedTag, onValueChange: onTagChange, options: tagOptions }),
14548
- /* @__PURE__ */ jsxRuntime.jsx(
14549
- SelectField,
14553
+ return columns?.map((column) => {
14554
+ return column.size;
14555
+ }).join(" ");
14556
+ }
14557
+
14558
+ function EntryListItem({
14559
+ item,
14560
+ selectedItemId,
14561
+ onClick,
14562
+ children,
14563
+ columns,
14564
+ isLoading
14565
+ }) {
14566
+ const isSelected = selectedItemId === item.id;
14567
+ const handleClick = () => {
14568
+ return onClick && onClick(item?.id);
14569
+ };
14570
+ return /* @__PURE__ */ jsxRuntime.jsx(
14571
+ "li",
14572
+ {
14573
+ className: cn("border-b text-[#ccc] border-border1 last:border-b-0 text-[0.875rem]", {
14574
+ "bg-surface5": isSelected
14575
+ }),
14576
+ children: /* @__PURE__ */ jsxRuntime.jsx(
14577
+ "button",
14578
+ {
14579
+ onClick: handleClick,
14580
+ className: cn("grid w-full px-[1.5rem] gap-[2rem] text-left items-center min-h-[3rem]", {
14581
+ "hover:bg-surface5": !isLoading
14582
+ }),
14583
+ style: { gridTemplateColumns: getColumnTemplate(columns) },
14584
+ disabled: isLoading,
14585
+ children
14586
+ }
14587
+ )
14588
+ }
14589
+ );
14590
+ }
14591
+
14592
+ function EntryList({
14593
+ items: dataItems,
14594
+ selectedItemId,
14595
+ onItemClick,
14596
+ isLoading,
14597
+ isLoadingNextPage,
14598
+ total,
14599
+ page,
14600
+ hasMore,
14601
+ onNextPage,
14602
+ onPrevPage,
14603
+ perPage,
14604
+ columns,
14605
+ searchTerm,
14606
+ setEndOfListElement
14607
+ }) {
14608
+ const loadingItems = Array.from({ length: 3 }).map((_, index) => {
14609
+ return {
14610
+ id: `loading-${index + 1}`,
14611
+ ...(columns || []).reduce(
14612
+ (acc, col) => {
14613
+ acc[col.name] = `...`;
14614
+ return acc;
14615
+ },
14616
+ {}
14617
+ )
14618
+ };
14619
+ });
14620
+ const items = isLoading ? loadingItems : dataItems;
14621
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid mb-[3rem]", children: [
14622
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("sticky top-0 bg-surface4 z-[1] rounded-t-lg border border-border1 px-[1.5rem]"), children: /* @__PURE__ */ jsxRuntime.jsx(
14623
+ "div",
14550
14624
  {
14551
- label: "Filter by provider",
14552
- value: selectedProvider,
14553
- onValueChange: onProviderChange,
14554
- options: providerOptions
14625
+ className: cn("grid gap-[2rem] text-left uppercase py-[.75rem] text-icon3 text-[0.75rem]"),
14626
+ style: { gridTemplateColumns: getColumnTemplate(columns) },
14627
+ children: columns?.map((col) => /* @__PURE__ */ jsxRuntime.jsx("span", { children: col.label || col.name }, col.name))
14555
14628
  }
14556
- ),
14557
- onReset && /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: onReset, children: [
14558
- "Reset ",
14559
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
14629
+ ) }),
14630
+ !isLoading && items?.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid border border-border1 border-t-0 bg-surface3 rounded-xl rounded-t-none", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon3 text-[0.875rem] text-center h-[3.5rem] items-center flex justify-center", children: searchTerm ? `No results found for "${searchTerm}"` : "No entries found" }) }),
14631
+ items?.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14632
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "grid border border-border1 border-t-0 bg-surface3 rounded-xl rounded-t-none overflow-y-auto", children: items.map((item) => {
14633
+ return /* @__PURE__ */ jsxRuntime.jsx(
14634
+ EntryListItem,
14635
+ {
14636
+ item,
14637
+ selectedItemId,
14638
+ onClick: isLoading ? void 0 : onItemClick,
14639
+ columns,
14640
+ isLoading,
14641
+ children: (columns || []).map((col) => {
14642
+ const isValidReactElement = React.isValidElement(item?.[col.name]);
14643
+ return isValidReactElement ? item?.[col.name] : /* @__PURE__ */ jsxRuntime.jsx(EntryListTextCell, { isLoading, children: item?.[col.name] }, col.name);
14644
+ })
14645
+ },
14646
+ item.id
14647
+ );
14648
+ }) }),
14649
+ setEndOfListElement && /* @__PURE__ */ jsxRuntime.jsxs(
14650
+ "div",
14651
+ {
14652
+ ref: setEndOfListElement,
14653
+ className: "text-[0.875rem] text-icon3 opacity-50 flex mt-[2rem] justify-center",
14654
+ children: [
14655
+ isLoadingNextPage && "Loading...",
14656
+ !hasMore && !isLoadingNextPage && !isLoading && "No more data to load"
14657
+ ]
14658
+ }
14659
+ ),
14660
+ typeof page === "number" && typeof perPage === "number" && typeof total === "number" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center justify-center text-icon3 text-[0.875rem] gap-[2rem]"), children: [
14661
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
14662
+ "Page ",
14663
+ page ? page + 1 : "1"
14664
+ ] }),
14665
+ /* @__PURE__ */ jsxRuntime.jsxs(
14666
+ "div",
14667
+ {
14668
+ className: cn(
14669
+ "flex gap-[1rem]",
14670
+ "[&>button]:flex [&>button]:items-center [&>button]:gap-[0.5rem] [&>button]:text-icon4 [&>button:hover]:text-icon5 [&>button]:transition-colors [&>button]:border [&>button]:border-border1 [&>button]:p-[0.25rem] [&>button]:px-[0.5rem] [&>button]:rounded-md",
14671
+ " [&_svg]:w-[1em] [&_svg]:h-[1em] [&_svg]:text-icon3"
14672
+ ),
14673
+ children: [
14674
+ typeof page === "number" && page > 0 && /* @__PURE__ */ jsxRuntime.jsxs("button", { onClick: onPrevPage, disabled: page === 0, children: [
14675
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeftIcon, {}),
14676
+ "Previous"
14677
+ ] }),
14678
+ hasMore && /* @__PURE__ */ jsxRuntime.jsxs("button", { onClick: onNextPage, disabled: !hasMore, children: [
14679
+ "Next",
14680
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightIcon, {})
14681
+ ] })
14682
+ ]
14683
+ }
14684
+ )
14685
+ ] })
14560
14686
  ] })
14561
14687
  ] });
14562
14688
  }
14563
14689
 
14564
- function getRepoName(githubUrl) {
14565
- return githubUrl.replace(/\/$/, "").split("/").pop();
14566
- }
14567
- function Container({ children, className }) {
14690
+ function EntryListToolbar({ children, className }) {
14568
14691
  return /* @__PURE__ */ jsxRuntime.jsx(
14692
+ "div",
14693
+ {
14694
+ className: cn("flex justify-between bg-surface4 z-[1] mt-[1rem] mb-[1rem] rounded-lg px-[1.5rem] ", className),
14695
+ children
14696
+ }
14697
+ );
14698
+ }
14699
+
14700
+ function EntryListPageHeader({ title, description, icon, children }) {
14701
+ return /* @__PURE__ */ jsxRuntime.jsxs(
14569
14702
  "div",
14570
14703
  {
14571
14704
  className: cn(
14572
- "border border-border1 rounded-lg mt-[3rem] py-[2rem] lg:min-h-[25rem] transition-height px-[1rem] lg:px-[3rem]",
14573
- className
14705
+ "grid z-[1] top-0 gap-y-[0.5rem] text-icon4 bg-surface2 py-[3rem]",
14706
+ "3xl:h-full 3xl:content-start 3xl:grid-rows-[auto_1fr] h-full 3xl:overflow-y-auto"
14574
14707
  ),
14575
- children
14708
+ children: [
14709
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-[1rem] w", children: [
14710
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-[.75em] items-center", "[&>svg]:w-[1.1em] [&>svg]:h-[1.1em] [&>svg]:text-icon4"), children: [
14711
+ icon,
14712
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-icon6 text-[1.25rem]", children: title })
14713
+ ] }),
14714
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "m-0 text-[0.875rem]", children: description })
14715
+ ] }),
14716
+ children
14717
+ ]
14576
14718
  }
14577
14719
  );
14578
14720
  }
14579
14721
 
14580
- function TemplatesList({ templates, linkComponent, className, isLoading }) {
14581
- const LinkComponent = linkComponent || "a";
14582
- if (isLoading) {
14583
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-y-[1rem]", className), children: Array.from({ length: 5 }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[4rem] bg-surface3 animate-pulse rounded-lg" }, index)) });
14584
- }
14585
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-y-[1rem]", className), children: templates.map((template) => {
14586
- const hasMetaInfo = template?.agents || template?.tools || template?.networks || template?.workflows || template?.mcp;
14587
- return /* @__PURE__ */ jsxRuntime.jsxs(
14588
- "article",
14722
+ function SideDialog({
14723
+ dialogTitle,
14724
+ dialogDescription,
14725
+ isOpen,
14726
+ onClose,
14727
+ children,
14728
+ variant = "default",
14729
+ hasCloseButton = true,
14730
+ className
14731
+ }) {
14732
+ const isConfirmation = variant === "confirmation";
14733
+ return /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Root, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.Portal, { children: [
14734
+ !isConfirmation && /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Overlay, { className: cn("bg-black top-0 bottom-0 right-0 left-0 fixed z-50 opacity-[0.25]") }),
14735
+ /* @__PURE__ */ jsxRuntime.jsxs(
14736
+ DialogPrimitive__namespace.Content,
14589
14737
  {
14590
14738
  className: cn(
14591
- "border border-border1 rounded-lg overflow-hidden w-full grid grid-cols-[1fr_auto] bg-surface3 transition-colors hover:bg-surface4"
14739
+ "fixed top-0 bottom-0 right-0 border-l border-border1 z-50 bg-surface4",
14740
+ "w-[calc(100vw-20rem)] max-w-[50rem]",
14741
+ "3xl:max-w-[60rem]",
14742
+ "4xl:max-w-[50%]",
14743
+ "data-[state=closed]:animate-out data-[state=closed]:fade-out-0",
14744
+ {
14745
+ "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-right-1/4": !isConfirmation,
14746
+ "bg-surface2/70": isConfirmation
14747
+ },
14748
+ className
14592
14749
  ),
14593
14750
  children: [
14594
- /* @__PURE__ */ jsxRuntime.jsxs(
14595
- LinkComponent,
14751
+ /* @__PURE__ */ jsxRuntime.jsxs(VisuallyHidden__namespace.Root, { children: [
14752
+ /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Title, { children: dialogTitle }),
14753
+ /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Description, { children: dialogDescription })
14754
+ ] }),
14755
+ !isConfirmation && hasCloseButton && /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
14756
+ "button",
14596
14757
  {
14597
- to: `/templates/${template.slug}`,
14598
- className: cn("grid [&:hover_p]:text-icon5", {
14599
- "grid-cols-[8rem_1fr] lg:grid-cols-[12rem_1fr]": template.imageURL
14758
+ className: cn(
14759
+ "flex appearance-none items-center justify-center rounded-bl-lg h-[3.5rem] w-[3.5rem] absolute too-0 left-[-3.5rem] bg-surface4 text-icon4 border-l border-b border-border1",
14760
+ "hover:surface5 hover:text-icon5"
14761
+ ),
14762
+ "aria-label": "Close",
14763
+ children: isConfirmation ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRightIcon, {})
14764
+ }
14765
+ ) }),
14766
+ /* @__PURE__ */ jsxRuntime.jsx(
14767
+ "div",
14768
+ {
14769
+ className: cn("grid h-full", {
14770
+ "grid-rows-[auto_1fr]": !isConfirmation
14600
14771
  }),
14601
- children: [
14602
- template.imageURL && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative overflow-hidden"), children: /* @__PURE__ */ jsxRuntime.jsx(
14603
- "div",
14604
- {
14605
- className: "w-full h-full bg-cover thumb transition-scale duration-150",
14606
- style: {
14607
- backgroundImage: `url(${template.imageURL})`
14608
- }
14609
- }
14610
- ) }),
14611
- /* @__PURE__ */ jsxRuntime.jsxs(
14612
- "div",
14613
- {
14614
- className: cn(
14615
- "grid py-[.75rem] px-[1.5rem] w-full gap-[0.1rem]",
14616
- "[&_svg]:w-[1em] [&_svg]:h-[1em] [&_svg]:text-icon3"
14617
- ),
14618
- children: [
14619
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[1rem] text-icon5", children: template.title }),
14620
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-icon4 transition-colors duration-500", children: template.description }),
14621
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden 2xl:flex text-icon3 text-[0.875rem] flex-wrap items-center gap-[1rem] mt-[0.75rem]", children: [
14622
- hasMetaInfo && /* @__PURE__ */ jsxRuntime.jsxs(
14623
- "ul",
14624
- {
14625
- className: cn(
14626
- "flex gap-[1rem] text-[0.875rem] text-icon3 m-0 p-0 list-none",
14627
- "[&>li]:flex [&>li]:items-center [&>li]:gap-[0.1rem] text-icon4"
14628
- ),
14629
- children: [
14630
- template?.agents && template.agents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
14631
- /* @__PURE__ */ jsxRuntime.jsx(AgentIcon, {}),
14632
- " ",
14633
- template.agents.length
14634
- ] }),
14635
- template?.tools && template.tools.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
14636
- /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, {}),
14637
- " ",
14638
- template.tools.length
14639
- ] }),
14640
- template?.networks && template.networks.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
14641
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.NetworkIcon, {}),
14642
- " ",
14643
- template.networks.length
14644
- ] }),
14645
- template?.workflows && template.workflows.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
14646
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WorkflowIcon, {}),
14647
- " ",
14648
- template.workflows.length
14649
- ] }),
14650
- template?.mcp && template.mcp.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
14651
- /* @__PURE__ */ jsxRuntime.jsx(McpServerIcon, {}),
14652
- " ",
14653
- template.mcp.length
14654
- ] })
14655
- ]
14656
- }
14657
- ),
14658
- hasMetaInfo && template.supportedProviders && /* @__PURE__ */ jsxRuntime.jsx("small", { children: "|" }),
14659
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center text-icon3 gap-[1rem]", children: template.supportedProviders.map((provider) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "", children: provider }, provider)) })
14660
- ] })
14661
- ]
14662
- }
14663
- )
14664
- ]
14665
- }
14666
- ),
14667
- /* @__PURE__ */ jsxRuntime.jsx(
14668
- "a",
14669
- {
14670
- href: template.githubUrl,
14671
- className: cn("group items-center gap-[0.5rem] text-[0.875rem] ml-auto pr-[1rem] hidden", "lg:flex"),
14672
- target: "_blank",
14673
- rel: "noopener noreferrer",
14674
- children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-[0.5rem] px-[0.5rem] py-[0.25rem] rounded bg-surface1 group-hover:bg-surface2 text-icon3 transition-colors group-hover:text-icon5 ", children: [
14675
- /* @__PURE__ */ jsxRuntime.jsx(GithubIcon, {}),
14676
- " ",
14677
- getRepoName(template.githubUrl)
14678
- ] })
14772
+ children
14679
14773
  }
14680
14774
  )
14681
14775
  ]
14682
- },
14683
- template.slug
14684
- );
14685
- }) });
14776
+ }
14777
+ )
14778
+ ] }) });
14686
14779
  }
14687
14780
 
14688
- function TemplateInfo({
14689
- title,
14690
- description,
14691
- imageURL,
14692
- githubUrl,
14693
- isLoading,
14694
- infoData,
14695
- templateSlug
14696
- }) {
14697
- const branchName = templateSlug ? `feat/install-template-${templateSlug}` : "feat/install-template-[slug]";
14698
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14699
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid lg:grid-cols-[1fr_1fr] gap-x-[6rem] mt-[2rem] lg:min-h-[4rem] items-center "), children: [
14700
- /* @__PURE__ */ jsxRuntime.jsxs(
14701
- "div",
14781
+ function SideDialogHeader({ children, className }) {
14782
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex justify-between items-center pb-[1rem]", className), children });
14783
+ }
14784
+
14785
+ function SideDialogFooter({ children, onNext, onPrevious, showInnerNav }) {
14786
+ const handleOnNext = () => {
14787
+ onNext?.();
14788
+ };
14789
+ const handleOnPrevious = () => {
14790
+ onPrevious?.();
14791
+ };
14792
+ return /* @__PURE__ */ jsxRuntime.jsxs(
14793
+ "div",
14794
+ {
14795
+ className: cn(
14796
+ "flex items-center justify-end gap-[1rem] px-[1.5rem] py-[1rem] min-h-[4rem] border-t border-border1",
14702
14797
  {
14703
- className: cn(
14704
- "text-[1.5rem] flex items-center gap-[0.75rem] ",
14705
- "[&>svg]:w-[1.2em] [&>svg]:h-[1.2em] [&>svg]:opacity-50",
14706
- {
14707
- "[&>svg]:opacity-20": isLoading
14708
- }
14709
- ),
14710
- children: [
14711
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageIcon, {}),
14712
- /* @__PURE__ */ jsxRuntime.jsx(
14713
- "h2",
14714
- {
14715
- className: cn({
14716
- "bg-surface4 flex rounded-lg min-w-[50%]": isLoading
14717
- }),
14718
- children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: " " }) : title
14719
- }
14720
- )
14721
- ]
14798
+ "justify-between": showInnerNav
14722
14799
  }
14723
14800
  ),
14724
- /* @__PURE__ */ jsxRuntime.jsx(
14725
- "div",
14726
- {
14727
- className: "w-full h-full bg-cover bg-center transition-scale duration-150 rounded-lg overflow-hidden min-h-[2rem] mt-[2rem] lg:mt-0",
14728
- style: {
14729
- backgroundImage: `url(${imageURL})`
14730
- }
14731
- }
14732
- )
14801
+ children: [
14802
+ (onNext || onPrevious) && showInnerNav && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-[1rem]"), children: [
14803
+ /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Close, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: handleOnNext, disabled: !onNext, variant: "ghost", children: [
14804
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {}),
14805
+ "Close"
14806
+ ] }) }),
14807
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: handleOnNext, disabled: !onNext, variant: "ghost", children: [
14808
+ "Next",
14809
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, {})
14810
+ ] }),
14811
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: handleOnPrevious, disabled: !onPrevious, variant: "ghost", children: [
14812
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, {}),
14813
+ "Previous"
14814
+ ] })
14815
+ ] }),
14816
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children })
14817
+ ]
14818
+ }
14819
+ );
14820
+ }
14821
+ function SideDialogFooterGroup({ children }) {
14822
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-baseline gap-[1rem]", children });
14823
+ }
14824
+
14825
+ function SideDialogContent({ children, className, isCentered, isFullHeight, variant }) {
14826
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("p-[3rem] py-[2rem] overflow-y-scroll", className), children: /* @__PURE__ */ jsxRuntime.jsx(
14827
+ "div",
14828
+ {
14829
+ className: cn("grid gap-[2rem] max-w-[50rem] w-full mx-auto pb-[1rem] ", {
14830
+ "items-center justify-center h-full content-center": isCentered,
14831
+ "min-h-full": isFullHeight,
14832
+ "content-start": !isFullHeight && !isCentered
14833
+ }),
14834
+ children
14835
+ }
14836
+ ) });
14837
+ }
14838
+ function SideDialogSection({ children }) {
14839
+ return /* @__PURE__ */ jsxRuntime.jsx(
14840
+ "div",
14841
+ {
14842
+ className: cn(
14843
+ "grid text-[0.875rem] text-icon5 gap-[1rem] justify-items-start",
14844
+ "[&>h3]:text-icon3 [&>h3]:text-[1rem] [&>h3]:font-semibold [&>h3]:border-b [&>h3]:border-border1 [&>h3]:pb-[1rem] [&>h3]:pr-[1rem] [&>h3]:inline-flex [&>h3]:gap-[.5rem] [&>h3]:items-center",
14845
+ "[&>h3>svg]:w-[1em] [&>h3>svg]:h-[1em] [&>h3>svg]:text-icon3"
14846
+ ),
14847
+ children
14848
+ }
14849
+ );
14850
+ }
14851
+ function SideDialogKeyValueList({ items, className }) {
14852
+ return /* @__PURE__ */ jsxRuntime.jsx("dl", { className: cn("grid grid-cols-[auto_1fr] gap-x-[2rem] gap-y-[.5rem] text-[0.875rem] content-start", className), children: items.map((item, index) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14853
+ /* @__PURE__ */ jsxRuntime.jsxs("dt", { className: "text-icon3", children: [
14854
+ item.key,
14855
+ ":"
14733
14856
  ] }),
14734
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid lg:grid-cols-[1fr_1fr] gap-x-[6rem] mt-[2rem] ", children: [
14735
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid", children: [
14736
- /* @__PURE__ */ jsxRuntime.jsx(
14737
- "p",
14738
- {
14739
- className: cn("mb-[1rem] text-[0.875rem] text-icon4 mt-[.5rem] leading-[1.75]", {
14740
- "bg-surface4 rounded-lg ": isLoading
14741
- }),
14742
- children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: " " }) : description
14743
- }
14744
- ),
14745
- !isLoading && templateSlug && /* @__PURE__ */ jsxRuntime.jsxs(
14746
- "div",
14747
- {
14748
- className: cn(
14749
- "bg-surface2 border border-surface4 rounded-lg p-[1rem] mb-[1rem]",
14750
- "flex items-start gap-[0.75rem]"
14751
- ),
14752
- children: [
14753
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 mt-[0.125rem]", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, { className: "w-[1.1em] h-[1.1em] text-blue-500" }) }),
14754
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-[0.5rem]", children: [
14755
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[0.5rem]", children: [
14756
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranchIcon, { className: "w-[1em] h-[1em] text-icon4" }),
14757
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] font-medium text-icon5", children: "A new Git branch will be created" })
14857
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-icon4", children: item.value })
14858
+ ] })) });
14859
+ }
14860
+
14861
+ function SideDialogTop({ children, onNext, onPrevious, showInnerNav, className }) {
14862
+ const handleOnNext = () => {
14863
+ onNext?.();
14864
+ };
14865
+ const handleOnPrevious = () => {
14866
+ onPrevious?.();
14867
+ };
14868
+ return /* @__PURE__ */ jsxRuntime.jsx(
14869
+ "div",
14870
+ {
14871
+ className: cn(`flex justify-between h-[3.5rem] items-center text-icon5 text-[.875rem] pl-[1.5rem]`, className),
14872
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-[2rem]", "[&_svg]:w-[1.1em] [&_svg]:h-[1.1em] [&_svg]:text-icon3"), children: [
14873
+ children,
14874
+ (onNext || onPrevious) && showInnerNav && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14875
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-icon3", children: "|" }),
14876
+ /* @__PURE__ */ jsxRuntime.jsxs(
14877
+ "div",
14878
+ {
14879
+ className: cn(
14880
+ "flex gap-[1rem] items-baseline"
14881
+ // '[&>button]:text-[0.875rem] [&>button]:flex [&>button]:items-center [&>button]:px-[0.5rem] [&>button]:py-[0.8rem] [&>button]:leading-[1]',
14882
+ ),
14883
+ children: [
14884
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: handleOnPrevious, disabled: !onPrevious, variant: "ghost", children: [
14885
+ "Previous",
14886
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpIcon, {})
14758
14887
  ] }),
14759
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[0.8125rem] text-icon4 space-y-[0.25rem]", children: [
14760
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
14761
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Branch name:" }),
14762
- " ",
14763
- /* @__PURE__ */ jsxRuntime.jsx("code", { className: "bg-surface3 px-[0.375rem] py-[0.125rem] rounded text-[0.75rem] font-mono", children: branchName })
14764
- ] }),
14765
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: "This ensures safe installation with easy rollback if needed. Your main branch remains unchanged." })
14888
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: handleOnNext, disabled: !onNext, variant: "ghost", children: [
14889
+ "Next",
14890
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowDownIcon, {})
14766
14891
  ] })
14767
- ] })
14768
- ]
14769
- }
14770
- ),
14771
- githubUrl && /* @__PURE__ */ jsxRuntime.jsxs(
14772
- "a",
14773
- {
14774
- href: githubUrl,
14775
- target: "_blank",
14776
- rel: "noopener noreferrer",
14777
- className: "flex items-center gap-[.5rem] mt-auto text-icon3 text-[0.875rem] hover:text-icon5",
14778
- children: [
14779
- /* @__PURE__ */ jsxRuntime.jsx(GithubIcon, {}),
14780
- githubUrl?.split("/")?.pop()
14781
- ]
14782
- }
14783
- )
14784
- ] }),
14785
- infoData && /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: infoData, LinkComponent: lucideReact.Link, labelsAreHidden: true, isLoading })
14786
- ] })
14787
- ] });
14892
+ ]
14893
+ }
14894
+ )
14895
+ ] })
14896
+ ] })
14897
+ }
14898
+ );
14788
14899
  }
14789
14900
 
14790
- function TemplateForm({
14791
- providerOptions,
14792
- selectedProvider,
14793
- onProviderChange,
14794
- variables,
14795
- errors,
14796
- handleInstallTemplate,
14797
- handleVariableChange,
14798
- isLoadingEnvVars,
14799
- defaultModelProvider,
14800
- defaultModelId,
14801
- onModelUpdate
14802
- }) {
14803
- return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[40rem] my-[1rem] p-[1rem] lg:p-[2rem] mx-auto gap-[2rem] grid", children: [
14804
- /* @__PURE__ */ jsxRuntime.jsxs(
14805
- "h2",
14806
- {
14807
- className: cn(
14808
- "text-icon5 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
14809
- "[&>svg]:w-[1.2em] [&_svg]:h-[1.2em] [&_svg]:opacity-70 "
14810
- ),
14811
- children: [
14812
- "Install Template ",
14813
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageOpenIcon, {})
14814
- ]
14815
- }
14816
- ),
14901
+ const useCodemirrorTheme = () => {
14902
+ return React.useMemo(
14903
+ () => codemirrorThemeDracula.draculaInit({
14904
+ settings: {
14905
+ fontFamily: "var(--geist-mono)",
14906
+ fontSize: "0.8125rem",
14907
+ lineHighlight: "transparent",
14908
+ gutterBackground: "transparent",
14909
+ gutterForeground: "#939393",
14910
+ background: "transparent"
14911
+ },
14912
+ styles: [{ tag: [highlight$1.tags.className, highlight$1.tags.propertyName] }]
14913
+ }),
14914
+ []
14915
+ );
14916
+ };
14917
+ function SideDialogCodeSection({ codeStr = "", title }) {
14918
+ const theme = useCodemirrorTheme();
14919
+ const [showAsMultilineText, setShowAsMultilineText] = React.useState(false);
14920
+ const hasMultilineText = React.useMemo(() => {
14921
+ try {
14922
+ const parsed = JSON.parse(codeStr);
14923
+ return containsInnerNewline(parsed || "");
14924
+ } catch {
14925
+ return false;
14926
+ }
14927
+ }, [codeStr]);
14928
+ const finalCodeStr = showAsMultilineText ? codeStr?.replace(/\\n/g, "\n") : codeStr;
14929
+ return /* @__PURE__ */ jsxRuntime.jsx("section", { className: "border border-border1 rounded-lg", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b border-border1 last:border-b-0 grid", children: [
14930
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-[1rem] px-[1.5rem] border-b border-border1 grid grid-cols-[1fr_auto]", children: [
14931
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { children: title }),
14932
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center justify-end", children: [
14933
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: codeStr || "No content" }),
14934
+ hasMultilineText && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "ghost", onClick: () => setShowAsMultilineText(!showAsMultilineText), children: showAsMultilineText ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignLeftIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlignJustifyIcon, {}) })
14935
+ ] })
14936
+ ] }),
14817
14937
  /* @__PURE__ */ jsxRuntime.jsx(
14818
- SelectField,
14938
+ "div",
14819
14939
  {
14820
- options: providerOptions,
14821
- label: "Provider",
14822
- onValueChange: onProviderChange,
14823
- value: selectedProvider,
14824
- placeholder: "Select a provider"
14825
- }
14826
- ),
14827
- selectedProvider && Object.entries(variables || {}).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
14828
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-[0.5rem]", children: [
14829
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem] font-medium", children: "Select AI Model for Template Installation *" }),
14830
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon4 text-[0.75rem]", children: "This model will be used by the workflow to process and install the template" }),
14831
- /* @__PURE__ */ jsxRuntime.jsx(
14832
- AgentMetadataModelSwitcher,
14833
- {
14834
- defaultProvider: defaultModelProvider || "",
14835
- defaultModel: defaultModelId || "",
14836
- updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
14837
- closeEditor: () => {
14838
- },
14839
- modelProviders: ["openai", "anthropic", "google", "xai", "groq"]
14840
- }
14841
- ),
14842
- (!defaultModelProvider || !defaultModelId) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-500 text-[0.75rem]", children: "Please select an AI model to continue" })
14843
- ] }),
14844
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem]", children: "Set required Environmental Variables" }),
14845
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[1fr_1fr] gap-[1rem] items-start", children: isLoadingEnvVars ? /* @__PURE__ */ jsxRuntime.jsxs(
14846
- "div",
14847
- {
14848
- className: cn(
14849
- "flex items-center justify-center col-span-2 text-icon3 text-[0.75rem] gap-[1rem]",
14850
- "[&_svg]:opacity-50 [&_svg]:w-[1.1em] [&_svg]:h-[1.1em]",
14851
- "animate-in fade-in duration-300"
14852
- ),
14853
- children: [
14854
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
14855
- " Loading variables..."
14856
- ]
14857
- }
14858
- ) : Object.entries(variables).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
14859
- /* @__PURE__ */ jsxRuntime.jsx(
14860
- InputField,
14861
- {
14862
- name: `env-${key}`,
14863
- labelIsHidden: true,
14864
- label: "Key",
14865
- value: key,
14866
- disabled: true,
14867
- className: "w-full"
14868
- }
14869
- ),
14870
- /* @__PURE__ */ jsxRuntime.jsx(
14871
- InputField,
14872
- {
14873
- name: key,
14874
- labelIsHidden: true,
14875
- label: "Value",
14876
- value,
14877
- onChange: handleVariableChange,
14878
- errorMsg: errors.includes(key) ? `Value is required.` : "",
14879
- autoComplete: "off",
14880
- className: "w-full"
14881
- }
14882
- )
14883
- ] }, key)) })
14884
- ] }),
14885
- selectedProvider && !isLoadingEnvVars && /* @__PURE__ */ jsxRuntime.jsxs(
14886
- "button",
14887
- {
14888
- className: cn(
14889
- "flex items-center gap-[0.5rem] justify-center text-[0.875rem] w-full bg-surface5 min-h-[2.5rem] rounded-lg text-icon5 hover:bg-surface6 transition-colors",
14890
- "[&>svg]:w-[1.1em] [&_svg]:h-[1.1em] [&_svg]:text-icon5"
14891
- ),
14892
- onClick: handleInstallTemplate,
14893
- disabled: !selectedProvider || !defaultModelProvider || !defaultModelId || errors.length > 0,
14894
- children: [
14895
- "Install ",
14896
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightIcon, {})
14897
- ]
14940
+ className: cn("bg-surface3 p-[1rem] overflow-auto text-icon4 text-[0.875rem] [&>div]:border-none break-all"),
14941
+ children: codeStr && /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { extensions: [langJson.json(), CodeMirror.EditorView.lineWrapping], theme, value: finalCodeStr })
14898
14942
  }
14899
14943
  )
14900
14944
  ] }) });
14901
14945
  }
14902
-
14903
- function getStatusIcon(status) {
14904
- switch (status) {
14905
- case "running":
14906
- return /* @__PURE__ */ jsxRuntime.jsx(Spinner, {});
14907
- case "success":
14908
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {});
14909
- case "failed":
14910
- return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {});
14911
- default:
14912
- return null;
14946
+ function containsInnerNewline(obj) {
14947
+ if (typeof obj === "string") {
14948
+ const idx = obj.indexOf("\n");
14949
+ return idx !== -1 && idx !== obj.length - 1;
14950
+ } else if (Array.isArray(obj)) {
14951
+ return obj.some((item) => containsInnerNewline(item));
14952
+ } else if (obj && typeof obj === "object") {
14953
+ return Object.values(obj).some((value) => containsInnerNewline(value));
14913
14954
  }
14955
+ return false;
14914
14956
  }
14915
14957
 
14916
- function ProcessStepListItem({ stepId, step, isActive, position }) {
14917
- const formatStepTitle = (stepId2) => {
14918
- return stepId2.charAt(0).toUpperCase() + stepId2.slice(1).replace(/-/g, " ");
14919
- };
14958
+ function SideDialogHeading({ children, className, as = "h1" }) {
14959
+ const HeadingTag = as;
14960
+ return /* @__PURE__ */ jsxRuntime.jsx(
14961
+ HeadingTag,
14962
+ {
14963
+ className: cn(
14964
+ "flex items-start text-icon4 text-[1.125rem] font-semibold gap-[1rem]",
14965
+ "[&>svg]:w-[1.5em] [&>svg]:h-[1.5em]",
14966
+ {
14967
+ "text-[1.125rem]": as === "h1",
14968
+ "text-[1rem]": as === "h2"
14969
+ },
14970
+ className
14971
+ ),
14972
+ children
14973
+ }
14974
+ );
14975
+ }
14976
+
14977
+ function EntityMainHeader({
14978
+ title,
14979
+ description,
14980
+ icon,
14981
+ children,
14982
+ isLoading,
14983
+ className,
14984
+ placement = "page"
14985
+ }) {
14920
14986
  return /* @__PURE__ */ jsxRuntime.jsxs(
14921
- "div",
14987
+ "header",
14922
14988
  {
14923
- className: cn("grid gap-[1.5rem] grid-cols-[1fr_auto] py-[.75rem] px-[1rem] rounded-lg", {
14924
- "border border-dashed border-gray-500": isActive
14925
- }),
14989
+ className: cn(
14990
+ "grid gap-[.5rem]",
14991
+ "[&>h1]:text-icon6 [&>h1]:text-[1.25rem] [&>h1]:font-normal [&>h1]:flex [&>h1]:items-center [&>h1]:gap-[0.5rem]",
14992
+ "[&_svg]:w-[1.4rem] [&_svg]:h-[1.4rem] [&_svg]:text-icon3",
14993
+ "[&>p]:text-icon4 [&>p]:text-[0.875rem] [&>p]:m-0",
14994
+ { "pt-[2rem] pb-[2rem]": placement === "page" },
14995
+ { "pt-[1.5em] pb-[1rem]": placement === "sidebar" },
14996
+ className
14997
+ ),
14926
14998
  children: [
14927
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[auto_1fr] gap-[.5rem]", children: [
14928
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.875rem] text-icon5 min-w-[1.5rem] flex justify-end", children: [
14929
- position,
14930
- "."
14931
- ] }),
14932
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
14933
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[0.875rem] text-icon5", children: formatStepTitle(stepId) }),
14934
- step.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] -mt-[0.125rem]", children: step.description })
14935
- ] })
14999
+ /* @__PURE__ */ jsxRuntime.jsxs("h1", { children: [
15000
+ icon && icon,
15001
+ " ",
15002
+ title
14936
15003
  ] }),
14937
- /* @__PURE__ */ jsxRuntime.jsx(
14938
- "div",
14939
- {
14940
- className: cn("w-[1.75rem] h-[1.75rem] rounded-full flex items-center justify-center self-center", {
14941
- "border border-gray-500 border-dashed": step.status === "pending",
14942
- "[&>svg]:text-white [&>svg]:w-[1rem] [&>svg]:h-[1rem]": step.status !== "running",
14943
- "w-[1.75rem] h-[1.75rem]": step.status === "running",
14944
- "bg-green-900": step.status === "success",
14945
- "bg-red-900": step.status === "failed"
14946
- }),
14947
- children: getStatusIcon(step.status)
14948
- }
14949
- )
15004
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { children: description })
14950
15005
  ]
14951
15006
  }
14952
15007
  );
14953
15008
  }
14954
15009
 
14955
- function ProcessStepList({ currentStep, steps = [], className }) {
14956
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(className), children: steps.map((step, idx) => /* @__PURE__ */ jsxRuntime.jsx(
14957
- ProcessStepListItem,
15010
+ function PageHeader({ title, description, icon, className }) {
15011
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15012
+ "header",
14958
15013
  {
14959
- stepId: step.id,
14960
- step,
14961
- isActive: currentStep?.id === step.id,
14962
- position: idx + 1
14963
- },
14964
- step.id
14965
- )) });
15014
+ className: cn(
15015
+ "grid gap-[.5rem] pt-[2rem] pb-[2rem]",
15016
+ "[&>h1]:text-icon6 [&>h1]:text-[1.25rem] [&>h1]:font-normal [&>h1]:flex [&>h1]:items-center [&>h1]:gap-[0.5rem]",
15017
+ "[&_svg]:w-[1.4rem] [&_svg]:h-[1.4rem] [&_svg]:text-icon3",
15018
+ "[&>p]:text-icon4 [&>p]:text-[0.875rem] [&>p]:m-0",
15019
+ className
15020
+ ),
15021
+ children: [
15022
+ /* @__PURE__ */ jsxRuntime.jsxs("h1", { children: [
15023
+ icon && icon,
15024
+ " ",
15025
+ title
15026
+ ] }),
15027
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { children: description })
15028
+ ]
15029
+ }
15030
+ );
14966
15031
  }
14967
15032
 
14968
- function ProcessStepProgressBar({ steps }) {
14969
- const totalSteps = steps.length;
14970
- const completedSteps = steps.filter((step) => step.status === "success").length;
14971
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center flex-col gap-[1rem] content-center w-full", children: [
14972
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[0_repeat(9,1fr)] w-full", children: steps.map((step, idx) => {
14973
- return /* @__PURE__ */ jsxRuntime.jsx(
14974
- "div",
14975
- {
14976
- className: cn("flex justify-end items-center relative h-[2rem] ", {
14977
- "bg-green-900": step.status === "success" && steps?.[idx - 1]?.status === "success"
14978
- }),
14979
- children: /* @__PURE__ */ jsxRuntime.jsx(
14980
- "div",
14981
- {
14982
- className: cn(
14983
- "w-[2rem] h-[2rem] rounded-full flex items-center justify-center self-center absolute right-0 translate-x-[50%] bg-surface3 z-10 text-icon3 font-bold text-[0.75rem]",
14984
- {
14985
- "border border-gray-500 border-dashed": step.status === "pending",
14986
- "[&>svg]:text-surface4 [&>svg]:w-[1.1rem] [&>svg]:h-[1.1rem]": step.status !== "running",
14987
- "bg-green-900 text-white": step.status === "success",
14988
- "bg-red-900 text-white": step.status === "failed"
14989
- }
14990
- ),
14991
- children: step.status === "running" ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : idx + 1
14992
- }
14993
- )
14994
- },
14995
- step.id
14996
- );
14997
- }) }),
14998
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-icon3 text-center", children: [
14999
- completedSteps,
15000
- " of ",
15001
- totalSteps,
15002
- " steps completed"
15003
- ] })
15033
+ function DatePicker({ className, classNames, showOutsideDays = true, ...props }) {
15034
+ return /* @__PURE__ */ jsxRuntime.jsx(
15035
+ reactDayPicker.DayPicker,
15036
+ {
15037
+ showOutsideDays,
15038
+ className: cn("p-3", className),
15039
+ classNames: {
15040
+ months: "flex flex-col space-y-4 sm:space-y-0 ",
15041
+ month: "space-y-4 text-[0.75rem] ",
15042
+ caption: "flex justify-between pt-1 items-center pl-2",
15043
+ caption_label: "text-text font-medium ",
15044
+ nav: "flex items-center",
15045
+ nav_button_previous: cn(
15046
+ "flex justify-center items-center h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"
15047
+ ),
15048
+ nav_button_next: cn("flex justify-center items-center h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100"),
15049
+ dropdown_month: "w-full border-collapse space-y-1",
15050
+ weeknumber: "flex",
15051
+ day: cn(
15052
+ "relative p-0 text-center focus-within:relative focus-within:z-20 [&:has([aria-selected])]:bg-accent [&:has([aria-selected].day-outside)]:bg-accent/50 [&:has([aria-selected].day-range-end)]:rounded-r-md",
15053
+ props.mode === "range" ? "[&:has(>.day-range-end)]:rounded-r-md [&:has(>.day-range-start)]:rounded-l-md first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md" : "[&:has([aria-selected])]:rounded-md",
15054
+ "h-8 w-8 p-0 hover:bg-lightGray-7/50 font-normal aria-selected:opacity-100"
15055
+ ),
15056
+ day_range_start: "day-range-start",
15057
+ day_range_end: "day-range-end",
15058
+ day_selected: "!bg-primary/50 !text-primary-foreground hover:bg-primary rounded-md hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground",
15059
+ day_today: "bg-primary/10 text-accent-foreground",
15060
+ day_outside: "day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30",
15061
+ day_disabled: "text-muted-foreground opacity-50",
15062
+ day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground",
15063
+ day_hidden: "invisible",
15064
+ head_cell: "text-[0.625rem] text-muted-foreground",
15065
+ ...classNames
15066
+ },
15067
+ ...props
15068
+ }
15069
+ );
15070
+ }
15071
+
15072
+ function Select({ name, onChange, defaultValue, value, options, placeholder }) {
15073
+ return /* @__PURE__ */ jsxRuntime.jsxs(Select$1, { name, onValueChange: onChange, value, children: [
15074
+ /* @__PURE__ */ jsxRuntime.jsx(SelectTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(SelectValue, { placeholder: placeholder || "Select..." }) }),
15075
+ /* @__PURE__ */ jsxRuntime.jsx(SelectContent, { children: (options || []).map((option, idx) => /* @__PURE__ */ jsxRuntime.jsx(SelectItem, { value: `${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-[0.5rem] [&>svg]:w-[1.2em] [&>svg]:h-[1.2em] [&>svg]:text-icon3", children: option }) }, option)) })
15004
15076
  ] });
15005
15077
  }
15006
15078
 
15007
- function TemplateInstallation({ name, streamResult, runId, workflowInfo }) {
15008
- const phase = streamResult?.phase || "initializing";
15009
- const workflowState = streamResult?.payload?.workflowState;
15010
- const currentStep = streamResult?.payload?.currentStep;
15011
- const error = streamResult?.error;
15012
- const workflowSteps = workflowState?.steps || {};
15013
- const hasSteps = Object.keys(workflowSteps).length > 0;
15014
- const isUserVisibleStep = (stepId) => {
15015
- if (stepId === "input" || stepId.endsWith(".input")) return false;
15016
- if (stepId.startsWith("Mapping_") && /[0-9a-f]{8}/.test(stepId)) return false;
15017
- if (/[0-9a-f]{8,}/.test(stepId)) return false;
15018
- if (workflowInfo?.allSteps) {
15019
- return stepId in workflowInfo.allSteps;
15079
+ const hourOptions = ["12", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"];
15080
+ const minuteOptions = ["00", "15", "30", "45", "59"];
15081
+ const timePeriodOptions = ["AM", "PM"];
15082
+ function TimePicker({ defaultValue, onValueChange, className }) {
15083
+ const [hour, setHour] = React.useState("12");
15084
+ const [minute, setMinute] = React.useState("00");
15085
+ const [timePeriod, setTimePeriod] = React.useState("AM");
15086
+ React.useEffect(() => {
15087
+ if (defaultValue) {
15088
+ const timeRegex = /^(\d{1,2}):(\d{2})(?::\d{2})?\s*(AM|PM|am|pm)?$/;
15089
+ const match = defaultValue.match(timeRegex);
15090
+ if (match) {
15091
+ let parsedHour = parseInt(match[1], 10);
15092
+ const parsedMinute = parseInt(match[2], 10);
15093
+ const period = match[3]?.toUpperCase();
15094
+ if (parsedHour >= 1 && parsedHour <= 12 && parsedMinute >= 0 && parsedMinute <= 59) {
15095
+ setHour(parsedHour.toString());
15096
+ setMinute(parsedMinute === 0 ? "00" : parsedMinute.toString());
15097
+ setTimePeriod(period || "AM");
15098
+ }
15099
+ }
15020
15100
  }
15021
- return true;
15101
+ }, [defaultValue]);
15102
+ const handleHourChange = (val) => {
15103
+ setHour(val);
15104
+ onValueChange(`${hourOptions[+val]}:${minute} ${timePeriod}`.trim());
15022
15105
  };
15023
- const visibleSteps = Object.entries(workflowSteps).filter(([stepId, _]) => isUserVisibleStep(stepId));
15024
- const totalSteps = visibleSteps.length;
15025
- const getPhaseMessage = () => {
15026
- switch (phase) {
15027
- case "initializing":
15028
- return "Preparing template installation...";
15029
- case "processing":
15030
- return `Installing ${name} template`;
15031
- case "completed":
15032
- return "Template installation completed!";
15033
- case "error":
15034
- return "Template installation failed";
15035
- default:
15036
- return "Installing template...";
15037
- }
15106
+ const handleMinuteChange = (val) => {
15107
+ setMinute(minuteOptions[+val]);
15108
+ onValueChange(`${hour}:${minuteOptions[+val]} ${timePeriod}`.trim());
15038
15109
  };
15039
- const steps = visibleSteps.map(([stepId, stepData]) => ({
15040
- id: stepId,
15041
- status: stepData?.status,
15042
- description: stepData?.description,
15043
- title: stepId.charAt(0).toUpperCase() + stepId.slice(1).replace(/-/g, " "),
15044
- isActive: currentStep?.id === stepId
15045
- }));
15046
- return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-6 text-icon3 mb-[2rem] content-center", children: [
15047
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
15048
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-icon5", children: getPhaseMessage() }),
15049
- streamResult?.runId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-[0.5rem] text-[0.75rem] text-icon3", children: [
15050
- "Run ID: ",
15051
- streamResult.runId
15052
- ] })
15053
- ] }),
15054
- hasSteps && totalSteps > 0 && !["error"].includes(phase) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[30rem] w-full mx-auto px-[1.5rem]", children: /* @__PURE__ */ jsxRuntime.jsx(ProcessStepProgressBar, { steps }) }),
15055
- error && phase === "error" && /* @__PURE__ */ jsxRuntime.jsxs(
15056
- "div",
15110
+ const handleTimePeriodChange = (val) => {
15111
+ setTimePeriod(timePeriodOptions[+val]);
15112
+ onValueChange(`${hour}:${minute} ${timePeriodOptions[+val]}`.trim());
15113
+ };
15114
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-[0.5rem] items-center", className), children: [
15115
+ /* @__PURE__ */ jsxRuntime.jsx(
15116
+ Select,
15057
15117
  {
15058
- className: cn(
15059
- "rounded-lg text-icon5 p-[1.5rem] flex items-center gap-[.75rem] text-[0.875rem] bg-red-500/10",
15060
- "[&>svg]:w-[1.5rem] [&>svg]:h-[1.5rem] [&>svg]:opacity-70 [&>svg]:text-red-500"
15061
- ),
15062
- children: [
15063
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.OctagonXIcon, {}),
15064
- error || "Something went wrong"
15065
- ]
15118
+ name: "hour",
15119
+ value: hourOptions.indexOf(hour).toString(),
15120
+ onChange: handleHourChange,
15121
+ options: hourOptions
15066
15122
  }
15067
15123
  ),
15068
- hasSteps && /* @__PURE__ */ jsxRuntime.jsx(ProcessStepList, { steps, currentStep, className: "pb-[1rem]" }),
15069
- !hasSteps && phase === "initializing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-sm text-icon3 grid gap-[1rem] justify-items-center", children: [
15070
- /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
15071
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: "This may take some time..." })
15072
- ] })
15124
+ ":",
15125
+ /* @__PURE__ */ jsxRuntime.jsx(
15126
+ Select,
15127
+ {
15128
+ name: "minute",
15129
+ value: minuteOptions.indexOf(minute).toString(),
15130
+ onChange: handleMinuteChange,
15131
+ options: minuteOptions
15132
+ }
15133
+ ),
15134
+ /* @__PURE__ */ jsxRuntime.jsx(
15135
+ Select,
15136
+ {
15137
+ name: "period",
15138
+ value: timePeriodOptions.indexOf(timePeriod).toString(),
15139
+ onChange: handleTimePeriodChange,
15140
+ options: timePeriodOptions
15141
+ }
15142
+ )
15073
15143
  ] });
15074
15144
  }
15075
15145
 
15076
- function TemplateSuccess({ name, installedEntities, linkComponent }) {
15077
- const LinkComponent = linkComponent || "a";
15146
+ const DateTimePicker = ({
15147
+ value,
15148
+ minValue,
15149
+ maxValue,
15150
+ defaultTimeStrValue,
15151
+ onValueChange,
15152
+ children,
15153
+ className,
15154
+ placeholder,
15155
+ ...props
15156
+ }) => {
15157
+ const [openPopover, setOpenPopover] = React__namespace.useState(false);
15158
+ return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: openPopover, onOpenChange: setOpenPopover, children: [
15159
+ /* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: children ? children : /* @__PURE__ */ jsxRuntime.jsx(
15160
+ DefaultTrigger,
15161
+ {
15162
+ value,
15163
+ placeholder,
15164
+ className,
15165
+ "data-testid": "datepicker-button"
15166
+ }
15167
+ ) }),
15168
+ /* @__PURE__ */ jsxRuntime.jsx(
15169
+ PopoverContent,
15170
+ {
15171
+ className: "backdrop-blur-4xl w-auto p-0 bg-surface4 max-w-[16.5rem]",
15172
+ align: "start",
15173
+ "data-testid": "datepicker-calendar",
15174
+ children: /* @__PURE__ */ jsxRuntime.jsx(
15175
+ DateTimePickerContent,
15176
+ {
15177
+ value,
15178
+ minValue,
15179
+ maxValue,
15180
+ onValueChange,
15181
+ setOpenPopover,
15182
+ defaultTimeStrValue,
15183
+ ...props
15184
+ }
15185
+ )
15186
+ }
15187
+ )
15188
+ ] });
15189
+ };
15190
+ function getCompoundDate({ date, timeStr = "" }) {
15191
+ if (!dateFns.isValid(date)) {
15192
+ return null;
15193
+ }
15194
+ if (timeStr) {
15195
+ const dateStr = dateFns.format(date, "yyyy-MM-dd");
15196
+ const newDate = /* @__PURE__ */ new Date(`${dateStr} ${timeStr}`);
15197
+ if (dateFns.isValid(newDate)) {
15198
+ return newDate;
15199
+ }
15200
+ }
15201
+ return date;
15202
+ }
15203
+ const DateTimePickerContent = ({
15204
+ value,
15205
+ minValue,
15206
+ maxValue,
15207
+ onValueChange,
15208
+ setOpenPopover,
15209
+ placeholder,
15210
+ className,
15211
+ defaultTimeStrValue,
15212
+ ...props
15213
+ }) => {
15214
+ const [localErrorMsg, setLocalErrorMsg] = React__namespace.useState(null);
15215
+ const [dateInputValue, setDateInputValue] = React__namespace.useState(
15216
+ value ? dateFns.format(getCompoundDate({ date: value, timeStr: defaultTimeStrValue }) || "", "PP p") : ""
15217
+ );
15218
+ const [timeStrValue, setTimeStrValue] = React__namespace.useState(defaultTimeStrValue || "");
15219
+ const [selected, setSelected] = React__namespace.useState(value ? new Date(value) : void 0);
15220
+ const debouncedDateUpdate = useDebounce.useDebouncedCallback((date) => {
15221
+ if (dateFns.isValid(date)) {
15222
+ setSelected(date);
15223
+ onValueChange?.(date);
15224
+ setOpenPopover?.(false);
15225
+ }
15226
+ }, 500);
15227
+ const handleInputChange = (e) => {
15228
+ setDateInputValue(e.currentTarget.value);
15229
+ const date = new Date(e.currentTarget.value);
15230
+ debouncedDateUpdate(date);
15231
+ };
15232
+ const updateInputValue = (date) => {
15233
+ if (dateFns.isValid(date)) {
15234
+ if (maxValue && date > maxValue) {
15235
+ setLocalErrorMsg(`The selected date should be before ${dateFns.format(maxValue, "PP p")}`);
15236
+ setDateInputValue("");
15237
+ } else if (minValue && date < minValue) {
15238
+ setLocalErrorMsg(`The selected date should be after ${dateFns.format(minValue, "PP p")}`);
15239
+ setDateInputValue("");
15240
+ } else {
15241
+ setDateInputValue(dateFns.format(date, "PP p"));
15242
+ setLocalErrorMsg("");
15243
+ }
15244
+ } else {
15245
+ setDateInputValue("");
15246
+ setLocalErrorMsg("");
15247
+ }
15248
+ };
15249
+ const dateInputValueDate = new Date(dateInputValue);
15250
+ const dateInputValueIsValid = dateFns.isValid(dateInputValueDate);
15251
+ const newValueDefined = dateInputValueIsValid && dateInputValueDate.getTime() !== value?.getTime();
15252
+ const handleDaySelect = (date) => {
15253
+ setSelected(date);
15254
+ if (date) {
15255
+ const newDate = getCompoundDate({ date, timeStr: timeStrValue });
15256
+ updateInputValue(newDate || "");
15257
+ } else {
15258
+ updateInputValue("");
15259
+ }
15260
+ };
15261
+ const handleMonthSelect = (date) => {
15262
+ setSelected(date);
15263
+ if (date) {
15264
+ const newDate = getCompoundDate({ date, timeStr: timeStrValue });
15265
+ updateInputValue(newDate || "");
15266
+ } else {
15267
+ updateInputValue("");
15268
+ }
15269
+ };
15270
+ const handleTimeStrChange = (val) => {
15271
+ setTimeStrValue(val);
15272
+ if (dateInputValueIsValid) {
15273
+ const newDate = getCompoundDate({ date: dateInputValueDate, timeStr: val });
15274
+ updateInputValue(newDate || "");
15275
+ }
15276
+ };
15277
+ const handleCancel = () => {
15278
+ setOpenPopover?.(false);
15279
+ };
15280
+ const handleApply = () => {
15281
+ if (dateFns.isValid(dateInputValueDate)) {
15282
+ onValueChange(dateInputValueDate);
15283
+ }
15284
+ setOpenPopover?.(false);
15285
+ };
15286
+ const handleClear = () => {
15287
+ onValueChange(void 0);
15288
+ setSelected(void 0);
15289
+ setDateInputValue("");
15290
+ setTimeStrValue("");
15291
+ setOpenPopover?.(false);
15292
+ };
15078
15293
  return /* @__PURE__ */ jsxRuntime.jsxs(
15079
- Container,
15294
+ "div",
15080
15295
  {
15081
- className: cn(
15082
- "grid items-center justify-items-center gap-[1rem] content-center",
15083
- "[&>svg]:w-[2rem] [&>svg]:h-[2rem]"
15084
- ),
15296
+ "aria-label": "Choose date",
15297
+ className: cn("relative mt-2 flex flex-col ", className),
15298
+ onKeyDown: (e) => {
15299
+ e.stopPropagation();
15300
+ if (e.key === "Escape") {
15301
+ setOpenPopover?.(false);
15302
+ }
15303
+ },
15085
15304
  children: [
15086
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageOpenIcon, {}),
15087
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[1.25rem ]", children: "Done!" }),
15088
- /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.875rem] text-center text-icon3 ", children: [
15089
- "The ",
15090
- /* @__PURE__ */ jsxRuntime.jsx("b", { className: "text-icon4", children: name }),
15091
- " template has been successfully installed.",
15092
- installedEntities && installedEntities.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15093
- /* @__PURE__ */ jsxRuntime.jsx("br", {}),
15094
- " Installed entities are listed below."
15095
- ] })
15096
- ] }),
15097
- installedEntities && installedEntities.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: installedEntities, LinkComponent })
15305
+ /* @__PURE__ */ jsxRuntime.jsx(
15306
+ InputField,
15307
+ {
15308
+ type: "text",
15309
+ value: dateInputValue,
15310
+ onChange: handleInputChange,
15311
+ placeholder,
15312
+ className: "m-4 mb-0 !w-auto"
15313
+ }
15314
+ ),
15315
+ localErrorMsg && /* @__PURE__ */ jsxRuntime.jsxs(
15316
+ "div",
15317
+ {
15318
+ className: cn(
15319
+ "text-[0.875rem] m-[1rem] mb-0 text-icon3",
15320
+ "[&>svg]:w-[1.1em] [&>svg]:h-[1.1em] [&>svg]:mt-[0.2em] [&>svg]:text-red-500 [&>svg]:float-left [&>svg]:mr-[0.5rem]"
15321
+ ),
15322
+ children: [
15323
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleAlertIcon, {}),
15324
+ " ",
15325
+ localErrorMsg
15326
+ ]
15327
+ }
15328
+ ),
15329
+ /* @__PURE__ */ jsxRuntime.jsx(
15330
+ DatePicker,
15331
+ {
15332
+ mode: "single",
15333
+ month: selected,
15334
+ selected,
15335
+ onMonthChange: handleMonthSelect,
15336
+ onSelect: handleDaySelect,
15337
+ ...props
15338
+ }
15339
+ ),
15340
+ /* @__PURE__ */ jsxRuntime.jsx(
15341
+ TimePicker,
15342
+ {
15343
+ onValueChange: handleTimeStrChange,
15344
+ className: "m-4 mt-0 w-auto",
15345
+ defaultValue: value ? dateFns.formatDate(new Date(value), "hh:mm a") : defaultTimeStrValue
15346
+ }
15347
+ ),
15348
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_auto] gap-[0.5rem] m-4 mt-0", children: [
15349
+ /* @__PURE__ */ jsxRuntime.jsx(
15350
+ Button,
15351
+ {
15352
+ variant: "primary",
15353
+ tabIndex: 0,
15354
+ onClick: () => {
15355
+ dateInputValueIsValid ? handleApply() : handleCancel();
15356
+ },
15357
+ children: newValueDefined ? `Apply` : `Cancel`
15358
+ }
15359
+ ),
15360
+ newValueDefined && /* @__PURE__ */ jsxRuntime.jsx(Button, { variant: "outline", tabIndex: 0, onClick: handleClear, children: "Clear" })
15361
+ ] })
15098
15362
  ]
15099
15363
  }
15100
15364
  );
15101
- }
15365
+ };
15366
+ const DefaultTrigger = React__namespace.forwardRef(
15367
+ ({ value, placeholder, className, ...props }, ref) => {
15368
+ return /* @__PURE__ */ jsxRuntime.jsxs(Button, { ref, variant: "outline", className: cn("justify-start", className), ...props, children: [
15369
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CalendarIcon, { className: "h-4 w-4" }),
15370
+ value ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-white", children: dateFns.format(value, "PPP p") }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray", children: placeholder ?? "Pick a date" })
15371
+ ] });
15372
+ }
15373
+ );
15102
15374
 
15103
- function TemplateFailure({ errorMsg, validationErrors }) {
15104
- const isSchemaError = errorMsg?.includes("Invalid schema for function");
15105
- const isValidationError = errorMsg?.includes("validation issue") || validationErrors && validationErrors.length > 0;
15106
- const getUserFriendlyMessage = () => {
15107
- if (isValidationError) {
15108
- return "Template installation completed but some validation issues remain. The template may still be functional, but you should review and fix these issues.";
15109
- }
15110
- if (isSchemaError) {
15111
- return "There was an issue with the AI model configuration. This may be related to the selected model or AI SDK version compatibility.";
15112
- }
15113
- return "An unexpected error occurred during template installation.";
15114
- };
15115
- const getIconAndTitle = () => {
15116
- if (isValidationError) {
15117
- return {
15118
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangleIcon, { className: "text-yellow-500" }),
15119
- title: "Template Installed with Warnings"
15120
- };
15375
+ function TextAndIcon({ children, className }) {
15376
+ return /* @__PURE__ */ jsxRuntime.jsx(
15377
+ "span",
15378
+ {
15379
+ className: cn(
15380
+ "flex items-center gap-[0.25rem] text-icon4 text-[0.875rem]",
15381
+ "[&>svg]:w-[1.2em] [&>svg]:h-[1.2em] [&>svg]:opacity-50",
15382
+ className
15383
+ ),
15384
+ children
15121
15385
  }
15122
- return {
15123
- icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FrownIcon, {}),
15124
- title: "Template Installation Failed"
15125
- };
15126
- };
15127
- const { icon, title } = getIconAndTitle();
15128
- return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center max-w-2xl mx-auto", children: [
15129
- /* @__PURE__ */ jsxRuntime.jsxs(
15386
+ );
15387
+ }
15388
+
15389
+ function getShortId(id) {
15390
+ if (!id) return void 0;
15391
+ return id.slice(0, 8);
15392
+ }
15393
+
15394
+ function TemplatesTools({
15395
+ tagOptions,
15396
+ selectedTag,
15397
+ providerOptions,
15398
+ selectedProvider,
15399
+ onTagChange,
15400
+ onProviderChange,
15401
+ searchTerm,
15402
+ onSearchChange,
15403
+ onReset,
15404
+ className,
15405
+ isLoading
15406
+ }) {
15407
+ if (isLoading) {
15408
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15130
15409
  "div",
15131
15410
  {
15132
15411
  className: cn(
15133
- "grid items-center justify-items-center gap-[1rem] content-center",
15134
- "[&>svg]:w-[2rem] [&>svg]:h-[2rem]"
15412
+ "h-[6.5rem] flex items-center gap-[2rem]",
15413
+ "[&>div]:bg-surface3 [&>div]:w-[12rem] [&>div]:h-[2rem] [&>div]:animate-pulse",
15414
+ className
15135
15415
  ),
15136
15416
  children: [
15137
- icon,
15138
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-2", children: [
15139
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium text-icon5", children: title }),
15140
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-icon3", children: getUserFriendlyMessage() })
15141
- ] })
15417
+ /* @__PURE__ */ jsxRuntime.jsx("div", {}),
15418
+ " ",
15419
+ /* @__PURE__ */ jsxRuntime.jsx("div", {}),
15420
+ " ",
15421
+ /* @__PURE__ */ jsxRuntime.jsx("div", {})
15142
15422
  ]
15143
15423
  }
15144
- ),
15145
- validationErrors && validationErrors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "text-xs", children: [
15146
- /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "cursor-pointer text-icon3 hover:text-icon4 select-none text-center", children: [
15147
- "Show Validation Issues (",
15148
- validationErrors.length,
15149
- ")"
15150
- ] }),
15151
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto max-h-60 text-left space-y-2", children: validationErrors.map((error, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-l-2 border-red-400 pl-2", children: [
15152
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-red-600 dark:text-red-400", children: error.type === "typescript" ? "🔴 TypeScript Error" : "⚠️ Lint Error" }),
15153
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-mono text-gray-700 dark:text-gray-300 mt-1 whitespace-pre-wrap break-words", children: error.message })
15154
- ] }, index)) })
15155
- ] }),
15156
- errorMsg && !isValidationError && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "text-xs", children: [
15157
- /* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer text-icon3 hover:text-icon4 select-none text-center", children: "Show Details" }),
15158
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs font-mono overflow-auto max-h-60 text-left", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words", children: errorMsg }) })
15424
+ );
15425
+ }
15426
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-wrap mx-auto sticky top-0 gap-[2rem] bg-surface2 py-[2rem]", className), children: [
15427
+ /* @__PURE__ */ jsxRuntime.jsx(
15428
+ SearchField,
15429
+ {
15430
+ label: "Search templates",
15431
+ value: searchTerm,
15432
+ onChange: (e) => onSearchChange?.(e.target.value),
15433
+ placeholder: "Search Template"
15434
+ }
15435
+ ),
15436
+ /* @__PURE__ */ jsxRuntime.jsx(SelectField, { label: "Filter by tag", value: selectedTag, onValueChange: onTagChange, options: tagOptions }),
15437
+ /* @__PURE__ */ jsxRuntime.jsx(
15438
+ SelectField,
15439
+ {
15440
+ label: "Filter by provider",
15441
+ value: selectedProvider,
15442
+ onValueChange: onProviderChange,
15443
+ options: providerOptions
15444
+ }
15445
+ ),
15446
+ onReset && /* @__PURE__ */ jsxRuntime.jsxs(Button, { onClick: onReset, children: [
15447
+ "Reset ",
15448
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
15159
15449
  ] })
15160
15450
  ] });
15161
15451
  }
15162
15452
 
15163
- const TraceContext = React.createContext({});
15164
- function TraceProvider({
15165
- children,
15166
- initialTraces: traces = []
15167
- }) {
15168
- const [open, setOpen] = React.useState(false);
15169
- const [trace, setTrace] = React.useState(null);
15170
- const [currentTraceIndex, setCurrentTraceIndex] = React.useState(0);
15171
- const [span, setSpan] = React.useState(null);
15172
- const nextTrace = () => {
15173
- if (currentTraceIndex < traces.length - 1) {
15174
- const nextIndex = currentTraceIndex + 1;
15175
- setCurrentTraceIndex(nextIndex);
15176
- const nextTrace2 = traces[nextIndex].trace;
15177
- setTrace(nextTrace2);
15178
- const parentSpan = nextTrace2.find((span2) => span2.parentSpanId === null) || nextTrace2[0];
15179
- setSpan(parentSpan);
15180
- }
15181
- };
15182
- const prevTrace = () => {
15183
- if (currentTraceIndex > 0) {
15184
- const prevIndex = currentTraceIndex - 1;
15185
- setCurrentTraceIndex(prevIndex);
15186
- const prevTrace2 = traces[prevIndex].trace;
15187
- setTrace(prevTrace2);
15188
- const parentSpan = prevTrace2.find((span2) => span2.parentSpanId === null) || prevTrace2[0];
15189
- setSpan(parentSpan);
15190
- }
15191
- };
15192
- const clearData = () => {
15193
- setOpen(false);
15194
- setTrace(null);
15195
- setSpan(null);
15196
- };
15453
+ function getRepoName(githubUrl) {
15454
+ return githubUrl.replace(/\/$/, "").split("/").pop();
15455
+ }
15456
+ function Container({ children, className }) {
15197
15457
  return /* @__PURE__ */ jsxRuntime.jsx(
15198
- TraceContext.Provider,
15458
+ "div",
15199
15459
  {
15200
- value: {
15201
- isOpen: open,
15202
- setIsOpen: setOpen,
15203
- trace,
15204
- setTrace,
15205
- traces,
15206
- currentTraceIndex,
15207
- setCurrentTraceIndex,
15208
- nextTrace,
15209
- prevTrace,
15210
- span,
15211
- setSpan,
15212
- clearData
15213
- },
15460
+ className: cn(
15461
+ "border border-border1 rounded-lg mt-[3rem] py-[2rem] lg:min-h-[25rem] transition-height px-[1rem] lg:px-[3rem]",
15462
+ className
15463
+ ),
15214
15464
  children
15215
15465
  }
15216
15466
  );
15217
15467
  }
15218
15468
 
15219
- const useOpenTrace = () => {
15220
- const {
15221
- setTrace,
15222
- isOpen: open,
15223
- setIsOpen: setOpen,
15224
- trace: currentTrace,
15225
- setSpan,
15226
- setCurrentTraceIndex
15227
- } = React.useContext(TraceContext);
15228
- const openTrace = (trace, traceIndex) => {
15229
- setTrace(trace);
15230
- const parentSpan = trace.find((span) => span.parentSpanId === null) || trace[0];
15231
- setSpan(parentSpan);
15232
- setCurrentTraceIndex(traceIndex);
15233
- if (open && currentTrace?.[0]?.id !== trace[0].id) return;
15234
- setOpen((prev) => !prev);
15235
- };
15236
- return { openTrace };
15237
- };
15238
-
15239
- const TracesTableEmpty = ({ colsCount }) => {
15240
- return /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: /* @__PURE__ */ jsxRuntime.jsx(Row, { children: /* @__PURE__ */ jsxRuntime.jsx(Cell, { colSpan: colsCount, className: "text-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { children: "No traces found" }) }) }) });
15241
- };
15242
- const TracesTableError = ({ error, colsCount }) => {
15243
- return /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: /* @__PURE__ */ jsxRuntime.jsx(Row, { children: /* @__PURE__ */ jsxRuntime.jsx(Cell, { colSpan: colsCount, className: "text-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { children: error.message }) }) }) });
15244
- };
15245
- const TraceRow = ({ trace, index, isActive }) => {
15246
- const { openTrace } = useOpenTrace();
15247
- const hasFailure = trace.trace.some((span) => span.status.code === 2);
15248
- return /* @__PURE__ */ jsxRuntime.jsxs(Row, { className: isActive ? "bg-surface4" : "", onClick: () => openTrace(trace.trace, index), children: [
15249
- /* @__PURE__ */ jsxRuntime.jsx(DateTimeCell, { dateTime: new Date(trace.started / 1e3) }),
15250
- /* @__PURE__ */ jsxRuntime.jsxs(TxtCell, { title: trace.traceId, children: [
15251
- trace.traceId.substring(0, 7),
15252
- "..."
15253
- ] }),
15254
- /* @__PURE__ */ jsxRuntime.jsx(UnitCell, { unit: "ms", children: toSigFigs(trace.duration / 1e3, 3) }),
15255
- /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => openTrace(trace.trace, index), children: /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(TraceIcon, {}), children: trace.trace.length }) }) }),
15256
- /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: hasFailure ? /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: "Failed" }) : /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}), variant: "success", children: "Success" }) })
15257
- ] });
15258
- };
15259
- const TracesTable = ({ traces, error }) => {
15260
- const hasNoTraces = !traces || traces.length === 0;
15261
- const { currentTraceIndex } = React.useContext(TraceContext);
15262
- const colsCount = 4;
15263
- return /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { size: "small", children: [
15264
- /* @__PURE__ */ jsxRuntime.jsxs(Thead, { children: [
15265
- /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Time" }),
15266
- /* @__PURE__ */ jsxRuntime.jsx(Th, { width: "auto", children: "Trace Id" }),
15267
- /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Duration" }),
15268
- /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Spans" }),
15269
- /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Status" })
15270
- ] }),
15271
- error ? /* @__PURE__ */ jsxRuntime.jsx(TracesTableError, { error, colsCount }) : hasNoTraces ? /* @__PURE__ */ jsxRuntime.jsx(TracesTableEmpty, { colsCount }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: traces.map((trace, index) => /* @__PURE__ */ jsxRuntime.jsx(
15272
- TraceRow,
15469
+ function TemplatesList({ templates, linkComponent, className, isLoading }) {
15470
+ const LinkComponent = linkComponent || "a";
15471
+ if (isLoading) {
15472
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-y-[1rem]", className), children: Array.from({ length: 5 }).map((_, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[4rem] bg-surface3 animate-pulse rounded-lg" }, index)) });
15473
+ }
15474
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid gap-y-[1rem]", className), children: templates.map((template) => {
15475
+ const hasMetaInfo = template?.agents || template?.tools || template?.networks || template?.workflows || template?.mcp;
15476
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15477
+ "article",
15273
15478
  {
15274
- trace,
15275
- index,
15276
- isActive: index === currentTraceIndex
15479
+ className: cn(
15480
+ "border border-border1 rounded-lg overflow-hidden w-full grid grid-cols-[1fr_auto] bg-surface3 transition-colors hover:bg-surface4"
15481
+ ),
15482
+ children: [
15483
+ /* @__PURE__ */ jsxRuntime.jsxs(
15484
+ LinkComponent,
15485
+ {
15486
+ to: `/templates/${template.slug}`,
15487
+ className: cn("grid [&:hover_p]:text-icon5", {
15488
+ "grid-cols-[8rem_1fr] lg:grid-cols-[12rem_1fr]": template.imageURL
15489
+ }),
15490
+ children: [
15491
+ template.imageURL && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("relative overflow-hidden"), children: /* @__PURE__ */ jsxRuntime.jsx(
15492
+ "div",
15493
+ {
15494
+ className: "w-full h-full bg-cover thumb transition-scale duration-150",
15495
+ style: {
15496
+ backgroundImage: `url(${template.imageURL})`
15497
+ }
15498
+ }
15499
+ ) }),
15500
+ /* @__PURE__ */ jsxRuntime.jsxs(
15501
+ "div",
15502
+ {
15503
+ className: cn(
15504
+ "grid py-[.75rem] px-[1.5rem] w-full gap-[0.1rem]",
15505
+ "[&_svg]:w-[1em] [&_svg]:h-[1em] [&_svg]:text-icon3"
15506
+ ),
15507
+ children: [
15508
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[1rem] text-icon5", children: template.title }),
15509
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-icon4 transition-colors duration-500", children: template.description }),
15510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "hidden 2xl:flex text-icon3 text-[0.875rem] flex-wrap items-center gap-[1rem] mt-[0.75rem]", children: [
15511
+ hasMetaInfo && /* @__PURE__ */ jsxRuntime.jsxs(
15512
+ "ul",
15513
+ {
15514
+ className: cn(
15515
+ "flex gap-[1rem] text-[0.875rem] text-icon3 m-0 p-0 list-none",
15516
+ "[&>li]:flex [&>li]:items-center [&>li]:gap-[0.1rem] text-icon4"
15517
+ ),
15518
+ children: [
15519
+ template?.agents && template.agents.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15520
+ /* @__PURE__ */ jsxRuntime.jsx(AgentIcon, {}),
15521
+ " ",
15522
+ template.agents.length
15523
+ ] }),
15524
+ template?.tools && template.tools.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15525
+ /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, {}),
15526
+ " ",
15527
+ template.tools.length
15528
+ ] }),
15529
+ template?.networks && template.networks.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15530
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.NetworkIcon, {}),
15531
+ " ",
15532
+ template.networks.length
15533
+ ] }),
15534
+ template?.workflows && template.workflows.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15535
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.WorkflowIcon, {}),
15536
+ " ",
15537
+ template.workflows.length
15538
+ ] }),
15539
+ template?.mcp && template.mcp.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15540
+ /* @__PURE__ */ jsxRuntime.jsx(McpServerIcon, {}),
15541
+ " ",
15542
+ template.mcp.length
15543
+ ] })
15544
+ ]
15545
+ }
15546
+ ),
15547
+ hasMetaInfo && template.supportedProviders && /* @__PURE__ */ jsxRuntime.jsx("small", { children: "|" }),
15548
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center text-icon3 gap-[1rem]", children: template.supportedProviders.map((provider) => /* @__PURE__ */ jsxRuntime.jsx("span", { className: "", children: provider }, provider)) })
15549
+ ] })
15550
+ ]
15551
+ }
15552
+ )
15553
+ ]
15554
+ }
15555
+ ),
15556
+ /* @__PURE__ */ jsxRuntime.jsx(
15557
+ "a",
15558
+ {
15559
+ href: template.githubUrl,
15560
+ className: cn("group items-center gap-[0.5rem] text-[0.875rem] ml-auto pr-[1rem] hidden", "lg:flex"),
15561
+ target: "_blank",
15562
+ rel: "noopener noreferrer",
15563
+ children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-[0.5rem] px-[0.5rem] py-[0.25rem] rounded bg-surface1 group-hover:bg-surface2 text-icon3 transition-colors group-hover:text-icon5 ", children: [
15564
+ /* @__PURE__ */ jsxRuntime.jsx(GithubIcon, {}),
15565
+ " ",
15566
+ getRepoName(template.githubUrl)
15567
+ ] })
15568
+ }
15569
+ )
15570
+ ]
15277
15571
  },
15278
- trace.traceId + index
15279
- )) }) })
15280
- ] });
15281
- };
15282
-
15572
+ template.slug
15573
+ );
15574
+ }) });
15575
+ }
15576
+
15577
+ function TemplateInfo({
15578
+ title,
15579
+ description,
15580
+ imageURL,
15581
+ githubUrl,
15582
+ isLoading,
15583
+ infoData,
15584
+ templateSlug
15585
+ }) {
15586
+ const branchName = templateSlug ? `feat/install-template-${templateSlug}` : "feat/install-template-[slug]";
15587
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15588
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid lg:grid-cols-[1fr_1fr] gap-x-[6rem] mt-[2rem] lg:min-h-[4rem] items-center "), children: [
15589
+ /* @__PURE__ */ jsxRuntime.jsxs(
15590
+ "div",
15591
+ {
15592
+ className: cn(
15593
+ "text-[1.5rem] flex items-center gap-[0.75rem] ",
15594
+ "[&>svg]:w-[1.2em] [&>svg]:h-[1.2em] [&>svg]:opacity-50",
15595
+ {
15596
+ "[&>svg]:opacity-20": isLoading
15597
+ }
15598
+ ),
15599
+ children: [
15600
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageIcon, {}),
15601
+ /* @__PURE__ */ jsxRuntime.jsx(
15602
+ "h2",
15603
+ {
15604
+ className: cn({
15605
+ "bg-surface4 flex rounded-lg min-w-[50%]": isLoading
15606
+ }),
15607
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: " " }) : title
15608
+ }
15609
+ )
15610
+ ]
15611
+ }
15612
+ ),
15613
+ /* @__PURE__ */ jsxRuntime.jsx(
15614
+ "div",
15615
+ {
15616
+ className: "w-full h-full bg-cover bg-center transition-scale duration-150 rounded-lg overflow-hidden min-h-[2rem] mt-[2rem] lg:mt-0",
15617
+ style: {
15618
+ backgroundImage: `url(${imageURL})`
15619
+ }
15620
+ }
15621
+ )
15622
+ ] }),
15623
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid lg:grid-cols-[1fr_1fr] gap-x-[6rem] mt-[2rem] ", children: [
15624
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid", children: [
15625
+ /* @__PURE__ */ jsxRuntime.jsx(
15626
+ "p",
15627
+ {
15628
+ className: cn("mb-[1rem] text-[0.875rem] text-icon4 mt-[.5rem] leading-[1.75]", {
15629
+ "bg-surface4 rounded-lg ": isLoading
15630
+ }),
15631
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: " " }) : description
15632
+ }
15633
+ ),
15634
+ !isLoading && templateSlug && /* @__PURE__ */ jsxRuntime.jsxs(
15635
+ "div",
15636
+ {
15637
+ className: cn(
15638
+ "bg-surface2 border border-surface4 rounded-lg p-[1rem] mb-[1rem]",
15639
+ "flex items-start gap-[0.75rem]"
15640
+ ),
15641
+ children: [
15642
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 mt-[0.125rem]", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.InfoIcon, { className: "w-[1.1em] h-[1.1em] text-blue-500" }) }),
15643
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 space-y-[0.5rem]", children: [
15644
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[0.5rem]", children: [
15645
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GitBranchIcon, { className: "w-[1em] h-[1em] text-icon4" }),
15646
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem] font-medium text-icon5", children: "A new Git branch will be created" })
15647
+ ] }),
15648
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-[0.8125rem] text-icon4 space-y-[0.25rem]", children: [
15649
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15650
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Branch name:" }),
15651
+ " ",
15652
+ /* @__PURE__ */ jsxRuntime.jsx("code", { className: "bg-surface3 px-[0.375rem] py-[0.125rem] rounded text-[0.75rem] font-mono", children: branchName })
15653
+ ] }),
15654
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: "This ensures safe installation with easy rollback if needed. Your main branch remains unchanged." })
15655
+ ] })
15656
+ ] })
15657
+ ]
15658
+ }
15659
+ ),
15660
+ githubUrl && /* @__PURE__ */ jsxRuntime.jsxs(
15661
+ "a",
15662
+ {
15663
+ href: githubUrl,
15664
+ target: "_blank",
15665
+ rel: "noopener noreferrer",
15666
+ className: "flex items-center gap-[.5rem] mt-auto text-icon3 text-[0.875rem] hover:text-icon5",
15667
+ children: [
15668
+ /* @__PURE__ */ jsxRuntime.jsx(GithubIcon, {}),
15669
+ githubUrl?.split("/")?.pop()
15670
+ ]
15671
+ }
15672
+ )
15673
+ ] }),
15674
+ infoData && /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: infoData, LinkComponent: lucideReact.Link, labelsAreHidden: true, isLoading })
15675
+ ] })
15676
+ ] });
15677
+ }
15678
+
15679
+ function TemplateForm({
15680
+ providerOptions,
15681
+ selectedProvider,
15682
+ onProviderChange,
15683
+ variables,
15684
+ errors,
15685
+ handleInstallTemplate,
15686
+ handleVariableChange,
15687
+ isLoadingEnvVars,
15688
+ defaultModelProvider,
15689
+ defaultModelId,
15690
+ onModelUpdate
15691
+ }) {
15692
+ return /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-[40rem] my-[1rem] p-[1rem] lg:p-[2rem] mx-auto gap-[2rem] grid", children: [
15693
+ /* @__PURE__ */ jsxRuntime.jsxs(
15694
+ "h2",
15695
+ {
15696
+ className: cn(
15697
+ "text-icon5 text-[1.125rem] font-semibold flex items-center gap-[0.5rem]",
15698
+ "[&>svg]:w-[1.2em] [&_svg]:h-[1.2em] [&_svg]:opacity-70 "
15699
+ ),
15700
+ children: [
15701
+ "Install Template ",
15702
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageOpenIcon, {})
15703
+ ]
15704
+ }
15705
+ ),
15706
+ /* @__PURE__ */ jsxRuntime.jsx(
15707
+ SelectField,
15708
+ {
15709
+ options: providerOptions,
15710
+ label: "Provider",
15711
+ onValueChange: onProviderChange,
15712
+ value: selectedProvider,
15713
+ placeholder: "Select a provider"
15714
+ }
15715
+ ),
15716
+ selectedProvider && Object.entries(variables || {}).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15717
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-[0.5rem]", children: [
15718
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem] font-medium", children: "Select AI Model for Template Installation *" }),
15719
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-icon4 text-[0.75rem]", children: "This model will be used by the workflow to process and install the template" }),
15720
+ /* @__PURE__ */ jsxRuntime.jsx(
15721
+ AgentMetadataModelSwitcher,
15722
+ {
15723
+ defaultProvider: defaultModelProvider || "",
15724
+ defaultModel: defaultModelId || "",
15725
+ updateModel: onModelUpdate || (() => Promise.resolve({ message: "Updated" })),
15726
+ closeEditor: () => {
15727
+ },
15728
+ modelProviders: ["openai", "anthropic", "google", "xai", "groq"]
15729
+ }
15730
+ ),
15731
+ (!defaultModelProvider || !defaultModelId) && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-red-500 text-[0.75rem]", children: "Please select an AI model to continue" })
15732
+ ] }),
15733
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-icon3 text-[0.875rem]", children: "Set required Environmental Variables" }),
15734
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[1fr_1fr] gap-[1rem] items-start", children: isLoadingEnvVars ? /* @__PURE__ */ jsxRuntime.jsxs(
15735
+ "div",
15736
+ {
15737
+ className: cn(
15738
+ "flex items-center justify-center col-span-2 text-icon3 text-[0.75rem] gap-[1rem]",
15739
+ "[&_svg]:opacity-50 [&_svg]:w-[1.1em] [&_svg]:h-[1.1em]",
15740
+ "animate-in fade-in duration-300"
15741
+ ),
15742
+ children: [
15743
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
15744
+ " Loading variables..."
15745
+ ]
15746
+ }
15747
+ ) : Object.entries(variables).map(([key, value]) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
15748
+ /* @__PURE__ */ jsxRuntime.jsx(
15749
+ InputField,
15750
+ {
15751
+ name: `env-${key}`,
15752
+ labelIsHidden: true,
15753
+ label: "Key",
15754
+ value: key,
15755
+ disabled: true,
15756
+ className: "w-full"
15757
+ }
15758
+ ),
15759
+ /* @__PURE__ */ jsxRuntime.jsx(
15760
+ InputField,
15761
+ {
15762
+ name: key,
15763
+ labelIsHidden: true,
15764
+ label: "Value",
15765
+ value,
15766
+ onChange: handleVariableChange,
15767
+ errorMsg: errors.includes(key) ? `Value is required.` : "",
15768
+ autoComplete: "off",
15769
+ className: "w-full"
15770
+ }
15771
+ )
15772
+ ] }, key)) })
15773
+ ] }),
15774
+ selectedProvider && !isLoadingEnvVars && /* @__PURE__ */ jsxRuntime.jsxs(
15775
+ "button",
15776
+ {
15777
+ className: cn(
15778
+ "flex items-center gap-[0.5rem] justify-center text-[0.875rem] w-full bg-surface5 min-h-[2.5rem] rounded-lg text-icon5 hover:bg-surface6 transition-colors",
15779
+ "[&>svg]:w-[1.1em] [&_svg]:h-[1.1em] [&_svg]:text-icon5"
15780
+ ),
15781
+ onClick: handleInstallTemplate,
15782
+ disabled: !selectedProvider || !defaultModelProvider || !defaultModelId || errors.length > 0,
15783
+ children: [
15784
+ "Install ",
15785
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightIcon, {})
15786
+ ]
15787
+ }
15788
+ )
15789
+ ] }) });
15790
+ }
15791
+
15792
+ function getStatusIcon(status) {
15793
+ switch (status) {
15794
+ case "running":
15795
+ return /* @__PURE__ */ jsxRuntime.jsx(Spinner, {});
15796
+ case "success":
15797
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {});
15798
+ case "failed":
15799
+ return /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {});
15800
+ default:
15801
+ return null;
15802
+ }
15803
+ }
15804
+
15805
+ function ProcessStepListItem({ stepId, step, isActive, position }) {
15806
+ const formatStepTitle = (stepId2) => {
15807
+ return stepId2.charAt(0).toUpperCase() + stepId2.slice(1).replace(/-/g, " ");
15808
+ };
15809
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15810
+ "div",
15811
+ {
15812
+ className: cn("grid gap-[1.5rem] grid-cols-[1fr_auto] py-[.75rem] px-[1rem] rounded-lg", {
15813
+ "border border-dashed border-gray-500": isActive
15814
+ }),
15815
+ children: [
15816
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[auto_1fr] gap-[.5rem]", children: [
15817
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-[0.875rem] text-icon5 min-w-[1.5rem] flex justify-end", children: [
15818
+ position,
15819
+ "."
15820
+ ] }),
15821
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15822
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-[0.875rem] text-icon5", children: formatStepTitle(stepId) }),
15823
+ step.description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] -mt-[0.125rem]", children: step.description })
15824
+ ] })
15825
+ ] }),
15826
+ /* @__PURE__ */ jsxRuntime.jsx(
15827
+ "div",
15828
+ {
15829
+ className: cn("w-[1.75rem] h-[1.75rem] rounded-full flex items-center justify-center self-center", {
15830
+ "border border-gray-500 border-dashed": step.status === "pending",
15831
+ "[&>svg]:text-white [&>svg]:w-[1rem] [&>svg]:h-[1rem]": step.status !== "running",
15832
+ "w-[1.75rem] h-[1.75rem]": step.status === "running",
15833
+ "bg-green-900": step.status === "success",
15834
+ "bg-red-900": step.status === "failed"
15835
+ }),
15836
+ children: getStatusIcon(step.status)
15837
+ }
15838
+ )
15839
+ ]
15840
+ }
15841
+ );
15842
+ }
15843
+
15844
+ function ProcessStepList({ currentStep, steps = [], className }) {
15845
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(className), children: steps.map((step, idx) => /* @__PURE__ */ jsxRuntime.jsx(
15846
+ ProcessStepListItem,
15847
+ {
15848
+ stepId: step.id,
15849
+ step,
15850
+ isActive: currentStep?.id === step.id,
15851
+ position: idx + 1
15852
+ },
15853
+ step.id
15854
+ )) });
15855
+ }
15856
+
15857
+ function ProcessStepProgressBar({ steps }) {
15858
+ const totalSteps = steps.length;
15859
+ const completedSteps = steps.filter((step) => step.status === "success").length;
15860
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-center flex-col gap-[1rem] content-center w-full", children: [
15861
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[0_repeat(9,1fr)] w-full", children: steps.map((step, idx) => {
15862
+ return /* @__PURE__ */ jsxRuntime.jsx(
15863
+ "div",
15864
+ {
15865
+ className: cn("flex justify-end items-center relative h-[2rem] ", {
15866
+ "bg-green-900": step.status === "success" && steps?.[idx - 1]?.status === "success"
15867
+ }),
15868
+ children: /* @__PURE__ */ jsxRuntime.jsx(
15869
+ "div",
15870
+ {
15871
+ className: cn(
15872
+ "w-[2rem] h-[2rem] rounded-full flex items-center justify-center self-center absolute right-0 translate-x-[50%] bg-surface3 z-10 text-icon3 font-bold text-[0.75rem]",
15873
+ {
15874
+ "border border-gray-500 border-dashed": step.status === "pending",
15875
+ "[&>svg]:text-surface4 [&>svg]:w-[1.1rem] [&>svg]:h-[1.1rem]": step.status !== "running",
15876
+ "bg-green-900 text-white": step.status === "success",
15877
+ "bg-red-900 text-white": step.status === "failed"
15878
+ }
15879
+ ),
15880
+ children: step.status === "running" ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) : idx + 1
15881
+ }
15882
+ )
15883
+ },
15884
+ step.id
15885
+ );
15886
+ }) }),
15887
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-icon3 text-center", children: [
15888
+ completedSteps,
15889
+ " of ",
15890
+ totalSteps,
15891
+ " steps completed"
15892
+ ] })
15893
+ ] });
15894
+ }
15895
+
15896
+ function TemplateInstallation({ name, streamResult, runId, workflowInfo }) {
15897
+ const phase = streamResult?.phase || "initializing";
15898
+ const workflowState = streamResult?.payload?.workflowState;
15899
+ const currentStep = streamResult?.payload?.currentStep;
15900
+ const error = streamResult?.error;
15901
+ const workflowSteps = workflowState?.steps || {};
15902
+ const hasSteps = Object.keys(workflowSteps).length > 0;
15903
+ const isUserVisibleStep = (stepId) => {
15904
+ if (stepId === "input" || stepId.endsWith(".input")) return false;
15905
+ if (stepId.startsWith("Mapping_") && /[0-9a-f]{8}/.test(stepId)) return false;
15906
+ if (/[0-9a-f]{8,}/.test(stepId)) return false;
15907
+ if (workflowInfo?.allSteps) {
15908
+ return stepId in workflowInfo.allSteps;
15909
+ }
15910
+ return true;
15911
+ };
15912
+ const visibleSteps = Object.entries(workflowSteps).filter(([stepId, _]) => isUserVisibleStep(stepId));
15913
+ const totalSteps = visibleSteps.length;
15914
+ const getPhaseMessage = () => {
15915
+ switch (phase) {
15916
+ case "initializing":
15917
+ return "Preparing template installation...";
15918
+ case "processing":
15919
+ return `Installing ${name} template`;
15920
+ case "completed":
15921
+ return "Template installation completed!";
15922
+ case "error":
15923
+ return "Template installation failed";
15924
+ default:
15925
+ return "Installing template...";
15926
+ }
15927
+ };
15928
+ const steps = visibleSteps.map(([stepId, stepData]) => ({
15929
+ id: stepId,
15930
+ status: stepData?.status,
15931
+ description: stepData?.description,
15932
+ title: stepId.charAt(0).toUpperCase() + stepId.slice(1).replace(/-/g, " "),
15933
+ isActive: currentStep?.id === stepId
15934
+ }));
15935
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-6 text-icon3 mb-[2rem] content-center", children: [
15936
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
15937
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-icon5", children: getPhaseMessage() }),
15938
+ streamResult?.runId && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-[0.5rem] text-[0.75rem] text-icon3", children: [
15939
+ "Run ID: ",
15940
+ streamResult.runId
15941
+ ] })
15942
+ ] }),
15943
+ hasSteps && totalSteps > 0 && !["error"].includes(phase) && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[30rem] w-full mx-auto px-[1.5rem]", children: /* @__PURE__ */ jsxRuntime.jsx(ProcessStepProgressBar, { steps }) }),
15944
+ error && phase === "error" && /* @__PURE__ */ jsxRuntime.jsxs(
15945
+ "div",
15946
+ {
15947
+ className: cn(
15948
+ "rounded-lg text-icon5 p-[1.5rem] flex items-center gap-[.75rem] text-[0.875rem] bg-red-500/10",
15949
+ "[&>svg]:w-[1.5rem] [&>svg]:h-[1.5rem] [&>svg]:opacity-70 [&>svg]:text-red-500"
15950
+ ),
15951
+ children: [
15952
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.OctagonXIcon, {}),
15953
+ error || "Something went wrong"
15954
+ ]
15955
+ }
15956
+ ),
15957
+ hasSteps && /* @__PURE__ */ jsxRuntime.jsx(ProcessStepList, { steps, currentStep, className: "pb-[1rem]" }),
15958
+ !hasSteps && phase === "initializing" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-sm text-icon3 grid gap-[1rem] justify-items-center", children: [
15959
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
15960
+ /* @__PURE__ */ jsxRuntime.jsx("p", { children: "This may take some time..." })
15961
+ ] })
15962
+ ] });
15963
+ }
15964
+
15965
+ function TemplateSuccess({ name, installedEntities, linkComponent }) {
15966
+ const LinkComponent = linkComponent || "a";
15967
+ return /* @__PURE__ */ jsxRuntime.jsxs(
15968
+ Container,
15969
+ {
15970
+ className: cn(
15971
+ "grid items-center justify-items-center gap-[1rem] content-center",
15972
+ "[&>svg]:w-[2rem] [&>svg]:h-[2rem]"
15973
+ ),
15974
+ children: [
15975
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PackageOpenIcon, {}),
15976
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[1.25rem ]", children: "Done!" }),
15977
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-[0.875rem] text-center text-icon3 ", children: [
15978
+ "The ",
15979
+ /* @__PURE__ */ jsxRuntime.jsx("b", { className: "text-icon4", children: name }),
15980
+ " template has been successfully installed.",
15981
+ installedEntities && installedEntities.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15982
+ /* @__PURE__ */ jsxRuntime.jsx("br", {}),
15983
+ " Installed entities are listed below."
15984
+ ] })
15985
+ ] }),
15986
+ installedEntities && installedEntities.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: installedEntities, LinkComponent })
15987
+ ]
15988
+ }
15989
+ );
15990
+ }
15991
+
15992
+ function TemplateFailure({ errorMsg, validationErrors }) {
15993
+ const isSchemaError = errorMsg?.includes("Invalid schema for function");
15994
+ const isValidationError = errorMsg?.includes("validation issue") || validationErrors && validationErrors.length > 0;
15995
+ const getUserFriendlyMessage = () => {
15996
+ if (isValidationError) {
15997
+ return "Template installation completed but some validation issues remain. The template may still be functional, but you should review and fix these issues.";
15998
+ }
15999
+ if (isSchemaError) {
16000
+ return "There was an issue with the AI model configuration. This may be related to the selected model or AI SDK version compatibility.";
16001
+ }
16002
+ return "An unexpected error occurred during template installation.";
16003
+ };
16004
+ const getIconAndTitle = () => {
16005
+ if (isValidationError) {
16006
+ return {
16007
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangleIcon, { className: "text-yellow-500" }),
16008
+ title: "Template Installed with Warnings"
16009
+ };
16010
+ }
16011
+ return {
16012
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FrownIcon, {}),
16013
+ title: "Template Installation Failed"
16014
+ };
16015
+ };
16016
+ const { icon, title } = getIconAndTitle();
16017
+ return /* @__PURE__ */ jsxRuntime.jsxs(Container, { className: "space-y-4 text-icon3 mb-[2rem] content-center max-w-2xl mx-auto", children: [
16018
+ /* @__PURE__ */ jsxRuntime.jsxs(
16019
+ "div",
16020
+ {
16021
+ className: cn(
16022
+ "grid items-center justify-items-center gap-[1rem] content-center",
16023
+ "[&>svg]:w-[2rem] [&>svg]:h-[2rem]"
16024
+ ),
16025
+ children: [
16026
+ icon,
16027
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center space-y-2", children: [
16028
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] font-medium text-icon5", children: title }),
16029
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[0.875rem] text-icon3", children: getUserFriendlyMessage() })
16030
+ ] })
16031
+ ]
16032
+ }
16033
+ ),
16034
+ validationErrors && validationErrors.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "text-xs", children: [
16035
+ /* @__PURE__ */ jsxRuntime.jsxs("summary", { className: "cursor-pointer text-icon3 hover:text-icon4 select-none text-center", children: [
16036
+ "Show Validation Issues (",
16037
+ validationErrors.length,
16038
+ ")"
16039
+ ] }),
16040
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs overflow-auto max-h-60 text-left space-y-2", children: validationErrors.map((error, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-l-2 border-red-400 pl-2", children: [
16041
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-red-600 dark:text-red-400", children: error.type === "typescript" ? "🔴 TypeScript Error" : "⚠️ Lint Error" }),
16042
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-mono text-gray-700 dark:text-gray-300 mt-1 whitespace-pre-wrap break-words", children: error.message })
16043
+ ] }, index)) })
16044
+ ] }),
16045
+ errorMsg && !isValidationError && /* @__PURE__ */ jsxRuntime.jsxs("details", { className: "text-xs", children: [
16046
+ /* @__PURE__ */ jsxRuntime.jsx("summary", { className: "cursor-pointer text-icon3 hover:text-icon4 select-none text-center", children: "Show Details" }),
16047
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-4 p-3 bg-gray-100 dark:bg-gray-800 rounded text-xs font-mono overflow-auto max-h-60 text-left", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words", children: errorMsg }) })
16048
+ ] })
16049
+ ] });
16050
+ }
16051
+
16052
+ const TraceContext = React.createContext({});
16053
+ function TraceProvider({
16054
+ children,
16055
+ initialTraces: traces = []
16056
+ }) {
16057
+ const [open, setOpen] = React.useState(false);
16058
+ const [trace, setTrace] = React.useState(null);
16059
+ const [currentTraceIndex, setCurrentTraceIndex] = React.useState(0);
16060
+ const [span, setSpan] = React.useState(null);
16061
+ const nextTrace = () => {
16062
+ if (currentTraceIndex < traces.length - 1) {
16063
+ const nextIndex = currentTraceIndex + 1;
16064
+ setCurrentTraceIndex(nextIndex);
16065
+ const nextTrace2 = traces[nextIndex].trace;
16066
+ setTrace(nextTrace2);
16067
+ const parentSpan = nextTrace2.find((span2) => span2.parentSpanId === null) || nextTrace2[0];
16068
+ setSpan(parentSpan);
16069
+ }
16070
+ };
16071
+ const prevTrace = () => {
16072
+ if (currentTraceIndex > 0) {
16073
+ const prevIndex = currentTraceIndex - 1;
16074
+ setCurrentTraceIndex(prevIndex);
16075
+ const prevTrace2 = traces[prevIndex].trace;
16076
+ setTrace(prevTrace2);
16077
+ const parentSpan = prevTrace2.find((span2) => span2.parentSpanId === null) || prevTrace2[0];
16078
+ setSpan(parentSpan);
16079
+ }
16080
+ };
16081
+ const clearData = () => {
16082
+ setOpen(false);
16083
+ setTrace(null);
16084
+ setSpan(null);
16085
+ };
16086
+ return /* @__PURE__ */ jsxRuntime.jsx(
16087
+ TraceContext.Provider,
16088
+ {
16089
+ value: {
16090
+ isOpen: open,
16091
+ setIsOpen: setOpen,
16092
+ trace,
16093
+ setTrace,
16094
+ traces,
16095
+ currentTraceIndex,
16096
+ setCurrentTraceIndex,
16097
+ nextTrace,
16098
+ prevTrace,
16099
+ span,
16100
+ setSpan,
16101
+ clearData
16102
+ },
16103
+ children
16104
+ }
16105
+ );
16106
+ }
16107
+
16108
+ const useOpenTrace = () => {
16109
+ const {
16110
+ setTrace,
16111
+ isOpen: open,
16112
+ setIsOpen: setOpen,
16113
+ trace: currentTrace,
16114
+ setSpan,
16115
+ setCurrentTraceIndex
16116
+ } = React.useContext(TraceContext);
16117
+ const openTrace = (trace, traceIndex) => {
16118
+ setTrace(trace);
16119
+ const parentSpan = trace.find((span) => span.parentSpanId === null) || trace[0];
16120
+ setSpan(parentSpan);
16121
+ setCurrentTraceIndex(traceIndex);
16122
+ if (open && currentTrace?.[0]?.id !== trace[0].id) return;
16123
+ setOpen((prev) => !prev);
16124
+ };
16125
+ return { openTrace };
16126
+ };
16127
+
16128
+ const TracesTableEmpty = ({ colsCount }) => {
16129
+ return /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: /* @__PURE__ */ jsxRuntime.jsx(Row, { children: /* @__PURE__ */ jsxRuntime.jsx(Cell, { colSpan: colsCount, className: "text-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { children: "No traces found" }) }) }) });
16130
+ };
16131
+ const TracesTableError = ({ error, colsCount }) => {
16132
+ return /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: /* @__PURE__ */ jsxRuntime.jsx(Row, { children: /* @__PURE__ */ jsxRuntime.jsx(Cell, { colSpan: colsCount, className: "text-center py-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { children: error.message }) }) }) });
16133
+ };
16134
+ const TraceRow = ({ trace, index, isActive }) => {
16135
+ const { openTrace } = useOpenTrace();
16136
+ const hasFailure = trace.trace.some((span) => span.status.code === 2);
16137
+ return /* @__PURE__ */ jsxRuntime.jsxs(Row, { className: isActive ? "bg-surface4" : "", onClick: () => openTrace(trace.trace, index), children: [
16138
+ /* @__PURE__ */ jsxRuntime.jsx(DateTimeCell, { dateTime: new Date(trace.started / 1e3) }),
16139
+ /* @__PURE__ */ jsxRuntime.jsxs(TxtCell, { title: trace.traceId, children: [
16140
+ trace.traceId.substring(0, 7),
16141
+ "..."
16142
+ ] }),
16143
+ /* @__PURE__ */ jsxRuntime.jsx(UnitCell, { unit: "ms", children: toSigFigs(trace.duration / 1e3, 3) }),
16144
+ /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => openTrace(trace.trace, index), children: /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(TraceIcon, {}), children: trace.trace.length }) }) }),
16145
+ /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: hasFailure ? /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: "Failed" }) : /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, {}), variant: "success", children: "Success" }) })
16146
+ ] });
16147
+ };
16148
+ const TracesTable = ({ traces, error }) => {
16149
+ const hasNoTraces = !traces || traces.length === 0;
16150
+ const { currentTraceIndex } = React.useContext(TraceContext);
16151
+ const colsCount = 4;
16152
+ return /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { size: "small", children: [
16153
+ /* @__PURE__ */ jsxRuntime.jsxs(Thead, { children: [
16154
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Time" }),
16155
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { width: "auto", children: "Trace Id" }),
16156
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Duration" }),
16157
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Spans" }),
16158
+ /* @__PURE__ */ jsxRuntime.jsx(Th, { width: 120, children: "Status" })
16159
+ ] }),
16160
+ error ? /* @__PURE__ */ jsxRuntime.jsx(TracesTableError, { error, colsCount }) : hasNoTraces ? /* @__PURE__ */ jsxRuntime.jsx(TracesTableEmpty, { colsCount }) : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: traces.map((trace, index) => /* @__PURE__ */ jsxRuntime.jsx(
16161
+ TraceRow,
16162
+ {
16163
+ trace,
16164
+ index,
16165
+ isActive: index === currentTraceIndex
16166
+ },
16167
+ trace.traceId + index
16168
+ )) }) })
16169
+ ] });
16170
+ };
16171
+
15283
16172
  const useResizeColumn = ({
15284
16173
  defaultWidth,
15285
16174
  minimumWidth,
@@ -15367,518 +16256,1362 @@ const TraceTree = ({ children }) => {
15367
16256
  return /* @__PURE__ */ jsxRuntime.jsx("ol", { children });
15368
16257
  };
15369
16258
 
15370
- const variantClasses = {
15371
- agent: "bg-accent1"
16259
+ const variantClasses = {
16260
+ agent: "bg-accent1"
16261
+ };
16262
+ const Time = ({ durationMs, tokenCount, variant, progressPercent, offsetPercent }) => {
16263
+ const variantClass = variant ? variantClasses[variant] : "bg-accent3";
16264
+ const percent = Math.min(100, progressPercent);
16265
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[80px] xl:w-[166px] shrink-0", children: [
16266
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 relative h-[6px] w-full rounded-full p-px overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
16267
+ "div",
16268
+ {
16269
+ className: clsx("absolute h-1 rounded-full", variantClass),
16270
+ style: { width: `${percent}%`, left: `${offsetPercent}%` }
16271
+ }
16272
+ ) }),
16273
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 pt-0.5", children: [
16274
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-sm", className: "text-icon2 font-medium", children: [
16275
+ toSigFigs(durationMs, 3),
16276
+ "ms"
16277
+ ] }),
16278
+ tokenCount && /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-sm", className: "text-icon2 font-medium", children: [
16279
+ tokenCount,
16280
+ "t"
16281
+ ] })
16282
+ ] })
16283
+ ] });
16284
+ };
16285
+
16286
+ const spanIconMap = {
16287
+ tool: ToolsIcon,
16288
+ agent: AgentIcon,
16289
+ workflow: WorkflowIcon,
16290
+ memory: MemoryIcon,
16291
+ rag: TraceIcon,
16292
+ storage: DbIcon,
16293
+ eval: ScoreIcon,
16294
+ other: TraceIcon
16295
+ };
16296
+ const spanVariantClasses = {
16297
+ tool: "text-[#ECB047]",
16298
+ agent: "text-accent1",
16299
+ workflow: "text-accent3",
16300
+ memory: "text-accent2",
16301
+ rag: "text-accent2",
16302
+ storage: "text-accent2",
16303
+ eval: "text-accent4",
16304
+ other: "text-icon6"
16305
+ };
16306
+ const Span = ({
16307
+ children,
16308
+ durationMs,
16309
+ variant,
16310
+ tokenCount,
16311
+ spans,
16312
+ isRoot,
16313
+ onClick,
16314
+ isActive,
16315
+ offsetMs,
16316
+ totalDurationMs
16317
+ }) => {
16318
+ const [isExpanded, setIsExpanded] = React.useState(true);
16319
+ const VariantIcon = spanIconMap[variant];
16320
+ const variantClass = spanVariantClasses[variant];
16321
+ const progressPercent = durationMs / totalDurationMs * 100;
16322
+ const offsetPercent = offsetMs / totalDurationMs * 100;
16323
+ const TextEl = onClick ? "button" : "div";
16324
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
16325
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("flex justify-between items-center gap-2 rounded-md pl-2", isActive && "bg-surface4"), children: [
16326
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-1 min-w-0", children: [
16327
+ spans ? /* @__PURE__ */ jsxRuntime.jsx(
16328
+ "button",
16329
+ {
16330
+ type: "button",
16331
+ "aria-label": isExpanded ? "Collapse span" : "Expand span",
16332
+ "aria-expanded": isExpanded,
16333
+ className: "text-icon3 flex h-4 w-4",
16334
+ onClick: () => setIsExpanded(!isExpanded),
16335
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { className: clsx("transition-transform -rotate-90", { "rotate-0": isExpanded }) }) })
16336
+ }
16337
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "h-full w-4", children: !isRoot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-[7px] h-full w-px rounded-full" }) }),
16338
+ /* @__PURE__ */ jsxRuntime.jsxs(TextEl, { className: "flex items-center gap-2 min-w-0", onClick, children: [
16339
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("bg-surface4 flex items-center justify-center rounded-md p-[3px]", variantClass), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(VariantIcon, {}) }) }),
16340
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-md", className: "text-icon6 truncate", children })
16341
+ ] })
16342
+ ] }),
16343
+ /* @__PURE__ */ jsxRuntime.jsx(
16344
+ Time,
16345
+ {
16346
+ durationMs,
16347
+ tokenCount,
16348
+ variant: variant === "agent" ? "agent" : void 0,
16349
+ progressPercent,
16350
+ offsetPercent
16351
+ }
16352
+ )
16353
+ ] }),
16354
+ isExpanded && spans && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4", children: spans })
16355
+ ] });
16356
+ };
16357
+
16358
+ const Spans = ({ children }) => {
16359
+ return /* @__PURE__ */ jsxRuntime.jsx("ol", { children });
16360
+ };
16361
+
16362
+ const Trace = ({
16363
+ name,
16364
+ spans,
16365
+ durationMs,
16366
+ tokenCount,
16367
+ onClick,
16368
+ variant,
16369
+ isActive,
16370
+ totalDurationMs
16371
+ }) => {
16372
+ return /* @__PURE__ */ jsxRuntime.jsx(
16373
+ Span,
16374
+ {
16375
+ isRoot: true,
16376
+ durationMs,
16377
+ variant,
16378
+ spans: /* @__PURE__ */ jsxRuntime.jsx(Spans, { children: spans }),
16379
+ onClick,
16380
+ isActive,
16381
+ offsetMs: 0,
16382
+ totalDurationMs,
16383
+ children: name
16384
+ }
16385
+ );
16386
+ };
16387
+
16388
+ const getSpanVariant = (span) => {
16389
+ const attributes = Object.keys(span.attributes || {}).map((k) => k.toLowerCase());
16390
+ const lowerCaseName = span.name.toLowerCase();
16391
+ const isAiSpan = lowerCaseName.startsWith("ai.");
16392
+ if (isAiSpan) {
16393
+ const isAiAboutTool = lowerCaseName.includes("tool");
16394
+ if (isAiAboutTool) return "tool";
16395
+ return "other";
16396
+ }
16397
+ const hasMemoryRelatedAttributes = attributes.some((key) => key.includes("memory") || key.includes("storage"));
16398
+ if (hasMemoryRelatedAttributes) return "memory";
16399
+ const hasToolRelatedAttributes = attributes.some((key) => key.includes("tool"));
16400
+ if (hasToolRelatedAttributes) return "tool";
16401
+ const hasAgentRelatedAttributes = attributes.some((key) => key.includes("agent."));
16402
+ if (hasAgentRelatedAttributes) return "agent";
16403
+ if (lowerCaseName.includes(".insert")) {
16404
+ const evalRelatedAttribute = attributes.find((key) => String(span.attributes?.[key])?.includes("mastra_evals"));
16405
+ if (evalRelatedAttribute) return "eval";
16406
+ }
16407
+ return "other";
16408
+ };
16409
+
16410
+ function buildTree(spans, minStartTime, totalDurationMs, parentSpanId = null) {
16411
+ return spans.filter((span) => span.parentSpanId === parentSpanId).map((span) => {
16412
+ return {
16413
+ ...span,
16414
+ children: buildTree(spans, minStartTime, totalDurationMs, span.id),
16415
+ offset: (span.startTime - minStartTime) / 1e3,
16416
+ // ns to ms
16417
+ duration: span.duration / 1e3,
16418
+ totalDurationMs
16419
+ };
16420
+ });
16421
+ }
16422
+ const createSpanTree = (spans) => {
16423
+ if (spans.length === 0) return [];
16424
+ let minStartTime;
16425
+ let maxEndTime;
16426
+ const orderedTree = [];
16427
+ const listSize = spans.length;
16428
+ for (let i = listSize - 1; i >= 0; i--) {
16429
+ const span = spans[i];
16430
+ if (!minStartTime || span.startTime < minStartTime) {
16431
+ minStartTime = span.startTime;
16432
+ }
16433
+ if (!maxEndTime || span.endTime > maxEndTime) {
16434
+ maxEndTime = span.endTime;
16435
+ }
16436
+ if (span.name !== ".insert" && span.name !== "mastra.getStorage") {
16437
+ orderedTree.push(span);
16438
+ }
16439
+ }
16440
+ if (!minStartTime || !maxEndTime) return [];
16441
+ const totalDurationMs = (maxEndTime - minStartTime) / 1e3;
16442
+ return buildTree(orderedTree, minStartTime, totalDurationMs);
16443
+ };
16444
+
16445
+ const NestedSpans = ({ spanNodes }) => {
16446
+ const { span: activeSpan, setSpan } = React.useContext(TraceContext);
16447
+ return /* @__PURE__ */ jsxRuntime.jsx(Spans, { children: spanNodes.map((spanNode) => {
16448
+ const isActive = spanNode.id === activeSpan?.id;
16449
+ return /* @__PURE__ */ jsxRuntime.jsx(
16450
+ Span,
16451
+ {
16452
+ spans: spanNode.children.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(NestedSpans, { spanNodes: spanNode.children }),
16453
+ durationMs: spanNode.duration,
16454
+ offsetMs: spanNode.offset,
16455
+ variant: getSpanVariant(spanNode),
16456
+ isActive,
16457
+ onClick: () => setSpan(spanNode),
16458
+ totalDurationMs: spanNode.totalDurationMs,
16459
+ children: spanNode.name
16460
+ },
16461
+ spanNode.id
16462
+ );
16463
+ }) });
16464
+ };
16465
+ function SpanView({ trace }) {
16466
+ const { span: activeSpan, setSpan } = React.useContext(TraceContext);
16467
+ const tree = createSpanTree(trace);
16468
+ return /* @__PURE__ */ jsxRuntime.jsx(TraceTree, { children: tree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
16469
+ Trace,
16470
+ {
16471
+ name: node.name,
16472
+ durationMs: node.duration,
16473
+ totalDurationMs: node.totalDurationMs,
16474
+ spans: /* @__PURE__ */ jsxRuntime.jsx(NestedSpans, { spanNodes: node.children }),
16475
+ variant: getSpanVariant(node),
16476
+ isActive: node.id === activeSpan?.id,
16477
+ onClick: () => setSpan(node)
16478
+ }
16479
+ )) });
16480
+ }
16481
+
16482
+ const Header = ({ children, border = true }) => {
16483
+ return /* @__PURE__ */ jsxRuntime.jsx(
16484
+ "header",
16485
+ {
16486
+ className: clsx("h-header-default z-50 flex w-full items-center gap-[18px] bg-transparent px-5", {
16487
+ "border-b-sm border-border1": border
16488
+ }),
16489
+ children
16490
+ }
16491
+ );
15372
16492
  };
15373
- const Time = ({ durationMs, tokenCount, variant, progressPercent, offsetPercent }) => {
15374
- const variantClass = variant ? variantClasses[variant] : "bg-accent3";
15375
- const percent = Math.min(100, progressPercent);
15376
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-[80px] xl:w-[166px] shrink-0", children: [
15377
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 relative h-[6px] w-full rounded-full p-px overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
15378
- "div",
15379
- {
15380
- className: clsx("absolute h-1 rounded-full", variantClass),
15381
- style: { width: `${percent}%`, left: `${offsetPercent}%` }
15382
- }
15383
- ) }),
15384
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4 pt-0.5", children: [
15385
- /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-sm", className: "text-icon2 font-medium", children: [
15386
- toSigFigs(durationMs, 3),
15387
- "ms"
15388
- ] }),
15389
- tokenCount && /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-sm", className: "text-icon2 font-medium", children: [
15390
- tokenCount,
15391
- "t"
15392
- ] })
15393
- ] })
15394
- ] });
16493
+ const HeaderTitle = ({ children }) => {
16494
+ return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h1", variant: "ui-lg", className: "font-medium text-white", children });
15395
16495
  };
15396
-
15397
- const spanIconMap = {
15398
- tool: ToolsIcon,
15399
- agent: AgentIcon,
15400
- workflow: WorkflowIcon,
15401
- memory: MemoryIcon,
15402
- rag: TraceIcon,
15403
- storage: DbIcon,
15404
- eval: ScoreIcon,
15405
- other: TraceIcon
16496
+ const HeaderAction = ({ children }) => {
16497
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto", children });
15406
16498
  };
15407
- const spanVariantClasses = {
15408
- tool: "text-[#ECB047]",
15409
- agent: "text-accent1",
15410
- workflow: "text-accent3",
15411
- memory: "text-accent2",
15412
- rag: "text-accent2",
15413
- storage: "text-accent2",
15414
- eval: "text-accent4",
15415
- other: "text-icon6"
16499
+ const HeaderGroup = ({ children }) => {
16500
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-lg flex items-center", children });
15416
16501
  };
15417
- const Span = ({
15418
- children,
15419
- durationMs,
15420
- variant,
15421
- tokenCount,
15422
- spans,
15423
- isRoot,
15424
- onClick,
15425
- isActive,
15426
- offsetMs,
15427
- totalDurationMs
15428
- }) => {
15429
- const [isExpanded, setIsExpanded] = React.useState(true);
15430
- const VariantIcon = spanIconMap[variant];
15431
- const variantClass = spanVariantClasses[variant];
15432
- const progressPercent = durationMs / totalDurationMs * 100;
15433
- const offsetPercent = offsetMs / totalDurationMs * 100;
15434
- const TextEl = onClick ? "button" : "div";
15435
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15436
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("flex justify-between items-center gap-2 rounded-md pl-2", isActive && "bg-surface4"), children: [
15437
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-8 items-center gap-1 min-w-0", children: [
15438
- spans ? /* @__PURE__ */ jsxRuntime.jsx(
15439
- "button",
16502
+
16503
+ function TraceDetails() {
16504
+ const { trace, currentTraceIndex, prevTrace, nextTrace, traces } = React.useContext(TraceContext);
16505
+ const actualTrace = traces[currentTraceIndex];
16506
+ if (!actualTrace || !trace) return null;
16507
+ const hasFailure = trace.some((span) => span.status.code === 2);
16508
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { children: [
16509
+ /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
16510
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
16511
+ /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: prevTrace, disabled: currentTraceIndex === 0, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}) }) }),
16512
+ /* @__PURE__ */ jsxRuntime.jsx(
16513
+ Button$1,
15440
16514
  {
15441
- type: "button",
15442
- "aria-label": isExpanded ? "Collapse span" : "Expand span",
15443
- "aria-expanded": isExpanded,
15444
- className: "text-icon3 flex h-4 w-4",
15445
- onClick: () => setIsExpanded(!isExpanded),
15446
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { className: clsx("transition-transform -rotate-90", { "rotate-0": isExpanded }) }) })
16515
+ className: "bg-transparent border-none",
16516
+ onClick: nextTrace,
16517
+ disabled: currentTraceIndex === traces.length - 1,
16518
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) })
15447
16519
  }
15448
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, className: "h-full w-4", children: !isRoot && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-[7px] h-full w-px rounded-full" }) }),
15449
- /* @__PURE__ */ jsxRuntime.jsxs(TextEl, { className: "flex items-center gap-2 min-w-0", onClick, children: [
15450
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: clsx("bg-surface4 flex items-center justify-center rounded-md p-[3px]", variantClass), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(VariantIcon, {}) }) }),
15451
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-md", className: "text-icon6 truncate", children })
15452
- ] })
16520
+ )
15453
16521
  ] }),
15454
- /* @__PURE__ */ jsxRuntime.jsx(
15455
- Time,
15456
- {
15457
- durationMs,
15458
- tokenCount,
15459
- variant: variant === "agent" ? "agent" : void 0,
15460
- progressPercent,
15461
- offsetPercent
15462
- }
15463
- )
16522
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 justify-between w-full", children: [
16523
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "font-medium text-icon5 shrink-0", children: [
16524
+ "Trace ",
16525
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-icon3", children: actualTrace.traceId.substring(0, 7) })
16526
+ ] }),
16527
+ hasFailure && /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: "Failed" })
16528
+ ] })
15464
16529
  ] }),
15465
- isExpanded && spans && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-4", children: spans })
16530
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-5", children: /* @__PURE__ */ jsxRuntime.jsx(SpanView, { trace }) })
16531
+ ] });
16532
+ }
16533
+
16534
+ function formatDuration(duration, fixedPoint = 2) {
16535
+ const durationInSecs = duration / 1e3;
16536
+ return durationInSecs.toFixed(fixedPoint);
16537
+ }
16538
+ function formatOtelTimestamp(otelTimestamp) {
16539
+ const date = new Date(otelTimestamp / 1e3);
16540
+ return new Intl.DateTimeFormat("en-US", {
16541
+ month: "numeric",
16542
+ day: "numeric",
16543
+ year: "numeric",
16544
+ hour: "numeric",
16545
+ minute: "numeric",
16546
+ second: "numeric",
16547
+ hour12: true
16548
+ }).format(date);
16549
+ }
16550
+ function formatOtelTimestamp2(otelTimestamp) {
16551
+ const date = new Date(otelTimestamp / 1e6);
16552
+ return new Intl.DateTimeFormat("en-US", {
16553
+ month: "numeric",
16554
+ day: "numeric",
16555
+ year: "numeric",
16556
+ hour: "numeric",
16557
+ minute: "numeric",
16558
+ second: "numeric",
16559
+ hour12: true
16560
+ }).format(date);
16561
+ }
16562
+ function transformKey(key) {
16563
+ if (key.includes(".argument.")) {
16564
+ return `Input`;
16565
+ }
16566
+ if (key.includes(".result")) {
16567
+ return "Output";
16568
+ }
16569
+ const newKey = key.split(".").join(" ").split("_").join(" ").replaceAll("ai", "AI");
16570
+ return newKey.substring(0, 1).toUpperCase() + newKey.substring(1);
16571
+ }
16572
+ function cleanString(string) {
16573
+ return string.replace(/\\n/g, "").replace(/\n/g, "").replace(/\s+/g, " ").trim();
16574
+ }
16575
+ const allowedAiSpanAttributes = [
16576
+ "operation.name",
16577
+ "ai.operationId",
16578
+ "ai.model.provider",
16579
+ "ai.model.id",
16580
+ "ai.prompt.format",
16581
+ "ai.prompt.messages",
16582
+ "ai.prompt.tools",
16583
+ "ai.prompt.toolChoice",
16584
+ "ai.settings.toolChoice",
16585
+ "ai.schema",
16586
+ "ai.settings.output",
16587
+ "ai.response.object",
16588
+ "ai.response.text",
16589
+ "ai.response.timestamp",
16590
+ "componentName",
16591
+ "ai.usage.promptTokens",
16592
+ "ai.usage.completionTokens"
16593
+ ];
16594
+
16595
+ function SpanDetail() {
16596
+ const { span, setSpan, trace, setIsOpen } = React.useContext(TraceContext);
16597
+ if (!span || !trace) return null;
16598
+ const prevSpan = () => {
16599
+ const currentIndex = trace.findIndex((t) => t.id === span.id);
16600
+ if (currentIndex !== -1 && currentIndex < trace.length - 1) {
16601
+ setSpan(trace[currentIndex + 1]);
16602
+ }
16603
+ };
16604
+ const nextSpan = () => {
16605
+ const currentIndex = trace.findIndex((t) => t.id === span.id);
16606
+ if (currentIndex !== -1 && currentIndex > 0) {
16607
+ setSpan(trace[currentIndex - 1]);
16608
+ }
16609
+ };
16610
+ const SpanIcon = spanIconMap[getSpanVariant(span)];
16611
+ const variantClass = spanVariantClasses[getSpanVariant(span)];
16612
+ return /* @__PURE__ */ jsxRuntime.jsxs("aside", { children: [
16613
+ /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
16614
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
16615
+ /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: prevSpan, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}) }) }),
16616
+ /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: nextSpan, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) }) })
16617
+ ] }),
16618
+ /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "font-medium text-icon5", as: "h2", children: [
16619
+ "Span ",
16620
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-icon3", children: span.id.substring(0, 7) })
16621
+ ] }) }),
16622
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}) }) }) })
16623
+ ] }),
16624
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5", children: [
16625
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "header-md", as: "h3", className: "text-icon-6 flex items-center gap-4 pb-3", children: [
16626
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "lg", className: "bg-surface4 p-1 rounded-md", children: /* @__PURE__ */ jsxRuntime.jsx(SpanIcon, { className: variantClass }) }),
16627
+ span.name
16628
+ ] }),
16629
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row gap-2 items-center", children: span.status.code === 2 ? /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: [
16630
+ "Failed in ",
16631
+ toSigFigs(span.duration, 3),
16632
+ "ms"
16633
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(LatencyIcon, {}), variant: "success", children: [
16634
+ toSigFigs(span.duration, 3),
16635
+ "ms"
16636
+ ] }) }),
16637
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
16638
+ /* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-2 justify-between gap-2", children: [
16639
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "ID" }),
16640
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: span.id }),
16641
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Created at" }),
16642
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: span.startTime ? formatOtelTimestamp(span.startTime) : "" })
16643
+ ] }),
16644
+ span.attributes && /* @__PURE__ */ jsxRuntime.jsx(Attributes, { attributes: span.attributes }),
16645
+ span.events?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Events, { span })
16646
+ ] })
15466
16647
  ] });
16648
+ }
16649
+ function Attributes({ attributes }) {
16650
+ if (!attributes) return null;
16651
+ const entries = Object.entries(attributes);
16652
+ if (entries.length === 0) return null;
16653
+ const keysToHide = ["http.request_id", "componentName"];
16654
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: entries.filter(([key]) => !keysToHide.includes(key)).map(([key, val]) => {
16655
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
16656
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
16657
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h4", variant: "ui-md", className: "text-icon3 pb-2", children: transformKey(key) }),
16658
+ /* @__PURE__ */ jsxRuntime.jsx(AttributeValue, { value: val })
16659
+ ] }, key);
16660
+ }) });
16661
+ }
16662
+ const AttributeValue = ({ value }) => {
16663
+ if (!value)
16664
+ return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: "N/A" });
16665
+ if (typeof value === "number" || typeof value === "boolean") {
16666
+ return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: String(value) });
16667
+ }
16668
+ if (typeof value === "object") {
16669
+ return /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: value });
16670
+ }
16671
+ try {
16672
+ return /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: JSON.parse(value) });
16673
+ } catch {
16674
+ return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: String(value) });
16675
+ }
15467
16676
  };
16677
+ function Events({ span }) {
16678
+ if (!span.events) return null;
16679
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
16680
+ /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
16681
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6 pb-2", children: "Events" }),
16682
+ span.events.map((event) => {
16683
+ const isLast = event === span.events[span.events.length - 1];
16684
+ return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
16685
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
16686
+ /* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-2 justify-between gap-2 pb-2", children: [
16687
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Name" }),
16688
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: event.name }),
16689
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Time" }),
16690
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: event.timeUnixNano ? formatOtelTimestamp2(Number(event.timeUnixNano)) : "N/A" })
16691
+ ] }),
16692
+ event.attributes?.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-2", children: event.attributes.filter((attribute) => attribute !== null).map((attribute) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
16693
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h4", variant: "ui-md", className: "text-icon3 pb-2", children: transformKey(attribute.key) }),
16694
+ /* @__PURE__ */ jsxRuntime.jsx(AttributeValue, { value: attribute.value })
16695
+ ] }, attribute.key)) }) : null
16696
+ ] }, event.name),
16697
+ !isLast && /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" })
16698
+ ] }, event.name);
16699
+ })
16700
+ ] });
16701
+ }
15468
16702
 
15469
- const Spans = ({ children }) => {
15470
- return /* @__PURE__ */ jsxRuntime.jsx("ol", { children });
15471
- };
15472
-
15473
- const Trace = ({
15474
- name,
15475
- spans,
15476
- durationMs,
15477
- tokenCount,
15478
- onClick,
15479
- variant,
15480
- isActive,
15481
- totalDurationMs
15482
- }) => {
16703
+ const TracesSidebar = ({ onResize }) => {
15483
16704
  return /* @__PURE__ */ jsxRuntime.jsx(
15484
- Span,
16705
+ MastraResizablePanel,
15485
16706
  {
15486
- isRoot: true,
15487
- durationMs,
15488
- variant,
15489
- spans: /* @__PURE__ */ jsxRuntime.jsx(Spans, { children: spans }),
15490
- onClick,
15491
- isActive,
15492
- offsetMs: 0,
15493
- totalDurationMs,
15494
- children: name
16707
+ className: "h-full absolute right-0 inset-y-0 bg-surface2",
16708
+ defaultWidth: 80,
16709
+ minimumWidth: 50,
16710
+ maximumWidth: 80,
16711
+ setCurrentWidth: onResize,
16712
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full grid grid-cols-2", children: [
16713
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-scroll w-full h-[calc(100%-40px)]", children: /* @__PURE__ */ jsxRuntime.jsx(TraceDetails, {}) }),
16714
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[calc(100%-40px)] overflow-x-scroll w-full border-l border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(SpanDetail, {}) })
16715
+ ] })
15495
16716
  }
15496
16717
  );
15497
16718
  };
15498
16719
 
15499
- const getSpanVariant = (span) => {
15500
- const attributes = Object.keys(span.attributes || {}).map((k) => k.toLowerCase());
15501
- const lowerCaseName = span.name.toLowerCase();
15502
- const isAiSpan = lowerCaseName.startsWith("ai.");
15503
- if (isAiSpan) {
15504
- const isAiAboutTool = lowerCaseName.includes("tool");
15505
- if (isAiAboutTool) return "tool";
15506
- return "other";
15507
- }
15508
- const hasMemoryRelatedAttributes = attributes.some((key) => key.includes("memory") || key.includes("storage"));
15509
- if (hasMemoryRelatedAttributes) return "memory";
15510
- const hasToolRelatedAttributes = attributes.some((key) => key.includes("tool"));
15511
- if (hasToolRelatedAttributes) return "tool";
15512
- const hasAgentRelatedAttributes = attributes.some((key) => key.includes("agent."));
15513
- if (hasAgentRelatedAttributes) return "agent";
15514
- if (lowerCaseName.includes(".insert")) {
15515
- const evalRelatedAttribute = attributes.find((key) => String(span.attributes?.[key])?.includes("mastra_evals"));
15516
- if (evalRelatedAttribute) return "eval";
16720
+ function TracesView({
16721
+ isLoading,
16722
+ error,
16723
+ traces,
16724
+ runId,
16725
+ stepName,
16726
+ className,
16727
+ setEndOfListElement
16728
+ }) {
16729
+ if (isLoading) {
16730
+ return /* @__PURE__ */ jsxRuntime.jsx(TracesViewSkeleton, {});
15517
16731
  }
15518
- return "other";
16732
+ return /* @__PURE__ */ jsxRuntime.jsx(TraceProvider, { initialTraces: traces || [], children: /* @__PURE__ */ jsxRuntime.jsx(
16733
+ TracesViewInner,
16734
+ {
16735
+ traces,
16736
+ error,
16737
+ runId,
16738
+ stepName,
16739
+ className,
16740
+ setEndOfListElement
16741
+ }
16742
+ ) });
16743
+ }
16744
+ function TracesViewInner({ traces, error, runId, stepName, className, setEndOfListElement }) {
16745
+ const hasRunRef = React.useRef(false);
16746
+ const [sidebarWidth, setSidebarWidth] = React.useState(100);
16747
+ const { isOpen: open, setTrace, setIsOpen, setSpan } = React.useContext(TraceContext);
16748
+ React.useEffect(() => {
16749
+ if (hasRunRef.current) return;
16750
+ if (!runId || !stepName) return;
16751
+ const matchingTrace = traces.find((trace) => trace.runId === runId);
16752
+ if (!matchingTrace) return;
16753
+ const matchingSpan = matchingTrace.trace.find((span) => span.name.includes(stepName));
16754
+ if (!matchingSpan) return;
16755
+ setTrace(matchingTrace.trace);
16756
+ setSpan(matchingSpan);
16757
+ setIsOpen(true);
16758
+ hasRunRef.current = true;
16759
+ }, [runId, traces, setTrace]);
16760
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("h-full relative overflow-hidden flex", className), children: [
16761
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full overflow-y-scroll w-full", children: [
16762
+ /* @__PURE__ */ jsxRuntime.jsx(TracesTable, { traces, error }),
16763
+ /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, ref: setEndOfListElement })
16764
+ ] }),
16765
+ open && /* @__PURE__ */ jsxRuntime.jsx(TracesSidebar, { width: sidebarWidth, onResize: setSidebarWidth })
16766
+ ] });
16767
+ }
16768
+ const TracesViewSkeleton = () => {
16769
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full relative overflow-hidden flex", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full overflow-y-scroll w-full", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-10" }) }) });
15519
16770
  };
15520
16771
 
15521
- function buildTree(spans, minStartTime, totalDurationMs, parentSpanId = null) {
15522
- return spans.filter((span) => span.parentSpanId === parentSpanId).map((span) => {
15523
- return {
15524
- ...span,
15525
- children: buildTree(spans, minStartTime, totalDurationMs, span.id),
15526
- offset: (span.startTime - minStartTime) / 1e3,
15527
- // ns to ms
15528
- duration: span.duration / 1e3,
15529
- totalDurationMs
16772
+ const formatHierarchicalSpans = (spans) => {
16773
+ if (!spans || spans.length === 0) {
16774
+ return [];
16775
+ }
16776
+ const spanMap = /* @__PURE__ */ new Map();
16777
+ const rootSpans = [];
16778
+ spans.forEach((spanRecord) => {
16779
+ const startDate = new Date(spanRecord.startedAt);
16780
+ const endDate = spanRecord.endedAt ? new Date(spanRecord.endedAt) : void 0;
16781
+ const uiSpan = {
16782
+ id: spanRecord.spanId,
16783
+ name: spanRecord.name,
16784
+ type: spanRecord.spanType,
16785
+ latency: endDate ? endDate.getTime() - startDate.getTime() : 0,
16786
+ startTime: startDate.toISOString(),
16787
+ endTime: endDate ? endDate.toISOString() : void 0,
16788
+ spans: []
15530
16789
  };
16790
+ spanMap.set(spanRecord.spanId, uiSpan);
16791
+ });
16792
+ spans.forEach((spanRecord) => {
16793
+ const uiSpan = spanMap.get(spanRecord.spanId);
16794
+ if (spanRecord?.parentSpanId === null) {
16795
+ rootSpans.push(uiSpan);
16796
+ } else {
16797
+ const parent = spanMap.get(spanRecord.parentSpanId);
16798
+ if (parent) {
16799
+ parent.spans.push(uiSpan);
16800
+ } else {
16801
+ rootSpans.push(uiSpan);
16802
+ }
16803
+ }
15531
16804
  });
16805
+ const sortSpansByStartTime = (spans2) => {
16806
+ return spans2.sort((a, b) => new Date(a.startTime).getTime() - new Date(b.startTime).getTime());
16807
+ };
16808
+ const sortedRootSpans = sortSpansByStartTime(rootSpans);
16809
+ const sortNestedSpans = (spans2) => {
16810
+ spans2.forEach((span) => {
16811
+ if (span.spans && span.spans.length > 0) {
16812
+ span.spans = sortSpansByStartTime(span.spans);
16813
+ sortNestedSpans(span.spans);
16814
+ }
16815
+ });
16816
+ };
16817
+ sortNestedSpans(sortedRootSpans);
16818
+ return sortedRootSpans;
16819
+ };
16820
+
16821
+ const spanTypePrefixes = ["agent", "workflow", "llm", "tool"];
16822
+ function getSpanTypeUi(type) {
16823
+ const typePrefix = type?.toLowerCase().split("_")[0];
16824
+ const spanTypeToUiElements = {
16825
+ agent: {
16826
+ icon: /* @__PURE__ */ jsxRuntime.jsx(AgentIcon, {}),
16827
+ color: "oklch(0.75 0.15 250)",
16828
+ label: "Agent"
16829
+ },
16830
+ workflow: {
16831
+ icon: /* @__PURE__ */ jsxRuntime.jsx(WorkflowIcon, {}),
16832
+ color: "oklch(0.75 0.15 200)",
16833
+ label: "Workflow"
16834
+ },
16835
+ llm: {
16836
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BrainIcon, {}),
16837
+ color: "oklch(0.75 0.15 320)",
16838
+ label: "LLM"
16839
+ },
16840
+ tool: {
16841
+ icon: /* @__PURE__ */ jsxRuntime.jsx(ToolsIcon, {}),
16842
+ color: "oklch(0.75 0.15 100)",
16843
+ label: "Tool"
16844
+ }
16845
+ };
16846
+ if (typePrefix in spanTypeToUiElements) {
16847
+ return spanTypeToUiElements[typePrefix];
16848
+ }
16849
+ return null;
16850
+ }
16851
+
16852
+ function TraceTimelineSpan({
16853
+ span,
16854
+ depth = 0,
16855
+ onSpanClick,
16856
+ selectedSpanId,
16857
+ isLastChild,
16858
+ overallLatency,
16859
+ overallStartTime
16860
+ }) {
16861
+ const { Link } = useLinkComponent();
16862
+ const [isHovered, setIsHovered] = React.useState(false);
16863
+ const hasChildren = span.spans && span.spans.length > 0;
16864
+ const isRootSpan = depth === 0;
16865
+ const percentageSpanLatency = overallLatency ? Math.ceil(span.latency / overallLatency * 100) : 0;
16866
+ const overallStartTimeDate = overallStartTime ? new Date(overallStartTime) : null;
16867
+ const spanStartTimeDate = span.startTime ? new Date(span.startTime) : null;
16868
+ const spanStartTimeShift = spanStartTimeDate && overallStartTimeDate ? spanStartTimeDate.getTime() - overallStartTimeDate.getTime() : 0;
16869
+ const percentageSpanStartTime = overallLatency && Math.floor(spanStartTimeShift / overallLatency * 100);
16870
+ const spanUI = getSpanTypeUi(span?.type);
16871
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16872
+ /* @__PURE__ */ jsxRuntime.jsx(
16873
+ "button",
16874
+ {
16875
+ onClick: () => onSpanClick?.(span.id),
16876
+ onMouseEnter: () => setIsHovered(true),
16877
+ onMouseLeave: () => setIsHovered(false),
16878
+ type: "button",
16879
+ "aria-label": `View details for span ${span.name}`,
16880
+ className: cn(
16881
+ "rounded-md transition-colors cursor-pointer flex py-[0.5rem] opacity-80 min-h-[3.5rem]",
16882
+ "mt-[1rem] xl:mt-0",
16883
+ {
16884
+ "bg-icon1/30 text-white": selectedSpanId === span.id,
16885
+ "bg-icon1/10 opacity-100": isHovered
16886
+ }
16887
+ ),
16888
+ style: { paddingLeft: `${depth * 1.4}rem` },
16889
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[1rem] w-full", children: [
16890
+ !isRootSpan && /* @__PURE__ */ jsxRuntime.jsx(TreePositionMark, { isLastChild, hasChildren: Boolean(hasChildren) }),
16891
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("text-[0.875rem] flex items-center text-left break-all gap-[0.5rem] text-[#fff] w-full"), children: [
16892
+ 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 }),
16893
+ span.name
16894
+ ] })
16895
+ ] })
16896
+ }
16897
+ ),
16898
+ /* @__PURE__ */ jsxRuntime.jsxs(HoverCard__namespace.Root, { openDelay: 250, children: [
16899
+ /* @__PURE__ */ jsxRuntime.jsxs(
16900
+ HoverCard__namespace.Trigger,
16901
+ {
16902
+ className: cn(
16903
+ "rounded-md transition-colors content-center cursor-help grid min-h-[3.5rem] opacity-80 px-[2.5rem] items-center relative",
16904
+ "bg-surface2 xl:bg-surface3",
16905
+ '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',
16906
+ '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',
16907
+ {
16908
+ "bg-icon1/10 xl:bg-icon1/10 opacity-100": isHovered
16909
+ }
16910
+ ),
16911
+ onMouseEnter: () => setIsHovered(true),
16912
+ onMouseLeave: () => setIsHovered(false),
16913
+ children: [
16914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-left text-[0.75rem] relative w-full h-[1.4rem] ", children: /* @__PURE__ */ jsxRuntime.jsxs(
16915
+ "span",
16916
+ {
16917
+ className: cn(
16918
+ "absolute flex pt-[0.1rem] items-center gap-[0.5rem] text-icon5",
16919
+ "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0 [&>svg]:opacity-50 mb-[0.1em] [&>svg]:mb-[0.1rem]"
16920
+ ),
16921
+ style: { width: `${percentageSpanLatency}%`, left: `${percentageSpanStartTime}%` },
16922
+ children: [
16923
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRight, {}),
16924
+ /* @__PURE__ */ jsxRuntime.jsxs(
16925
+ "span",
16926
+ {
16927
+ style: {
16928
+ transform: percentageSpanStartTime && percentageSpanStartTime > 70 ? "translateX(calc((100% + 2rem) * -1))" : "none"
16929
+ },
16930
+ children: [
16931
+ (span.latency / 1e3).toFixed(2),
16932
+ " s"
16933
+ ]
16934
+ }
16935
+ )
16936
+ ]
16937
+ }
16938
+ ) }),
16939
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full bg-surface5 h-[3px] ", children: /* @__PURE__ */ jsxRuntime.jsx(
16940
+ "div",
16941
+ {
16942
+ className: cn("bg-icon1 h-full absolute rounded-full"),
16943
+ style: {
16944
+ width: `${percentageSpanLatency}%`,
16945
+ left: `${percentageSpanStartTime}%`,
16946
+ backgroundColor: spanUI?.color
16947
+ }
16948
+ }
16949
+ ) })
16950
+ ]
16951
+ }
16952
+ ),
16953
+ /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsxs(
16954
+ HoverCard__namespace.Content,
16955
+ {
16956
+ 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",
16957
+ sideOffset: 5,
16958
+ side: "top",
16959
+ children: [
16960
+ /* @__PURE__ */ jsxRuntime.jsxs(
16961
+ "div",
16962
+ {
16963
+ className: cn(
16964
+ "text-[0.875rem] flex items-center gap-[0.5rem] mb-[1rem]",
16965
+ "[&>svg]:w-[1.25em] [&>svg]:h-[1.25em] [&>svg]:shrink-0 [&>svg]:opacity-50"
16966
+ ),
16967
+ children: [
16968
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TimerIcon, {}),
16969
+ " Span Timing"
16970
+ ]
16971
+ }
16972
+ ),
16973
+ /* @__PURE__ */ jsxRuntime.jsx(
16974
+ KeyValueList,
16975
+ {
16976
+ className: " [&>dd]:text-[0.875rem] [&>dt]:text-[0.875rem] [&>dt]:min-h-0 [&>dd]:min-h-0",
16977
+ data: [
16978
+ {
16979
+ key: "Latency",
16980
+ label: "Latency",
16981
+ value: `${span.latency} ms`,
16982
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightIcon, {})
16983
+ },
16984
+ {
16985
+ key: "startTime",
16986
+ label: "Started at",
16987
+ value: span.startTime ? format.format(new Date(span.startTime), "hh:mm:ss:SSS a") : "-",
16988
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronFirstIcon, {})
16989
+ },
16990
+ {
16991
+ key: "endTime",
16992
+ label: "Ended at",
16993
+ value: span.endTime ? format.format(new Date(span.endTime), "hh:mm:ss:SSS a") : "-",
16994
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronLastIcon, {})
16995
+ },
16996
+ {
16997
+ key: "startShift",
16998
+ label: "Start Shift",
16999
+ value: `${spanStartTimeShift}ms`,
17000
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsRightIcon, {})
17001
+ }
17002
+ ],
17003
+ LinkComponent: Link
17004
+ }
17005
+ ),
17006
+ /* @__PURE__ */ jsxRuntime.jsx(HoverCard__namespace.Arrow, { className: "fill-surface5" })
17007
+ ]
17008
+ }
17009
+ ) })
17010
+ ] }),
17011
+ hasChildren && span.spans?.map((childSpan, idx, array) => {
17012
+ const isLastChild2 = idx === array.length - 1;
17013
+ return /* @__PURE__ */ jsxRuntime.jsx(
17014
+ TraceTimelineSpan,
17015
+ {
17016
+ span: childSpan,
17017
+ depth: depth + 1,
17018
+ onSpanClick,
17019
+ selectedSpanId,
17020
+ isLastChild: isLastChild2,
17021
+ overallLatency,
17022
+ overallStartTime
17023
+ },
17024
+ childSpan.id
17025
+ );
17026
+ })
17027
+ ] });
15532
17028
  }
15533
- const createSpanTree = (spans) => {
15534
- if (spans.length === 0) return [];
15535
- let minStartTime;
15536
- let maxEndTime;
15537
- const orderedTree = [];
15538
- const listSize = spans.length;
15539
- for (let i = listSize - 1; i >= 0; i--) {
15540
- const span = spans[i];
15541
- if (!minStartTime || span.startTime < minStartTime) {
15542
- minStartTime = span.startTime;
15543
- }
15544
- if (!maxEndTime || span.endTime > maxEndTime) {
15545
- maxEndTime = span.endTime;
15546
- }
15547
- if (span.name !== ".insert" && span.name !== "mastra.getStorage") {
15548
- orderedTree.push(span);
15549
- }
15550
- }
15551
- if (!minStartTime || !maxEndTime) return [];
15552
- const totalDurationMs = (maxEndTime - minStartTime) / 1e3;
15553
- return buildTree(orderedTree, minStartTime, totalDurationMs);
15554
- };
15555
-
15556
- const NestedSpans = ({ spanNodes }) => {
15557
- const { span: activeSpan, setSpan } = React.useContext(TraceContext);
15558
- return /* @__PURE__ */ jsxRuntime.jsx(Spans, { children: spanNodes.map((spanNode) => {
15559
- const isActive = spanNode.id === activeSpan?.id;
15560
- return /* @__PURE__ */ jsxRuntime.jsx(
15561
- Span,
15562
- {
15563
- spans: spanNode.children.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(NestedSpans, { spanNodes: spanNode.children }),
15564
- durationMs: spanNode.duration,
15565
- offsetMs: spanNode.offset,
15566
- variant: getSpanVariant(spanNode),
15567
- isActive,
15568
- onClick: () => setSpan(spanNode),
15569
- totalDurationMs: spanNode.totalDurationMs,
15570
- children: spanNode.name
15571
- },
15572
- spanNode.id
15573
- );
15574
- }) });
15575
- };
15576
- function SpanView({ trace }) {
15577
- const { span: activeSpan, setSpan } = React.useContext(TraceContext);
15578
- const tree = createSpanTree(trace);
15579
- return /* @__PURE__ */ jsxRuntime.jsx(TraceTree, { children: tree.map((node) => /* @__PURE__ */ jsxRuntime.jsx(
15580
- Trace,
17029
+ function TreePositionMark({ isLastChild, hasChildren = false }) {
17030
+ return /* @__PURE__ */ jsxRuntime.jsx(
17031
+ "div",
15581
17032
  {
15582
- name: node.name,
15583
- durationMs: node.duration,
15584
- totalDurationMs: node.totalDurationMs,
15585
- spans: /* @__PURE__ */ jsxRuntime.jsx(NestedSpans, { spanNodes: node.children }),
15586
- variant: getSpanVariant(node),
15587
- isActive: node.id === activeSpan?.id,
15588
- onClick: () => setSpan(node)
17033
+ className: cn(
17034
+ "w-[1.5rem] h-[2.2rem] relative opacity-50 ",
17035
+ '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',
17036
+ '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',
17037
+ {
17038
+ "after:bottom-[50%]": isLastChild
17039
+ }
17040
+ ),
17041
+ children: hasChildren && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute -right-[1px] top-[50%] bottom-0 w-[0px] border-r-[0.5px] border-white border-dashed" })
15589
17042
  }
15590
- )) });
17043
+ );
15591
17044
  }
15592
17045
 
15593
- const Header = ({ children, border = true }) => {
15594
- return /* @__PURE__ */ jsxRuntime.jsx(
15595
- "header",
15596
- {
15597
- className: clsx("h-header-default z-50 flex w-full items-center gap-[18px] bg-transparent px-5", {
15598
- "border-b-sm border-border1": border
15599
- }),
15600
- children
15601
- }
17046
+ function TraceTimelineLegend({ spans = [] }) {
17047
+ const activeSpanTypes = spanTypePrefixes.filter(
17048
+ (typePrefix) => spans.some((span) => span?.spanType?.startsWith(typePrefix))
15602
17049
  );
15603
- };
15604
- const HeaderTitle = ({ children }) => {
15605
- return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h1", variant: "ui-lg", className: "font-medium text-white", children });
15606
- };
15607
- const HeaderAction = ({ children }) => {
15608
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto", children });
15609
- };
15610
- const HeaderGroup = ({ children }) => {
15611
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "gap-lg flex items-center", children });
15612
- };
17050
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex justify-start gap-[2rem] mb-2 text-[0.75rem] opacity-90"), children: activeSpanTypes.map((item) => {
17051
+ const spanUI = getSpanTypeUi(item);
17052
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-[.5rem]"), children: [
17053
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("[&>svg]:w-[1.2em] [&>svg]:h-[1.2em]"), style: { color: spanUI?.color }, children: spanUI?.icon && spanUI.icon }),
17054
+ spanUI?.label
17055
+ ] }, item);
17056
+ }) });
17057
+ }
15613
17058
 
15614
- function TraceDetails() {
15615
- const { trace, currentTraceIndex, prevTrace, nextTrace, traces } = React.useContext(TraceContext);
15616
- const actualTrace = traces[currentTraceIndex];
15617
- if (!actualTrace || !trace) return null;
15618
- const hasFailure = trace.some((span) => span.status.code === 2);
15619
- return /* @__PURE__ */ jsxRuntime.jsxs("aside", { children: [
15620
- /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
15621
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
15622
- /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: prevTrace, disabled: currentTraceIndex === 0, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}) }) }),
15623
- /* @__PURE__ */ jsxRuntime.jsx(
15624
- Button$1,
15625
- {
15626
- className: "bg-transparent border-none",
15627
- onClick: nextTrace,
15628
- disabled: currentTraceIndex === traces.length - 1,
15629
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) })
15630
- }
15631
- )
17059
+ function TraceTimeline({
17060
+ spans = [],
17061
+ hierarchicalSpans = [],
17062
+ onSpanClick,
17063
+ selectedSpanId,
17064
+ isLoading,
17065
+ className
17066
+ }) {
17067
+ const overallLatency = hierarchicalSpans?.[0]?.latency || 0;
17068
+ const overallStartTime = hierarchicalSpans?.[0]?.startTime || "";
17069
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid gap-[1rem]", className), children: [
17070
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full justify-between pr-[2.5rem]", children: [
17071
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", children: [
17072
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ListTreeIcon, {}),
17073
+ " Timeline"
15632
17074
  ] }),
15633
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 justify-between w-full", children: [
15634
- /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "font-medium text-icon5 shrink-0", children: [
15635
- "Trace ",
15636
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-icon3", children: actualTrace.traceId.substring(0, 7) })
15637
- ] }),
15638
- hasFailure && /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: "Failed" })
15639
- ] })
17075
+ /* @__PURE__ */ jsxRuntime.jsx(TraceTimelineLegend, { spans })
15640
17076
  ] }),
15641
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-5", children: /* @__PURE__ */ jsxRuntime.jsx(SpanView, { trace }) })
17077
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsxs(
17078
+ "div",
17079
+ {
17080
+ className: cn(
17081
+ "flex items-center text-[0.875rem] gap-[1rem] bg-surface3/50 rounded-md p-[1.5rem] mr-[1.5rem] justify-center text-icon3 mt-[.5rem]",
17082
+ "[&_svg]:w-[1.25em] [&_svg]:h-[1.25em] [&_svg]:opacity-50"
17083
+ ),
17084
+ children: [
17085
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}),
17086
+ " Loading Trace Timeline ..."
17087
+ ]
17088
+ }
17089
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
17090
+ "div",
17091
+ {
17092
+ className: cn(
17093
+ "overflow-y-auto grid items-start content-start gap-y-[2px] xl:py-[1rem]",
17094
+ "xl:grid-cols-[3fr_2fr] xl:gap-x-[1rem]"
17095
+ ),
17096
+ children: hierarchicalSpans?.map((span) => /* @__PURE__ */ jsxRuntime.jsx(
17097
+ TraceTimelineSpan,
17098
+ {
17099
+ span,
17100
+ onSpanClick,
17101
+ selectedSpanId,
17102
+ overallLatency,
17103
+ overallStartTime
17104
+ },
17105
+ span.id
17106
+ ))
17107
+ }
17108
+ )
15642
17109
  ] });
15643
17110
  }
15644
17111
 
15645
- function formatDuration(duration, fixedPoint = 2) {
15646
- const durationInSecs = duration / 1e3;
15647
- return durationInSecs.toFixed(fixedPoint);
15648
- }
15649
- function formatOtelTimestamp(otelTimestamp) {
15650
- const date = new Date(otelTimestamp / 1e3);
15651
- return new Intl.DateTimeFormat("en-US", {
15652
- month: "numeric",
15653
- day: "numeric",
15654
- year: "numeric",
15655
- hour: "numeric",
15656
- minute: "numeric",
15657
- second: "numeric",
15658
- hour12: true
15659
- }).format(date);
15660
- }
15661
- function formatOtelTimestamp2(otelTimestamp) {
15662
- const date = new Date(otelTimestamp / 1e6);
15663
- return new Intl.DateTimeFormat("en-US", {
15664
- month: "numeric",
15665
- day: "numeric",
15666
- year: "numeric",
15667
- hour: "numeric",
15668
- minute: "numeric",
15669
- second: "numeric",
15670
- hour12: true
15671
- }).format(date);
15672
- }
15673
- function transformKey(key) {
15674
- if (key.includes(".argument.")) {
15675
- return `Input`;
17112
+ function TraceSpanUsage({ traceUsage, traceSpans = [], spanUsage, className }) {
17113
+ if (!traceUsage && !spanUsage) {
17114
+ console.warn("No usage data available");
17115
+ return null;
15676
17116
  }
15677
- if (key.includes(".result")) {
15678
- return "Output";
17117
+ if (traceUsage && spanUsage) {
17118
+ console.warn("Only one of traceUsage or spanUsage should be provided");
17119
+ return null;
15679
17120
  }
15680
- const newKey = key.split(".").join(" ").split("_").join(" ").replaceAll("ai", "AI");
15681
- return newKey.substring(0, 1).toUpperCase() + newKey.substring(1);
15682
- }
15683
- function cleanString(string) {
15684
- return string.replace(/\\n/g, "").replace(/\n/g, "").replace(/\s+/g, " ").trim();
15685
- }
15686
- const allowedAiSpanAttributes = [
15687
- "operation.name",
15688
- "ai.operationId",
15689
- "ai.model.provider",
15690
- "ai.model.id",
15691
- "ai.prompt.format",
15692
- "ai.prompt.messages",
15693
- "ai.prompt.tools",
15694
- "ai.prompt.toolChoice",
15695
- "ai.settings.toolChoice",
15696
- "ai.schema",
15697
- "ai.settings.output",
15698
- "ai.response.object",
15699
- "ai.response.text",
15700
- "ai.response.timestamp",
15701
- "componentName",
15702
- "ai.usage.promptTokens",
15703
- "ai.usage.completionTokens"
15704
- ];
15705
-
15706
- function SpanDetail() {
15707
- const { span, setSpan, trace, setIsOpen } = React.useContext(TraceContext);
15708
- if (!span || !trace) return null;
15709
- const prevSpan = () => {
15710
- const currentIndex = trace.findIndex((t) => t.id === span.id);
15711
- if (currentIndex !== -1 && currentIndex < trace.length - 1) {
15712
- setSpan(trace[currentIndex + 1]);
15713
- }
15714
- };
15715
- const nextSpan = () => {
15716
- const currentIndex = trace.findIndex((t) => t.id === span.id);
15717
- if (currentIndex !== -1 && currentIndex > 0) {
15718
- setSpan(trace[currentIndex - 1]);
15719
- }
15720
- };
15721
- const SpanIcon = spanIconMap[getSpanVariant(span)];
15722
- const variantClass = spanVariantClasses[getSpanVariant(span)];
15723
- return /* @__PURE__ */ jsxRuntime.jsxs("aside", { children: [
15724
- /* @__PURE__ */ jsxRuntime.jsxs(Header, { children: [
15725
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
15726
- /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: prevSpan, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronUp, {}) }) }),
15727
- /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: nextSpan, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, {}) }) })
15728
- ] }),
15729
- /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "font-medium text-icon5", as: "h2", children: [
15730
- "Span ",
15731
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 text-icon3", children: span.id.substring(0, 7) })
15732
- ] }) }),
15733
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "ml-auto flex items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsx(Button$1, { className: "bg-transparent border-none", onClick: () => setIsOpen(false), children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}) }) }) })
15734
- ] }),
15735
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-5", children: [
15736
- /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "header-md", as: "h3", className: "text-icon-6 flex items-center gap-4 pb-3", children: [
15737
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "lg", className: "bg-surface4 p-1 rounded-md", children: /* @__PURE__ */ jsxRuntime.jsx(SpanIcon, { className: variantClass }) }),
15738
- span.name
15739
- ] }),
15740
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-row gap-2 items-center", children: span.status.code === 2 ? /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { variant: "error", icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, {}), children: [
15741
- "Failed in ",
15742
- toSigFigs(span.duration, 3),
15743
- "ms"
15744
- ] }) : /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(LatencyIcon, {}), variant: "success", children: [
15745
- toSigFigs(span.duration, 3),
15746
- "ms"
15747
- ] }) }),
15748
- /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
15749
- /* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-2 justify-between gap-2", children: [
15750
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "ID" }),
15751
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: span.id }),
15752
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Created at" }),
15753
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: span.startTime ? formatOtelTimestamp(span.startTime) : "" })
15754
- ] }),
15755
- span.attributes && /* @__PURE__ */ jsxRuntime.jsx(Attributes, { attributes: span.attributes }),
15756
- span.events?.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(Events, { span })
15757
- ] })
15758
- ] });
17121
+ const generationSpans = traceSpans.filter((span) => span.spanType === "llm_generation");
17122
+ const tokensByProvider = generationSpans.reduce(
17123
+ (acc, span) => {
17124
+ const spanUsage2 = span.attributes?.usage || {};
17125
+ const model = span?.attributes?.model || "";
17126
+ const provider = span?.attributes?.provider || "";
17127
+ const spanModelProvider = `${provider}${provider && model ? " / " : ""}${model}`;
17128
+ if (!acc?.[spanModelProvider]) {
17129
+ acc[spanModelProvider] = { promptTokens: 0, completionTokens: 0, totalTokens: 0 };
17130
+ }
17131
+ acc[spanModelProvider].promptTokens += spanUsage2.promptTokens || 0;
17132
+ acc[spanModelProvider].completionTokens += spanUsage2.completionTokens || 0;
17133
+ acc[spanModelProvider].totalTokens += (spanUsage2.promptTokens || 0) + (spanUsage2.completionTokens || 0);
17134
+ return acc;
17135
+ },
17136
+ {}
17137
+ );
17138
+ const traceTokensBasedOnSpans = Object.keys(
17139
+ tokensByProvider
17140
+ ).reduce(
17141
+ (acc, provider) => {
17142
+ const { promptTokens, completionTokens, totalTokens } = tokensByProvider[provider];
17143
+ acc.promptTokens += promptTokens;
17144
+ acc.completionTokens += completionTokens;
17145
+ acc.totalTokens += totalTokens;
17146
+ return acc;
17147
+ },
17148
+ { promptTokens: 0, completionTokens: 0, totalTokens: 0 }
17149
+ );
17150
+ const tokensByProviderValid = JSON.stringify(traceUsage) === JSON.stringify(traceTokensBasedOnSpans);
17151
+ const tokenPresentations = {
17152
+ totalTokens: {
17153
+ label: "Total LLM Tokens",
17154
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CoinsIcon, {})
17155
+ },
17156
+ promptTokens: {
17157
+ label: "Prompt Tokens",
17158
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightIcon, {})
17159
+ },
17160
+ completionTokens: {
17161
+ label: "Completion Tokens",
17162
+ icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRightToLineIcon, {})
17163
+ }
17164
+ };
17165
+ const usageKeyOrder = ["totalTokens", "promptTokens", "completionTokens"];
17166
+ const usageAsArray = Object.entries(traceUsage || spanUsage || {}).map(([key, value]) => ({ key, value })).sort((a, b) => usageKeyOrder.indexOf(a.key) - usageKeyOrder.indexOf(b.key));
17167
+ return /* @__PURE__ */ jsxRuntime.jsx(
17168
+ "div",
17169
+ {
17170
+ className: cn(
17171
+ "grid gap-[1.5rem]",
17172
+ {
17173
+ "xl:grid-cols-3": usageAsArray.length === 3,
17174
+ "xl:grid-cols-2": usageAsArray.length === 2
17175
+ },
17176
+ className
17177
+ ),
17178
+ children: usageAsArray.map(({ key, value }) => /* @__PURE__ */ jsxRuntime.jsxs(
17179
+ "div",
17180
+ {
17181
+ className: cn("bg-white/5 p-[1rem] px-[1.25rem] rounded-lg text-[0.875rem]", {
17182
+ "min-h-[5.5rem]": traceUsage
17183
+ }),
17184
+ children: [
17185
+ /* @__PURE__ */ jsxRuntime.jsxs(
17186
+ "div",
17187
+ {
17188
+ className: cn(
17189
+ "grid grid-cols-[1.5rem_1fr_auto] gap-[.5rem] items-center",
17190
+ "[&>svg]:w-[1.5em] [&>svg]:h-[1.5em] [&>svg]:opacity-70"
17191
+ ),
17192
+ children: [
17193
+ tokenPresentations?.[key]?.icon,
17194
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[0.875rem]", children: tokenPresentations?.[key]?.label }),
17195
+ /* @__PURE__ */ jsxRuntime.jsx("b", { className: "text-[1rem]", children: value })
17196
+ ]
17197
+ }
17198
+ ),
17199
+ tokensByProviderValid && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[0.875rem] mt-[0.5rem] pl-[2rem] ", children: Object.entries(tokensByProvider).map(([provider, providerTokens]) => /* @__PURE__ */ jsxRuntime.jsxs(
17200
+ "dl",
17201
+ {
17202
+ className: "grid grid-cols-[1fr_auto] gap-x-[1rem] gap-y-[.25rem] justify-between text-icon3",
17203
+ children: [
17204
+ /* @__PURE__ */ jsxRuntime.jsx("dt", { children: provider }),
17205
+ /* @__PURE__ */ jsxRuntime.jsx("dd", { children: providerTokens?.[key] })
17206
+ ]
17207
+ },
17208
+ provider
17209
+ )) })
17210
+ ]
17211
+ },
17212
+ key
17213
+ ))
17214
+ }
17215
+ );
15759
17216
  }
15760
- function Attributes({ attributes }) {
15761
- if (!attributes) return null;
15762
- const entries = Object.entries(attributes);
15763
- if (entries.length === 0) return null;
15764
- const keysToHide = ["http.request_id", "componentName"];
15765
- return /* @__PURE__ */ jsxRuntime.jsx("div", { children: entries.filter(([key]) => !keysToHide.includes(key)).map(([key, val]) => {
15766
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15767
- /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
15768
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h4", variant: "ui-md", className: "text-icon3 pb-2", children: transformKey(key) }),
15769
- /* @__PURE__ */ jsxRuntime.jsx(AttributeValue, { value: val })
15770
- ] }, key);
15771
- }) });
17217
+
17218
+ function getTraceInfo(trace) {
17219
+ if (!trace) {
17220
+ return [];
17221
+ }
17222
+ return [
17223
+ {
17224
+ key: "entityId",
17225
+ label: "Entity Id",
17226
+ value: [
17227
+ {
17228
+ id: trace?.metadata?.resourceId,
17229
+ name: trace?.attributes?.agentId || trace?.attributes?.workflowId || "-",
17230
+ path: trace?.attributes?.agentId ? `/agents/${trace?.metadata?.resourceId}` : trace?.attributes?.workflowId ? `/workflows/${trace?.metadata?.resourceId}` : void 0
17231
+ }
17232
+ ]
17233
+ },
17234
+ {
17235
+ key: "entityType",
17236
+ label: "Entity Type",
17237
+ value: [
17238
+ {
17239
+ id: trace?.attributes?.agentId || trace?.attributes?.workflowId,
17240
+ name: trace?.attributes?.agentId ? "Agent" : trace?.attributes?.workflowId ? "Workflow" : "-",
17241
+ path: trace?.attributes?.agentId ? `/agents` : trace?.attributes?.workflowId ? `/workflows` : void 0
17242
+ }
17243
+ ]
17244
+ },
17245
+ {
17246
+ key: "status",
17247
+ label: "Status",
17248
+ value: trace?.attributes?.status || "-"
17249
+ },
17250
+ {
17251
+ key: "createdAt",
17252
+ label: "Created at",
17253
+ value: trace?.createdAt ? dateFns.format(new Date(trace?.createdAt), "PPpp") : "-"
17254
+ }
17255
+ ];
15772
17256
  }
15773
- const AttributeValue = ({ value }) => {
15774
- if (!value)
15775
- return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: "N/A" });
15776
- if (typeof value === "number" || typeof value === "boolean") {
15777
- return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: String(value) });
17257
+ function getSpanInfo({ span, withTraceId = true, withSpanId = true }) {
17258
+ if (!span) {
17259
+ return [];
15778
17260
  }
15779
- if (typeof value === "object") {
15780
- return /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: value });
17261
+ const baseInfo = [
17262
+ {
17263
+ key: "spanType",
17264
+ label: "Span Type",
17265
+ value: span?.spanType
17266
+ },
17267
+ {
17268
+ key: "createdAt",
17269
+ label: "Created at",
17270
+ value: span?.createdAt ? dateFns.format(new Date(span?.createdAt), "MMM dd, HH:mm:ss.SSS") : "-"
17271
+ },
17272
+ {
17273
+ key: "startedAt",
17274
+ label: "Started At",
17275
+ value: span?.startedAt ? dateFns.format(new Date(span.startedAt), "MMM dd, HH:mm:ss.SSS") : "-"
17276
+ },
17277
+ {
17278
+ key: "endedAt",
17279
+ label: "Ended At",
17280
+ value: span?.endedAt ? dateFns.format(new Date(span.endedAt), "MMM dd, HH:mm:ss.SSS") : "-"
17281
+ }
17282
+ ];
17283
+ if (withTraceId) {
17284
+ baseInfo.unshift({
17285
+ key: "traceId",
17286
+ label: "Trace Id",
17287
+ value: span?.traceId
17288
+ });
15781
17289
  }
15782
- try {
15783
- return /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: JSON.parse(value) });
15784
- } catch {
15785
- return /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6", children: String(value) });
17290
+ if (withSpanId) {
17291
+ baseInfo.unshift({
17292
+ key: "spanId",
17293
+ label: "Span Id",
17294
+ value: span?.spanId
17295
+ });
15786
17296
  }
15787
- };
15788
- function Events({ span }) {
15789
- if (!span.events) return null;
15790
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15791
- /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
15792
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "p", variant: "ui-md", className: "text-icon6 pb-2", children: "Events" }),
15793
- span.events.map((event) => {
15794
- const isLast = event === span.events[span.events.length - 1];
15795
- return /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
15796
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15797
- /* @__PURE__ */ jsxRuntime.jsxs("dl", { className: "grid grid-cols-2 justify-between gap-2 pb-2", children: [
15798
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Name" }),
15799
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: event.name }),
15800
- /* @__PURE__ */ jsxRuntime.jsx("dt", { className: "font-medium text-ui-md text-icon3", children: "Time" }),
15801
- /* @__PURE__ */ jsxRuntime.jsx("dd", { className: "text-ui-md text-icon6", children: event.timeUnixNano ? formatOtelTimestamp2(Number(event.timeUnixNano)) : "N/A" })
15802
- ] }),
15803
- event.attributes?.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-2", children: event.attributes.filter((attribute) => attribute !== null).map((attribute) => /* @__PURE__ */ jsxRuntime.jsxs("li", { children: [
15804
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h4", variant: "ui-md", className: "text-icon3 pb-2", children: transformKey(attribute.key) }),
15805
- /* @__PURE__ */ jsxRuntime.jsx(AttributeValue, { value: attribute.value })
15806
- ] }, attribute.key)) }) : null
15807
- ] }, event.name),
15808
- !isLast && /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" })
15809
- ] }, event.name);
15810
- })
17297
+ return baseInfo;
17298
+ }
17299
+
17300
+ function SpanDetails({ span }) {
17301
+ if (!span) {
17302
+ return null;
17303
+ }
17304
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-[1.5rem] mb-[2rem]", children: [
17305
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Input", codeStr: JSON.stringify(span.input || null, null, 2) }),
17306
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Output", codeStr: JSON.stringify(span.output || null, null, 2) }),
17307
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Metadata", codeStr: JSON.stringify(span.metadata || null, null, 2) }),
17308
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogCodeSection, { title: "Attributes", codeStr: JSON.stringify(span.attributes || null, null, 2) })
15811
17309
  ] });
15812
17310
  }
15813
17311
 
15814
- const TracesSidebar = ({ onResize }) => {
15815
- return /* @__PURE__ */ jsxRuntime.jsx(
15816
- MastraResizablePanel,
17312
+ function SpanDialog({
17313
+ span,
17314
+ isOpen,
17315
+ onClose,
17316
+ onNext,
17317
+ onPrevious,
17318
+ onViewToggle,
17319
+ spanInfo = []
17320
+ }) {
17321
+ const { Link } = useLinkComponent();
17322
+ return /* @__PURE__ */ jsxRuntime.jsxs(
17323
+ SideDialog,
15817
17324
  {
15818
- className: "h-full absolute right-0 inset-y-0 bg-surface2",
15819
- defaultWidth: 80,
15820
- minimumWidth: 50,
15821
- maximumWidth: 80,
15822
- setCurrentWidth: onResize,
15823
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full grid grid-cols-2", children: [
15824
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-scroll w-full h-[calc(100%-40px)]", children: /* @__PURE__ */ jsxRuntime.jsx(TraceDetails, {}) }),
15825
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-[calc(100%-40px)] overflow-x-scroll w-full border-l border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(SpanDetail, {}) })
15826
- ] })
17325
+ dialogTitle: "Observability Span",
17326
+ dialogDescription: "View and analyze span details",
17327
+ isOpen,
17328
+ onClose,
17329
+ hasCloseButton: true,
17330
+ className: cn("w-[calc(100vw-20rem)] max-w-[60%]", "3xl:max-w-[50rem]", "4xl:max-w-[40%]"),
17331
+ children: [
17332
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pr-[1.5rem]", children: [
17333
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogTop, { onNext, onPrevious, showInnerNav: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[1rem] text-icon4 text-[0.875rem]", children: [
17334
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17335
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
17336
+ " ",
17337
+ getShortId(span?.traceId)
17338
+ ] }),
17339
+ "›",
17340
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17341
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
17342
+ getShortId(span?.spanId)
17343
+ ] })
17344
+ ] }) }),
17345
+ /* @__PURE__ */ jsxRuntime.jsx("button", { className: "flex items-center gap-1", onClick: onViewToggle, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelTopIcon, {}) })
17346
+ ] }),
17347
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-[1.5rem] px-[2.5rem] overflow-y-auto grid gap-[1.5rem] content-start", children: [
17348
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
17349
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { children: [
17350
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
17351
+ " ",
17352
+ span?.name
17353
+ ] }),
17354
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17355
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HashIcon, {}),
17356
+ " ",
17357
+ span?.spanId
17358
+ ] })
17359
+ ] }),
17360
+ span?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(TraceSpanUsage, { spanUsage: span.attributes.usage, className: "mt-[1.5rem]" }),
17361
+ /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: spanInfo, LinkComponent: Link, className: "mt-[1.5rem]" }),
17362
+ /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span })
17363
+ ] })
17364
+ ]
15827
17365
  }
15828
17366
  );
15829
- };
17367
+ }
15830
17368
 
15831
- function TracesView({
15832
- isLoading,
15833
- error,
15834
- traces,
15835
- runId,
15836
- stepName,
15837
- className,
15838
- setEndOfListElement
17369
+ function TraceDialog({
17370
+ traceId,
17371
+ traceSpans = [],
17372
+ traceDetails,
17373
+ isOpen,
17374
+ onClose,
17375
+ onNext,
17376
+ onPrevious,
17377
+ isLoadingSpans
15839
17378
  }) {
15840
- if (isLoading) {
15841
- return /* @__PURE__ */ jsxRuntime.jsx(TracesViewSkeleton, {});
15842
- }
15843
- return /* @__PURE__ */ jsxRuntime.jsx(TraceProvider, { initialTraces: traces || [], children: /* @__PURE__ */ jsxRuntime.jsx(
15844
- TracesViewInner,
15845
- {
15846
- traces,
15847
- error,
15848
- runId,
15849
- stepName,
15850
- className,
15851
- setEndOfListElement
17379
+ const { Link } = useLinkComponent();
17380
+ const [dialogIsOpen, setDialogIsOpen] = React.useState(false);
17381
+ const [selectedSpanId, setSelectedSpanId] = React.useState(void 0);
17382
+ const [combinedView, setCombinedView] = React.useState(false);
17383
+ const selectedSpan = traceSpans.find((span) => span.spanId === selectedSpanId);
17384
+ const hierarchicalSpans = React.useMemo(() => {
17385
+ return formatHierarchicalSpans(traceSpans);
17386
+ }, [traceSpans]);
17387
+ const flatSpans = React.useMemo(() => {
17388
+ const flattenSpans = (spans) => {
17389
+ const result = [];
17390
+ const traverse = (span) => {
17391
+ result.push(span);
17392
+ if (span.spans && span.spans.length > 0) {
17393
+ span.spans.forEach(traverse);
17394
+ }
17395
+ };
17396
+ spans.forEach(traverse);
17397
+ return result;
17398
+ };
17399
+ return flattenSpans(hierarchicalSpans);
17400
+ }, [hierarchicalSpans]);
17401
+ const handleSpanClick = (id) => {
17402
+ setSelectedSpanId(id);
17403
+ setDialogIsOpen(true);
17404
+ };
17405
+ const toNextSpan = () => {
17406
+ const currentIndex = flatSpans.findIndex((span) => span.id === selectedSpanId);
17407
+ const nextItem = flatSpans[currentIndex + 1];
17408
+ if (nextItem) {
17409
+ setSelectedSpanId(nextItem.id);
15852
17410
  }
15853
- ) });
17411
+ };
17412
+ const toPreviousSpan = () => {
17413
+ const currentIndex = flatSpans.findIndex((span) => span.id === selectedSpanId);
17414
+ const previousItem = flatSpans[currentIndex - 1];
17415
+ if (previousItem) {
17416
+ setSelectedSpanId(previousItem.id);
17417
+ }
17418
+ };
17419
+ const thereIsNextSpan = () => {
17420
+ const currentIndex = flatSpans.findIndex((span) => span.id === selectedSpanId);
17421
+ return currentIndex < flatSpans.length - 1;
17422
+ };
17423
+ const thereIsPreviousSpan = () => {
17424
+ const currentIndex = flatSpans.findIndex((span) => span.id === selectedSpanId);
17425
+ return currentIndex > 0;
17426
+ };
17427
+ const traceInfo = getTraceInfo(traceDetails);
17428
+ const selectedSpanInfo = getSpanInfo({ span: selectedSpan, withTraceId: !combinedView, withSpanId: combinedView });
17429
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17430
+ /* @__PURE__ */ jsxRuntime.jsxs(
17431
+ SideDialog,
17432
+ {
17433
+ dialogTitle: "Observability Trace",
17434
+ dialogDescription: "View and analyze trace details",
17435
+ isOpen,
17436
+ onClose,
17437
+ hasCloseButton: !dialogIsOpen || combinedView,
17438
+ className: cn("w-[calc(100vw-20rem)] max-w-[75%]", "3xl:max-w-[60rem]", "4xl:max-w-[60%]"),
17439
+ children: [
17440
+ /* @__PURE__ */ jsxRuntime.jsx(SideDialogTop, { onNext, onPrevious, showInnerNav: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17441
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
17442
+ " ",
17443
+ getShortId(traceId)
17444
+ ] }) }),
17445
+ /* @__PURE__ */ jsxRuntime.jsxs(
17446
+ "div",
17447
+ {
17448
+ className: cn("pt-[1.5rem] pl-[2.5rem] grid-rows-[auto_1fr] grid h-full overflow-y-auto", {
17449
+ "grid-rows-[auto_1fr_1fr]": selectedSpan && combinedView
17450
+ }),
17451
+ children: [
17452
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeader, { className: "flex gap-[1rem] items-baseline pr-[2.5rem]", children: [
17453
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { children: [
17454
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
17455
+ " ",
17456
+ traceDetails?.name
17457
+ ] }),
17458
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17459
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HashIcon, {}),
17460
+ " ",
17461
+ traceId
17462
+ ] })
17463
+ ] }),
17464
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto pb-[2.5rem]", children: [
17465
+ traceDetails?.metadata?.usage && /* @__PURE__ */ jsxRuntime.jsx(
17466
+ TraceSpanUsage,
17467
+ {
17468
+ traceUsage: traceDetails?.metadata?.usage,
17469
+ traceSpans,
17470
+ className: "mt-[2rem] pr-[1.5rem]"
17471
+ }
17472
+ ),
17473
+ /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: traceInfo, LinkComponent: Link, className: "mt-[2rem]" }),
17474
+ /* @__PURE__ */ jsxRuntime.jsx(
17475
+ TraceTimeline,
17476
+ {
17477
+ hierarchicalSpans,
17478
+ spans: traceSpans,
17479
+ onSpanClick: handleSpanClick,
17480
+ selectedSpanId,
17481
+ isLoading: isLoadingSpans,
17482
+ className: "pr-[2.5rem] pt-[2.5rem]"
17483
+ }
17484
+ )
17485
+ ] }),
17486
+ selectedSpan && combinedView && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto grid grid-rows-[auto_1fr] relative", children: [
17487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute left-0 right-[2.5rem] h-[.5rem] bg-surface1 rounded-full top-0" }),
17488
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between pb-[.5rem] pt-[1rem] border-b border-border1 pr-[2.5rem]", children: [
17489
+ /* @__PURE__ */ jsxRuntime.jsx(
17490
+ SideDialogTop,
17491
+ {
17492
+ onNext: thereIsNextSpan() ? toNextSpan : void 0,
17493
+ onPrevious: thereIsPreviousSpan() ? toPreviousSpan : void 0,
17494
+ showInnerNav: true,
17495
+ className: "pl-0",
17496
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[1rem] text-icon4 text-[0.875rem]", children: [
17497
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17498
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
17499
+ " ",
17500
+ getShortId(traceId)
17501
+ ] }),
17502
+ "›",
17503
+ /* @__PURE__ */ jsxRuntime.jsxs(TextAndIcon, { children: [
17504
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EyeIcon, {}),
17505
+ " ",
17506
+ getShortId(selectedSpanId)
17507
+ ] })
17508
+ ] })
17509
+ }
17510
+ ),
17511
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-[1rem]", children: /* @__PURE__ */ jsxRuntime.jsx("button", { className: "flex items-center gap-1", onClick: () => setCombinedView(false), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PanelLeftIcon, {}) }) })
17512
+ ] }),
17513
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[20rem_1fr] gap-[1rem] overflow-y-auto", children: [
17514
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto grid content-start p-[1.5rem] pl-0 gap-[2rem]", children: [
17515
+ /* @__PURE__ */ jsxRuntime.jsxs(SideDialogHeading, { as: "h2", children: [
17516
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronsLeftRightEllipsisIcon, {}),
17517
+ " ",
17518
+ selectedSpan?.name
17519
+ ] }),
17520
+ selectedSpan?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(
17521
+ TraceSpanUsage,
17522
+ {
17523
+ spanUsage: selectedSpan.attributes.usage,
17524
+ className: "xl:grid-cols-1 xl:gap-[1rem]"
17525
+ }
17526
+ ),
17527
+ /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: selectedSpanInfo, LinkComponent: Link })
17528
+ ] }),
17529
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto pr-[2.5rem] pt-[2rem]", children: /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span: selectedSpan }) })
17530
+ ] })
17531
+ ] })
17532
+ ]
17533
+ }
17534
+ )
17535
+ ]
17536
+ }
17537
+ ),
17538
+ /* @__PURE__ */ jsxRuntime.jsx(
17539
+ SpanDialog,
17540
+ {
17541
+ span: selectedSpan,
17542
+ isOpen: Boolean(dialogIsOpen && selectedSpanId && !combinedView),
17543
+ onClose: () => setDialogIsOpen(false),
17544
+ onNext: thereIsNextSpan() ? toNextSpan : void 0,
17545
+ onPrevious: thereIsPreviousSpan() ? toPreviousSpan : void 0,
17546
+ onViewToggle: () => setCombinedView(!combinedView),
17547
+ spanInfo: selectedSpanInfo
17548
+ }
17549
+ )
17550
+ ] });
15854
17551
  }
15855
- function TracesViewInner({ traces, error, runId, stepName, className, setEndOfListElement }) {
15856
- const hasRunRef = React.useRef(false);
15857
- const [sidebarWidth, setSidebarWidth] = React.useState(100);
15858
- const { isOpen: open, setTrace, setIsOpen, setSpan } = React.useContext(TraceContext);
15859
- React.useEffect(() => {
15860
- if (hasRunRef.current) return;
15861
- if (!runId || !stepName) return;
15862
- const matchingTrace = traces.find((trace) => trace.runId === runId);
15863
- if (!matchingTrace) return;
15864
- const matchingSpan = matchingTrace.trace.find((span) => span.name.includes(stepName));
15865
- if (!matchingSpan) return;
15866
- setTrace(matchingTrace.trace);
15867
- setSpan(matchingSpan);
15868
- setIsOpen(true);
15869
- hasRunRef.current = true;
15870
- }, [runId, traces, setTrace]);
15871
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: clsx("h-full relative overflow-hidden flex", className), children: [
15872
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "h-full overflow-y-scroll w-full", children: [
15873
- /* @__PURE__ */ jsxRuntime.jsx(TracesTable, { traces, error }),
15874
- /* @__PURE__ */ jsxRuntime.jsx("div", { "aria-hidden": true, ref: setEndOfListElement })
17552
+
17553
+ function TracesTools({
17554
+ onEntityChange,
17555
+ onReset,
17556
+ selectedEntity,
17557
+ entityOptions,
17558
+ onDateChange,
17559
+ selectedDateFrom,
17560
+ selectedDateTo,
17561
+ isLoading
17562
+ }) {
17563
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex flex-wrap gap-x-[2rem] gap-y-[1rem]"), children: [
17564
+ /* @__PURE__ */ jsxRuntime.jsx(
17565
+ SelectField,
17566
+ {
17567
+ label: "Filter by Entity",
17568
+ name: "select-entity",
17569
+ placeholder: "Select...",
17570
+ options: entityOptions || [],
17571
+ onValueChange: (val) => {
17572
+ const entity = entityOptions?.find((entity2) => entity2.value === val);
17573
+ if (entity) {
17574
+ onEntityChange(entity);
17575
+ }
17576
+ },
17577
+ value: selectedEntity?.value || "",
17578
+ className: "min-w-[20rem]",
17579
+ disabled: isLoading
17580
+ }
17581
+ ),
17582
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex gap-[1rem] items-center flex-wrap mr-auto"), children: [
17583
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("shrink-0 text-[0.875rem] text-icon3"), children: "Filter by Date & time range" }),
17584
+ /* @__PURE__ */ jsxRuntime.jsx(
17585
+ DateTimePicker,
17586
+ {
17587
+ placeholder: "From",
17588
+ value: selectedDateFrom,
17589
+ maxValue: selectedDateTo,
17590
+ onValueChange: (date) => onDateChange?.(date, "from"),
17591
+ className: "min-w-[15rem]",
17592
+ defaultTimeStrValue: "12:00 AM",
17593
+ disabled: isLoading
17594
+ }
17595
+ ),
17596
+ /* @__PURE__ */ jsxRuntime.jsx(
17597
+ DateTimePicker,
17598
+ {
17599
+ placeholder: "To",
17600
+ value: selectedDateTo,
17601
+ minValue: selectedDateFrom,
17602
+ onValueChange: (date) => onDateChange?.(date, "to"),
17603
+ className: "min-w-[15rem]",
17604
+ defaultTimeStrValue: "11:59 PM",
17605
+ disabled: isLoading
17606
+ }
17607
+ )
15875
17608
  ] }),
15876
- open && /* @__PURE__ */ jsxRuntime.jsx(TracesSidebar, { width: sidebarWidth, onResize: setSidebarWidth })
17609
+ /* @__PURE__ */ jsxRuntime.jsxs(Button, { variant: "primary", onClick: onReset, disabled: isLoading, children: [
17610
+ "Reset ",
17611
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XIcon, {})
17612
+ ] })
15877
17613
  ] });
15878
17614
  }
15879
- const TracesViewSkeleton = () => {
15880
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full relative overflow-hidden flex", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full overflow-y-scroll w-full", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-10" }) }) });
15881
- };
15882
17615
 
15883
17616
  const DataTable = ({
15884
17617
  columns,
@@ -16523,8 +18256,11 @@ exports.Crumb = Crumb;
16523
18256
  exports.DarkLogo = DarkLogo;
16524
18257
  exports.DataTable = DataTable;
16525
18258
  exports.DateTimeCell = DateTimeCell;
18259
+ exports.DateTimePicker = DateTimePicker;
18260
+ exports.DateTimePickerContent = DateTimePickerContent;
16526
18261
  exports.DbIcon = DbIcon;
16527
18262
  exports.DebugIcon = DebugIcon;
18263
+ exports.DefaultTrigger = DefaultTrigger;
16528
18264
  exports.DeploymentIcon = DeploymentIcon;
16529
18265
  exports.DividerIcon = DividerIcon;
16530
18266
  exports.DocsIcon = DocsIcon;
@@ -16538,9 +18274,16 @@ exports.EntityContent = EntityContent;
16538
18274
  exports.EntityDescription = EntityDescription;
16539
18275
  exports.EntityHeader = EntityHeader;
16540
18276
  exports.EntityIcon = EntityIcon;
18277
+ exports.EntityMainHeader = EntityMainHeader;
16541
18278
  exports.EntityName = EntityName;
16542
18279
  exports.Entry = Entry;
16543
18280
  exports.EntryCell = EntryCell;
18281
+ exports.EntryList = EntryList;
18282
+ exports.EntryListItem = EntryListItem;
18283
+ exports.EntryListPageHeader = EntryListPageHeader;
18284
+ exports.EntryListStatusCell = EntryListStatusCell;
18285
+ exports.EntryListTextCell = EntryListTextCell;
18286
+ exports.EntryListToolbar = EntryListToolbar;
16544
18287
  exports.EnvIcon = EnvIcon;
16545
18288
  exports.EvaluatorCoinIcon = EvaluatorCoinIcon;
16546
18289
  exports.FiltersIcon = FiltersIcon;
@@ -16580,6 +18323,7 @@ exports.NetworkTable = NetworkTable;
16580
18323
  exports.NetworkTableEmpty = NetworkTableEmpty;
16581
18324
  exports.NetworkTableSkeleton = NetworkTableSkeleton;
16582
18325
  exports.OpenAIIcon = OpenAIIcon;
18326
+ exports.PageHeader = PageHeader;
16583
18327
  exports.PlaygroundQueryClient = PlaygroundQueryClient;
16584
18328
  exports.PlaygroundTabs = PlaygroundTabs;
16585
18329
  exports.PromptIcon = PromptIcon;
@@ -16597,6 +18341,16 @@ exports.SearchField = SearchField;
16597
18341
  exports.Searchbar = Searchbar;
16598
18342
  exports.SelectField = SelectField;
16599
18343
  exports.SettingsIcon = SettingsIcon;
18344
+ exports.SideDialog = SideDialog;
18345
+ exports.SideDialogCodeSection = SideDialogCodeSection;
18346
+ exports.SideDialogContent = SideDialogContent;
18347
+ exports.SideDialogFooter = SideDialogFooter;
18348
+ exports.SideDialogFooterGroup = SideDialogFooterGroup;
18349
+ exports.SideDialogHeader = SideDialogHeader;
18350
+ exports.SideDialogHeading = SideDialogHeading;
18351
+ exports.SideDialogKeyValueList = SideDialogKeyValueList;
18352
+ exports.SideDialogSection = SideDialogSection;
18353
+ exports.SideDialogTop = SideDialogTop;
16600
18354
  exports.SlashIcon = SlashIcon;
16601
18355
  exports.SliderField = SliderField;
16602
18356
  exports.Tab = Tab;
@@ -16611,6 +18365,7 @@ exports.TemplateInstallation = TemplateInstallation;
16611
18365
  exports.TemplateSuccess = TemplateSuccess;
16612
18366
  exports.TemplatesList = TemplatesList;
16613
18367
  exports.TemplatesTools = TemplatesTools;
18368
+ exports.TextAndIcon = TextAndIcon;
16614
18369
  exports.TextareaField = TextareaField;
16615
18370
  exports.Th = Th;
16616
18371
  exports.Thead = Thead;
@@ -16624,7 +18379,12 @@ exports.ToolList = ToolList;
16624
18379
  exports.ToolListEmpty = ToolListEmpty;
16625
18380
  exports.ToolListSkeleton = ToolListSkeleton;
16626
18381
  exports.ToolsIcon = ToolsIcon;
18382
+ exports.TraceDialog = TraceDialog;
16627
18383
  exports.TraceIcon = TraceIcon;
18384
+ exports.TraceTimeline = TraceTimeline;
18385
+ exports.TraceTimelineLegend = TraceTimelineLegend;
18386
+ exports.TraceTimelineSpan = TraceTimelineSpan;
18387
+ exports.TracesTools = TracesTools;
16628
18388
  exports.TracesView = TracesView;
16629
18389
  exports.TracesViewSkeleton = TracesViewSkeleton;
16630
18390
  exports.TsIcon = TsIcon;
@@ -16647,9 +18407,14 @@ exports.WorkingMemoryProvider = WorkingMemoryProvider;
16647
18407
  exports.allowedAiSpanAttributes = allowedAiSpanAttributes;
16648
18408
  exports.cleanString = cleanString;
16649
18409
  exports.formatDuration = formatDuration;
18410
+ exports.formatHierarchicalSpans = formatHierarchicalSpans;
16650
18411
  exports.formatOtelTimestamp = formatOtelTimestamp;
16651
18412
  exports.formatOtelTimestamp2 = formatOtelTimestamp2;
18413
+ exports.getColumnTemplate = getColumnTemplate;
18414
+ exports.getShortId = getShortId;
18415
+ exports.getSpanTypeUi = getSpanTypeUi;
16652
18416
  exports.providerMapToIcon = providerMapToIcon;
18417
+ exports.spanTypePrefixes = spanTypePrefixes;
16653
18418
  exports.transformKey = transformKey;
16654
18419
  exports.useAgentSettings = useAgentSettings;
16655
18420
  exports.useCurrentRun = useCurrentRun;