@mastra/playground-ui 5.1.2-alpha.4 → 5.1.2-alpha.6

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
@@ -4234,11 +4234,12 @@ const AttachmentPreviewDialog = ({ children }) => {
4234
4234
  };
4235
4235
  const AttachmentThumbnail = () => {
4236
4236
  const isImage = react.useAttachment((a) => a.type === "image");
4237
+ const document = react.useAttachment((a) => a.type === "document" ? a : void 0);
4237
4238
  const src = useAttachmentSrc();
4238
4239
  const canRemove = react.useAttachment((a) => a.source !== "message");
4239
4240
  return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
4240
4241
  /* @__PURE__ */ jsxRuntime.jsxs(react.AttachmentPrimitive.Root, { className: "relative", children: [
4241
- /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full aspect-ratio overflow-hidden rounded-lg", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, className: "object-cover aspect-ratio size-16", alt: "Preview", height: 64, width: 64 }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "text-icon3" }) }) }) }) }),
4242
+ /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full aspect-ratio overflow-hidden rounded-lg", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, className: "object-cover aspect-ratio size-16", alt: "Preview", height: 64, width: 64 }) }) : document?.contentType === "application/pdf" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "text-accent2" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "text-icon3" }) }) }) }) }),
4242
4243
  canRemove && /* @__PURE__ */ jsxRuntime.jsx(AttachmentRemove, {})
4243
4244
  ] }),
4244
4245
  /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Name, {}) })
@@ -4260,9 +4261,10 @@ const UserMessageAttachments = () => {
4260
4261
  };
4261
4262
  const InMessageAttachment = () => {
4262
4263
  const isImage = react.useAttachment((a) => a.type === "image");
4264
+ const document = react.useAttachment((a) => a.type === "document" ? a : void 0);
4263
4265
  const src = useAttachmentSrc();
4264
4266
  return /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
4265
- /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Root, { className: "relative pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full aspect-ratio overflow-hidden rounded-lg", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, className: "object-cover aspect-ratio max-h-[140px] max-w-[320px]", alt: "Preview" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "text-icon3" }) }) }) }) }) }),
4267
+ /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Root, { className: "relative pt-4", children: /* @__PURE__ */ jsxRuntime.jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full w-full aspect-ratio overflow-hidden rounded-lg", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src, className: "object-cover aspect-ratio max-h-[140px] max-w-[320px]", alt: "Preview" }) }) : document?.contentType === "application/pdf" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: "text-accent2" }) }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-lg border-sm border-border1 flex items-center justify-center p-4", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileIcon, { className: "text-icon3" }) }) }) }) }) }),
4266
4268
  /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(react.AttachmentPrimitive.Name, {}) })
4267
4269
  ] }) });
4268
4270
  };
@@ -4528,20 +4530,96 @@ const fileToBase64 = async (file) => {
4528
4530
  });
4529
4531
  };
4530
4532
 
4533
+ class PDFAttachmentAdapter {
4534
+ accept = "application/pdf";
4535
+ async add({ file }) {
4536
+ const maxSize = 20 * 1024 * 1024;
4537
+ if (file.size > maxSize) {
4538
+ throw new Error("PDF size exceeds 20MB limit");
4539
+ }
4540
+ return {
4541
+ id: crypto.randomUUID(),
4542
+ type: "document",
4543
+ name: file.name,
4544
+ file,
4545
+ status: {
4546
+ type: "running",
4547
+ reason: "uploading",
4548
+ progress: 0
4549
+ },
4550
+ contentType: "application/pdf"
4551
+ };
4552
+ }
4553
+ async send(attachment) {
4554
+ const base64Data = await this.fileToBase64(attachment.file);
4555
+ return {
4556
+ id: attachment.id,
4557
+ type: "document",
4558
+ name: attachment.name,
4559
+ content: [
4560
+ {
4561
+ type: "text",
4562
+ text: base64Data
4563
+ }
4564
+ ],
4565
+ status: { type: "complete" },
4566
+ contentType: "application/pdf"
4567
+ };
4568
+ }
4569
+ async remove(attachment) {
4570
+ }
4571
+ async fileToBase64(file) {
4572
+ const arrayBuffer = await file.arrayBuffer();
4573
+ const bytes = new Uint8Array(arrayBuffer);
4574
+ let binary = "";
4575
+ bytes.forEach((byte) => {
4576
+ binary += String.fromCharCode(byte);
4577
+ });
4578
+ return btoa(binary);
4579
+ }
4580
+ // Optional: Extract text from PDF using a library like pdf.js
4581
+ async extractTextFromPDF(file) {
4582
+ return "Extracted PDF text content";
4583
+ }
4584
+ }
4585
+
4531
4586
  const convertMessage$1 = (message) => {
4532
4587
  return message;
4533
4588
  };
