@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.cjs.js CHANGED
@@ -3373,8 +3373,8 @@ const ChevronIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "1
3373
3373
  {
3374
3374
  d: "M4.60059 6.30005L8.00098 9.70005L11.3996 6.30142",
3375
3375
  stroke: "currentColor",
3376
- "stroke-width": "1.5",
3377
- "stroke-linecap": "round"
3376
+ strokeWidth: "1.5",
3377
+ strokeLinecap: "round"
3378
3378
  }
3379
3379
  ) });
3380
3380
 
@@ -6075,13 +6075,15 @@ const refineTraces = (traces, isWorkflow = false) => {
6075
6075
  parentSpanId: parentSpan?.id === span.id ? null : span?.parentSpanId
6076
6076
  }));
6077
6077
  const failedStatus = value.find((span) => span.status.code !== 0)?.status;
6078
+ const runId = value?.[0]?.attributes?.runId;
6078
6079
  return {
6079
6080
  traceId: key,
6080
6081
  serviceName: parentSpan?.name || key,
6081
6082
  duration: parentSpan?.duration || value.reduce((acc, curr) => acc + curr.duration, 0),
6082
6083
  status: failedStatus || parentSpan?.status || value[0].status,
6083
6084
  started: value[0].startTime,
6084
- trace: enrichedSpans
6085
+ trace: enrichedSpans,
6086
+ runId: runId ? String(runId) : void 0
6085
6087
  };
6086
6088
  });
6087
6089
  return tracesData;
