@mastra/playground-ui 6.5.2-alpha.0 → 6.6.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
@@ -47,7 +47,7 @@ import * as LabelPrimitive from '@radix-ui/react-label';
47
47
  import { ZodProvider, getFieldConfigInZodStack, getDefaultValueInZodStack } from '@autoform/zod/v4';
48
48
  import { z as z$1 } from 'zod/v3';
49
49
  import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
50
- import { useMastraClient, useChat, toAssistantUIMessage } from '@mastra/react';
50
+ import { useMastraClient, resolveToChildMessages, useChat, toAssistantUIMessage } from '@mastra/react';
51
51
  import { useQuery, useMutation, QueryClient, QueryClientProvider } from '@tanstack/react-query';
52
52
  import './index.css';export * from '@tanstack/react-query';
53
53
  import { useReactTable, getCoreRowModel, flexRender } from '@tanstack/react-table';
@@ -4350,11 +4350,12 @@ const useCodemirrorTheme$2 = () => {
4350
4350
  };
4351
4351
  const SyntaxHighlighter$2 = ({
4352
4352
  data,
4353
- className
4353
+ className,
4354
+ ...props
4354
4355
  }) => {
4355
4356
  const formattedCode = JSON.stringify(data, null, 2);
4356
4357
  const theme = useCodemirrorTheme$2();
4357
- return /* @__PURE__ */ jsxs("div", { className: clsx("rounded-md bg-surface4 p-1 font-mono relative", className), children: [
4358
+ return /* @__PURE__ */ jsxs("div", { className: clsx("rounded-md bg-surface4 p-1 font-mono relative", className), ...props, children: [
4358
4359
  /* @__PURE__ */ jsx(CopyButton, { content: formattedCode, className: "absolute top-2 right-2 z-20" }),
4359
4360
  /* @__PURE__ */ jsx(CodeMirror, { value: formattedCode, theme, extensions: [jsonLanguage] })
4360
4361
  ] });
@@ -4515,11 +4516,11 @@ const ToolBadge = ({ toolName, args, result, metadata, toolOutput }) => {
4515
4516
  let argSlot = null;
4516
4517
  try {
4517
4518
  const { __mastraMetadata: _, ...formattedArgs } = typeof args === "object" ? args : JSON.parse(args);
4518
- argSlot = /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: formattedArgs });
4519
+ argSlot = /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: formattedArgs, "data-testid": "tool-args" });
4519
4520
  } catch {
4520
4521
  argSlot = /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap", children: args });
4521
4522
  }
4522
- let resultSlot = typeof result === "string" ? /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap bg-surface4 p-4 rounded-md", children: result }) : /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: result });
4523
+ let resultSlot = typeof result === "string" ? /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap bg-surface4 p-4 rounded-md", children: result }) : /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: result, "data-testid": "tool-result" });
4523
4524
  const selectionReason = metadata?.mode === "network" ? metadata.selectionReason : void 0;
4524
4525
  const agentNetworkInput = metadata?.mode === "network" ? metadata.agentInput : void 0;
4525
4526
  return /* @__PURE__ */ jsx(
@@ -4546,7 +4547,7 @@ const ToolBadge = ({ toolName, args, result, metadata, toolOutput }) => {
4546
4547
  ] }),
4547
4548
  toolOutput.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
4548
4549
  /* @__PURE__ */ jsx("p", { className: "font-medium pb-2", children: "Tool output" }),
4549
- /* @__PURE__ */ jsx("div", { className: "h-40 overflow-y-auto", children: /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: toolOutput }) })
4550
+ /* @__PURE__ */ jsx("div", { className: "h-40 overflow-y-auto", children: /* @__PURE__ */ jsx(SyntaxHighlighter$2, { data: toolOutput, "data-testid": "tool-output" }) })
4550
4551
  ] })
4551
4552
  ] })
4552
4553
  }
