@mastra/playground-ui 5.1.10-alpha.0 → 5.1.10-alpha.1

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
@@ -3,7 +3,7 @@ import * as React from 'react';
3
3
  import React__default, { createContext, useContext, forwardRef, useState, useEffect, memo, useRef, useCallback, useMemo, Suspense, Fragment as Fragment$1 } from 'react';
4
4
  import { MastraClient } from '@mastra/client-js';
5
5
  import { useMessage, MessagePrimitive, ActionBarPrimitive, useComposerRuntime, ComposerPrimitive, useAttachment, AttachmentPrimitive, ThreadPrimitive, useExternalStoreRuntime, CompositeAttachmentAdapter, SimpleImageAttachmentAdapter, SimpleTextAttachmentAdapter, AssistantRuntimeProvider } from '@assistant-ui/react';
6
- import { CheckIcon as CheckIcon$1, CopyIcon, Check, Copy, ChevronUpIcon, X, FileText, FileIcon, CircleXIcon, Mic, PlusIcon, ArrowUp, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, ChevronUp, ChevronDown, Circle, RefreshCw, LoaderCircle, ChevronDownIcon, ExternalLinkIcon, Network, PauseIcon, HourglassIcon, Loader2, CircleDashed, Footprints, CircleCheck, CircleX, Minus, Plus, Maximize, Workflow, AlertCircleIcon, AlertCircle, CalendarIcon, Braces, Brackets, TrashIcon, CirclePause } from 'lucide-react';
6
+ import { CheckIcon as CheckIcon$1, CopyIcon, Check, Copy, ChevronUpIcon, X, FileText, FileIcon, CircleXIcon, Mic, PlusIcon, ArrowUp, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, ChevronUp, ChevronDown, Circle, RefreshCw, LoaderCircle, ChevronDownIcon, ExternalLinkIcon, Braces, Loader2, Network, PauseIcon, HourglassIcon, CircleDashed, Footprints, CircleCheck, CircleX, Minus, Plus, Maximize, Workflow, AlertCircleIcon, AlertCircle, CalendarIcon, Brackets, TrashIcon, CirclePause } from 'lucide-react';
7
7
  import { Slot } from '@radix-ui/react-slot';
8
8
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
9
9
  import { TooltipProvider as TooltipProvider$1 } from '@radix-ui/react-tooltip';
@@ -38,11 +38,11 @@ import '@xyflow/react/dist/style.css';
38
38
  import Dagre from '@dagrejs/dagre';
39
39
  import { Highlight, themes } from 'prism-react-renderer';
40
40
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
41
- import { useDebouncedCallback } from 'use-debounce';
42
- import { v4 } from '@lukeed/uuid';
43
41
  import prettier from 'prettier';
44
42
  import prettierPluginBabel from 'prettier/plugins/babel';
45
43
  import prettierPluginEstree from 'prettier/plugins/estree';
44
+ import { useDebouncedCallback } from 'use-debounce';
45
+ import { v4 } from '@lukeed/uuid';
46
46
  import jsonSchemaToZod from 'json-schema-to-zod';
47
47
  import { parse } from 'superjson';
48
48
  import z$1, { z, ZodObject } from 'zod';
@@ -8085,6 +8085,92 @@ const CodeDialogContent = ({ data }) => {
8085
8085
  }
8086
8086
  };
8087
8087
 
