@mastra/playground-ui 3.0.0-alpha.2 → 3.0.0-alpha.4

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.
@@ -0,0 +1,3 @@
1
+ import { ToolCallContentPartComponent } from '@assistant-ui/react';
2
+
3
+ export declare const ToolFallback: ToolCallContentPartComponent;
package/dist/index.es.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { MessagePrimitive, ActionBarPrimitive, BranchPickerPrimitive, ThreadPrimitive, ComposerPrimitive, useExternalStoreRuntime, AssistantRuntimeProvider } from '@assistant-ui/react';
3
- import { CheckIcon, CopyIcon, ChevronLeftIcon, ChevronRightIcon, ArrowUp, Copy, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Braces, Clock1, ChevronDown, XIcon, Check, LoaderCircle, ChevronUpIcon, ChevronDownIcon, ExternalLinkIcon, X, Footprints, CircleCheck, CircleX, AlertCircleIcon, Plus, CalendarIcon, Loader2 } from 'lucide-react';
3
+ import { CheckIcon, CopyIcon, ChevronUpIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ArrowUp, Copy, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Braces, Clock1, ChevronDown, XIcon, Check, LoaderCircle, ExternalLinkIcon, X, Footprints, CircleCheck, CircleX, AlertCircleIcon, Plus, CalendarIcon, Loader2 } from 'lucide-react';
4
4
  import * as React from 'react';
5
5
  import React__default, { forwardRef, memo, useState, useRef, useEffect, createContext, useContext, useMemo, useCallback, Suspense, Fragment as Fragment$1 } from 'react';
6
6
  import { Slot } from '@radix-ui/react-slot';
@@ -3120,9 +3120,38 @@ const defaultComponents = unstable_memoizeMarkdownComponents({
3120
3120
  SyntaxHighlighter: SyntaxHighlighter$1
3121
3121
  });
3122
3122
 
