@mastra/playground-ui 5.1.1 → 5.1.2-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.
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { useMessage, MessagePrimitive, ActionBarPrimitive, useComposerRuntime, ComposerPrimitive, useAttachment, AttachmentPrimitive, ThreadPrimitive, useExternalStoreRuntime, CompositeAttachmentAdapter, SimpleImageAttachmentAdapter, AssistantRuntimeProvider } from '@assistant-ui/react';
3
- import { CheckIcon as CheckIcon$1, CopyIcon, ChevronUpIcon, X, FileIcon, CircleXIcon, Mic, PlusIcon, ArrowUp, Copy, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Check, ChevronUp, ChevronDown, LoaderCircle, ChevronDownIcon, ExternalLinkIcon, PauseIcon, Loader2, CircleDashed, Footprints, CircleCheck, CircleX, Workflow, AlertCircleIcon, AlertCircle, CalendarIcon, Braces, Brackets, TrashIcon, Plus, Minus, Maximize, CirclePause } from 'lucide-react';
3
+ import { CheckIcon as CheckIcon$1, CopyIcon, ChevronUpIcon, X, FileIcon, CircleXIcon, Mic, PlusIcon, ArrowUp, Copy, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Check, ChevronUp, ChevronDown, LoaderCircle, ChevronDownIcon, ExternalLinkIcon, Network, PauseIcon, Loader2, CircleDashed, Footprints, CircleCheck, CircleX, Workflow, AlertCircleIcon, AlertCircle, CalendarIcon, Braces, Brackets, TrashIcon, Plus, Minus, Maximize, CirclePause } from 'lucide-react';
4
4
  import * as React from 'react';
5
5
  import React__default, { forwardRef, useState, useEffect, memo, useMemo, useRef, createContext, useContext, useCallback, Suspense, Fragment as Fragment$1 } from 'react';
6
6
  import { Slot } from '@radix-ui/react-slot';
@@ -3341,8 +3341,8 @@ const ChevronIcon = (props) => /* @__PURE__ */ jsx("svg", { width: "16", height:
3341
3341
  {
3342
3342
  d: "M4.60059 6.30005L8.00098 9.70005L11.3996 6.30142",
3343
3343
  stroke: "currentColor",
3344
- "stroke-width": "1.5",
3345
- "stroke-linecap": "round"
3344
+ strokeWidth: "1.5",
3345
+ strokeLinecap: "round"
3346
3346
  }
3347
3347
  ) });
3348
3348
 
@@ -6043,13 +6043,15 @@ const refineTraces = (traces, isWorkflow = false) => {
6043
6043
  parentSpanId: parentSpan?.id === span.id ? null : span?.parentSpanId
6044
6044
  }));
6045
6045
  const failedStatus = value.find((span) => span.status.code !== 0)?.status;
6046
+ const runId = value?.[0]?.attributes?.runId;
6046
6047
  return {
6047
6048
  traceId: key,
6048
6049
  serviceName: parentSpan?.name || key,
6049
6050
  duration: parentSpan?.duration || value.reduce((acc, curr) => acc + curr.duration, 0),
6050
6051
  status: failedStatus || parentSpan?.status || value[0].status,
6051
6052
  started: value[0].startTime,
6052
- trace: enrichedSpans
6053
+ trace: enrichedSpans,
6054
+ runId: runId ? String(runId) : void 0
6053
6055
  };
6054
6056
  });
6055
6057
  return tracesData;
@@ -6639,12 +6641,25 @@ const NetworkChat = ({ agentId, memory }) => {
6639
6641
  return /* @__PURE__ */ jsx(MastraNetworkRuntimeProvider, { agentId, memory, modelSettings, children: /* @__PURE__ */ jsx("div", { className: "h-full pb-4", children: /* @__PURE__ */ jsx(Thread, { ToolFallback }) }) });
6640
6642
  };
6641
6643
 