8088
+ const formatJSON = async (code) => {
8089
+ const formatted = await prettier.format(code, {
8090
+ semi: false,
8091
+ parser: "json",
8092
+ printWidth: 80,
8093
+ tabWidth: 2,
8094
+ plugins: [prettierPluginBabel, prettierPluginEstree]
8095
+ });
8096
+ return formatted;
8097
+ };
8098
+ const isValidJson = (str) => {
8099
+ try {
8100
+ const obj = JSON.parse(str);
8101
+ return !!obj && typeof obj === "object";
8102
+ } catch (e) {
8103
+ return false;
8104
+ }
8105
+ };
8106
+
8107
+ const WorkflowRunEventForm = ({ event, runId, onSendEvent }) => {
8108
+ const [eventData, setEventData] = useState("");
8109
+ const [isLoading, setIsLoading] = useState(false);
8110
+ const [error, setError] = useState(null);
8111
+ const theme = useCodemirrorTheme();
8112
+ const { handleCopy } = useCopyToClipboard({ text: eventData });
8113
+ const handleSendEvent = async () => {
8114
+ let data;
8115
+ setIsLoading(true);
8116
+ setError(null);
8117
+ try {
8118
+ data = JSON.parse(eventData);
8119
+ } catch (error2) {
8120
+ setError("Invalid JSON");
8121
+ setIsLoading(false);
8122
+ return;
8123
+ }
8124
+ try {
8125
+ const result = await onSendEvent({ event, data, runId });
8126
+ toast.success(result.message);
8127
+ } catch (error2) {
8128
+ console.error("Error sending event", error2);
8129
+ setError("Error sending event");
8130
+ } finally {
8131
+ setIsLoading(false);
8132
+ }
8133
+ };
8134
+ const buttonClass = "text-icon3 hover:text-icon6";
8135
+ const formatEventData = async () => {
8136
+ if (!isValidJson(eventData)) {
8137
+ setError("Invalid JSON");
8138
+ return;
8139
+ }
8140
+ const formatted = await formatJSON(eventData);
8141
+ setEventData(formatted);
8142
+ };
8143
+ return /* @__PURE__ */ jsxs("div", { children: [
8144
+ /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
8145
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pb-2", children: [
8146
+ /* @__PURE__ */ jsx(Txt, { as: "label", variant: "ui-md", className: "text-icon3", children: "Event data (JSON)" }),
8147
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8148
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
8149
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { onClick: formatEventData, className: buttonClass, children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(Braces, {}) }) }) }),
8150
+ /* @__PURE__ */ jsx(TooltipContent, { children: "Format the event data JSON" })
8151
+ ] }),
8152
+ /* @__PURE__ */ jsxs(Tooltip, { children: [
8153
+ /* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("button", { onClick: handleCopy, className: buttonClass, children: /* @__PURE__ */ jsx(Icon, { children: /* @__PURE__ */ jsx(CopyIcon, {}) }) }) }),
8154
+ /* @__PURE__ */ jsx(TooltipContent, { children: "Copy event data" })
8155
+ ] })
8156
+ ] })
8157
+ ] }),
8158
+ /* @__PURE__ */ jsx(
8159
+ CodeMirror,
8160
+ {
8161
+ value: eventData,
8162
+ onChange: setEventData,
8163
+ theme,
8164
+ extensions: [jsonLanguage],
8165
+ className: "h-[400px] overflow-y-scroll bg-surface3 rounded-lg overflow-hidden p-3"
8166
+ }
8167
+ ),
8168
+ error && /* @__PURE__ */ jsx(Txt, { variant: "ui-md", className: "text-accent2", children: error })
8169
+ ] }),
8170
+ /* @__PURE__ */ jsx("div", { className: "flex justify-end pt-4", children: /* @__PURE__ */ jsx(Button, { onClick: handleSendEvent, disabled: isLoading, children: isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin" }) : "Send" }) })
8171
+ ] });
8172
+ };
8173
+
8088
8174
  const WorkflowStepActionBar = ({
8089
8175
  input,
8090
8176
  output,
@@ -8092,17 +8178,22 @@ const WorkflowStepActionBar = ({
8092
8178
  error,
8093
8179
  mapConfig,
8094
8180
  stepName,
8181
+ event,
8095
8182
  onShowTrace,
8096
- onShowNestedGraph
8183
+ onShowNestedGraph,
8184
+ onSendEvent,
8185
+ runId
8097
8186
  }) => {
8098
8187
  const [isInputOpen, setIsInputOpen] = useState(false);
8099
8188
  const [isOutputOpen, setIsOutputOpen] = useState(false);
8100
8189
  const [isResumeDataOpen, setIsResumeDataOpen] = useState(false);
8101
8190
  const [isErrorOpen, setIsErrorOpen] = useState(false);
8102
8191
  const [isMapConfigOpen, setIsMapConfigOpen] = useState(false);
8192
+ const [isEventFormOpen, setIsEventFormOpen] = useState(false);
8103
8193
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
8104
8194
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
8105
- return /* @__PURE__ */ jsx(Fragment, { children: (input || output || error || mapConfig || resumeData || onShowNestedGraph) && /* @__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: [
8195
+ const showEventForm = event && onSendEvent && runId;
8196
+ return /* @__PURE__ */ jsx(Fragment, { children: (input || output || error || mapConfig || resumeData || onShowNestedGraph || showEventForm) && /* @__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: [
8106
8197
  onShowNestedGraph && /* @__PURE__ */ jsx(Button, { onClick: onShowNestedGraph, children: "View nested graph" }),
8107
8198
  mapConfig && /* @__PURE__ */ jsxs(Fragment, { children: [
8108
8199
  /* @__PURE__ */ jsx(Button, { onClick: () => setIsMapConfigOpen(true), children: "Map config" }),
@@ -8154,7 +8245,18 @@ const WorkflowStepActionBar = ({
8154
8245
  /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(CodeDialogContent, { data: error }) })
8155
8246
  ] }) })
8156
8247
  ] }),
8157
- onShowTrace && /* @__PURE__ */ jsx(Button, { onClick: onShowTrace, children: "Show trace" })
8248
+ onShowTrace && /* @__PURE__ */ jsx(Button, { onClick: onShowTrace, children: "Show trace" }),
8249
+ showEventForm && /* @__PURE__ */ jsxs(Fragment, { children: [
8250
+ /* @__PURE__ */ jsx(Button, { onClick: () => setIsEventFormOpen(true), children: "Send event" }),
8251
+ /* @__PURE__ */ jsx(Dialog, { open: isEventFormOpen, onOpenChange: setIsEventFormOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: dialogContentClass, children: [
8252
+ /* @__PURE__ */ jsxs(DialogTitle, { className: dialogTitleClass, children: [
8253
+ "Send ",
8254
+ event,
8255
+ " event"
8256
+ ] }),
8257
+ /* @__PURE__ */ jsx("div", { className: "px-4 overflow-hidden", children: /* @__PURE__ */ jsx(WorkflowRunEventForm, { event, runId, onSendEvent }) })
8258
+ ] }) })
8259
+ ] })
8158
8260
  ] }) });