@@ -6671,12 +6673,25 @@ const NetworkChat = ({ agentId, memory }) => {
6671
6673
  return /* @__PURE__ */ jsxRuntime.jsx(MastraNetworkRuntimeProvider, { agentId, memory, modelSettings, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full pb-4", children: /* @__PURE__ */ jsxRuntime.jsx(Thread, { ToolFallback }) }) });
6672
6674
  };
6673
6675
 
6674
- function WorkflowTraces({ traces, isLoading, error }) {
6675
- return /* @__PURE__ */ jsxRuntime.jsx(WorkflowTracesInner, { traces, isLoading, error });
6676
+ function WorkflowTraces({ traces, isLoading, error, runId, stepName }) {
6677
+ return /* @__PURE__ */ jsxRuntime.jsx(WorkflowTracesInner, { traces, isLoading, error, runId, stepName });
6676
6678
  }
6677
- function WorkflowTracesInner({ traces, isLoading, error }) {
6679
+ function WorkflowTracesInner({ traces, isLoading, error, runId, stepName }) {
6680
+ const hasRunRef = React.useRef(false);
6678
6681
  const [sidebarWidth, setSidebarWidth] = React.useState(100);
6679
- const { isOpen: open } = React.useContext(TraceContext);
6682
+ const { isOpen: open, setTrace, setIsOpen, setSpan } = React.useContext(TraceContext);
6683
+ React.useEffect(() => {
6684
+ if (hasRunRef.current) return;
6685
+ if (!runId || !stepName) return;
6686
+ const matchingTrace = traces.find((trace) => trace.runId === runId);
6687
+ if (!matchingTrace) return;
6688
+ const matchingSpan = matchingTrace.trace.find((span) => span.name.includes(stepName));
6689
+ if (!matchingSpan) return;
6690
+ setTrace(matchingTrace.trace);
6691
+ setSpan(matchingSpan);
6692
+ setIsOpen(true);
6693
+ hasRunRef.current = true;
6694
+ }, [runId, traces, setTrace]);
6680
6695
  return /* @__PURE__ */ jsxRuntime.jsxs("main", { className: "h-full relative overflow-hidden flex", children: [
6681
6696
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full overflow-y-scroll w-full", children: /* @__PURE__ */ jsxRuntime.jsx(TracesTable, { traces, isLoading, error }) }),
6682
6697
  open && /* @__PURE__ */ jsxRuntime.jsx(TracesSidebar, { width: sidebarWidth, onResize: setSidebarWidth })
@@ -7793,7 +7808,88 @@ const useCurrentRun = () => {
7793
7808
  }
7794
7809
  };
7795
7810
  }, {});
7796
- return { steps, isRunning: Boolean(context.payload) };
7811
+ return { steps, isRunning: Boolean(context.payload), runId: context.result?.runId };
7812
+ };
7813
+
7814
+ const CodeDialogContent = ({ data }) => {
7815
+ const theme = useCodemirrorTheme();
7816
+ if (typeof data !== "string") {
7817
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7818
+ /* @__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) }) }),
7819
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: JSON.stringify(data, null, 2), theme, extensions: [langJson.jsonLanguage] }) })
7820
+ ] });
7821
+ }
7822
+ try {
7823
+ const json = JSON.parse(data);
7824
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7825
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: data }) }),
7826
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: JSON.stringify(json, null, 2), theme, extensions: [langJson.jsonLanguage] }) })
7827
+ ] });
7828
+ } catch (error) {
7829
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7830
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: data }) }),
7831
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: data, theme, extensions: [] }) })
7832
+ ] });
7833
+ }
7834
+ };
7835
+
7836
+ const WorkflowStepActionBar = ({
7837
+ input,
7838
+ output,
7839
+ error,
7840
+ mapConfig,
7841
+ stepName,
7842
+ onShowTrace
7843
+ }) => {
7844
+ const [isInputOpen, setIsInputOpen] = React.useState(false);
7845
+ const [isOutputOpen, setIsOutputOpen] = React.useState(false);
7846
+ const [isErrorOpen, setIsErrorOpen] = React.useState(false);
7847
+ const [isMapConfigOpen, setIsMapConfigOpen] = React.useState(false);
7848
+ const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7849
+ const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
7850
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (input || output || error || mapConfig) && /* @__PURE__ */ jsxRuntime.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: [
7851
+ mapConfig && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7852
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
7853
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7854
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7855
+ stepName,
7856
+ " map config"
7857
+ ] }),
7858
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: mapConfig }) })
7859
+ ] }) })
7860
+ ] }),
7861
+ input && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7862
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsInputOpen(true), children: "Input" }),
7863
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isInputOpen, onOpenChange: setIsInputOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7864
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7865
+ stepName,
7866
+ " input"
7867
+ ] }),
7868
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: input }) })
7869
+ ] }) })
7870
+ ] }),
7871
+ output && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7872
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsOutputOpen(true), children: "Output" }),
7873
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOutputOpen, onOpenChange: setIsOutputOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7874
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7875
+ stepName,
7876
+ " output"
7877
+ ] }),
7878
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: output }) })
7879
+ ] }) })
7880
+ ] }),
7881
+ error && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7882
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsErrorOpen(true), children: "Error" }),
7883
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isErrorOpen, onOpenChange: setIsErrorOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7884
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7885
+ stepName,
7886
+ " error"
7887
+ ] }),
7888
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: error }) })
7889
+ ] }) })
7890
+ ] }),
7891
+ onShowTrace && /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: onShowTrace, children: "Show trace" })
7892
+ ] }) });
7797
7893
  };
7798
7894
 