6642
- function WorkflowTraces({ traces, isLoading, error }) {
6643
- return /* @__PURE__ */ jsx(WorkflowTracesInner, { traces, isLoading, error });
6644
+ function WorkflowTraces({ traces, isLoading, error, runId, stepName }) {
6645
+ return /* @__PURE__ */ jsx(WorkflowTracesInner, { traces, isLoading, error, runId, stepName });
6644
6646
  }
6645
- function WorkflowTracesInner({ traces, isLoading, error }) {
6647
+ function WorkflowTracesInner({ traces, isLoading, error, runId, stepName }) {
6648
+ const hasRunRef = useRef(false);
6646
6649
  const [sidebarWidth, setSidebarWidth] = useState(100);
6647
- const { isOpen: open } = useContext(TraceContext);
6650
+ const { isOpen: open, setTrace, setIsOpen, setSpan } = useContext(TraceContext);
6651
+ useEffect(() => {
6652
+ if (hasRunRef.current) return;
6653
+ if (!runId || !stepName) return;
6654
+ const matchingTrace = traces.find((trace) => trace.runId === runId);
6655
+ if (!matchingTrace) return;
6656
+ const matchingSpan = matchingTrace.trace.find((span) => span.name.includes(stepName));
6657
+ if (!matchingSpan) return;
6658
+ setTrace(matchingTrace.trace);
6659
+ setSpan(matchingSpan);
6660
+ setIsOpen(true);
6661
+ hasRunRef.current = true;
6662
+ }, [runId, traces, setTrace]);
6648
6663
  return /* @__PURE__ */ jsxs("main", { className: "h-full relative overflow-hidden flex", children: [
6649
6664
  /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-scroll w-full", children: /* @__PURE__ */ jsx(TracesTable, { traces, isLoading, error }) }),
6650
6665
  open && /* @__PURE__ */ jsx(TracesSidebar, { width: sidebarWidth, onResize: setSidebarWidth })
@@ -7761,7 +7776,88 @@ const useCurrentRun = () => {
7761
7776
  }
7762
7777
  };
7763
7778
  }, {});
7764
- return { steps, isRunning: Boolean(context.payload) };
7779
+ return { steps, isRunning: Boolean(context.payload), runId: context.result?.runId };
7780
+ };
7781
+
7782
+ const CodeDialogContent = ({ data }) => {
7783
+ const theme = useCodemirrorTheme();
7784
+ if (typeof data !== "string") {
7785
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7786
+ /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: JSON.stringify(data, null, 2) }) }),
7787
+ /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: JSON.stringify(data, null, 2), theme, extensions: [jsonLanguage] }) })
7788
+ ] });
7789
+ }
7790
+ try {
7791
+ const json = JSON.parse(data);
7792
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7793
+ /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: data }) }),
7794
+ /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: JSON.stringify(json, null, 2), theme, extensions: [jsonLanguage] }) })
7795
+ ] });
7796
+ } catch (error) {
7797
+ return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7798
+ /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: data }) }),
7799
+ /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: data, theme, extensions: [] }) })
7800
+ ] });
7801
+ }
7802
+ };
7803
+
7804
+ const WorkflowStepActionBar = ({
7805
+ input,
7806
+ output,
7807
+ error,
7808
+ mapConfig,
7809
+ stepName,
7810
+ onShowTrace
7811
+ }) => {
7812
+ const [isInputOpen, setIsInputOpen] = useState(false);
7813
+ const [isOutputOpen, setIsOutputOpen] = useState(false);
7814
+ const [isErrorOpen, setIsErrorOpen] = useState(false);
7815
+ const [isMapConfigOpen, setIsMapConfigOpen] = useState(false);
7816
+ const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7817
+ const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
7818
+ return /* @__PURE__ */ jsx(Fragment, { children: (input || output || error || mapConfig) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center bg-surface4 border-t-sm border-border1 px-2 py-1 gap-2 rounded-b-lg", children: [
7819
+ mapConfig && /* @__PURE__ */ jsxs(Fragment, { children: [
7820
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
7821
+ /* @__PURE__ */ jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7822
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7823
+ stepName,
7824
+ " map config"
7825
+ ] }),
7826
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: mapConfig }) })
7827
+ ] }) })
7828
+ ] }),
7829
+ input && /* @__PURE__ */ jsxs(Fragment, { children: [
7830
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsInputOpen(true), children: "Input" }),
7831
+ /* @__PURE__ */ jsx(Dialog, { open: isInputOpen, onOpenChange: setIsInputOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7832
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7833
+ stepName,
7834
+ " input"
7835
+ ] }),
7836
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: input }) })
7837
+ ] }) })
7838
+ ] }),
7839
+ output && /* @__PURE__ */ jsxs(Fragment, { children: [
7840
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsOutputOpen(true), children: "Output" }),
7841
+ /* @__PURE__ */ jsx(Dialog, { open: isOutputOpen, onOpenChange: setIsOutputOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7842
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7843
+ stepName,
7844
+ " output"
7845
+ ] }),
7846
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: output }) })
7847
+ ] }) })
7848
+ ] }),
7849
+ error && /* @__PURE__ */ jsxs(Fragment, { children: [
7850
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsErrorOpen(true), children: "Error" }),
7851
+ /* @__PURE__ */ jsx(Dialog, { open: isErrorOpen, onOpenChange: setIsErrorOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7852
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7853
+ stepName,
7854
+ " error"
7855
+ ] }),
7856
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: error }) })
7857
+ ] }) })
7858
+ ] }),
7859
+ onShowTrace && /* @__PURE__ */ jsx(Button, { onClick: onShowTrace, children: "Show trace" })
7860
+ ] }) });
7765
7861
  };