4534
4589
  const convertToAIAttachments = async (attachments) => {
4535
- const promises = attachments.filter((attachment) => attachment.file).map(async (attachment) => ({
4536
- role: "user",
4537
- content: [
4538
- {
4539
- type: "image",
4540
- image: await fileToBase64(attachment.file),
4541
- mimeType: attachment.file.type
4590
+ const promises = attachments.filter((attachment) => attachment.type === "image" || attachment.type === "document").map(async (attachment) => {
4591
+ if (attachment.type === "document") {
4592
+ if (attachment.contentType === "application/pdf") {
4593
+ return {
4594
+ role: "user",
4595
+ content: [
4596
+ {
4597
+ type: "file",
4598
+ // @ts-expect-error - TODO: fix this type issue somehow
4599
+ data: attachment.content?.[0]?.text || "",
4600
+ mimeType: attachment.contentType,
4601
+ filename: attachment.name
4602
+ }
4603
+ ]
4604
+ };
4542
4605
  }
4543
- ]
4544
- }));
4606
+ return {
4607
+ role: "user",
4608
+ // @ts-expect-error - TODO: fix this type issue somehow
4609
+ content: attachment.content[0]?.text || ""
4610
+ };
4611
+ }
4612
+ return {
4613
+ role: "user",
4614
+ content: [
4615
+ {
4616
+ type: "image",
4617
+ image: await fileToBase64(attachment.file),
4618
+ mimeType: attachment.file.type
4619
+ }
4620
+ ]
4621
+ };
4622
+ });
4545
4623
  return Promise.all(promises);
4546
4624
  };
4547
4625
  function MastraRuntimeProvider({
@@ -4843,7 +4921,11 @@ function MastraRuntimeProvider({
4843
4921
  convertMessage: convertMessage$1,
4844
4922
  onNew,
4845
4923
  adapters: {
4846
- attachments: new react.CompositeAttachmentAdapter([new react.SimpleImageAttachmentAdapter()])
4924
+ attachments: new react.CompositeAttachmentAdapter([
4925
+ new react.SimpleImageAttachmentAdapter(),
4926
+ new react.SimpleTextAttachmentAdapter(),
4927
+ new PDFAttachmentAdapter()
4928
+ ])
4847
4929
  }
4848
4930
  });
4849
4931
  return /* @__PURE__ */ jsxRuntime.jsxs(react.AssistantRuntimeProvider, { runtime, children: [
@@ -6057,42 +6139,6 @@ function transformKey(key) {
6057
6139
  const newKey = key.split(".").join(" ").split("_").join(" ").replaceAll("ai", "AI");
6058
6140
  return newKey.substring(0, 1).toUpperCase() + newKey.substring(1);
6059
6141
  }
6060
- const refineTraces = (traces, isWorkflow = false) => {
6061
- const listOfSpanIds = /* @__PURE__ */ new Set();
6062
- const newName = (name) => {
6063
- if (name?.startsWith("workflow.") && isWorkflow) {
6064
- return name?.split(".")?.slice(2)?.join(".");
6065
- }
6066
- if (name?.startsWith("agent.") && !isWorkflow) {
6067
- return name?.split(".")?.slice(1)?.join(".");
6068
- }
6069
- return name;
6070
- };
6071
- const groupedTraces = traces?.reduce((acc, curr) => {
6072
- const newCurr = { ...curr, name: newName(curr.name), duration: curr.endTime - curr.startTime };
6073
- listOfSpanIds.add(curr.id);
6074
- return { ...acc, [curr.traceId]: [...acc[curr.traceId] || [], newCurr] };
6075
- }, {});
6076
- const tracesData = Object.entries(groupedTraces).map(([key, value]) => {
6077
- const parentSpan = value.find((span) => !span.parentSpanId || !listOfSpanIds.has(span.parentSpanId));
6078
- const enrichedSpans = value.map((span) => ({
6079
- ...span,
6080
- parentSpanId: parentSpan?.id === span.id ? null : span?.parentSpanId
6081
- }));
6082
- const failedStatus = value.find((span) => span.status.code !== 0)?.status;
6083
- const runId = value?.[0]?.attributes?.runId;
6084
- return {
6085
- traceId: key,
6086
- serviceName: parentSpan?.name || key,
6087
- duration: parentSpan?.duration || value.reduce((acc, curr) => acc + curr.duration, 0),
6088
- status: failedStatus || parentSpan?.status || value[0].status,
6089
- started: value[0].startTime,
6090
- trace: enrichedSpans,
6091
- runId: runId ? String(runId) : void 0
6092
- };
6093
- });
6094
- return tracesData;
6095
- };
6096
6142
 
6097
6143
  function SpanDetail() {
6098
6144
  const { span, setSpan, trace, setIsOpen } = React.useContext(TraceContext);
@@ -9779,6 +9825,28 @@ function WorkflowTrigger({ workflowId, setRunId }) {
9779
9825
  ] }) });
9780
9826
  }
9781
9827
 
9828
+ const WorkflowRuns = ({ workflowId, runId, isLoading, runs, onPressRun }) => {
9829
+ if (isLoading) {
9830
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-[600px]" }) });
9831
+ }
9832
+ if (runs.length === 0) {
9833
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-md", className: "text-icon6 text-center", children: "No previous run" }) });
9834
+ }
9835
+ return /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "pb-10", children: runs.map((run) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsxs(
9836
+ "button",
9837
+ {
9838
+ onClick: () => onPressRun({ workflowId, runId: run.runId }),
9839
+ className: clsx("px-3 py-2 border-b-sm border-border1 block w-full hover:bg-surface4 text-left", {
9840
+ "bg-surface4": run.runId === runId
9841
+ }),
9842
+ children: [
9843
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-lg", className: "font-medium text-icon6 truncate", as: "p", children: run.runId }),
9844
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "font-medium text-icon3 truncate", as: "p", children: typeof run?.snapshot === "string" ? "" : run?.snapshot?.timestamp ? dateFns.formatDate(run?.snapshot?.timestamp, "MMM d, yyyy h:mm a") : "" })
9845
+ ]
9846
+ }
9847
+ ) }, run.runId)) });
9848
+ };
9849
+
9782
9850
  const DataTable = ({
9783
9851
  columns,
9784
9852
  data,
@@ -9826,7 +9894,7 @@ const DataTable = ({
9826
9894
  const rows = table.getRowModel().rows;
9827
9895
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9828
9896
  /* @__PURE__ */ jsxRuntime.jsxs(Table, { children: [
9829
- /* @__PURE__ */ jsxRuntime.jsx(Thead, { className: "sticky top-0", children: ths.headers.map((header) => {
9897
+ /* @__PURE__ */ jsxRuntime.jsx(Thead, { className: "sticky top-0 bg-surface2", children: ths.headers.map((header) => {
9830
9898
  const size = header.column.getSize();
9831
9899
  const meta = header.column.columnDef.meta;
9832
9900
  return /* @__PURE__ */ jsxRuntime.jsx(Th, { style: { width: meta?.width || size || "auto" }, children: header.isPlaceholder ? null : reactTable.flexRender(header.column.columnDef.header, header.getContext()) }, header.id);
@@ -10134,48 +10202,6 @@ function usePolling({
10134
10202
  };
10135
10203
  }
10136
10204
 
10137
- const useTraces = (componentName, isWorkflow = false) => {
10138
- const [traces, setTraces] = React.useState([]);
10139
- const client = React.useMemo(() => useMastraClient(), []);
10140
- const fetchFn = React.useCallback(async () => {
10141
- try {
10142
- const res = await client.getTelemetry({
10143
- attribute: {
10144
- componentName
10145
- }
10146
- });
10147
- if (!res.traces) {
10148
- throw new Error("Error fetching traces");
10149
- }
10150
- const refinedTraces = refineTraces(res?.traces || [], isWorkflow);
10151
- return refinedTraces;
10152
- } catch (error2) {
10153
- throw error2;
10154
- }
10155
- }, [client, componentName, isWorkflow]);
10156
- const onSuccess = React.useCallback((newTraces) => {
10157
- if (newTraces.length > 0) {
10158
- setTraces(() => newTraces);
10159
- }
10160
- }, []);
10161
- const onError = React.useCallback((error2) => {
10162
- console.log(`error, onError`, error2);
10163
- sonner.toast.error(error2.message);
10164
- }, []);
10165
- const shouldContinue = React.useCallback(() => {
10166
- return true;
10167
- }, []);
10168
- const { firstCallLoading, error } = usePolling({
10169
- fetchFn,
10170
- interval: 3e3,
10171
- onSuccess,
10172
- onError,
10173
- shouldContinue,
10174
- enabled: true
10175
- });
10176
- return { traces, firstCallLoading, error };
10177
- };
10178
-
10179
10205
  exports.AgentChat = AgentChat;
10180
10206
  exports.AgentCoinIcon = AgentCoinIcon;
10181
10207
  exports.AgentContext = AgentContext;
@@ -10268,13 +10294,12 @@ exports.WorkflowGraph = WorkflowGraph;
10268
10294
  exports.WorkflowIcon = WorkflowIcon;
10269
10295
  exports.WorkflowRunContext = WorkflowRunContext;
10270
10296
  exports.WorkflowRunProvider = WorkflowRunProvider;
10297
+ exports.WorkflowRuns = WorkflowRuns;
10271
10298
  exports.WorkflowTraces = WorkflowTraces;
10272
10299
  exports.WorkflowTrigger = WorkflowTrigger;
10273
- exports.refineTraces = refineTraces;
10274
10300
  exports.useCurrentRun = useCurrentRun;
10275
10301
  exports.useMastraClient = useMastraClient;
10276
10302
  exports.usePlaygroundStore = usePlaygroundStore;
10277
10303
  exports.usePolling = usePolling;
10278
10304
  exports.useSpeechRecognition = useSpeechRecognition;
10279
- exports.useTraces = useTraces;
10280
10305
  //# sourceMappingURL=index.cjs.js.map