7799
7895
  function WorkflowConditionNode({ data }) {
@@ -7805,101 +7901,98 @@ function WorkflowConditionNode({ data }) {
7805
7901
  const { steps } = useCurrentRun();
7806
7902
  const previousStep = steps[previousStepId];
7807
7903
  const nextStep = steps[nextStepId];
7808
- return /* @__PURE__ */ jsxRuntime.jsxs(
7809
- Collapsible,
7810
- {
7811
- open: !isCollapsible ? true : open,
7812
- onOpenChange: (_open) => {
7813
- if (isCollapsible) {
7814
- setOpen(_open);
7815
- }
7816
- },
7817
- className: cn(
7818
- "bg-mastra-bg-3 rounded-md w-[274px] flex flex-col p-2 gap-2 border-sm border-border1",
7819
- previousStep?.status === "success" && nextStep && "ring-2 ring-accent1",
7820
- previousStep?.status === "failed" && nextStep && "ring-2 ring-accent2"
7821
- ),
7822
- children: [
7823
- /* @__PURE__ */ jsxRuntime.jsx(react$2.Handle, { type: "target", position: react$2.Position.Top, style: { visibility: "hidden" } }),
7824
- /* @__PURE__ */ jsxRuntime.jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full", children: [
7825
- /* @__PURE__ */ jsxRuntime.jsx(
7826
- Text,
7904
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7905
+ /* @__PURE__ */ jsxRuntime.jsx(react$2.Handle, { type: "target", position: react$2.Position.Top, style: { visibility: "hidden" } }),
7906
+ /* @__PURE__ */ jsxRuntime.jsxs(
7907
+ "div",
7908
+ {
7909
+ className: cn(
7910
+ "bg-surface3 rounded-lg w-[300px] border-sm border-border1",
7911
+ previousStep?.status === "success" && nextStep && "ring-2 ring-accent1",
7912
+ previousStep?.status === "failed" && nextStep && "ring-2 ring-accent2"
7913
+ ),
7914
+ children: [
7915
+ /* @__PURE__ */ jsxRuntime.jsxs(
7916
+ Collapsible,
7827
7917
  {
7828
- size: "xs",
7829
- weight: "medium",
7830
- className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px] w-fit",
7831
- children: type?.toUpperCase()
7918
+ open: !isCollapsible ? true : open,
7919
+ onOpenChange: (_open) => {
7920
+ if (isCollapsible) {
7921
+ setOpen(_open);
7922
+ }
7923
+ },
7924
+ children: [
7925
+ /* @__PURE__ */ jsxRuntime.jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full px-3 py-2", children: [
7926
+ /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: type === "when" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Network, { className: "text-[#ECB047]" }) : null, children: type?.toUpperCase() }),
7927
+ isCollapsible && /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(
7928
+ lucideReact.ChevronDown,
7929
+ {
7930
+ className: cn("transition-transform text-icon3", {
7931
+ "transform rotate-180": open
7932
+ })
7933
+ }
7934
+ ) })
7935
+ ] }),
7936
+ type === "else" ? null : /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent, { className: "flex flex-col gap-2 pb-2", children: conditions.map((condition, index) => {
7937
+ return condition.fnString ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3", children: [
7938
+ /* @__PURE__ */ jsxRuntime.jsx(prismReactRenderer.Highlight, { theme: prismReactRenderer.themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsxRuntime.jsx(
7939
+ "pre",
7940
+ {
7941
+ className: `${className} relative font-mono p-3 w-full cursor-pointer rounded-lg text-xs !bg-surface4 overflow-scroll`,
7942
+ onClick: () => setOpenDialog(true),
7943
+ style,
7944
+ children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ...getLineProps({ line }), children: [
7945
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7946
+ line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
7947
+ ] }, i))
7948
+ }
7949
+ ) }),
7950
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: openDialog, onOpenChange: setOpenDialog, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-[30rem] bg-surface2 p-4", children: [
7951
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "sr-only", children: "Condition Function" }),
7952
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "w-full p-2 pt-4", maxHeight: "400px", children: /* @__PURE__ */ jsxRuntime.jsx(
7953
+ prismReactRenderer.Highlight,
7954
+ {
7955
+ theme: prismReactRenderer.themes.oneDark,
7956
+ code: String(condition.fnString).trim(),
7957
+ language: "javascript",
7958
+ children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsxRuntime.jsx(
7959
+ "pre",
7960
+ {
7961
+ className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full rounded-lg mt-2 dark:bg-zinc-800`,
7962
+ style: {
7963
+ ...style,
7964
+ backgroundColor: "#121212",
7965
+ padding: "0 0.75rem 0 0"
7966
+ },
7967
+ children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ...getLineProps({ line }), children: [
7968
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7969
+ line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
7970
+ ] }, i))
7971
+ }
7972
+ )
7973
+ }
7974
+ ) })
7975
+ ] }) })
7976
+ ] }, `${condition.fnString}-${index}`) : /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: condition.ref?.step ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
7977
+ index === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Network, { className: "text-[#ECB047]" }), children: condition.conj?.toLocaleUpperCase() || "WHEN" }),
7978
+ /* @__PURE__ */ jsxRuntime.jsxs(Text, { size: "xs", className: " text-mastra-el-3 flex-1", children: [
7979
+ condition.ref.step.id || condition.ref.step,
7980
+ "'s ",
7981
+ condition.ref.path,
7982
+ " ",
7983
+ Object.entries(condition.query).map(([key, value]) => `${key} ${String(value)}`)
7984
+ ] })
7985
+ ] }) : null }, `${condition.ref?.path}-${index}`);
7986
+ }) })
7987
+ ]
7832
7988
  }
7833
7989
  ),
7834
- isCollapsible && /* @__PURE__ */ jsxRuntime.jsx(
7835
- lucideReact.ChevronDown,
7836
- {
7837
- className: cn("w-4 h-4 transition-transform", {
7838
- "transform rotate-180": open
7839
- })
7840
- }
7841
- )
7842
- ] }),
7843
- type === "else" ? null : /* @__PURE__ */ jsxRuntime.jsx(CollapsibleContent, { className: "flex flex-col gap-2", children: conditions.map((condition, index) => {
7844
- return condition.fnString ? /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
7845
- /* @__PURE__ */ jsxRuntime.jsx(prismReactRenderer.Highlight, { theme: prismReactRenderer.themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsxRuntime.jsx(
7846
- "pre",
7847
- {
7848
- className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full cursor-pointer rounded-lg mt-2`,
7849
- style: {
7850
- ...style,
7851
- backgroundColor: "transparent",
7852
- border: "1px solid #343434",
7853
- maxHeight: "9.62rem"
7854
- },
7855
- onClick: () => setOpenDialog(true),
7856
- children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ...getLineProps({ line }), children: [
7857
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7858
- line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
7859
- ] }, i))
7860
- }
7861
- ) }),
7862
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: openDialog, onOpenChange: setOpenDialog, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "max-w-[30rem] bg-[#121212] p-[0.5rem]", children: [
7863
- /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "sr-only", children: "Condition Function" }),
7864
- /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "w-full p-2", maxHeight: "400px", children: /* @__PURE__ */ jsxRuntime.jsx(prismReactRenderer.Highlight, { theme: prismReactRenderer.themes.oneDark, code: String(condition.fnString).trim(), language: "javascript", children: ({ className, style, tokens, getLineProps, getTokenProps }) => /* @__PURE__ */ jsxRuntime.jsx(
7865
- "pre",
7866
- {
7867
- className: `${className} relative font-mono text-sm overflow-x-auto p-3 w-full rounded-lg mt-2 dark:bg-zinc-800`,
7868
- style: {
7869
- ...style,
7870
- backgroundColor: "#121212",
7871
- padding: "0 0.75rem 0 0"
7872
- },
7873
- children: tokens.map((line, i) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ...getLineProps({ line }), children: [
7874
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block mr-2 text-muted-foreground", children: i + 1 }),
7875
- line.map((token, key) => /* @__PURE__ */ jsxRuntime.jsx("span", { ...getTokenProps({ token }) }, key))
7876
- ] }, i))
7877
- }
7878
- ) }) })
7879
- ] }) })
7880
- ] }, `${condition.fnString}-${index}`) : /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: condition.ref?.step ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
7881
- index === 0 ? null : /* @__PURE__ */ jsxRuntime.jsx(
7882
- Text,
7883
- {
7884
- size: "xs",
7885
- weight: "medium",
7886
- className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px]",
7887
- children: condition.conj?.toLocaleUpperCase() || "WHEN"
7888
- }
7889
- ),
7890
- /* @__PURE__ */ jsxRuntime.jsxs(Text, { size: "xs", className: " text-mastra-el-3 flex-1", children: [
7891
- condition.ref.step.id || condition.ref.step,
7892
- "'s ",
7893
- condition.ref.path,
7894
- " ",
7895
- Object.entries(condition.query).map(([key, value]) => `${key} ${String(value)}`)
7896
- ] })
7897
- ] }) : null }, `${condition.ref?.path}-${index}`);
7898
- }) }),
7899
- /* @__PURE__ */ jsxRuntime.jsx(react$2.Handle, { type: "source", position: react$2.Position.Bottom, style: { visibility: "hidden" } })
7900
- ]
7901
- }
7902
- );
7990
+ /* @__PURE__ */ jsxRuntime.jsx(WorkflowStepActionBar, { stepName: nextStepId, input: previousStep?.output, mapConfig: data.mapConfig })
7991
+ ]
7992
+ }
7993
+ ),
7994
+ /* @__PURE__ */ jsxRuntime.jsx(react$2.Handle, { type: "source", position: react$2.Position.Bottom, style: { visibility: "hidden" } })
7995
+ ] });
7903
7996
  }