7766
7862
 
7767
7863
  function WorkflowConditionNode({ data }) {
@@ -7773,101 +7869,98 @@ function WorkflowConditionNode({ data }) {
7773
7869
  const { steps } = useCurrentRun();
7774
7870
  const previousStep = steps[previousStepId];
7775
7871
  const nextStep = steps[nextStepId];
7776
- return /* @__PURE__ */ jsxs(
7777
- Collapsible,
7778
- {
7779
- open: !isCollapsible ? true : open,
7780
- onOpenChange: (_open) => {
7781
- if (isCollapsible) {
7782
- setOpen(_open);
7783
- }
7784
- },
7785
- className: cn(
7786
- "bg-mastra-bg-3 rounded-md w-[274px] flex flex-col p-2 gap-2 border-sm border-border1",
7787
- previousStep?.status === "success" && nextStep && "ring-2 ring-accent1",
7788
- previousStep?.status === "failed" && nextStep && "ring-2 ring-accent2"
7789
- ),
7790
- children: [
7791
- /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
7792
- /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full", children: [
7793
- /* @__PURE__ */ jsx(
7794
- Text,
7872
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
7873
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
7874
+ /* @__PURE__ */ jsxs(
7875
+ "div",
7876
+ {
7877
+ className: cn(
7878
+ "bg-surface3 rounded-lg w-[300px] border-sm border-border1",
7879
+ previousStep?.status === "success" && nextStep && "ring-2 ring-accent1",
7880
+ previousStep?.status === "failed" && nextStep && "ring-2 ring-accent2"
7881
+ ),
7882
+ children: [
7883
+ /* @__PURE__ */ jsxs(
7884
+ Collapsible,
7795
7885
  {
7796
- size: "xs",
7797
- weight: "medium",
7798
- className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px] w-fit",
7799
- children: type?.toUpperCase()
7886
+ open: !isCollapsible ? true : open,
7887
+ onOpenChange: (_open) => {
7888
+ if (isCollapsible) {
7889
+ setOpen(_open);
7890
+ }
7891
+ },
7892
+ children: [
7893
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full px-3 py-2", children: [
7894
+ /* @__PURE__ */ jsx(Badge$1, { icon: type === "when" ? /* @__PURE__ */ jsx(Network, { className: "text-[#ECB047]" }) : null, children: type?.toUpperCase() }),
7895
+ isCollapsible && /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(
7896
+ ChevronDown,
7897
+ {
7898
+ className: cn("transition-transform text-icon3", {
7899
+ "transform rotate-180": open
7900
+ })
7901
+ }
7902
+ ) })
7903
+ ] }),
7904
+ type === "else" ? null : /* @__PURE__ */ jsx(CollapsibleContent, { className: "flex flex-col gap-2 pb-2", children: conditions.map((condition, index) => {
7905
+ return condition.fnString ? /* @__PURE__ */ jsxs("div", { className: "px-3", children: [
7906
+ /* @__PURE__ */ jsx(Highlight, { theme: themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx(
7907
+ "pre",
7908
+ {
7909
+ className: `${className} relative font-mono p-3 w-full cursor-pointer rounded-lg text-xs !bg-surface4 overflow-scroll`,
7910
+ onClick: () => setOpenDialog(true),
7911
+ style,
7912
+ children: tokens.map((line, i) => /* @__PURE__ */ jsxs("div", { ...getLineProps({ line }), children: [
7913
+ /* @__PURE__ */ jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7914
+ line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
7915
+ ] }, i))
7916
+ }
7917
+ ) }),
7918
+ /* @__PURE__ */ jsx(Dialog, { open: openDialog, onOpenChange: setOpenDialog, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-[30rem] bg-surface2 p-4", children: [
7919
+ /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: "Condition Function" }),
7920
+ /* @__PURE__ */ jsx(ScrollArea, { className: "w-full p-2 pt-4", maxHeight: "400px", children: /* @__PURE__ */ jsx(
7921
+ Highlight,
7922
+ {
7923
+ theme: themes.oneDark,
7924
+ code: String(condition.fnString).trim(),
7925
+ language: "javascript",
7926
+ children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx(
7927
+ "pre",
7928
+ {
7929
+ className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full rounded-lg mt-2 dark:bg-zinc-800`,
7930
+ style: {
7931
+ ...style,
7932
+ backgroundColor: "#121212",
7933
+ padding: "0 0.75rem 0 0"
7934
+ },
7935
+ children: tokens.map((line, i) => /* @__PURE__ */ jsxs("div", { ...getLineProps({ line }), children: [
7936
+ /* @__PURE__ */ jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7937
+ line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
7938
+ ] }, i))
7939
+ }
7940
+ )
7941
+ }
7942
+ ) })
7943
+ ] }) })
7944
+ ] }, `${condition.fnString}-${index}`) : /* @__PURE__ */ jsx(Fragment$1, { children: condition.ref?.step ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
7945
+ index === 0 ? null : /* @__PURE__ */ jsx(Badge$1, { icon: /* @__PURE__ */ jsx(Network, { className: "text-[#ECB047]" }), children: condition.conj?.toLocaleUpperCase() || "WHEN" }),
7946
+ /* @__PURE__ */ jsxs(Text, { size: "xs", className: " text-mastra-el-3 flex-1", children: [
7947
+ condition.ref.step.id || condition.ref.step,
7948
+ "'s ",
7949
+ condition.ref.path,
7950
+ " ",
7951
+ Object.entries(condition.query).map(([key, value]) => `${key} ${String(value)}`)
7952
+ ] })
7953
+ ] }) : null }, `${condition.ref?.path}-${index}`);
7954
+ }) })
7955
+ ]
7800
7956
  }
7801
7957
  ),
7802
- isCollapsible && /* @__PURE__ */ jsx(
7803
- ChevronDown,
7804
- {
7805
- className: cn("w-4 h-4 transition-transform", {
7806
- "transform rotate-180": open
7807
- })
7808
- }
7809
- )
7810
- ] }),
7811
- type === "else" ? null : /* @__PURE__ */ jsx(CollapsibleContent, { className: "flex flex-col gap-2", children: conditions.map((condition, index) => {
7812
- return condition.fnString ? /* @__PURE__ */ jsxs(Fragment$1, { children: [
7813
- /* @__PURE__ */ jsx(Highlight, { theme: themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx(
7814
- "pre",
7815
- {
7816
- className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full cursor-pointer rounded-lg mt-2`,
7817
- style: {
7818
- ...style,
7819
- backgroundColor: "transparent",
7820
- border: "1px solid #343434",
7821
- maxHeight: "9.62rem"
7822
- },
7823
- onClick: () => setOpenDialog(true),
7824
- children: tokens.map((line, i) => /* @__PURE__ */ jsxs("div", { ...getLineProps({ line }), children: [
7825
- /* @__PURE__ */ jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7826
- line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
7827
- ] }, i))
7828
- }
7829
- ) }),
7830
- /* @__PURE__ */ jsx(Dialog, { open: openDialog, onOpenChange: setOpenDialog, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-[30rem] bg-[#121212] p-[0.5rem]", children: [
7831
- /* @__PURE__ */ jsx(DialogTitle, { className: "sr-only", children: "Condition Function" }),
7832
- /* @__PURE__ */ jsx(ScrollArea, { className: "w-full p-2", maxHeight: "400px", children: /* @__PURE__ */ jsx(Highlight, { theme: themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsx(
7833
- "pre",
7834
- {
7835
- className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full rounded-lg mt-2 dark:bg-zinc-800`,
7836
- style: {
7837
- ...style,
7838
- backgroundColor: "#121212",
7839
- padding: "0 0.75rem 0 0"
7840
- },
7841
- children: tokens.map((line, i) => /* @__PURE__ */ jsxs("div", { ...getLineProps({ line }), children: [
7842
- /* @__PURE__ */ jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7843
- line.map((token, key) => /* @__PURE__ */ jsx("span", { ...getTokenProps({ token }) }, key))
7844
- ] }, i))
7845
- }
7846
- ) }) })
7847
- ] }) })
7848
- ] }, `${condition.fnString}-${index}`) : /* @__PURE__ */ jsx(Fragment$1, { children: condition.ref?.step ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
7849
- index === 0 ? null : /* @__PURE__ */ jsx(
7850
- Text,
7851
- {
7852
- size: "xs",
7853
- weight: "medium",
7854
- className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px]",
7855
- children: condition.conj?.toLocaleUpperCase() || "WHEN"
7856
- }
7857
- ),
7858
- /* @__PURE__ */ jsxs(Text, { size: "xs", className: " text-mastra-el-3 flex-1", children: [
7859
- condition.ref.step.id || condition.ref.step,
7860
- "'s ",
7861
- condition.ref.path,
7862
- " ",
7863
- Object.entries(condition.query).map(([key, value]) => `${key} ${String(value)}`)
7864
- ] })
7865
- ] }) : null }, `${condition.ref?.path}-${index}`);
7866
- }) }),
7867
- /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: { visibility: "hidden" } })
7868
- ]
7869
- }
7870
- );
7958
+ /* @__PURE__ */ jsx(WorkflowStepActionBar, { stepName: nextStepId, input: previousStep?.output, mapConfig: data.mapConfig })
7959
+ ]
7960
+ }
7961
+ ),
7962
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: { visibility: "hidden" } })
7963
+ ] });
7871
7964
  }
7872
7965
 
7873
7966
  const Clock = ({ startedAt, endedAt }) => {
@@ -7885,38 +7978,15 @@ const Clock = ({ startedAt, endedAt }) => {
7885
7978
  ] });
7886
7979
  };
7887
7980
 
7888
- const CodeDialogContent = ({ data }) => {
7889
- const theme = useCodemirrorTheme();
7890
- if (typeof data !== "string") {
7891
- return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7892
- /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: JSON.stringify(data, null, 2) }) }),
7893
- /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: JSON.stringify(data, null, 2), theme, extensions: [jsonLanguage] }) })
7894
- ] });
7895
- }
7896
- try {
7897
- const json = JSON.parse(data);
7898
- return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7899
- /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: data }) }),
7900
- /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: JSON.stringify(json, null, 2), theme, extensions: [jsonLanguage] }) })
7901
- ] });
7902
- } catch (error) {
7903
- return /* @__PURE__ */ jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7904
- /* @__PURE__ */ jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsx(CopyButton, { content: data }) }),
7905
- /* @__PURE__ */ jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsx(CodeMirror, { value: data, theme, extensions: [] }) })
7906
- ] });
7907
- }
7908
- };
7909
-
7910
- function WorkflowDefaultNode({ data }) {
7911
- const [isInputOpen, setIsInputOpen] = useState(false);
7912
- const [isOutputOpen, setIsOutputOpen] = useState(false);
7913
- const [isErrorOpen, setIsErrorOpen] = useState(false);
7914
- const [isMapConfigOpen, setIsMapConfigOpen] = useState(false);
7915
- const { steps, isRunning } = useCurrentRun();
7916
- const { label, description, withoutTopHandle, withoutBottomHandle, mapConfig } = data;
7917
- const step = steps[label];
7918
- const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7919
- const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
7981
+ function WorkflowDefaultNode({
7982
+ data,
7983
+ onShowTrace,
7984
+ parentWorkflowName
7985
+ }) {
7986
+ const { steps, isRunning, runId } = useCurrentRun();
7987
+ const { label, description, withoutTopHandle, withoutBottomHandle } = data;
7988
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
7989
+ const step = steps[fullLabel];
7920
7990
  return /* @__PURE__ */ jsxs(Fragment, { children: [
7921
7991
  !withoutTopHandle && /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
7922
7992
  /* @__PURE__ */ jsxs(
@@ -7943,48 +8013,17 @@ function WorkflowDefaultNode({ data }) {
7943
8013
  ] })
7944
8014
  ] }),
7945
8015
  description && /* @__PURE__ */ jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
7946
- (step?.input || step?.output || step?.error || mapConfig) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center bg-surface4 border-t-sm border-border1 px-2 py-1 gap-2 rounded-b-lg", children: [
7947
- mapConfig && /* @__PURE__ */ jsxs(Fragment, { children: [
7948
- /* @__PURE__ */ jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
7949
- /* @__PURE__ */ jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7950
- /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7951
- label,
7952
- " map config"
7953
- ] }),
7954
- /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: mapConfig }) })
7955
- ] }) })
7956
- ] }),
7957
- step?.input && /* @__PURE__ */ jsxs(Fragment, { children: [
7958
- /* @__PURE__ */ jsx(Button, { onClick: () => setIsInputOpen(true), children: "Input" }),
7959
- /* @__PURE__ */ jsx(Dialog, { open: isInputOpen, onOpenChange: setIsInputOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7960
- /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7961
- label,
7962
- " input"
7963
- ] }),
7964
- /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: step.input }) })
7965
- ] }) })
7966
- ] }),
7967
- step?.output && /* @__PURE__ */ jsxs(Fragment, { children: [
7968
- /* @__PURE__ */ jsx(Button, { onClick: () => setIsOutputOpen(true), children: "Output" }),
7969
- /* @__PURE__ */ jsx(Dialog, { open: isOutputOpen, onOpenChange: setIsOutputOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7970
- /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7971
- label,
7972
- " output"
7973
- ] }),
7974
- /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: step.output }) })
7975
- ] }) })
7976
- ] }),
7977
- step?.error && /* @__PURE__ */ jsxs(Fragment, { children: [
7978
- /* @__PURE__ */ jsx(Button, { onClick: () => setIsErrorOpen(true), children: "Error" }),
7979
- /* @__PURE__ */ jsx(Dialog, { open: isErrorOpen, onOpenChange: setIsErrorOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
7980
- /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
7981
- label,
7982
- " error"
7983
- ] }),
7984
- /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: step?.error }) })
7985
- ] }) })
7986
- ] })
7987
- ] })
8016
+ /* @__PURE__ */ jsx(
8017
+ WorkflowStepActionBar,
8018
+ {
8019
+ stepName: label,
8020
+ input: step?.input,
8021
+ output: step?.output,
8022
+ error: step?.error,
8023
+ mapConfig: data.mapConfig,
8024
+ onShowTrace: runId ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0
8025
+ }
8026
+ )
7988
8027
  ]
7989
8028
  }
7990
8029
  ),
@@ -9273,19 +9312,20 @@ const ZoomSlider = forwardRef(({ className, ...props }) => {
9273
9312
  });
9274
9313
  ZoomSlider.displayName = "ZoomSlider";
9275
9314
 
9276
- function WorkflowNestedGraph({ stepGraph, open }) {
9315
+ function WorkflowNestedGraph({ stepGraph, open, workflowName }) {
9277
9316
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
9278
9317
  stepGraph
9279
9318
  });
9280
9319
  const [isMounted, setIsMounted] = useState(false);
9281
9320
  const [nodes, _, onNodesChange] = useNodesState(initialNodes);
9282
9321
  const [edges] = useEdgesState(initialEdges);
9322
+ const { steps } = useCurrentRun();
9283
9323
  const nodeTypes = {
9284
- "default-node": WorkflowDefaultNode,
9324
+ "default-node": (props) => /* @__PURE__ */ jsx(WorkflowDefaultNode, { parentWorkflowName: workflowName, ...props }),
9285
9325
  "condition-node": WorkflowConditionNode,
9286
9326
  "after-node": WorkflowAfterNode,
9287
9327
  "loop-result-node": WorkflowLoopResultNode,
9288
- "nested-node": WorkflowNestedNode
9328
+ "nested-node": (props) => /* @__PURE__ */ jsx(WorkflowNestedNode, { parentWorkflowName: workflowName, ...props })
9289
9329
  };
9290
9330
  useEffect(() => {
9291
9331
  if (open) {
@@ -9298,7 +9338,13 @@ function WorkflowNestedGraph({ stepGraph, open }) {
9298
9338
  ReactFlow,
9299
9339
  {
9300
9340
  nodes,
9301
- edges,
9341
+ edges: edges.map((e) => ({
9342
+ ...e,
9343
+ style: {
9344
+ ...e.style,
9345
+ stroke: steps[`${workflowName}.${e.data?.previousStepId}`]?.status === "success" && steps[`${workflowName}.${e.data?.nextStepId}`] ? "#22c55e" : void 0
9346
+ }
9347
+ })),
9302
9348
  fitView: true,
9303
9349
  fitViewOptions: {
9304
9350
  maxZoom: 1
@@ -9324,6 +9370,7 @@ function WorkflowNestedGraphProvider({ children }) {
9324
9370
  const [parentStepGraphList, setParentStepGraphList] = useState([]);
9325
9371
  const [openDialog, setOpenDialog] = useState(false);
9326
9372
  const [label, setLabel] = useState("");
9373
+ const [fullStep, setFullStep] = useState("");
9327
9374
  const [switching, setSwitching] = useState(false);
9328
9375
  const closeNestedGraph = () => {
9329
9376
  if (parentStepGraphList.length) {
@@ -9331,6 +9378,7 @@ function WorkflowNestedGraphProvider({ children }) {
9331
9378
  const lastStepGraph = parentStepGraphList[parentStepGraphList.length - 1];
9332
9379
  setStepGraph(lastStepGraph.stepGraph);
9333
9380
  setLabel(lastStepGraph.label);
9381
+ setFullStep(lastStepGraph.fullStep);
9334
9382
  setParentStepGraphList(parentStepGraphList.slice(0, -1));
9335
9383
  setTimeout(() => {
9336
9384
  setSwitching(false);
@@ -9339,17 +9387,20 @@ function WorkflowNestedGraphProvider({ children }) {
9339
9387
  setOpenDialog(false);
9340
9388
  setStepGraph(null);
9341
9389
  setLabel("");
9390
+ setFullStep("");
9342
9391
  }
9343
9392
  };
9344
9393
  const showNestedGraph = ({
9345
9394
  label: newLabel,
9346
- stepGraph: newStepGraph
9395
+ stepGraph: newStepGraph,
9396
+ fullStep: newFullStep
9347
9397
  }) => {
9348
9398
  if (stepGraph) {
9349
9399
  setSwitching(true);
9350
- setParentStepGraphList([...parentStepGraphList, { stepGraph, label }]);
9400
+ setParentStepGraphList([...parentStepGraphList, { stepGraph, label, fullStep }]);
9351
9401
  }
9352
9402
  setLabel(newLabel);
9403
+ setFullStep(newFullStep);
9353
9404
  setStepGraph(newStepGraph);
9354
9405
  setOpenDialog(true);
9355
9406
  setTimeout(() => {
@@ -9373,14 +9424,17 @@ function WorkflowNestedGraphProvider({ children }) {
9373
9424
  " workflow"
9374
9425
  ] })
9375
9426
  ] }),
9376
- switching ? /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowNestedGraph, { stepGraph, open: openDialog }) })
9427
+ switching ? /* @__PURE__ */ jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsx(Spinner, {}) }) : /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowNestedGraph, { stepGraph, open: openDialog, workflowName: fullStep }) })
9377
9428
  ] }) }) })
9378
9429
  ]
9379
9430
  }
9380
9431
  );
9381
9432
  }
9382
9433
 
9383
- function WorkflowNestedNode({ data }) {
9434
+ function WorkflowNestedNode({
9435
+ data,
9436
+ parentWorkflowName
9437
+ }) {
9384
9438
  const [isInputOpen, setIsInputOpen] = useState(false);
9385
9439
  const [isOutputOpen, setIsOutputOpen] = useState(false);
9386
9440
  const [isErrorOpen, setIsErrorOpen] = useState(false);
@@ -9388,7 +9442,8 @@ function WorkflowNestedNode({ data }) {
9388
9442
  const { steps, isRunning } = useCurrentRun();
9389
9443
  const { showNestedGraph } = useContext(WorkflowNestedGraphContext);
9390
9444
  const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig } = data;
9391
- const step = steps[label];
9445
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
9446
+ const step = steps[fullLabel];
9392
9447
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
9393
9448
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
9394
9449
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -9418,7 +9473,7 @@ function WorkflowNestedNode({ data }) {
9418
9473
  ] }),
9419
9474
  description && /* @__PURE__ */ jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
9420
9475
  /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center bg-surface4 border-t-sm border-border1 px-2 py-1 gap-2 rounded-b-lg", children: [
9421
- /* @__PURE__ */ jsx(Button, { onClick: () => showNestedGraph({ label, stepGraph }), children: "View workflow" }),
9476
+ /* @__PURE__ */ jsx(Button, { onClick: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }), children: "View workflow" }),
9422
9477
  mapConfig && /* @__PURE__ */ jsxs(Fragment, { children: [
9423
9478
  /* @__PURE__ */ jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
9424
9479
  /* @__PURE__ */ jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
@@ -9467,13 +9522,13 @@ function WorkflowNestedNode({ data }) {
9467
9522
  ] });
9468
9523
  }
9469
9524
 
9470
- function WorkflowGraphInner({ workflow }) {
9525
+ function WorkflowGraphInner({ workflow, onShowTrace }) {
9471
9526
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
9472
9527
  const [nodes, _, onNodesChange] = useNodesState(initialNodes);
9473
9528
  const [edges] = useEdgesState(initialEdges);
9474
- const { steps } = useCurrentRun();
9529
+ const { steps, runId } = useCurrentRun();
9475
9530
  const nodeTypes = {
9476
- "default-node": WorkflowDefaultNode,
9531
+ "default-node": (props) => /* @__PURE__ */ jsx(WorkflowDefaultNode, { onShowTrace, ...props }),
9477
9532
  "condition-node": WorkflowConditionNode,
9478
9533
  "after-node": WorkflowAfterNode,
9479
9534
  "loop-result-node": WorkflowLoopResultNode,
@@ -9507,7 +9562,7 @@ function WorkflowGraphInner({ workflow }) {
9507
9562
  ) });
9508
9563
  }
9509
9564
 
9510
- function WorkflowGraph({ workflowId, baseUrl }) {
9565
+ function WorkflowGraph({ workflowId, baseUrl, onShowTrace }) {
9511
9566
  const { workflow, isLoading } = useWorkflow(workflowId, baseUrl);
9512
9567
  if (isLoading) {
9513
9568
  return /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-[600px]" }) });
@@ -9522,7 +9577,7 @@ function WorkflowGraph({ workflowId, baseUrl }) {
9522
9577
  ] })
9523
9578
  ] }) });
9524
9579
  }
9525
- return /* @__PURE__ */ jsx(WorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowGraphInner, { workflow }) }) });
9580
+ return /* @__PURE__ */ jsx(WorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(WorkflowGraphInner, { workflow, onShowTrace }) }) });
9526
9581
  }
9527
9582
 
9528
9583
  const WorkflowStatus = ({ stepId, status }) => {