8159
8261
  };
8160
8262
 
@@ -8264,7 +8366,8 @@ function WorkflowConditionNode({ data }) {
8264
8366
  function WorkflowDefaultNode({
8265
8367
  data,
8266
8368
  onShowTrace,
8267
- parentWorkflowName
8369
+ parentWorkflowName,
8370
+ onSendEvent
8268
8371
  }) {
8269
8372
  const { steps, isRunning, runId } = useCurrentRun();
8270
8373
  const { label, description, withoutTopHandle, withoutBottomHandle, mapConfig, event, duration, date } = data;
@@ -8323,7 +8426,10 @@ function WorkflowDefaultNode({
8323
8426
  output: step?.output,
8324
8427
  error: step?.error,
8325
8428
  mapConfig,
8326
- onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0
8429
+ event: step?.status === "waiting" ? event : void 0,
8430
+ onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0,
8431
+ runId,
8432
+ onSendEvent
8327
8433
  }
8328
8434
  )
8329
8435
  ]
@@ -8413,7 +8519,13 @@ const ZoomSlider = forwardRef(({ className, ...props }) => {
8413
8519
  });
8414
8520
  ZoomSlider.displayName = "ZoomSlider";
8415
8521
 
8416
- function WorkflowNestedGraph({ stepGraph, open, workflowName, onShowTrace }) {
8522
+ function WorkflowNestedGraph({
8523
+ stepGraph,
8524
+ open,
8525
+ workflowName,
8526
+ onShowTrace,
8527
+ onSendEvent
8528
+ }) {
8417
8529
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
8418
8530
  stepGraph
8419
8531
  });
@@ -8422,11 +8534,27 @@ function WorkflowNestedGraph({ stepGraph, open, workflowName, onShowTrace }) {
8422
8534
  const [edges] = useEdgesState(initialEdges);
8423
8535
  const { steps } = useCurrentRun();
8424
8536
  const nodeTypes = {
8425
- "default-node": (props) => /* @__PURE__ */ jsx(WorkflowDefaultNode, { parentWorkflowName: workflowName, onShowTrace, ...props }),
8537
+ "default-node": (props) => /* @__PURE__ */ jsx(
8538
+ WorkflowDefaultNode,
8539
+ {
8540
+ parentWorkflowName: workflowName,
8541
+ onShowTrace,
8542
+ onSendEvent,
8543
+ ...props
8544
+ }
8545
+ ),
8426
8546
  "condition-node": WorkflowConditionNode,
8427
8547
  "after-node": WorkflowAfterNode,
8428
8548
  "loop-result-node": WorkflowLoopResultNode,
8429
- "nested-node": (props) => /* @__PURE__ */ jsx(WorkflowNestedNode, { parentWorkflowName: workflowName, onShowTrace, ...props })
8549
+ "nested-node": (props) => /* @__PURE__ */ jsx(
8550
+ WorkflowNestedNode,
8551
+ {
8552
+ parentWorkflowName: workflowName,
8553
+ onShowTrace,
8554
+ onSendEvent,
8555
+ ...props
8556
+ }
8557
+ )
8430
8558
  };
8431
8559
  useEffect(() => {
8432
8560
  if (open) {
@@ -8468,7 +8596,8 @@ const WorkflowNestedGraphContext = createContext(
8468
8596
  );
8469
8597
  function WorkflowNestedGraphProvider({
8470
8598
  children,
8471
- onShowTrace
8599
+ onShowTrace,
8600
+ onSendEvent
8472
8601
  }) {
8473
8602
  const [stepGraph, setStepGraph] = useState(null);
8474
8603
  const [parentStepGraphList, setParentStepGraphList] = useState([]);
@@ -8525,7 +8654,8 @@ function WorkflowNestedGraphProvider({
8525
8654
  stepGraph,
8526
8655
  open: openDialog,
8527
8656
  workflowName: fullStep,
8528
- onShowTrace
8657
+ onShowTrace,
8658
+ onSendEvent
8529
8659
  }
8530
8660
  ) })
8531
8661
  ] }) }) }, `${label}-${fullStep}`)