7904
7997
 
7905
7998
  const Clock = ({ startedAt, endedAt }) => {
@@ -7917,38 +8010,15 @@ const Clock = ({ startedAt, endedAt }) => {
7917
8010
  ] });
7918
8011
  };
7919
8012
 
7920
- const CodeDialogContent = ({ data }) => {
7921
- const theme = useCodemirrorTheme();
7922
- if (typeof data !== "string") {
7923
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7924
- /* @__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) }) }),
7925
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: JSON.stringify(data, null, 2), theme, extensions: [langJson.jsonLanguage] }) })
7926
- ] });
7927
- }
7928
- try {
7929
- const json = JSON.parse(data);
7930
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7931
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: data }) }),
7932
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: JSON.stringify(json, null, 2), theme, extensions: [langJson.jsonLanguage] }) })
7933
- ] });
7934
- } catch (error) {
7935
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-h-[500px] overflow-auto relative p-4", children: [
7936
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute right-2 top-2 bg-surface4 rounded-full z-10", children: /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: data }) }),
7937
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-surface4 rounded-lg p-4", children: /* @__PURE__ */ jsxRuntime.jsx(CodeMirror, { value: data, theme, extensions: [] }) })
7938
- ] });
7939
- }
7940
- };
7941
-
7942
- function WorkflowDefaultNode({ data }) {
7943
- const [isInputOpen, setIsInputOpen] = React.useState(false);
7944
- const [isOutputOpen, setIsOutputOpen] = React.useState(false);
7945
- const [isErrorOpen, setIsErrorOpen] = React.useState(false);
7946
- const [isMapConfigOpen, setIsMapConfigOpen] = React.useState(false);
7947
- const { steps, isRunning } = useCurrentRun();
7948
- const { label, description, withoutTopHandle, withoutBottomHandle, mapConfig } = data;
7949
- const step = steps[label];
7950
- const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7951
- const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
8013
+ function WorkflowDefaultNode({
8014
+ data,
8015
+ onShowTrace,
8016
+ parentWorkflowName
8017
+ }) {
8018
+ const { steps, isRunning, runId } = useCurrentRun();
8019
+ const { label, description, withoutTopHandle, withoutBottomHandle } = data;
8020
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
8021
+ const step = steps[fullLabel];
7952
8022
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7953
8023
  !withoutTopHandle && /* @__PURE__ */ jsxRuntime.jsx(react$2.Handle, { type: "target", position: react$2.Position.Top, style: { visibility: "hidden" } }),
7954
8024
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7975,48 +8045,17 @@ function WorkflowDefaultNode({ data }) {
7975
8045
  ] })