@@ -6606,12 +6607,16 @@ const SelectField$1 = ({ field, inputProps, error, id, value }) => {
6606
6607
 
6607
6608
  const ObjectWrapper = ({ label, children }) => {
6608
6609
  const hasLabel = label !== "​" && label !== "";
6610
+ const [isOpen, setIsOpen] = useState(false);
6609
6611
  return /* @__PURE__ */ jsxs("div", { className: "", children: [
6610
- hasLabel && /* @__PURE__ */ jsxs(Txt, { as: "h3", variant: "ui-sm", className: "text-icon3 flex items-center gap-1 pb-2", children: [
6611
- /* @__PURE__ */ jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsx(Braces, {}) }),
6612
- label
6612
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
6613
+ hasLabel && /* @__PURE__ */ jsxs(Txt, { as: "h3", variant: "ui-sm", className: "text-icon3 flex items-center gap-1 pb-2", children: [
6614
+ /* @__PURE__ */ jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsx(Braces, {}) }),
6615
+ label
6616
+ ] }),
6617
+ /* @__PURE__ */ jsx(Button$1, { onClick: () => setIsOpen(!isOpen), type: "button", className: "ml-auto", children: /* @__PURE__ */ jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsx(ChevronDownIcon, { className: cn("transition-all", isOpen ? "rotate-180" : "rotate-0") }) }) })
6613
6618
  ] }),