@@ -8537,11 +8667,12 @@ function WorkflowNestedGraphProvider({
8537
8667
  function WorkflowNestedNode({
8538
8668
  data,
8539
8669
  parentWorkflowName,
8540
- onShowTrace
8670
+ onShowTrace,
8671
+ onSendEvent
8541
8672
  }) {
8542
8673
  const { steps, isRunning, runId } = useCurrentRun();
8543
8674
  const { showNestedGraph } = useContext(WorkflowNestedGraphContext);
8544
- const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig } = data;
8675
+ const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig, event } = data;
8545
8676
  const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
8546
8677
  const step = steps[fullLabel];
8547
8678
  return /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -8552,14 +8683,17 @@ function WorkflowNestedNode({
8552
8683
  className: cn(
8553
8684
  "bg-surface3 rounded-lg w-[274px] border-sm border-border1 pt-2",
8554
8685
  step?.status === "success" && "ring-2 ring-accent1",
8555
- step?.status === "failed" && "ring-2 ring-accent2"
8686
+ step?.status === "failed" && "ring-2 ring-accent2",
8687
+ step?.status === "suspended" && "ring-2 ring-accent3",
8688
+ step?.status === "waiting" && "ring-2 ring-accent5"
8556
8689
  ),
8557
8690
  children: [
8558
8691
  /* @__PURE__ */ jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
8559
8692
  isRunning && /* @__PURE__ */ jsxs(Icon, { children: [
8560
8693
  step?.status === "failed" && /* @__PURE__ */ jsx(CrossIcon, { className: "text-accent2" }),
8561
8694
  step?.status === "success" && /* @__PURE__ */ jsx(CheckIcon, { className: "text-accent1" }),
8562
- step?.status === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-icon3" }),
8695
+ step?.status === "suspended" && /* @__PURE__ */ jsx(PauseIcon, { className: "text-accent3" }),
8696
+ step?.status === "waiting" && /* @__PURE__ */ jsx(HourglassIcon, { className: "text-accent5" }),
8563
8697
  step?.status === "running" && /* @__PURE__ */ jsx(Loader2, { className: "text-icon6 animate-spin" }),
8564
8698
  !step && /* @__PURE__ */ jsx(CircleDashed, { className: "text-icon2" })
8565
8699
  ] }),
@@ -8580,7 +8714,10 @@ function WorkflowNestedNode({
8580
8714
  error: step?.error,
8581
8715
  mapConfig,
8582
8716
  onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0,
8583
- onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph })
8717
+ onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
8718
+ onSendEvent,
8719
+ event: step?.status === "waiting" ? event : void 0,
8720
+ runId
8584
8721
  }
8585
8722
  )
8586
8723
  ]
@@ -8590,17 +8727,17 @@ function WorkflowNestedNode({
8590
8727
  ] });