7976
8046
  ] }),
7977
8047
  description && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
7978
- (step?.input || step?.output || step?.error || mapConfig) && /* @__PURE__ */ jsxRuntime.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: [
7979
- mapConfig && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7980
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
7981
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7982
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7983
- label,
7984
- " map config"
7985
- ] }),
7986
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: mapConfig }) })
7987
- ] }) })
7988
- ] }),
7989
- step?.input && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7990
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsInputOpen(true), children: "Input" }),
7991
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isInputOpen, onOpenChange: setIsInputOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
7992
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
7993
- label,
7994
- " input"
7995
- ] }),
7996
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: step.input }) })
7997
- ] }) })
7998
- ] }),
7999
- step?.output && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8000
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsOutputOpen(true), children: "Output" }),
8001
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isOutputOpen, onOpenChange: setIsOutputOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
8002
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
8003
- label,
8004
- " output"
8005
- ] }),
8006
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: step.output }) })
8007
- ] }) })
8008
- ] }),
8009
- step?.error && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8010
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsErrorOpen(true), children: "Error" }),
8011
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isErrorOpen, onOpenChange: setIsErrorOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
8012
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
8013
- label,
8014
- " error"
8015
- ] }),
8016
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(CodeDialogContent, { data: step?.error }) })
8017
- ] }) })
8018
- ] })
8019
- ] })
8048
+ /* @__PURE__ */ jsxRuntime.jsx(
8049
+ WorkflowStepActionBar,
8050
+ {
8051
+ stepName: label,
8052
+ input: step?.input,
8053
+ output: step?.output,
8054
+ error: step?.error,
8055
+ mapConfig: data.mapConfig,
8056
+ onShowTrace: runId ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0
8057
+ }
8058
+ )
8020
8059
  ]