6614
- /* @__PURE__ */ jsx(
6619
+ isOpen && /* @__PURE__ */ jsx(
6615
6620
  "div",
6616
6621
  {
6617
6622
  className: hasLabel ? "flex flex-col gap-1 [&>*]:border-dashed [&>*]:border-l [&>*]:border-l-border1 [&>*]:pl-4" : "",
@@ -7757,7 +7762,46 @@ const EmptyWorkflowsTable = () => /* @__PURE__ */ jsx("div", { className: "flex
7757
7762
  }
7758
7763
  ) });
7759
7764
 
7760
- const WorkflowBadge = ({ workflow, runId, workflowId, isStreaming, metadata }) => {
7765
+ const LoadingBadge = () => {
7766
+ return /* @__PURE__ */ jsx(
7767
+ BadgeWrapper,
7768
+ {
7769
+ icon: /* @__PURE__ */ jsx(Spinner, { color: IconColors.icon3 }),
7770
+ title: /* @__PURE__ */ jsx(Skeleton, { className: "ml-2 w-12 h-2" }),
7771
+ collapsible: false
7772
+ }
7773
+ );
7774
+ };
7775
+
7776
+ const useInView = () => {
7777
+ const [inView, setInView] = useState(false);
7778
+ const setRef = useCallback((node) => {
7779
+ if (node) {
7780
+ const observer = new IntersectionObserver(([entry]) => {
7781
+ setInView(entry.isIntersecting);
7782
+ });
7783
+ observer.observe(node);
7784
+ return () => observer.disconnect();
7785
+ }
7786
+ }, []);
7787
+ return { inView, setRef };
7788
+ };
7789
+
7790
+ const useWorkflow = (workflowId) => {
7791
+ const client = useMastraClient();
7792
+ const { runtimeContext } = usePlaygroundStore();
7793
+ return useQuery({
7794
+ queryKey: ["workflow", workflowId],
7795
+ queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
7796
+ enabled: Boolean(workflowId),
7797
+ retry: false,
7798
+ refetchOnWindowFocus: false,
7799
+ throwOnError: false
7800
+ });
7801
+ };
7802
+
7803
+ const WorkflowBadge = ({ runId, workflowId, isStreaming, metadata }) => {
7804
+ const { data: workflow, isLoading: isWorkflowLoading } = useWorkflow(workflowId);
7761
7805
  const { data: runs, isLoading: isRunsLoading } = useWorkflowRuns(workflowId, {
7762
7806
  enabled: Boolean(runId) && !isStreaming
7763
7807
  });
@@ -7766,6 +7810,7 @@ const WorkflowBadge = ({ workflow, runId, workflowId, isStreaming, metadata }) =
7766
7810
  const snapshot = typeof run?.snapshot === "object" ? run?.snapshot : void 0;
7767
7811
  const selectionReason = metadata?.mode === "network" ? metadata.selectionReason : void 0;
7768
7812
  const agentNetworkInput = metadata?.mode === "network" ? metadata.agentInput : void 0;
7813
+ if (isWorkflowLoading || !workflow) return /* @__PURE__ */ jsx(LoadingBadge, {});
7769
7814
  return /* @__PURE__ */ jsxs(
7770
7815
  BadgeWrapper,
7771
7816
  {
@@ -7792,7 +7837,7 @@ const WorkflowBadgeExtended = ({ workflowId, workflow, runId }) => {
7792
7837
  return /* @__PURE__ */ jsxs(Fragment, { children: [
7793
7838
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 pb-2", children: [
7794
7839
  /* @__PURE__ */ jsx(Button$1, { as: Link, href: `/workflows/${workflowId}/graph`, children: "Go to workflow" }),
7795
- /* @__PURE__ */ jsx(Button$1, { as: Link, href: `/workflows/${workflowId}/graph/${runId}`, children: "See run" })
7840
+ runId && /* @__PURE__ */ jsx(Button$1, { as: Link, href: `/workflows/${workflowId}/graph/${runId}`, children: "See run" })
7796
7841
  ] }),
7797
7842
  /* @__PURE__ */ jsx("div", { className: "rounded-md overflow-hidden h-[60vh] w-full", children: /* @__PURE__ */ jsx(WorkflowGraph, { workflowId, workflow }) })
7798
7843
  ] });
@@ -7805,30 +7850,6 @@ const useWorkflowStream = (workflowFullState) => {
7805
7850
  }, [workflowFullState]);
7806
7851
  };
7807
7852
 
7808
- const useWorkflow = (workflowId) => {
7809
- const client = useMastraClient();
7810
- const { runtimeContext } = usePlaygroundStore();
7811
- return useQuery({
7812
- queryKey: ["workflow", workflowId],
7813
- queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
7814
- enabled: Boolean(workflowId),
7815
- retry: false,
7816
- refetchOnWindowFocus: false,
7817
- throwOnError: false
7818
- });
7819
- };
7820
-
7821
- const LoadingBadge = () => {
7822
- return /* @__PURE__ */ jsx(
7823
- BadgeWrapper,
7824
- {
7825
- icon: /* @__PURE__ */ jsx(Spinner, { color: IconColors.icon3 }),
7826
- title: /* @__PURE__ */ jsx(Skeleton, { className: "ml-2 w-12 h-2" }),
7827
- collapsible: false
7828
- }
7829
- );
7830
- };
7831
-
7832
7853
  const AgentBadge = ({ agentId, messages = [], metadata }) => {
7833
7854
  const selectionReason = metadata?.mode === "network" ? metadata.selectionReason : void 0;
7834
7855
  const agentNetworkInput = metadata?.mode === "network" ? metadata.agentInput : void 0;
@@ -7873,25 +7894,51 @@ const AgentBadge = ({ agentId, messages = [], metadata }) => {
7873
7894
  );
7874
7895
  };
7875
7896
 
7897
+ const useAgentMessages = ({
7898
+ threadId,
7899
+ agentId,
7900
+ memory
7901
+ }) => {
7902
+ const client = useMastraClient();
7903
+ return useQuery({
7904
+ queryKey: ["memory", "messages", threadId, agentId],
7905
+ queryFn: () => client.getThreadMessages(threadId, { agentId }),
7906
+ enabled: memory && Boolean(threadId),
7907
+ staleTime: 0,
7908
+ gcTime: 0,
7909
+ retry: false,
7910
+ refetchOnWindowFocus: false
7911
+ });
7912
+ };
7913
+
7914
+ const AgentBadgeWrapper = ({ agentId, result, metadata }) => {
7915
+ const { data: memoryMessages } = useAgentMessages({
7916
+ threadId: result?.subAgentThreadId ?? "",
7917
+ agentId,
7918
+ memory: true
7919
+ });
7920
+ const childMessages = result?.childMessages ?? resolveToChildMessages(memoryMessages?.uiMessages ?? []);
7921
+ return /* @__PURE__ */ jsx(AgentBadge, { agentId, messages: childMessages, metadata });
7922
+ };
7923
+
7876
7924
  const ToolFallback = ({ toolName, result, args, ...props }) => {
7877
7925
  return /* @__PURE__ */ jsx(WorkflowRunProvider, { children: /* @__PURE__ */ jsx(ToolFallbackInner, { toolName, result, args, ...props }) });
7878
7926
  };
7879
7927
  const ToolFallbackInner = ({ toolName, result, args, metadata, ...props }) => {
7928
+ const isAgent = metadata?.mode === "network" && metadata.from === "AGENT" || toolName.startsWith("agent-");
7929
+ const isWorkflow = metadata?.mode === "network" && metadata.from === "WORKFLOW" || toolName.startsWith("workflow-");
7930
+ const agentToolName = toolName.startsWith("agent-") ? toolName.substring("agent-".length) : toolName;
7931
+ const workflowToolName = toolName.startsWith("workflow-") ? toolName.substring("workflow-".length) : toolName;
7880
7932
  useWorkflowStream(result);
7881
- const { data: workflow, isLoading } = useWorkflow(toolName);
7882
- const isAgent = metadata?.mode === "network" && metadata.from === "AGENT";
7883
7933
  if (isAgent) {
7884
- const messages = result?.childMessages ?? [];
7885
- return /* @__PURE__ */ jsx(AgentBadge, { agentId: toolName, messages, metadata });
7934
+ return /* @__PURE__ */ jsx(AgentBadgeWrapper, { agentId: agentToolName, result, metadata });
7886
7935
  }
7887
- if (isLoading) return /* @__PURE__ */ jsx(LoadingBadge, {});
7888
- if (workflow) {
7936
+ if (isWorkflow) {
7889
7937
  const isStreaming = metadata?.mode === "stream" || metadata?.mode === "network";
7890
7938
  return /* @__PURE__ */ jsx(
7891
7939
  WorkflowBadge,
7892
7940
  {
7893
- workflowId: toolName,
7894
- workflow,
7941
+ workflowId: workflowToolName,
7895
7942
  isStreaming,
7896
7943
  runId: result?.runId,
7897
7944
  metadata
@@ -10068,15 +10115,36 @@ const AgentChat = ({
10068
10115
  agentId,
10069
10116
  agentName,
10070
10117
  threadId,
10071
- initialMessages,
10072
- initialLegacyMessages,
10073
10118
  memory,
10074
10119
  refreshThreadList,
10075
10120
  modelVersion,
10076
- modelList
10121
+ modelList,
10122
+ messageId
10077
10123
  }) => {
10078
10124
  const { settings } = useAgentSettings();
10079
10125
  const { runtimeContext } = usePlaygroundStore();
10126
+ const { data: messages, isLoading: isMessagesLoading } = useAgentMessages({
10127
+ agentId,
10128
+ threadId: threadId ?? "",
10129
+ memory: memory ?? false
10130
+ });
10131
+ useEffect(() => {
10132
+ if (messageId && messages && !isMessagesLoading) {
10133
+ setTimeout(() => {
10134
+ const messageElement = document.querySelector(`[data-message-id="${messageId}"]`);
10135
+ if (messageElement) {
10136
+ messageElement.scrollIntoView({ behavior: "smooth", block: "center" });
10137
+ messageElement.classList.add("bg-surface4");
10138
+ setTimeout(() => {
10139
+ messageElement.classList.remove("bg-surface4");
10140
+ }, 2e3);
10141
+ }
10142
+ }, 100);
10143
+ }
10144
+ }, [messageId, messages, isMessagesLoading]);
10145
+ if (isMessagesLoading) {
10146
+ return null;
10147
+ }
10080
10148
  return /* @__PURE__ */ jsx(
10081
10149
  MastraRuntimeProvider,
10082
10150
  {
@@ -10084,8 +10152,8 @@ const AgentChat = ({
10084
10152
  agentName,
10085
10153
  modelVersion,
10086
10154
  threadId,
10087
- initialMessages,
10088
- initialLegacyMessages,
10155
+ initialMessages: messages?.uiMessages || [],
10156
+ initialLegacyMessages: messages?.legacyMessages || [],
10089
10157
  memory,
10090
10158
  refreshThreadList,
10091
10159
  settings,
@@ -17319,20 +17387,6 @@ function usePolling({
17319
17387
  };
17320
17388
  }
17321
17389
 
17322
- const useInView = () => {
17323
- const [inView, setInView] = useState(false);
17324
- const setRef = useCallback((node) => {
17325
- if (node) {
17326
- const observer = new IntersectionObserver(([entry]) => {
17327
- setInView(entry.isIntersecting);
17328
- });
17329
- observer.observe(node);
17330
- return () => observer.disconnect();
17331
- }
17332
- }, []);
17333
- return { inView, setRef };
17334
- };
17335
-
17336
17390
  const PlaygroundQueryClient = ({ children }) => {
17337
17391
  const queryClient = new QueryClient();
17338
17392
  return /* @__PURE__ */ jsx(QueryClientProvider, { client: queryClient, children });