8591
8728
  }
8592
8729
 
8593
- function WorkflowGraphInner({ workflow, onShowTrace }) {
8730
+ function WorkflowGraphInner({ workflow, onShowTrace, onSendEvent }) {
8594
8731
  const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
8595
8732
  const [nodes, _, onNodesChange] = useNodesState(initialNodes);
8596
8733
  const [edges] = useEdgesState(initialEdges);
8597
8734
  const { steps, runId } = useCurrentRun();
8598
8735
  const nodeTypes = {
8599
- "default-node": (props) => /* @__PURE__ */ jsx(WorkflowDefaultNode, { onShowTrace, ...props }),
8736
+ "default-node": (props) => /* @__PURE__ */ jsx(WorkflowDefaultNode, { onShowTrace, onSendEvent, ...props }),
8600
8737
  "condition-node": WorkflowConditionNode,
8601
8738
  "after-node": WorkflowAfterNode,
8602
8739
  "loop-result-node": WorkflowLoopResultNode,
8603
- "nested-node": (props) => /* @__PURE__ */ jsx(WorkflowNestedNode, { onShowTrace, ...props })
8740
+ "nested-node": (props) => /* @__PURE__ */ jsx(WorkflowNestedNode, { onShowTrace, onSendEvent, ...props })
8604
8741
  };
8605
8742
  return /* @__PURE__ */ jsx("div", { className: "w-full h-full bg-surface1", children: /* @__PURE__ */ jsxs(
8606
8743
  ReactFlow,
@@ -8630,7 +8767,7 @@ function WorkflowGraphInner({ workflow, onShowTrace }) {
8630
8767
  ) });
8631
8768
  }
8632
8769
 
8633
- function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading }) {
8770
+ function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading, onSendEvent }) {
8634
8771
  const { snapshot } = useContext(WorkflowRunContext);
8635
8772
  if (isLoading) {
8636
8773
  return /* @__PURE__ */ jsx("div", { className: "p-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-full" }) });
@@ -8645,13 +8782,22 @@ function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading }) {
8645
8782
  ] })
8646
8783
  ] }) });
8647
8784
  }
8648
- return /* @__PURE__ */ jsx(WorkflowNestedGraphProvider, { onShowTrace, children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(
8649
- WorkflowGraphInner,
8785
+ return /* @__PURE__ */ jsx(
8786
+ WorkflowNestedGraphProvider,
8650
8787
  {
8651
- workflow: snapshot?.serializedStepGraph ? { stepGraph: snapshot?.serializedStepGraph } : workflow,
8652
- onShowTrace
8653
- }
8654
- ) }) }, snapshot?.runId ?? workflowId);
8788
+ onShowTrace,
8789
+ onSendEvent,
8790
+ children: /* @__PURE__ */ jsx(ReactFlowProvider, { children: /* @__PURE__ */ jsx(
8791
+ WorkflowGraphInner,
8792
+ {
8793
+ workflow: snapshot?.serializedStepGraph ? { stepGraph: snapshot?.serializedStepGraph } : workflow,
8794
+ onShowTrace,
8795
+ onSendEvent
8796
+ }
8797
+ ) })
8798
+ },
8799
+ snapshot?.runId ?? workflowId
8800
+ );
8655
8801
  }
8656
8802
 
8657
8803
  const useWorkflowRuns = (workflowId) => {
@@ -9216,17 +9362,6 @@ const MessagesProvider = ({ children }) => {
9216
9362
  };
9217
9363
  const useMessages = () => useContext(MessagesContext);
9218
9364
 
9219
- const formatJSON = async (code) => {
9220
- const formatted = await prettier.format(code, {
9221
- semi: false,
9222
- parser: "json",
9223
- printWidth: 80,
9224
- tabWidth: 2,
9225
- plugins: [prettierPluginBabel, prettierPluginEstree]
9226
- });
9227
- return formatted;
9228
- };
9229
-
9230
9365
  const convertMessage = (message) => {
9231
9366
  return message;
9232
9367
  };