8021
8060
  }
8022
8061
  ),
@@ -9305,19 +9344,20 @@ const ZoomSlider = React.forwardRef(({ className, ...props }) => {
9305
9344
  });
9306
9345
  ZoomSlider.displayName = "ZoomSlider";
9307
9346
 
9308
- function WorkflowNestedGraph({ stepGraph, open }) {
9347
+ function WorkflowNestedGraph({ stepGraph, open, workflowName }) {
9309
9348
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
9310
9349
  stepGraph
9311
9350
  });
9312
9351
  const [isMounted, setIsMounted] = React.useState(false);
9313
9352
  const [nodes, _, onNodesChange] = react$2.useNodesState(initialNodes);
9314
9353
  const [edges] = react$2.useEdgesState(initialEdges);
9354
+ const { steps } = useCurrentRun();
9315
9355
  const nodeTypes = {
9316
- "default-node": WorkflowDefaultNode,
9356
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { parentWorkflowName: workflowName, ...props }),
9317
9357
  "condition-node": WorkflowConditionNode,
9318
9358
  "after-node": WorkflowAfterNode,
9319
9359
  "loop-result-node": WorkflowLoopResultNode,
9320
- "nested-node": WorkflowNestedNode
9360
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { parentWorkflowName: workflowName, ...props })
9321
9361
  };
9322
9362
  React.useEffect(() => {
9323
9363
  if (open) {
@@ -9330,7 +9370,13 @@ function WorkflowNestedGraph({ stepGraph, open }) {
9330
9370
  react$2.ReactFlow,
9331
9371
  {
9332
9372
  nodes,
9333
- edges,
9373
+ edges: edges.map((e) => ({
9374
+ ...e,
9375
+ style: {
9376
+ ...e.style,
9377
+ stroke: steps[`${workflowName}.${e.data?.previousStepId}`]?.status === "success" && steps[`${workflowName}.${e.data?.nextStepId}`] ? "#22c55e" : void 0
9378
+ }
9379
+ })),
9334
9380
  fitView: true,
9335
9381
  fitViewOptions: {
9336
9382
  maxZoom: 1
@@ -9356,6 +9402,7 @@ function WorkflowNestedGraphProvider({ children }) {
9356
9402
  const [parentStepGraphList, setParentStepGraphList] = React.useState([]);
9357
9403
  const [openDialog, setOpenDialog] = React.useState(false);
9358
9404
  const [label, setLabel] = React.useState("");
9405
+ const [fullStep, setFullStep] = React.useState("");
9359
9406
  const [switching, setSwitching] = React.useState(false);
9360
9407
  const closeNestedGraph = () => {
9361
9408
  if (parentStepGraphList.length) {
@@ -9363,6 +9410,7 @@ function WorkflowNestedGraphProvider({ children }) {
9363
9410
  const lastStepGraph = parentStepGraphList[parentStepGraphList.length - 1];
9364
9411
  setStepGraph(lastStepGraph.stepGraph);
9365
9412
  setLabel(lastStepGraph.label);
9413
+ setFullStep(lastStepGraph.fullStep);
9366
9414
  setParentStepGraphList(parentStepGraphList.slice(0, -1));
9367
9415
  setTimeout(() => {
9368
9416
  setSwitching(false);
@@ -9371,17 +9419,20 @@ function WorkflowNestedGraphProvider({ children }) {
9371
9419
  setOpenDialog(false);
9372
9420
  setStepGraph(null);
9373
9421
  setLabel("");
9422
+ setFullStep("");
9374
9423
  }
9375
9424
  };
9376
9425
  const showNestedGraph = ({
9377
9426
  label: newLabel,
9378
- stepGraph: newStepGraph
9427
+ stepGraph: newStepGraph,
9428
+ fullStep: newFullStep
9379
9429
  }) => {
9380
9430
  if (stepGraph) {
9381
9431
  setSwitching(true);
9382
- setParentStepGraphList([...parentStepGraphList, { stepGraph, label }]);
9432
+ setParentStepGraphList([...parentStepGraphList, { stepGraph, label, fullStep }]);
9383
9433
  }
9384
9434
  setLabel(newLabel);
9435
+ setFullStep(newFullStep);
9385
9436
  setStepGraph(newStepGraph);
9386
9437
  setOpenDialog(true);
9387
9438
  setTimeout(() => {
@@ -9405,14 +9456,17 @@ function WorkflowNestedGraphProvider({ children }) {
9405
9456
  " workflow"
9406
9457
  ] })
9407
9458
  ] }),
9408
- switching ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) : /* @__PURE__ */ jsxRuntime.jsx(react$2.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedGraph, { stepGraph, open: openDialog }) })
9459
+ switching ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) : /* @__PURE__ */ jsxRuntime.jsx(react$2.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedGraph, { stepGraph, open: openDialog, workflowName: fullStep }) })
9409
9460
  ] }) }) })