3123
- const AssistantMessage = ({ ToolFallback }) => {
3124
- return /* @__PURE__ */ jsxs(MessagePrimitive.Root, { className: "grid group grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] max-w-[var(--thread-max-width)] relative w-full py-4", children: [
3125
- /* @__PURE__ */ jsx("div", { className: "text-foreground max-w-[calc(var(--thread-max-width)*0.8)] sm:max-w-[70%] break-words leading-7 col-span-2 py-2 col-start-2 row-start-1 my-1.5", children: /* @__PURE__ */ jsx(MessagePrimitive.Content, { components: { Text: MarkdownText, tools: { Fallback: ToolFallback } } }) }),
3123
+ const ToolFallback$1 = ({ toolName, argsText, result }) => {
3124
+ const [isCollapsed, setIsCollapsed] = useState(true);
3125
+ return /* @__PURE__ */ jsxs("div", { className: "mb-2 flex w-full flex-col gap-3 rounded-lg border py-3 text-sm", children: [
3126
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 px-4", children: [
3127
+ /* @__PURE__ */ jsx(CheckIcon, { className: "size-4" }),
3128
+ /* @__PURE__ */ jsxs("p", { className: "", children: [
3129
+ "Used tool: ",
3130
+ /* @__PURE__ */ jsx("b", { children: toolName })
3131
+ ] }),
3132
+ /* @__PURE__ */ jsx("div", { className: "flex-grow" }),
3133
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsCollapsed(!isCollapsed), children: isCollapsed ? /* @__PURE__ */ jsx(ChevronUpIcon, {}) : /* @__PURE__ */ jsx(ChevronDownIcon, {}) })
3134
+ ] }),
3135
+ !isCollapsed && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 border-t pt-2", children: [
3136
+ /* @__PURE__ */ jsx("div", { className: "px-4", children: /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap", children: argsText }) }),
3137
+ result !== void 0 && /* @__PURE__ */ jsxs("div", { className: "border-t border-dashed px-4 pt-2", children: [
3138
+ /* @__PURE__ */ jsx("p", { className: "font-semibold", children: "Result:" }),
3139
+ /* @__PURE__ */ jsx("pre", { className: "whitespace-pre-wrap", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
3140
+ ] })
3141
+ ] })
3142
+ ] });
3143
+ };
3144
+
3145
+ const AssistantMessage = ({
3146
+ ToolFallback: ToolFallbackCustom
3147
+ }) => {
3148
+ return /* @__PURE__ */ jsxs(MessagePrimitive.Root, { className: "grid group grid-cols-[auto_auto_1fr] grid-rows-[auto_1fr] max-w-[var(--thread-max-width)] relative w-full", children: [
3149
+ /* @__PURE__ */ jsx("div", { className: "text-foreground max-w-[calc(var(--thread-max-width)*0.8)] sm:max-w-[70%] break-words leading-7 col-span-2 py-2 col-start-2 row-start-1", children: /* @__PURE__ */ jsx(
3150
+ MessagePrimitive.Content,
3151
+ {
3152
+ components: { Text: MarkdownText, tools: { Fallback: ToolFallbackCustom || ToolFallback$1 } }
3153
+ }
3154
+ ) }),
3126
3155
  /* @__PURE__ */ jsx(AssistantActionBar, {}),
3127
3156
  /* @__PURE__ */ jsx(BranchPicker, { className: "col-start-2 row-start-2 -ml-2 mr-2" })
3128
3157
  ] });
@@ -3169,7 +3198,7 @@ const UserMessage = () => {
3169
3198
  style: {
3170
3199
  placeItems: "end"
3171
3200
  },
3172
- className: "grid w-full py-4",
3201
+ className: "grid w-full",
3173
3202
  children: /* @__PURE__ */ jsx(
3174
3203
  "div",
3175
3204
  {
@@ -3477,21 +3506,49 @@ function MastraRuntimeProvider({
3477
3506
  const hasNewInitialMessages = initialMessages && initialMessages?.length > messages?.length;
3478
3507
  if (messages.length === 0 || currentThreadId !== threadId || hasNewInitialMessages && currentThreadId === threadId) {
3479
3508
  if (initialMessages && threadId && memory) {
3480
- setMessages(initialMessages);
3509
+ const convertedMessages = initialMessages?.map((message) => {
3510
+ if (message?.toolInvocations?.length > 0) {
3511
+ return {
3512
+ ...message,
3513
+ content: message.toolInvocations.map((toolInvocation) => ({
3514
+ type: "tool-call",
3515
+ toolCallId: toolInvocation?.toolCallId,
3516
+ toolName: toolInvocation?.toolName,
3517
+ args: toolInvocation?.args,
3518
+ result: toolInvocation?.result
3519
+ }))
3520
+ };
3521
+ }
3522
+ return message;
3523
+ }).filter(Boolean);
3524
+ setMessages(convertedMessages);
3481
3525
  setCurrentThreadId(threadId);
3482
3526
  }
3483
3527
  }
3484
- }, [initialMessages, threadId, memory, messages]);
3528
+ }, [initialMessages, threadId, memory]);
3485
3529
  const mastra = new MastraClient({
3486
3530
  baseUrl: baseUrl || ""
3487
3531
  });
3532
+ const agent = mastra.getAgent(agentId);
3488
3533
  const onNew = async (message) => {
3489
3534
  if (message.content[0]?.type !== "text") throw new Error("Only text messages are supported");
3490
3535
  const input = message.content[0].text;
3491
3536
  setMessages((currentConversation) => [...currentConversation, { role: "user", content: input }]);
3492
3537
  setIsRunning(true);
3493
3538
  try {
3494
- const agent = mastra.getAgent(agentId);
3539
+ let updater = function() {
3540
+ setMessages((currentConversation) => {
3541
+ const message2 = {
3542
+ role: "assistant",
3543
+ content: [{ type: "text", text: content }]
3544
+ };
3545
+ if (!assistantMessageAdded) {
3546
+ assistantMessageAdded = true;
3547
+ return [...currentConversation, message2];
3548
+ }
3549
+ return [...currentConversation.slice(0, -1), message2];
3550
+ });
3551
+ };
3495
3552
  const response = await agent.stream({
3496
3553
  messages: [
3497
3554
  {
@@ -3502,65 +3559,98 @@ function MastraRuntimeProvider({
3502
3559
  runId: agentId,
3503
3560
  ...memory ? { threadId, resourceId: agentId } : {}
3504
3561
  });
3505
- const reader = response.body?.getReader();
3506
- const decoder = new TextDecoder();
3507
- let buffer = "";
3508
- let assistantMessage = "";
3509
- let assistantMessageAdded = false;
3510
- let errorMessage = "";
3511
- if (!reader) {
3512
- throw new Error("No reader found");
3562
+ if (!response.body) {
3563
+ throw new Error("No response body");
3513
3564
  }
3514
- try {
3515
- while (true) {
3516
- const { done, value } = await reader.read();
3517
- if (done) break;
3518
- const chunk = decoder.decode(value);
3519
- buffer += chunk;
3520
- const matches = buffer.matchAll(/0:"((?:\\.|(?!").)*?)"/g);
3521
- const errorMatches = buffer.matchAll(/3:"((?:\\.|(?!").)*?)"/g);
3522
- if (errorMatches) {
3523
- for (const match of errorMatches) {
3524
- const content = match[1];
3525
- errorMessage += content;
3526
- setMessages((currentConversation) => [
3527
- ...currentConversation.slice(0, -1),
3565
+ const parts = [];
3566
+ let content = "";
3567
+ let currentTextPart = null;
3568
+ let assistantMessageAdded = false;
3569
+ await response.processDataStream({
3570
+ onTextPart(value) {
3571
+ if (currentTextPart == null) {
3572
+ currentTextPart = {
3573
+ type: "text",
3574
+ text: value
3575
+ };
3576
+ parts.push(currentTextPart);
3577
+ } else {
3578
+ currentTextPart.text += value;
3579
+ }
3580
+ content += value;
3581
+ updater();
3582
+ },
3583
+ async onToolCallPart(value) {
3584
+ setMessages((currentConversation) => {
3585
+ const lastMessage = currentConversation[currentConversation.length - 1];
3586
+ if (lastMessage && lastMessage.role === "assistant") {
3587
+ const updatedMessage = {
3588
+ ...lastMessage,
3589
+ content: Array.isArray(lastMessage.content) ? [
3590
+ ...lastMessage.content,
3591
+ {
3592
+ type: "tool-call",
3593
+ toolCallId: value.toolCallId,
3594
+ toolName: value.toolName,
3595
+ args: value.args
3596
+ }
3597
+ ] : [
3598
+ ...typeof lastMessage.content === "string" ? [{ type: "text", text: lastMessage.content }] : [],
3599
+ {
3600
+ type: "tool-call",
3601
+ toolCallId: value.toolCallId,
3602
+ toolName: value.toolName,
3603
+ args: value.args
3604
+ }
3605
+ ]
3606
+ };
3607
+ return [...currentConversation.slice(0, -1), updatedMessage];
3608
+ }
3609
+ const newMessage = {
3610
+ role: "assistant",
3611
+ content: [
3612
+ { type: "text", text: content },
3528
3613
  {
3529
- role: "assistant",
3530
- content: [{ type: "text", text: errorMessage }],
3531
- isError: true
3614
+ type: "tool-call",
3615
+ toolCallId: value.toolCallId,
3616
+ toolName: value.toolName,
3617
+ args: value.args
3532
3618
  }
3533
- ]);
3534
- }
3535
- }
3536
- for (const match of matches) {
3537
- const content = match[1].replace(/\\"/g, '"').replace(/\\n/g, "\n");
3538
- assistantMessage += content;
3539
- setMessages((currentConversation) => {
3540
- const message2 = {
3541
- role: "assistant",
3542
- content: [{ type: "text", text: assistantMessage }]
3619
+ ]
3620
+ };
3621
+ return [...currentConversation, newMessage];
3622
+ });
3623
+ },
3624
+ async onToolResultPart(value) {
3625
+ setMessages((currentConversation) => {
3626
+ const lastMessage = currentConversation[currentConversation.length - 1];
3627
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
3628
+ const updatedContent = lastMessage.content.map((part) => {
3629
+ if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === value.toolCallId) {
3630
+ return {
3631
+ ...part,
3632
+ result: value.result
3633
+ };
3634
+ }
3635
+ return part;
3636
+ });
3637
+ const updatedMessage = {
3638
+ ...lastMessage,
3639
+ content: updatedContent
3543
3640
  };
3544
- const lastMessage = currentConversation[currentConversation.length - 1];
3545
- if (lastMessage.id) {
3546
- return currentConversation;
3547
- }
3548
- if (!assistantMessageAdded) {
3549
- assistantMessageAdded = true;
3550
- return [...currentConversation, message2];
3551
- }
3552
- return [...currentConversation.slice(0, -1), message2];
3553
- });
3554
- }
3555
- buffer = "";
3641
+ return [...currentConversation.slice(0, -1), updatedMessage];
3642
+ }
3643
+ return currentConversation;
3644
+ });
3645
+ },
3646
+ onErrorPart(error) {
3647
+ throw new Error(error);
3556
3648
  }
3557
- } finally {
3558
- reader.releaseLock();
3559
- setIsRunning(false);
3560
- setTimeout(() => {
3561
- refreshThreadList?.();
3562
- }, 500);
3563
- }
3649
+ });
3650
+ setIsRunning(false);
3651
+ setTimeout(() => {
3652
+ refreshThreadList?.();
3653
+ }, 500);
3564
3654
  } catch (error) {
3565
3655
  console.error("Error occurred in MastraRuntimeProvider", error);
3566
3656
  setIsRunning(false);
@@ -4862,6 +4952,7 @@ function usePolling({
4862
4952
 
4863
4953
  const useTraces = (componentName, baseUrl, isWorkflow = false) => {
4864
4954
  const [traces, setTraces] = useState([]);
4955
+ const { setTraces: setTraceContextTraces } = useContext(TraceContext);
4865
4956
  const client = useMemo(
4866
4957
  () => new MastraClient({
4867
4958
  baseUrl: baseUrl || ""
@@ -4884,11 +4975,15 @@ const useTraces = (componentName, baseUrl, isWorkflow = false) => {
4884
4975
  throw error2;
4885
4976
  }
4886
4977
  }, [client, componentName, isWorkflow]);
4887
- const onSuccess = useCallback((newTraces) => {
4888
- if (newTraces.length > 0) {
4889
- setTraces(() => newTraces);
4890
- }
4891
- }, []);
4978
+ const onSuccess = useCallback(
4979
+ (newTraces) => {
4980
+ if (newTraces.length > 0) {
4981
+ setTraces(() => newTraces);
4982
+ setTraceContextTraces(() => newTraces);
4983
+ }
4984
+ },
4985
+ [setTraceContextTraces]
4986
+ );
4892
4987
  const onError = useCallback((error2) => {
4893
4988
  toast.error(error2.message);
4894
4989
  }, []);