9410
9461
  ]
9411
9462
  }
9412
9463
  );
9413
9464
  }
9414
9465
 
9415
- function WorkflowNestedNode({ data }) {
9466
+ function WorkflowNestedNode({
9467
+ data,
9468
+ parentWorkflowName
9469
+ }) {
9416
9470
  const [isInputOpen, setIsInputOpen] = React.useState(false);
9417
9471
  const [isOutputOpen, setIsOutputOpen] = React.useState(false);
9418
9472
  const [isErrorOpen, setIsErrorOpen] = React.useState(false);
@@ -9420,7 +9474,8 @@ function WorkflowNestedNode({ data }) {
9420
9474
  const { steps, isRunning } = useCurrentRun();
9421
9475
  const { showNestedGraph } = React.useContext(WorkflowNestedGraphContext);
9422
9476
  const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig } = data;
9423
- const step = steps[label];
9477
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
9478
+ const step = steps[fullLabel];
9424
9479
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
9425
9480
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
9426
9481
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -9450,7 +9505,7 @@ function WorkflowNestedNode({ data }) {
9450
9505
  ] }),
9451
9506
  description && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
9452
9507
  /* @__PURE__ */ jsxRuntime.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: [
9453
- /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => showNestedGraph({ label, stepGraph }), children: "View workflow" }),
9508
+ /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }), children: "View workflow" }),
9454
9509
  mapConfig && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9455
9510
  /* @__PURE__ */ jsxRuntime.jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
9456
9511
  /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isMapConfigOpen, onOpenChange: setIsMapConfigOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
@@ -9499,13 +9554,13 @@ function WorkflowNestedNode({ data }) {
9499
9554
  ] });
9500
9555
  }
9501
9556
 
9502
- function WorkflowGraphInner({ workflow }) {
9557
+ function WorkflowGraphInner({ workflow, onShowTrace }) {
9503
9558
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
9504
9559
  const [nodes, _, onNodesChange] = react$2.useNodesState(initialNodes);
9505
9560
  const [edges] = react$2.useEdgesState(initialEdges);
9506
- const { steps } = useCurrentRun();
9561
+ const { steps, runId } = useCurrentRun();
9507
9562
  const nodeTypes = {
9508
- "default-node": WorkflowDefaultNode,
9563
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { onShowTrace, ...props }),
9509
9564
  "condition-node": WorkflowConditionNode,
9510
9565
  "after-node": WorkflowAfterNode,
9511
9566
  "loop-result-node": WorkflowLoopResultNode,
@@ -9539,7 +9594,7 @@ function WorkflowGraphInner({ workflow }) {
9539
9594
  ) });
9540
9595
  }
9541
9596
 
9542
- function WorkflowGraph({ workflowId, baseUrl }) {
9597
+ function WorkflowGraph({ workflowId, baseUrl, onShowTrace }) {
9543
9598
  const { workflow, isLoading } = useWorkflow(workflowId, baseUrl);
9544
9599
  if (isLoading) {
9545
9600
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-[600px]" }) });
@@ -9554,7 +9609,7 @@ function WorkflowGraph({ workflowId, baseUrl }) {
9554
9609
  ] })
9555
9610
  ] }) });
9556
9611
  }
9557
- return /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowGraphInner, { workflow }) }) });
9612
+ return /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowGraphInner, { workflow, onShowTrace }) }) });
9558
9613
  }
9559
9614
 
9560
9615
  const WorkflowStatus = ({ stepId, status }) => {