@mastra/playground-ui 6.2.2 → 6.2.3-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.
Files changed (25) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/index.cjs.js +1295 -2067
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +1297 -2064
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/domains/agents/components/agent-metadata/agent-metadata-model-list.d.ts +17 -0
  7. package/dist/src/domains/agents/components/agent-metadata/agent-metadata.d.ts +4 -1
  8. package/dist/src/domains/agents/components/agent-table/types.d.ts +2 -1
  9. package/dist/src/domains/agents/components/provider-map-icon.d.ts +1 -0
  10. package/dist/src/domains/workflows/components/workflow-table/types.d.ts +0 -1
  11. package/dist/src/domains/workflows/components/workflow-table/workflow-table.d.ts +2 -3
  12. package/dist/src/domains/workflows/context/workflow-run-context.d.ts +0 -3
  13. package/dist/src/domains/workflows/index.d.ts +0 -2
  14. package/dist/src/domains/workflows/workflow/utils.d.ts +0 -10
  15. package/dist/src/hooks/use-workflows.d.ts +1 -45
  16. package/dist/src/services/stream-chunk-message.d.ts +9 -18
  17. package/dist/src/types.d.ts +7 -1
  18. package/package.json +6 -4
  19. package/dist/src/domains/workflows/context/legacy-workflow-nested-graph-context.d.ts +0 -13
  20. package/dist/src/domains/workflows/workflow/legacy-workflow-graph-inner.d.ts +0 -4
  21. package/dist/src/domains/workflows/workflow/legacy-workflow-graph.d.ts +0 -3
  22. package/dist/src/domains/workflows/workflow/legacy-workflow-nested-graph.d.ts +0 -5
  23. package/dist/src/domains/workflows/workflow/legacy-workflow-nested-node.d.ts +0 -11
  24. package/dist/src/domains/workflows/workflow/legacy-workflow-status.d.ts +0 -6
  25. package/dist/src/domains/workflows/workflow/legacy-workflow-trigger.d.ts +0 -4
package/dist/index.cjs.js CHANGED
@@ -21,26 +21,27 @@ const codemirrorThemeDracula = require('@uiw/codemirror-theme-dracula');
21
21
  const CodeMirror = require('@uiw/react-codemirror');
22
22
  const sonner = require('sonner');
23
23
  const DialogPrimitive = require('@radix-ui/react-dialog');
24
- const useDebounce = require('use-debounce');
25
- const zustand = require('zustand');
26
- const middleware = require('zustand/middleware');
27
- const reactQuery = require('@tanstack/react-query');
28
24
  const react = require('@xyflow/react');
29
25
  require('@xyflow/react/dist/style.css');
30
26
  const Dagre = require('@dagrejs/dagre');
31
27
  const prismReactRenderer = require('prism-react-renderer');
32
28
  const CollapsiblePrimitive = require('@radix-ui/react-collapsible');
33
29
  const ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
30
+ const colors = require('./colors-DLwJ7rFA.cjs');
34
31
  const prettier = require('prettier');
35
32
  const prettierPluginBabel = require('prettier/plugins/babel');
36
33
  const prettierPluginEstree = require('prettier/plugins/estree');
37
- const colors = require('./colors-DLwJ7rFA.cjs');
34
+ const SliderPrimitive = require('@radix-ui/react-slider');
38
35
  const jsonSchemaToZod = require('json-schema-to-zod');
39
36
  const superjson = require('superjson');
40
37
  const z = require('zod');
38
+ const reactCodeBlock = require('react-code-block');
39
+ const zustand = require('zustand');
40
+ const middleware = require('zustand/middleware');
41
41
  const react$1 = require('@autoform/react');
42
42
  const CheckboxPrimitive = require('@radix-ui/react-checkbox');
43
43
  const dateFns = require('date-fns');
44
+ const useDebounce = require('use-debounce');
44
45
  const reactDayPicker = require('react-day-picker');
45
46
  const PopoverPrimitive = require('@radix-ui/react-popover');
46
47
  const SelectPrimitive = require('@radix-ui/react-select');
@@ -48,18 +49,19 @@ const uuid = require('@lukeed/uuid');
48
49
  const LabelPrimitive = require('@radix-ui/react-label');
49
50
  const v4 = require('@autoform/zod/v4');
50
51
  const v3 = require('zod/v3');
51
- const reactCodeBlock = require('react-code-block');
52
- const SliderPrimitive = require('@radix-ui/react-slider');
53
52
  const RadioGroupPrimitive = require('@radix-ui/react-radio-group');
53
+ const reactQuery = require('@tanstack/react-query');
54
54
  const reactTable = require('@tanstack/react-table');
55
55
  const Markdown = require('react-markdown');
56
56
  const shallow = require('zustand/shallow');
57
57
  const di = require('@mastra/core/di');
58
- const reactDom = require('react-dom');
58
+ const reactHooks = require('@mastra/react-hooks');
59
59
  const react$3 = require('motion/react');
60
60
  const TabsPrimitive = require('@radix-ui/react-tabs');
61
61
  const VisuallyHidden = require('@radix-ui/react-visually-hidden');
62
62
  const HoverCard = require('@radix-ui/react-hover-card');
63
+ const dnd = require('@hello-pangea/dnd');
64
+ const SwitchPrimitives = require('@radix-ui/react-switch');
63
65
  const AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
64
66
  const runtimeContext = require('@mastra/core/runtime-context');
65
67
  const format = require('date-fns/format');
@@ -88,15 +90,16 @@ const AvatarPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(AvatarP
88
90
  const DialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DialogPrimitive);
89
91
  const CollapsiblePrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(CollapsiblePrimitive);
90
92
  const ScrollAreaPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(ScrollAreaPrimitive);
93
+ const SliderPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(SliderPrimitive);
91
94
  const CheckboxPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(CheckboxPrimitive);
92
95
  const PopoverPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(PopoverPrimitive);
93
96
  const SelectPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(SelectPrimitive);
94
97
  const LabelPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(LabelPrimitive);
95
- const SliderPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(SliderPrimitive);
96
98
  const RadioGroupPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(RadioGroupPrimitive);
97
99
  const TabsPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(TabsPrimitive);
98
100
  const VisuallyHidden__namespace = /*#__PURE__*/_interopNamespaceDefault(VisuallyHidden);
99
101
  const HoverCard__namespace = /*#__PURE__*/_interopNamespaceDefault(HoverCard);
102
+ const SwitchPrimitives__namespace = /*#__PURE__*/_interopNamespaceDefault(SwitchPrimitives);
100
103
  const AlertDialogPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(AlertDialogPrimitive);
101
104
  const DropdownMenuPrimitive__namespace = /*#__PURE__*/_interopNamespaceDefault(DropdownMenuPrimitive);
102
105
 
@@ -4538,549 +4541,284 @@ const ToolBadge = ({ toolName, args, result, networkMetadata, toolOutput }) => {
4538
4541
  );
4539
4542
  };
4540
4543
 
4541
- function Skeleton({ className, ...props }) {
4542
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("animate-pulse rounded-md bg-muted/50", className), ...props });
4543
- }
4544
-
4545
- const usePlaygroundStore = zustand.create()(
4546
- middleware.persist(
4547
- (set) => ({
4548
- runtimeContext: {},
4549
- setRuntimeContext: (runtimeContext) => set({ runtimeContext })
4550
- }),
4551
- {
4552
- name: "mastra-playground-store"
4544
+ function convertWorkflowRunStateToWatchResult(runState) {
4545
+ const runId = runState.runId;
4546
+ const steps = {};
4547
+ const context = runState.context || {};
4548
+ Object.entries(context).forEach(([stepId, stepResult]) => {
4549
+ if (stepId !== "input" && "status" in stepResult) {
4550
+ const result = stepResult;
4551
+ steps[stepId] = {
4552
+ status: result.status,
4553
+ output: "output" in result ? result.output : void 0,
4554
+ payload: "payload" in result ? result.payload : void 0,
4555
+ resumePayload: "resumePayload" in result ? result.resumePayload : void 0,
4556
+ error: "error" in result ? result.error : void 0,
4557
+ startedAt: "startedAt" in result ? result.startedAt : Date.now(),
4558
+ endedAt: "endedAt" in result ? result.endedAt : void 0,
4559
+ suspendedAt: "suspendedAt" in result ? result.suspendedAt : void 0,
4560
+ resumedAt: "resumedAt" in result ? result.resumedAt : void 0
4561
+ };
4553
4562
  }
4554
- )
4555
- );
4556
-
4557
- const useWorkflow = (workflowId) => {
4558
- const client = useMastraClient();
4559
- const { runtimeContext } = usePlaygroundStore();
4560
- return reactQuery.useQuery({
4561
- queryKey: ["workflow", workflowId],
4562
- queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
4563
- enabled: Boolean(workflowId),
4564
- retry: false,
4565
- refetchOnWindowFocus: false,
4566
- throwOnError: false
4567
4563
  });
4568
- };
4569
- const useLegacyWorkflow = (workflowId) => {
4570
- const [legacyWorkflow, setLegacyWorkflow] = React.useState(null);
4571
- const [isLoading, setIsLoading] = React.useState(true);
4572
- const client = useMastraClient();
4573
- React.useEffect(() => {
4574
- const fetchWorkflow = async () => {
4575
- setIsLoading(true);
4576
- try {
4577
- if (!workflowId) {
4578
- setLegacyWorkflow(null);
4579
- setIsLoading(false);
4580
- return;
4581
- }
4582
- const { runtimeContext } = usePlaygroundStore.getState();
4583
- const res = await client.getLegacyWorkflow(workflowId).details(runtimeContext);
4584
- if (!res) {
4585
- setLegacyWorkflow(null);
4586
- console.error("Error fetching legacy workflow");
4587
- sonner.toast.error("Error fetching legacy workflow");
4588
- return;
4589
- }
4590
- const steps = res.steps;
4591
- const stepsWithWorkflow = await Promise.all(
4592
- Object.values(steps)?.map(async (step) => {
4593
- if (!step.workflowId) return step;
4594
- const wFlow = await client.getLegacyWorkflow(step.workflowId).details(runtimeContext);
4595
- if (!wFlow) return step;
4596
- return { ...step, stepGraph: wFlow.stepGraph, stepSubscriberGraph: wFlow.stepSubscriberGraph };
4597
- })
4598
- );
4599
- const _steps = stepsWithWorkflow.reduce((acc, b) => {
4600
- return { ...acc, [b.id]: b };
4601
- }, {});
4602
- setLegacyWorkflow({ ...res, steps: _steps });
4603
- } catch (error) {
4604
- setLegacyWorkflow(null);
4605
- console.error("Error fetching legacy workflow", error);
4606
- sonner.toast.error("Error fetching legacy workflow");
4607
- } finally {
4608
- setIsLoading(false);
4609
- }
4610
- };
4611
- fetchWorkflow();
4612
- }, [workflowId]);
4613
- return { legacyWorkflow, isLoading };
4614
- };
4615
- const useExecuteWorkflow = () => {
4616
- const client = useMastraClient();
4617
- const createLegacyWorkflowRun = async ({ workflowId, prevRunId }) => {
4618
- try {
4619
- const workflow = client.getLegacyWorkflow(workflowId);
4620
- const { runId: newRunId } = await workflow.createRun({ runId: prevRunId });
4621
- return { runId: newRunId };
4622
- } catch (error) {
4623
- console.error("Error creating workflow run:", error);
4624
- throw error;
4625
- }
4626
- };
4627
- const startLegacyWorkflowRun = async ({
4628
- workflowId,
4629
- runId,
4630
- input
4631
- }) => {
4632
- try {
4633
- const workflow = client.getLegacyWorkflow(workflowId);
4634
- await workflow.start({ runId, triggerData: input || {} });
4635
- } catch (error) {
4636
- console.error("Error starting workflow run:", error);
4637
- throw error;
4638
- }
4639
- };
4640
- return {
4641
- startLegacyWorkflowRun,
4642
- createLegacyWorkflowRun
4643
- };
4644
- };
4645
- const useWatchWorkflow = () => {
4646
- const [isWatchingLegacyWorkflow, setIsWatchingLegacyWorkflow] = React.useState(false);
4647
- const [legacyWatchResult, setLegacyWatchResult] = React.useState(null);
4648
- const client = useMastraClient();
4649
- const debouncedSetLegacyWorkflowWatchResult = useDebounce.useDebouncedCallback((record) => {
4650
- const formattedResults = Object.entries(record.results || {}).reduce(
4651
- (acc, [key, value]) => {
4652
- let output = value.status === "success" ? value.output : void 0;
4653
- if (output) {
4654
- output = Object.entries(output).reduce(
4655
- (_acc, [_key, _value]) => {
4656
- const val = _value;
4657
- _acc[_key] = val.type?.toLowerCase() === "buffer" ? { type: "Buffer", data: `[...buffered data]` } : val;
4658
- return _acc;
4659
- },
4660
- {}
4661
- );
4662
- }
4663
- acc[key] = { ...value, output };
4664
- return acc;
4665
- },
4666
- {}
4667
- );
4668
- const sanitizedRecord = {
4669
- ...record,
4670
- sanitizedOutput: record ? JSON.stringify({ ...record, results: formattedResults }, null, 2).slice(0, 5e4) : null
4671
- };
4672
- setLegacyWatchResult(sanitizedRecord);
4673
- }, 100);
4674
- const watchLegacyWorkflow = async ({ workflowId, runId }) => {
4675
- try {
4676
- setIsWatchingLegacyWorkflow(true);
4677
- const workflow = client.getLegacyWorkflow(workflowId);
4678
- await workflow.watch({ runId }, (record) => {
4679
- try {
4680
- debouncedSetLegacyWorkflowWatchResult(record);
4681
- } catch (err) {
4682
- console.error("Error processing workflow record:", err);
4683
- setLegacyWatchResult({
4684
- ...record
4685
- });
4686
- }
4687
- });
4688
- } catch (error) {
4689
- console.error("Error watching workflow:", error);
4690
- throw error;
4691
- } finally {
4692
- setIsWatchingLegacyWorkflow(false);
4693
- }
4694
- };
4695
- return {
4696
- watchLegacyWorkflow,
4697
- isWatchingLegacyWorkflow,
4698
- legacyWatchResult
4699
- };
4700
- };
4701
- const useResumeWorkflow = () => {
4702
- const [isResumingLegacyWorkflow, setIsResumingLegacyWorkflow] = React.useState(false);
4703
- const client = useMastraClient();
4704
- const resumeLegacyWorkflow = async ({
4705
- workflowId,
4706
- stepId,
4707
- runId,
4708
- context
4709
- }) => {
4710
- try {
4711
- setIsResumingLegacyWorkflow(true);
4712
- const response = await client.getLegacyWorkflow(workflowId).resume({ stepId, runId, context });
4713
- return response;
4714
- } catch (error) {
4715
- console.error("Error resuming workflow:", error);
4716
- throw error;
4717
- } finally {
4718
- setIsResumingLegacyWorkflow(false);
4719
- }
4720
- };
4564
+ const status = determineWorkflowStatus(steps);
4721
4565
  return {
4722
- resumeLegacyWorkflow,
4723
- isResumingLegacyWorkflow
4724
- };
4725
- };
4726
-
4727
- function extractConditions(group, type) {
4728
- let result = [];
4729
- if (!group) return result;
4730
- function recurse(group2, conj) {
4731
- if (typeof group2 === "string") {
4732
- result.push({ type, fnString: group2 });
4733
- } else {
4734
- const simpleCondition = Object.entries(group2).find(([key]) => key.includes("."));
4735
- if (simpleCondition) {
4736
- const [key, queryValue] = simpleCondition;
4737
- const [stepId, ...pathParts] = key.split(".");
4738
- const ref = {
4739
- step: {
4740
- id: stepId
4741
- },
4742
- path: pathParts.join(".")
4743
- };
4744
- result.push({
4745
- type,
4746
- ref,
4747
- query: { [queryValue === true || queryValue === false ? "is" : "eq"]: String(queryValue) },
4748
- conj
4749
- });
4750
- }
4751
- if ("ref" in group2) {
4752
- const { ref, query } = group2;
4753
- result.push({ type, ref, query, conj });
4754
- }
4755
- if ("and" in group2) {
4756
- for (const subGroup of group2.and) {
4757
- recurse({ ...subGroup }, "and");
4758
- }
4759
- }
4760
- if ("or" in group2) {
4761
- for (const subGroup of group2.or) {
4762
- recurse({ ...subGroup }, "or");
4763
- }
4764
- }
4765
- if ("not" in group2) {
4766
- recurse({ ...group2.not }, "not");
4566
+ type: "watch",
4567
+ payload: {
4568
+ workflowState: {
4569
+ status,
4570
+ steps,
4571
+ result: runState.value,
4572
+ payload: context.input,
4573
+ error: void 0
4767
4574
  }
4768
- }
4769
- }
4770
- recurse(group);
4771
- return result.reverse();
4772
- }
4773
- const getLayoutedElements = (nodes, edges) => {
4774
- const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
4775
- g.setGraph({ rankdir: "TB" });
4776
- edges.forEach((edge) => g.setEdge(edge.source, edge.target));
4777
- nodes.forEach(
4778
- (node) => g.setNode(node.id, {
4779
- ...node,
4780
- width: node.measured?.width ?? 274,
4781
- height: node.measured?.height ?? (node?.data?.isLarge ? 260 : 100)
4782
- })
4783
- );
4784
- Dagre.layout(g);
4785
- const fullWidth = g.graph()?.width ? g.graph().width / 2 : 0;
4786
- const fullHeight = g.graph()?.height ? g.graph().height / 2 : 0;
4787
- return {
4788
- nodes: nodes.map((node) => {
4789
- const position = g.node(node.id);
4790
- const positionX = position.x - (node.measured?.width ?? 274) / 2;
4791
- const positionY = position.y - (node.measured?.height ?? (node?.data?.isLarge ? 260 : 100)) / 2;
4792
- const x = positionX;
4793
- const y = positionY;
4794
- return { ...node, position: { x, y } };
4795
- }),
4796
- edges,
4797
- fullWidth,
4798
- fullHeight
4575
+ },
4576
+ eventTimestamp: new Date(runState.timestamp),
4577
+ runId
4799
4578
  };
4800
- };
4801
- const defaultEdgeOptions = {
4802
- animated: true,
4803
- markerEnd: {
4804
- type: react.MarkerType.ArrowClosed,
4805
- width: 20,
4806
- height: 20,
4807
- color: "#8e8e8e"
4579
+ }
4580
+ function determineWorkflowStatus(steps) {
4581
+ const stepStatuses = Object.values(steps).map((step) => step.status);
4582
+ if (stepStatuses.includes("failed")) {
4583
+ return "failed";
4808
4584
  }
4809
- };
4810
- const contructLegacyNodesAndEdges = ({
4811
- stepGraph,
4812
- stepSubscriberGraph,
4813
- steps: mainSteps = {}
4814
- }) => {
4815
- if (!stepGraph) {
4816
- return { nodes: [], edges: [] };
4585
+ if (stepStatuses.includes("suspended")) {
4586
+ return "suspended";
4817
4587
  }
4818
- const { initial, ...stepsList } = stepGraph;
4819
- if (!initial.length) {
4820
- return { nodes: [], edges: [] };
4588
+ if (stepStatuses.every((status) => status === "success")) {
4589
+ return "success";
4821
4590
  }
4822
- let nodes = [];
4823
- let edges = [];
4824
- let allSteps = [];
4825
- for (const [_index, _step] of initial.entries()) {
4826
- const step = _step.step;
4827
- const stepId = step.id;
4828
- const steps = [_step, ...stepsList?.[stepId] || []]?.reduce((acc, step2, i) => {
4829
- const { stepGraph: stepWflowGraph, stepSubscriberGraph: stepWflowSubscriberGraph } = mainSteps[step2.step.id] || {};
4830
- const hasGraph = !!stepWflowGraph;
4831
- const nodeId = nodes.some((node) => node.id === step2.step.id) ? `${step2.step.id}-${i}` : step2.step.id;
4832
- let newStep = {
4833
- ...step2.step,
4834
- label: step2.step.id,
4835
- originalId: step2.step.id,
4836
- type: hasGraph ? "nested-node" : "default-node",
4837
- id: nodeId,
4838
- stepGraph: stepWflowGraph,
4839
- stepSubscriberGraph: stepWflowSubscriberGraph
4840
- };
4841
- let conditionType = "when";
4842
- if (step2.config?.serializedWhen) {
4843
- conditionType = step2.step.id?.endsWith("_if") ? "if" : step2.step.id?.endsWith("_else") ? "else" : "when";
4844
- const conditions = extractConditions(step2.config.serializedWhen, conditionType);
4845
- const conditionStep = {
4846
- id: crypto.randomUUID(),
4847
- conditions,
4848
- type: "condition-node",
4849
- isLarge: (conditions?.length > 1 || conditions.some(({ fnString }) => !!fnString)) && conditionType !== "else"
4850
- };
4851
- acc.push(conditionStep);
4852
- }
4853
- if (conditionType === "if" || conditionType === "else") {
4854
- newStep = {
4855
- ...newStep,
4856
- label: conditionType === "if" ? "start if" : "start else"
4857
- };
4858
- }
4859
- newStep = {
4860
- ...newStep,
4861
- label: step2.config?.loopLabel || newStep.label
4862
- };
4863
- acc.push(newStep);
4864
- return acc;
4865
- }, []);
4866
- allSteps = [...allSteps, ...steps];
4867
- const newNodes = [...steps].map((step2, index) => {
4868
- const subscriberGraph = stepSubscriberGraph?.[step2.id];
4869
- return {
4870
- id: step2.id,
4871
- position: { x: _index * 300, y: index * 100 },
4872
- type: step2.type,
4873
- data: {
4874
- conditions: step2.conditions,
4875
- label: step2.label,
4876
- description: step2.description,
4877
- withoutTopHandle: subscriberGraph?.[step2.id] ? false : index === 0,
4878
- withoutBottomHandle: subscriberGraph ? false : index === steps.length - 1,
4879
- isLarge: step2.isLarge,
4880
- stepGraph: step2.stepGraph,
4881
- stepSubscriberGraph: step2.stepSubscriberGraph
4591
+ return "running";
4592
+ }
4593
+ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
4594
+ if (chunk.type === "workflow-start") {
4595
+ return {
4596
+ ...prev,
4597
+ runId: chunk.runId,
4598
+ eventTimestamp: /* @__PURE__ */ new Date(),
4599
+ payload: {
4600
+ ...prev?.payload || {},
4601
+ workflowState: {
4602
+ ...prev?.payload?.workflowState,
4603
+ status: "running",
4604
+ steps: {}
4882
4605
  }
4883
- };
4884
- });
4885
- nodes = [...nodes, ...newNodes];
4886
- const edgeSteps = [...steps].slice(0, -1);
4887
- const newEdges = edgeSteps.map((step2, index) => ({
4888
- id: `e${step2.id}-${steps[index + 1].id}`,
4889
- source: step2.id,
4890
- target: steps[index + 1].id,
4891
- ...defaultEdgeOptions
4892
- }));
4893
- edges = [...edges, ...newEdges];
4894
- }
4895
- if (!stepSubscriberGraph || !Object.keys(stepSubscriberGraph).length) {
4896
- const { nodes: layoutedNodes2, edges: layoutedEdges2 } = getLayoutedElements(nodes, edges);
4897
- return { nodes: layoutedNodes2, edges: layoutedEdges2 };
4606
+ }
4607
+ };
4898
4608
  }
4899
- for (const [connectingStepId, stepInfoGraph] of Object.entries(stepSubscriberGraph)) {
4900
- const { initial: initial2, ...stepsList2 } = stepInfoGraph;
4901
- let untilOrWhileConditionId;
4902
- const loopResultSteps = [];
4903
- let finishedLoopStep;
4904
- let otherLoopStep;
4905
- if (initial2.length) {
4906
- for (const [_index, _step] of initial2.entries()) {
4907
- const step = _step.step;
4908
- const stepId = step.id;
4909
- const steps = [_step, ...stepsList2?.[stepId] || []]?.reduce((acc, step2, i) => {
4910
- const { stepGraph: stepWflowGraph, stepSubscriberGraph: stepWflowSubscriberGraph } = mainSteps[step2.step.id] || {};
4911
- const hasGraph = !!stepWflowGraph;
4912
- const nodeId = nodes.some((node) => node.id === step2.step.id) ? `${step2.step.id}-${i}` : step2.step.id;
4913
- let newStep = {
4914
- ...step2.step,
4915
- originalId: step2.step.id,
4916
- label: step2.step.id,
4917
- type: hasGraph ? "nested-node" : "default-node",
4918
- id: nodeId,
4919
- stepGraph: stepWflowGraph,
4920
- stepSubscriberGraph: stepWflowSubscriberGraph
4921
- };
4922
- let conditionType = "when";
4923
- const isFinishedLoop = step2.config?.loopLabel?.endsWith("loop finished");
4924
- if (step2.config?.serializedWhen && !isFinishedLoop) {
4925
- conditionType = step2.step.id?.endsWith("_if") ? "if" : step2.step.id?.endsWith("_else") ? "else" : step2.config?.loopType ?? "when";
4926
- const conditions = extractConditions(step2.config.serializedWhen, conditionType);
4927
- const conditionStep = {
4928
- id: crypto.randomUUID(),
4929
- conditions,
4930
- type: "condition-node",
4931
- isLarge: (conditions?.length > 1 || conditions.some(({ fnString }) => !!fnString)) && conditionType !== "else"
4932
- };
4933
- if (conditionType === "until" || conditionType === "while") {
4934
- untilOrWhileConditionId = conditionStep.id;
4609
+ if (chunk.type === "workflow-step-start") {
4610
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4611
+ return {
4612
+ ...prev,
4613
+ payload: {
4614
+ ...prev.payload,
4615
+ currentStep: {
4616
+ id: chunk.payload.id,
4617
+ ...chunk.payload
4618
+ },
4619
+ workflowState: {
4620
+ ...prev?.payload?.workflowState,
4621
+ steps: {
4622
+ ...prev?.payload?.workflowState?.steps,
4623
+ [chunk.payload.id]: {
4624
+ ...current || {},
4625
+ ...chunk.payload
4935
4626
  }
4936
- acc.push(conditionStep);
4937
- }
4938
- if (isFinishedLoop) {
4939
- const loopResultStep = {
4940
- id: crypto.randomUUID(),
4941
- type: "loop-result-node",
4942
- loopType: "finished",
4943
- loopResult: step2.config.loopType === "until" ? true : false
4944
- };
4945
- loopResultSteps.push(loopResultStep);
4946
- acc.push(loopResultStep);
4947
- }
4948
- if (!isFinishedLoop && step2.config?.loopType) {
4949
- const loopResultStep = {
4950
- id: crypto.randomUUID(),
4951
- type: "loop-result-node",
4952
- loopType: step2.config.loopType,
4953
- loopResult: step2.config.loopType === "until" ? false : true
4954
- };
4955
- loopResultSteps.push(loopResultStep);
4956
- acc.push(loopResultStep);
4957
4627
  }
4958
- if (conditionType === "if" || conditionType === "else") {
4959
- newStep = {
4960
- ...newStep,
4961
- label: conditionType === "if" ? "start if" : "start else"
4962
- };
4963
- }
4964
- if (step2.config.loopType) {
4965
- if (isFinishedLoop) {
4966
- finishedLoopStep = newStep;
4967
- } else {
4968
- otherLoopStep = newStep;
4628
+ }
4629
+ },
4630
+ eventTimestamp: /* @__PURE__ */ new Date()
4631
+ };
4632
+ }
4633
+ if (chunk.type === "workflow-step-suspended") {
4634
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4635
+ return {
4636
+ ...prev,
4637
+ payload: {
4638
+ ...prev?.payload,
4639
+ currentStep: {
4640
+ id: chunk.payload.id,
4641
+ ...prev?.payload?.currentStep,
4642
+ ...chunk.payload
4643
+ },
4644
+ workflowState: {
4645
+ ...prev?.payload?.workflowState,
4646
+ status: "suspended",
4647
+ steps: {
4648
+ ...prev?.payload?.workflowState?.steps,
4649
+ [chunk.payload.id]: {
4650
+ ...current || {},
4651
+ ...chunk.payload
4969
4652
  }
4970
4653
  }
4971
- newStep = {
4972
- ...newStep,
4973
- loopType: isFinishedLoop ? "finished" : step2.config.loopType,
4974
- label: step2.config?.loopLabel || newStep.label
4975
- };
4976
- acc.push(newStep);
4977
- return acc;
4978
- }, []);
4979
- let afterStep = [];
4980
- let afterStepStepList = connectingStepId?.includes("&&") ? connectingStepId.split("&&") : [];
4981
- if (connectingStepId?.includes("&&")) {
4982
- afterStep = [
4983
- {
4984
- id: connectingStepId,
4985
- label: connectingStepId,
4986
- type: "after-node",
4987
- steps: afterStepStepList
4988
- }
4989
- ];
4990
4654
  }
4991
- const newNodes = [...steps, ...afterStep].map((step2, index) => {
4992
- const subscriberGraph = stepSubscriberGraph?.[step2.id];
4993
- const withBottomHandle = step2.originalId === connectingStepId || subscriberGraph;
4994
- return {
4995
- id: step2.id,
4996
- position: { x: _index * 300 + 300, y: index * 100 + 100 },
4997
- type: step2.type,
4998
- data: {
4999
- conditions: step2.conditions,
5000
- label: step2.label,
5001
- description: step2.description,
5002
- result: step2.loopResult,
5003
- loopType: step2.loopType,
5004
- steps: step2.steps,
5005
- withoutBottomHandle: withBottomHandle ? false : index === steps.length - 1,
5006
- isLarge: step2.isLarge,
5007
- stepGraph: step2.stepGraph,
5008
- stepSubscriberGraph: step2.stepSubscriberGraph
4655
+ },
4656
+ eventTimestamp: /* @__PURE__ */ new Date()
4657
+ };
4658
+ }
4659
+ if (chunk.type === "workflow-step-waiting") {
4660
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4661
+ return {
4662
+ ...prev,
4663
+ payload: {
4664
+ ...prev?.payload,
4665
+ currentStep: {
4666
+ id: chunk.payload.id,
4667
+ ...prev?.payload?.currentStep || {},
4668
+ ...chunk.payload
4669
+ },
4670
+ workflowState: {
4671
+ ...prev?.payload?.workflowState,
4672
+ status: "waiting",
4673
+ steps: {
4674
+ ...prev?.payload?.workflowState?.steps,
4675
+ [chunk.payload.id]: {
4676
+ ...current,
4677
+ ...chunk.payload
5009
4678
  }
5010
- };
5011
- });
5012
- nodes = [...nodes, ...newNodes].map((node) => ({
5013
- ...node,
5014
- data: {
5015
- ...node.data,
5016
- withoutBottomHandle: afterStepStepList.includes(node.id) ? false : node.data.withoutBottomHandle
5017
- }
5018
- }));
5019
- const edgeSteps = [...steps].slice(0, -1);
5020
- const firstEdgeStep = steps[0];
5021
- const lastEdgeStep = steps[steps.length - 1];
5022
- const afterEdges = afterStepStepList?.map((step2) => ({
5023
- id: `e${step2}-${connectingStepId}`,
5024
- source: step2,
5025
- target: connectingStepId,
5026
- ...defaultEdgeOptions
5027
- }));
5028
- const finishedLoopResult = loopResultSteps?.find((step2) => step2.loopType === "finished");
5029
- const newEdges = edgeSteps.map((step2, index) => ({
5030
- id: `e${step2.id}-${steps[index + 1].id}`,
5031
- source: step2.id,
5032
- target: steps[index + 1].id,
5033
- remove: finishedLoopResult?.id === steps[index + 1].id,
5034
- //remove if target is a finished loop result
5035
- ...defaultEdgeOptions
5036
- }))?.filter((edge) => !edge.remove);
5037
- const connectingEdge = connectingStepId === firstEdgeStep.id ? [] : [
5038
- {
5039
- id: `e${connectingStepId}-${firstEdgeStep.id}`,
5040
- source: connectingStepId,
5041
- target: firstEdgeStep.id,
5042
- remove: finishedLoopResult?.id === firstEdgeStep.id,
5043
- ...defaultEdgeOptions
5044
4679
  }
5045
- ]?.filter((edge) => !edge.remove);
5046
- const lastEdge = lastEdgeStep.originalId === connectingStepId ? [
5047
- {
5048
- id: `e${lastEdgeStep.id}-${connectingStepId}`,
5049
- source: lastEdgeStep.id,
5050
- target: connectingStepId,
5051
- ...defaultEdgeOptions
4680
+ }
4681
+ },
4682
+ eventTimestamp: /* @__PURE__ */ new Date()
4683
+ };
4684
+ }
4685
+ if (chunk.type === "workflow-step-result") {
4686
+ const status = chunk.payload.status;
4687
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4688
+ const next = {
4689
+ ...prev,
4690
+ payload: {
4691
+ ...prev?.payload,
4692
+ currentStep: {
4693
+ id: chunk.payload.id,
4694
+ ...prev?.payload?.currentStep || {},
4695
+ ...chunk.payload
4696
+ },
4697
+ workflowState: {
4698
+ ...prev?.payload?.workflowState,
4699
+ status,
4700
+ steps: {
4701
+ ...prev?.payload?.workflowState?.steps,
4702
+ [chunk.payload.id]: {
4703
+ ...current,
4704
+ ...chunk.payload
4705
+ }
5052
4706
  }
5053
- ] : [];
5054
- edges = [...edges, ...afterEdges, ...connectingEdge, ...newEdges, ...lastEdge];
5055
- allSteps = [...allSteps, ...steps];
5056
- }
5057
- if (untilOrWhileConditionId && loopResultSteps.length && finishedLoopStep && otherLoopStep) {
5058
- const loopResultStepsEdges = loopResultSteps.map((step) => ({
5059
- id: `e${untilOrWhileConditionId}-${step.id}`,
5060
- source: untilOrWhileConditionId,
5061
- target: step.id,
5062
- ...defaultEdgeOptions
5063
- }));
5064
- const finishedLoopResult = loopResultSteps?.find((res) => res.loopType === "finished");
5065
- const otherLoopResult = loopResultSteps?.find((res) => res.loopType !== "finished");
5066
- const otherLoopEdge = {
5067
- id: `e${otherLoopResult?.id}-${otherLoopStep?.id}`,
5068
- source: otherLoopResult?.id,
5069
- target: otherLoopStep.id,
5070
- ...defaultEdgeOptions
5071
- };
5072
- const finishedLoopEdge = {
5073
- id: `e${finishedLoopResult?.id}-${finishedLoopStep?.id}`,
5074
- source: finishedLoopResult?.id,
5075
- target: finishedLoopStep.id,
5076
- ...defaultEdgeOptions
5077
- };
5078
- edges = [...edges, ...loopResultStepsEdges, otherLoopEdge, finishedLoopEdge];
5079
- }
4707
+ }
4708
+ },
4709
+ eventTimestamp: /* @__PURE__ */ new Date()
4710
+ };
4711
+ return next;
4712
+ }
4713
+ if (chunk.type === "workflow-canceled") {
4714
+ return {
4715
+ ...prev,
4716
+ payload: {
4717
+ ...prev?.payload,
4718
+ workflowState: {
4719
+ ...prev?.payload?.workflowState,
4720
+ status: "canceled"
4721
+ }
4722
+ },
4723
+ eventTimestamp: /* @__PURE__ */ new Date()
4724
+ };
4725
+ }
4726
+ if (chunk.type === "workflow-finish") {
4727
+ return {
4728
+ ...prev,
4729
+ payload: {
4730
+ ...prev?.payload,
4731
+ currentStep: void 0,
4732
+ workflowState: {
4733
+ ...prev?.payload?.workflowState,
4734
+ status: chunk.payload.workflowStatus
4735
+ }
4736
+ },
4737
+ eventTimestamp: /* @__PURE__ */ new Date()
4738
+ };
4739
+ }
4740
+ return prev;
4741
+ };
4742
+
4743
+ const WorkflowRunContext = React.createContext({});
4744
+ function WorkflowRunProvider({
4745
+ children,
4746
+ snapshot
4747
+ }) {
4748
+ const [result, setResult] = React.useState(
4749
+ () => snapshot ? convertWorkflowRunStateToWatchResult(snapshot) : null
4750
+ );
4751
+ const [payload, setPayload] = React.useState(null);
4752
+ const clearData = () => {
4753
+ setResult(null);
4754
+ setPayload(null);
4755
+ };
4756
+ React.useEffect(() => {
4757
+ if (snapshot?.runId) {
4758
+ setResult(convertWorkflowRunStateToWatchResult(snapshot));
4759
+ }
4760
+ }, [snapshot]);
4761
+ return /* @__PURE__ */ jsxRuntime.jsx(
4762
+ WorkflowRunContext.Provider,
4763
+ {
4764
+ value: {
4765
+ result,
4766
+ setResult,
4767
+ payload,
4768
+ setPayload,
4769
+ clearData,
4770
+ snapshot
4771
+ },
4772
+ children
5080
4773
  }
4774
+ );
4775
+ }
4776
+
4777
+ function Skeleton({ className, ...props }) {
4778
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("animate-pulse rounded-md bg-muted/50", className), ...props });
4779
+ }
4780
+
4781
+ const lodashTitleCase = (str) => {
4782
+ const camelCased = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
4783
+ return camelCased.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).trim();
4784
+ };
4785
+
4786
+ const getLayoutedElements = (nodes, edges) => {
4787
+ const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
4788
+ g.setGraph({ rankdir: "TB" });
4789
+ edges.forEach((edge) => g.setEdge(edge.source, edge.target));
4790
+ nodes.forEach(
4791
+ (node) => g.setNode(node.id, {
4792
+ ...node,
4793
+ width: node.measured?.width ?? 274,
4794
+ height: node.measured?.height ?? (node?.data?.isLarge ? 260 : 100)
4795
+ })
4796
+ );
4797
+ Dagre.layout(g);
4798
+ const fullWidth = g.graph()?.width ? g.graph().width / 2 : 0;
4799
+ const fullHeight = g.graph()?.height ? g.graph().height / 2 : 0;
4800
+ return {
4801
+ nodes: nodes.map((node) => {
4802
+ const position = g.node(node.id);
4803
+ const positionX = position.x - (node.measured?.width ?? 274) / 2;
4804
+ const positionY = position.y - (node.measured?.height ?? (node?.data?.isLarge ? 260 : 100)) / 2;
4805
+ const x = positionX;
4806
+ const y = positionY;
4807
+ return { ...node, position: { x, y } };
4808
+ }),
4809
+ edges,
4810
+ fullWidth,
4811
+ fullHeight
4812
+ };
4813
+ };
4814
+ const defaultEdgeOptions = {
4815
+ animated: true,
4816
+ markerEnd: {
4817
+ type: react.MarkerType.ArrowClosed,
4818
+ width: 20,
4819
+ height: 20,
4820
+ color: "#8e8e8e"
5081
4821
  }
5082
- const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(nodes, edges);
5083
- return { nodes: layoutedNodes, edges: layoutedEdges };
5084
4822
  };
5085
4823
  const getStepNodeAndEdge = ({
5086
4824
  stepFlow,
@@ -5518,257 +5256,20 @@ const ScrollBar = React__namespace.forwardRef(({ className, orientation = "verti
5518
5256
  ));
5519
5257
  ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
5520
5258
 
5521
- function convertWorkflowRunStateToWatchResult(runState) {
5522
- const runId = runState.runId;
5523
- const steps = {};
5524
- const context = runState.context || {};
5525
- Object.entries(context).forEach(([stepId, stepResult]) => {
5526
- if (stepId !== "input" && "status" in stepResult) {
5527
- const result = stepResult;
5528
- steps[stepId] = {
5529
- status: result.status,
5530
- output: "output" in result ? result.output : void 0,
5531
- payload: "payload" in result ? result.payload : void 0,
5532
- resumePayload: "resumePayload" in result ? result.resumePayload : void 0,
5533
- error: "error" in result ? result.error : void 0,
5534
- startedAt: "startedAt" in result ? result.startedAt : Date.now(),
5535
- endedAt: "endedAt" in result ? result.endedAt : void 0,
5536
- suspendedAt: "suspendedAt" in result ? result.suspendedAt : void 0,
5537
- resumedAt: "resumedAt" in result ? result.resumedAt : void 0
5538
- };
5539
- }
5540
- });
5541
- const status = determineWorkflowStatus(steps);
5542
- return {
5543
- type: "watch",
5544
- payload: {
5545
- workflowState: {
5546
- status,
5547
- steps,
5548
- result: runState.value,
5549
- payload: context.input,
5550
- error: void 0
5551
- }
5552
- },
5553
- eventTimestamp: new Date(runState.timestamp),
5554
- runId
5555
- };
5556
- }
5557
- function determineWorkflowStatus(steps) {
5558
- const stepStatuses = Object.values(steps).map((step) => step.status);
5559
- if (stepStatuses.includes("failed")) {
5560
- return "failed";
5561
- }
5562
- if (stepStatuses.includes("suspended")) {
5563
- return "suspended";
5564
- }
5565
- if (stepStatuses.every((status) => status === "success")) {
5566
- return "success";
5567
- }
5568
- return "running";
5569
- }
5570
- const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
5571
- if (chunk.type === "workflow-start") {
5572
- return {
5573
- ...prev,
5574
- runId: chunk.runId,
5575
- eventTimestamp: /* @__PURE__ */ new Date(),
5576
- payload: {
5577
- ...prev?.payload || {},
5578
- workflowState: {
5579
- ...prev?.payload?.workflowState,
5580
- status: "running",
5581
- steps: {}
5582
- }
5583
- }
5584
- };
5585
- }
5586
- if (chunk.type === "workflow-step-start") {
5587
- const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
5588
- return {
5589
- ...prev,
5590
- payload: {
5591
- ...prev.payload,
5592
- currentStep: {
5593
- id: chunk.payload.id,
5594
- ...chunk.payload
5595
- },
5596
- workflowState: {
5597
- ...prev?.payload?.workflowState,
5598
- steps: {
5599
- ...prev?.payload?.workflowState?.steps,
5600
- [chunk.payload.id]: {
5601
- ...current || {},
5602
- ...chunk.payload
5603
- }
5604
- }
5605
- }
5606
- },
5607
- eventTimestamp: /* @__PURE__ */ new Date()
5608
- };
5609
- }
5610
- if (chunk.type === "workflow-step-suspended") {
5611
- const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
5612
- return {
5613
- ...prev,
5614
- payload: {
5615
- ...prev?.payload,
5616
- currentStep: {
5617
- id: chunk.payload.id,
5618
- ...prev?.payload?.currentStep,
5619
- ...chunk.payload
5620
- },
5621
- workflowState: {
5622
- ...prev?.payload?.workflowState,
5623
- status: "suspended",
5624
- steps: {
5625
- ...prev?.payload?.workflowState?.steps,
5626
- [chunk.payload.id]: {
5627
- ...current || {},
5628
- ...chunk.payload
5629
- }
5630
- }
5631
- }
5632
- },
5633
- eventTimestamp: /* @__PURE__ */ new Date()
5634
- };
5635
- }
5636
- if (chunk.type === "workflow-step-waiting") {
5637
- const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
5638
- return {
5639
- ...prev,
5640
- payload: {
5641
- ...prev?.payload,
5642
- currentStep: {
5643
- id: chunk.payload.id,
5644
- ...prev?.payload?.currentStep || {},
5645
- ...chunk.payload
5646
- },
5647
- workflowState: {
5648
- ...prev?.payload?.workflowState,
5649
- status: "waiting",
5650
- steps: {
5651
- ...prev?.payload?.workflowState?.steps,
5652
- [chunk.payload.id]: {
5653
- ...current,
5654
- ...chunk.payload
5655
- }
5656
- }
5657
- }
5658
- },
5659
- eventTimestamp: /* @__PURE__ */ new Date()
5660
- };
5661
- }
5662
- if (chunk.type === "workflow-step-result") {
5663
- const status = chunk.payload.status;
5664
- const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
5665
- const next = {
5666
- ...prev,
5667
- payload: {
5668
- ...prev?.payload,
5669
- currentStep: {
5670
- id: chunk.payload.id,
5671
- ...prev?.payload?.currentStep || {},
5672
- ...chunk.payload
5673
- },
5674
- workflowState: {
5675
- ...prev?.payload?.workflowState,
5676
- status,
5677
- steps: {
5678
- ...prev?.payload?.workflowState?.steps,
5679
- [chunk.payload.id]: {
5680
- ...current,
5681
- ...chunk.payload
5682
- }
5683
- }
5684
- }
5685
- },
5686
- eventTimestamp: /* @__PURE__ */ new Date()
5687
- };
5688
- return next;
5689
- }
5690
- if (chunk.type === "workflow-canceled") {
5691
- return {
5692
- ...prev,
5693
- payload: {
5694
- ...prev?.payload,
5695
- workflowState: {
5696
- ...prev?.payload?.workflowState,
5697
- status: "canceled"
5698
- }
5699
- },
5700
- eventTimestamp: /* @__PURE__ */ new Date()
5701
- };
5702
- }
5703
- if (chunk.type === "workflow-finish") {
5704
- return {
5705
- ...prev,
5706
- payload: {
5707
- ...prev?.payload,
5708
- currentStep: void 0,
5709
- workflowState: {
5710
- ...prev?.payload?.workflowState,
5711
- status: chunk.payload.workflowStatus
5712
- }
5713
- },
5714
- eventTimestamp: /* @__PURE__ */ new Date()
5715
- };
5716
- }
5717
- return prev;
5718
- };
5719
-
5720
- const WorkflowRunContext = React.createContext({});
5721
- function WorkflowRunProvider({
5722
- children,
5723
- snapshot
5724
- }) {
5725
- const [legacyResult, setLegacyResult] = React.useState(null);
5726
- const [result, setResult] = React.useState(
5727
- () => snapshot ? convertWorkflowRunStateToWatchResult(snapshot) : null
5728
- );
5729
- const [payload, setPayload] = React.useState(null);
5730
- const clearData = () => {
5731
- setLegacyResult(null);
5732
- setResult(null);
5733
- setPayload(null);
5734
- };
5735
- React.useEffect(() => {
5736
- if (snapshot?.runId) {
5737
- setResult(convertWorkflowRunStateToWatchResult(snapshot));
5738
- }
5739
- }, [snapshot]);
5740
- return /* @__PURE__ */ jsxRuntime.jsx(
5741
- WorkflowRunContext.Provider,
5742
- {
5743
- value: {
5744
- legacyResult,
5745
- setLegacyResult,
5746
- result,
5747
- setResult,
5748
- payload,
5749
- setPayload,
5750
- clearData,
5751
- snapshot
5752
- },
5753
- children
5754
- }
5755
- );
5756
- }
5757
-
5758
- const useCurrentRun = () => {
5759
- const context = React.useContext(WorkflowRunContext);
5760
- const workflowCurrentSteps = context.result?.payload?.workflowState?.steps ?? {};
5761
- const steps = Object.entries(workflowCurrentSteps).reduce((acc, [key, value]) => {
5762
- return {
5763
- ...acc,
5764
- [key]: {
5765
- error: value.error,
5766
- startedAt: value.startedAt,
5767
- endedAt: value.endedAt,
5768
- status: value.status,
5769
- output: value.output,
5770
- input: value.payload,
5771
- resumeData: value.resumePayload
5259
+ const useCurrentRun = () => {
5260
+ const context = React.useContext(WorkflowRunContext);
5261
+ const workflowCurrentSteps = context.result?.payload?.workflowState?.steps ?? {};
5262
+ const steps = Object.entries(workflowCurrentSteps).reduce((acc, [key, value]) => {
5263
+ return {
5264
+ ...acc,
5265
+ [key]: {
5266
+ error: value.error,
5267
+ startedAt: value.startedAt,
5268
+ endedAt: value.endedAt,
5269
+ status: value.status,
5270
+ output: value.output,
5271
+ input: value.payload,
5272
+ resumeData: value.resumePayload
5772
5273
  }
5773
5274
  };
5774
5275
  }, {});
@@ -6323,74 +5824,161 @@ function Spinner({ color = "#fff", className }) {
6323
5824
  );
6324
5825
  }
6325
5826
 
6326
- function LegacyWorkflowNestedGraph({
6327
- stepGraph,
6328
- stepSubscriberGraph,
6329
- open
6330
- }) {
6331
- const { nodes: initialNodes, edges: initialEdges } = contructLegacyNodesAndEdges({
6332
- stepGraph,
6333
- stepSubscriberGraph
6334
- });
6335
- const [isMounted, setIsMounted] = React.useState(false);
6336
- const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
6337
- const [edges] = react.useEdgesState(initialEdges);
6338
- const nodeTypes = {
6339
- "default-node": WorkflowDefaultNode,
6340
- "condition-node": WorkflowConditionNode,
6341
- "after-node": WorkflowAfterNode,
6342
- "loop-result-node": WorkflowLoopResultNode
6343
- };
6344
- React.useEffect(() => {
6345
- if (open) {
6346
- setTimeout(() => {
6347
- setIsMounted(true);
6348
- }, 500);
6349
- }
6350
- }, [open]);
6351
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full relative", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(
6352
- react.ReactFlow,
6353
- {
6354
- nodes,
6355
- edges,
6356
- fitView: true,
6357
- fitViewOptions: { maxZoom: 0.85 },
6358
- nodeTypes,
6359
- onNodesChange,
6360
- children: [
6361
- /* @__PURE__ */ jsxRuntime.jsx(react.Controls, {}),
6362
- /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Lines, gap: 12, size: 0.5 })
6363
- ]
6364
- }
6365
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) });
6366
- }
6367
-
6368
- const LegacyWorkflowNestedGraphContext = React.createContext(
6369
- {}
6370
- );
6371
- function LegacyWorkflowNestedGraphProvider({ children }) {
6372
- const [stepGraph, setStepGraph] = React.useState(null);
6373
- const [stepSubscriberGraph, setStepSubscriberGraph] = React.useState(null);
6374
- const [openDialog, setOpenDialog] = React.useState(false);
6375
- const [label, setLabel] = React.useState("");
6376
- const closeNestedGraph = () => {
6377
- setOpenDialog(false);
6378
- setStepGraph(null);
6379
- setStepSubscriberGraph(null);
6380
- setLabel("");
6381
- };
6382
- const showNestedGraph = ({
6383
- label: label2,
6384
- stepGraph: stepGraph2,
6385
- stepSubscriberGraph: stepSubscriberGraph2
6386
- }) => {
6387
- setLabel(label2);
6388
- setStepGraph(stepGraph2);
6389
- setStepSubscriberGraph(stepSubscriberGraph2);
6390
- setOpenDialog(true);
5827
+ const Slider = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
5828
+ SliderPrimitive__namespace.Root,
5829
+ {
5830
+ ref,
5831
+ className: cn("relative flex w-full touch-none select-none items-center", className),
5832
+ ...props,
5833
+ children: [
5834
+ /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20", children: /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Range, { className: "absolute h-full bg-primary/50" }) }),
5835
+ /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Thumb, { className: "block h-4 w-4 rounded-full border border-primary/50 bg-white shadow transition-colors disabled:pointer-events-none disabled:opacity-50" })
5836
+ ]
5837
+ }
5838
+ ));
5839
+ Slider.displayName = SliderPrimitive__namespace.Root.displayName;
5840
+
5841
+ const ZoomSlider = React.forwardRef(({ className, ...props }) => {
5842
+ const { zoom } = react.useViewport();
5843
+ const { zoomTo, zoomIn, zoomOut, fitView } = react.useReactFlow();
5844
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Panel, { className: cn("flex gap-1 rounded-md bg-primary-foreground p-1 text-foreground", className), ...props, children: [
5845
+ /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomOut({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "h-4 w-4" }) }),
5846
+ /* @__PURE__ */ jsxRuntime.jsx(
5847
+ Slider,
5848
+ {
5849
+ className: "w-[140px]",
5850
+ value: [zoom],
5851
+ min: 0.01,
5852
+ max: 1,
5853
+ step: 0.01,
5854
+ onValueChange: (values) => {
5855
+ zoomTo(values[0]);
5856
+ }
5857
+ }
5858
+ ),
5859
+ /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomIn({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }) }),
5860
+ /* @__PURE__ */ jsxRuntime.jsxs(Button$2, { className: "min-w-20 tabular-nums", variant: "ghost", onClick: () => zoomTo(1, { duration: 300 }), children: [
5861
+ (100 * zoom).toFixed(0),
5862
+ "%"
5863
+ ] }),
5864
+ /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => fitView({ duration: 300, maxZoom: 1 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize, { className: "h-4 w-4" }) })
5865
+ ] });
5866
+ });
5867
+ ZoomSlider.displayName = "ZoomSlider";
5868
+
5869
+ function WorkflowNestedGraph({
5870
+ stepGraph,
5871
+ open,
5872
+ workflowName,
5873
+ onShowTrace,
5874
+ onSendEvent
5875
+ }) {
5876
+ const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
5877
+ stepGraph
5878
+ });
5879
+ const [isMounted, setIsMounted] = React.useState(false);
5880
+ const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
5881
+ const [edges] = react.useEdgesState(initialEdges);
5882
+ const { steps } = useCurrentRun();
5883
+ const nodeTypes = {
5884
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
5885
+ WorkflowDefaultNode,
5886
+ {
5887
+ parentWorkflowName: workflowName,
5888
+ onShowTrace,
5889
+ onSendEvent,
5890
+ ...props
5891
+ }
5892
+ ),
5893
+ "condition-node": WorkflowConditionNode,
5894
+ "after-node": WorkflowAfterNode,
5895
+ "loop-result-node": WorkflowLoopResultNode,
5896
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
5897
+ WorkflowNestedNode,
5898
+ {
5899
+ parentWorkflowName: workflowName,
5900
+ onShowTrace,
5901
+ onSendEvent,
5902
+ ...props
5903
+ }
5904
+ )
5905
+ };
5906
+ React.useEffect(() => {
5907
+ if (open) {
5908
+ setTimeout(() => {
5909
+ setIsMounted(true);
5910
+ }, 500);
5911
+ }
5912
+ }, [open]);
5913
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full relative bg-surface1", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(
5914
+ react.ReactFlow,
5915
+ {
5916
+ nodes,
5917
+ edges: edges.map((e) => ({
5918
+ ...e,
5919
+ style: {
5920
+ ...e.style,
5921
+ stroke: steps[`${workflowName}.${e.data?.previousStepId}`]?.status === "success" && steps[`${workflowName}.${e.data?.nextStepId}`] ? "#22c55e" : e.data?.conditionNode && !steps[`${workflowName}.${e.data?.previousStepId}`] && Boolean(steps[`${workflowName}.${e.data?.nextStepId}`]?.status) ? "#22c55e" : void 0
5922
+ }
5923
+ })),
5924
+ fitView: true,
5925
+ fitViewOptions: {
5926
+ maxZoom: 1
5927
+ },
5928
+ minZoom: 0.01,
5929
+ maxZoom: 1,
5930
+ nodeTypes,
5931
+ onNodesChange,
5932
+ children: [
5933
+ /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
5934
+ /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Lines, gap: 12, size: 0.5 })
5935
+ ]
5936
+ }
5937
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) });
5938
+ }
5939
+
5940
+ const WorkflowNestedGraphContext = React.createContext(
5941
+ {}
5942
+ );
5943
+ function WorkflowNestedGraphProvider({
5944
+ children,
5945
+ onShowTrace,
5946
+ onSendEvent
5947
+ }) {
5948
+ const [stepGraph, setStepGraph] = React.useState(null);
5949
+ const [parentStepGraphList, setParentStepGraphList] = React.useState([]);
5950
+ const [openDialog, setOpenDialog] = React.useState(false);
5951
+ const [label, setLabel] = React.useState("");
5952
+ const [fullStep, setFullStep] = React.useState("");
5953
+ const closeNestedGraph = () => {
5954
+ if (parentStepGraphList.length) {
5955
+ const lastStepGraph = parentStepGraphList[parentStepGraphList.length - 1];
5956
+ setStepGraph(lastStepGraph.stepGraph);
5957
+ setLabel(lastStepGraph.label);
5958
+ setFullStep(lastStepGraph.fullStep);
5959
+ setParentStepGraphList(parentStepGraphList.slice(0, -1));
5960
+ } else {
5961
+ setOpenDialog(false);
5962
+ setStepGraph(null);
5963
+ setLabel("");
5964
+ setFullStep("");
5965
+ }
5966
+ };
5967
+ const showNestedGraph = ({
5968
+ label: newLabel,
5969
+ stepGraph: newStepGraph,
5970
+ fullStep: newFullStep
5971
+ }) => {
5972
+ if (stepGraph) {
5973
+ setParentStepGraphList([...parentStepGraphList, { stepGraph, label, fullStep }]);
5974
+ }
5975
+ setLabel(newLabel);
5976
+ setFullStep(newFullStep);
5977
+ setStepGraph(newStepGraph);
5978
+ setOpenDialog(true);
6391
5979
  };
6392
5980
  return /* @__PURE__ */ jsxRuntime.jsxs(
6393
- LegacyWorkflowNestedGraphContext.Provider,
5981
+ WorkflowNestedGraphContext.Provider,
6394
5982
  {
6395
5983
  value: {
6396
5984
  showNestedGraph,
@@ -6398,8 +5986,8 @@ function LegacyWorkflowNestedGraphProvider({ children }) {
6398
5986
  },
6399
5987
  children: [
6400
5988
  children,
6401
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: openDialog, onOpenChange: closeNestedGraph, children: /* @__PURE__ */ jsxRuntime.jsx(DialogPortal, { children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[40rem] h-[40rem] bg-[#121212] p-[0.5rem]", children: [
6402
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-1.5 absolute top-2.5 left-2.5", children: [
5989
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: openDialog, onOpenChange: closeNestedGraph, children: /* @__PURE__ */ jsxRuntime.jsx(DialogPortal, { children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[45rem] h-[45rem] max-w-[unset] bg-[#121212] p-[0.5rem]", children: [
5990
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-1.5 absolute top-3 left-3 z-50", children: [
6403
5991
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Workflow, { className: "text-current w-4 h-4" }),
6404
5992
  /* @__PURE__ */ jsxRuntime.jsxs(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: [
6405
5993
  label,
@@ -6407,77 +5995,131 @@ function LegacyWorkflowNestedGraphProvider({ children }) {
6407
5995
  ] })
6408
5996
  ] }),
6409
5997
  /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
6410
- LegacyWorkflowNestedGraph,
5998
+ WorkflowNestedGraph,
6411
5999
  {
6412
6000
  stepGraph,
6413
6001
  open: openDialog,
6414
- stepSubscriberGraph
6002
+ workflowName: fullStep,
6003
+ onShowTrace,
6004
+ onSendEvent
6415
6005
  }
6416
6006
  ) })
6417
- ] }) }) })
6007
+ ] }) }) }, `${label}-${fullStep}`)
6418
6008
  ]
6419
6009
  }
6420
6010
  );
6421
6011
  }
6422
6012
 
6423
- function LegacyWorkflowNestedNode({ data }) {
6424
- const { label, withoutTopHandle, withoutBottomHandle, stepGraph, stepSubscriberGraph } = data;
6425
- const { showNestedGraph } = React.useContext(LegacyWorkflowNestedGraphContext);
6426
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("bg-[rgba(29,29,29,0.5)] rounded-md h-full overflow-scroll w-[274px]"), children: [
6013
+ function WorkflowNestedNode({
6014
+ data,
6015
+ parentWorkflowName,
6016
+ onShowTrace,
6017
+ onSendEvent
6018
+ }) {
6019
+ const { steps, runId } = useCurrentRun();
6020
+ const { showNestedGraph } = React.useContext(WorkflowNestedGraphContext);
6021
+ const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig, event } = data;
6022
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
6023
+ const step = steps[fullLabel];
6024
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6427
6025
  !withoutTopHandle && /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Top, style: { visibility: "hidden" } }),
6428
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-2 cursor-pointer", onClick: () => showNestedGraph({ label, stepGraph, stepSubscriberGraph }), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm bg-mastra-bg-9 flex items-center gap-1.5 rounded-sm p-2 cursor-pointer", children: [
6429
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Workflow, { className: "text-current w-4 h-4" }),
6430
- /* @__PURE__ */ jsxRuntime.jsx(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: label })
6431
- ] }) }),
6026
+ /* @__PURE__ */ jsxRuntime.jsxs(
6027
+ "div",
6028
+ {
6029
+ className: cn(
6030
+ "bg-surface3 rounded-lg w-[274px] border-sm border-border1 pt-2",
6031
+ step?.status === "success" && "bg-accent1Darker",
6032
+ step?.status === "failed" && "bg-accent2Darker",
6033
+ step?.status === "suspended" && "bg-accent3Darker",
6034
+ step?.status === "waiting" && "bg-accent5Darker",
6035
+ step?.status === "running" && "bg-accent6Darker"
6036
+ ),
6037
+ children: [
6038
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
6039
+ /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
6040
+ step?.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
6041
+ step?.status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
6042
+ step?.status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PauseIcon, { className: "text-accent3" }),
6043
+ step?.status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
6044
+ step?.status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" }),
6045
+ !step && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, { className: "text-icon2" })
6046
+ ] }),
6047
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "text-icon6 font-medium inline-flex items-center gap-1 justify-between w-full", children: [
6048
+ label,
6049
+ " ",
6050
+ step?.startedAt && /* @__PURE__ */ jsxRuntime.jsx(Clock, { startedAt: step.startedAt, endedAt: step.endedAt })
6051
+ ] })
6052
+ ] }),
6053
+ description && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
6054
+ /* @__PURE__ */ jsxRuntime.jsx(
6055
+ WorkflowStepActionBar,
6056
+ {
6057
+ stepName: label,
6058
+ input: step?.input,
6059
+ resumeData: step?.resumeData,
6060
+ output: step?.output,
6061
+ error: step?.error,
6062
+ mapConfig,
6063
+ onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0,
6064
+ onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
6065
+ onSendEvent,
6066
+ event: step?.status === "waiting" ? event : void 0,
6067
+ runId,
6068
+ status: step?.status
6069
+ }
6070
+ )
6071
+ ]
6072
+ }
6073
+ ),
6432
6074
  !withoutBottomHandle && /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { visibility: "hidden" } })
6433
6075
  ] });
6434
6076
  }
6435
6077
 
6436
- function LegacyWorkflowGraphInner({ workflow }) {
6437
- const { nodes: initialNodes, edges: initialEdges } = contructLegacyNodesAndEdges({
6438
- stepGraph: workflow.serializedStepGraph || workflow.stepGraph,
6439
- stepSubscriberGraph: workflow.serializedStepSubscriberGraph || workflow.stepSubscriberGraph,
6440
- steps: workflow.steps
6441
- });
6078
+ function WorkflowGraphInner({ workflow, onShowTrace, onSendEvent }) {
6079
+ const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
6442
6080
  const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
6443
6081
  const [edges] = react.useEdgesState(initialEdges);
6082
+ const { steps, runId } = useCurrentRun();
6444
6083
  const nodeTypes = {
6445
- "default-node": WorkflowDefaultNode,
6084
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { onShowTrace, onSendEvent, ...props }),
6446
6085
  "condition-node": WorkflowConditionNode,
6447
6086
  "after-node": WorkflowAfterNode,
6448
6087
  "loop-result-node": WorkflowLoopResultNode,
6449
- "nested-node": LegacyWorkflowNestedNode
6088
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { onShowTrace, onSendEvent, ...props })
6450
6089
  };
6451
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
6090
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs(
6452
6091
  react.ReactFlow,
6453
6092
  {
6454
6093
  nodes,
6455
- edges,
6094
+ edges: edges.map((e) => ({
6095
+ ...e,
6096
+ style: {
6097
+ ...e.style,
6098
+ stroke: steps[e.data?.previousStepId]?.status === "success" && steps[e.data?.nextStepId] ? "#22c55e" : e.data?.conditionNode && !steps[e.data?.previousStepId] && Boolean(steps[e.data?.nextStepId]?.status) ? "#22c55e" : void 0
6099
+ }
6100
+ })),
6456
6101
  nodeTypes,
6457
6102
  onNodesChange,
6458
6103
  fitView: true,
6459
6104
  fitViewOptions: {
6460
- maxZoom: 0.85
6105
+ maxZoom: 1
6461
6106
  },
6107
+ minZoom: 0.01,
6108
+ maxZoom: 1,
6462
6109
  children: [
6463
- /* @__PURE__ */ jsxRuntime.jsx(react.Controls, {}),
6110
+ /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
6464
6111
  /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Dots, gap: 12, size: 0.5 })
6465
6112
  ]
6466
6113
  }
6467
6114
  ) });
6468
6115
  }
6469
6116
 
6470
- const lodashTitleCase = (str) => {
6471
- const camelCased = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
6472
- return camelCased.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).trim();
6473
- };
6474
-
6475
- function LegacyWorkflowGraph({ workflowId }) {
6476
- const { legacyWorkflow, isLoading } = useLegacyWorkflow(workflowId);
6117
+ function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading, onSendEvent }) {
6118
+ const { snapshot } = React.useContext(WorkflowRunContext);
6477
6119
  if (isLoading) {
6478
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-[600px]" }) });
6120
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-full" }) });
6479
6121
  }
6480
- if (!legacyWorkflow) {
6122
+ if (!workflow) {
6481
6123
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid h-full place-items-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
6482
6124
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, {}),
6483
6125
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -6487,13 +6129,99 @@ function LegacyWorkflowGraph({ workflowId }) {
6487
6129
  ] })
6488
6130
  ] }) });
6489
6131
  }
6490
- return /* @__PURE__ */ jsxRuntime.jsx(LegacyWorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(LegacyWorkflowGraphInner, { workflow: legacyWorkflow }) }) });
6491
- }
6492
-
6493
- const Form = React.forwardRef(({ children, ...props }, ref) => {
6494
- return /* @__PURE__ */ jsxRuntime.jsx("form", { ref, className: "space-y-4", ...props, children });
6495
- });
6496
-
6132
+ return /* @__PURE__ */ jsxRuntime.jsx(
6133
+ WorkflowNestedGraphProvider,
6134
+ {
6135
+ onShowTrace,
6136
+ onSendEvent,
6137
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
6138
+ WorkflowGraphInner,
6139
+ {
6140
+ workflow: snapshot?.serializedStepGraph ? { stepGraph: snapshot?.serializedStepGraph } : workflow,
6141
+ onShowTrace,
6142
+ onSendEvent
6143
+ }
6144
+ ) })
6145
+ },
6146
+ snapshot?.runId ?? workflowId
6147
+ );
6148
+ }
6149
+
6150
+ function resolveSerializedZodOutput(obj) {
6151
+ return Function("z", `"use strict";return (${obj});`)(z.z);
6152
+ }
6153
+
6154
+ function CodeBlockDemo({
6155
+ code = "",
6156
+ language = "ts",
6157
+ filename,
6158
+ className
6159
+ }) {
6160
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactCodeBlock.CodeBlock, { code, language, theme: prismReactRenderer.themes.oneDark, children: [
6161
+ filename ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute w-full px-6 py-2 pl-4 text-sm rounded bg-mastra-bg-2 text-mastra-el-6/50", children: filename }) : null,
6162
+ /* @__PURE__ */ jsxRuntime.jsx(
6163
+ reactCodeBlock.CodeBlock.Code,
6164
+ {
6165
+ className: cn("bg-transparent h-full p-6 rounded-xl whitespace-pre-wrap", filename ? "pt-10" : "", className),
6166
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-row", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
6167
+ /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineNumber, { className: "table-cell pr-4 text-sm text-right select-none text-gray-500/50" }),
6168
+ /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineContent, { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.Token, { className: "font-mono text-sm mastra-token" }) })
6169
+ ] }) })
6170
+ }
6171
+ )
6172
+ ] });
6173
+ }
6174
+
6175
+ const usePlaygroundStore = zustand.create()(
6176
+ middleware.persist(
6177
+ (set) => ({
6178
+ runtimeContext: {},
6179
+ setRuntimeContext: (runtimeContext) => set({ runtimeContext })
6180
+ }),
6181
+ {
6182
+ name: "mastra-playground-store"
6183
+ }
6184
+ )
6185
+ );
6186
+
6187
+ const WorkflowCard = ({ header, children, footer }) => {
6188
+ const [expanded, setExpanded] = React.useState(false);
6189
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border-sm border-border1 bg-surface4", children: [
6190
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "py-1 px-2 flex items-center gap-3 justify-between w-full", onClick: () => setExpanded((s) => !s), children: [
6191
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: header }),
6192
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: cn("text-icon3 transition-transform -rotate-90", expanded && "rotate-0") }) })
6193
+ ] }),
6194
+ children && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t-sm border-border1", children }),
6195
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1 px-2 border-t-sm border-border1", children: footer })
6196
+ ] });
6197
+ };
6198
+
6199
+ const WorkflowStatus = ({ stepId, status, result }) => {
6200
+ return /* @__PURE__ */ jsxRuntime.jsx(
6201
+ WorkflowCard,
6202
+ {
6203
+ header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
6204
+ /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
6205
+ status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
6206
+ status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
6207
+ status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CirclePause, { className: "text-accent3" }),
6208
+ status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
6209
+ status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" })
6210
+ ] }),
6211
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-lg", className: "text-icon6 font-medium", children: stepId.charAt(0).toUpperCase() + stepId.slice(1) })
6212
+ ] }),
6213
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md bg-surface4 p-1 font-mono relative", children: [
6214
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: JSON.stringify(result, null, 2), className: "absolute top-2 right-2 z-10" }),
6215
+ /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: result })
6216
+ ] })
6217
+ }
6218
+ );
6219
+ };
6220
+
6221
+ const Form = React.forwardRef(({ children, ...props }, ref) => {
6222
+ return /* @__PURE__ */ jsxRuntime.jsx("form", { ref, className: "space-y-4", ...props, children });
6223
+ });
6224
+
6497
6225
  const DISABLED_LABELS = ["boolean", "object", "array"];
6498
6226
  const FieldWrapper = ({ label, children, id, field, error }) => {
6499
6227
  const isDisabled = DISABLED_LABELS.includes(field.type);
@@ -7304,610 +7032,30 @@ function DynamicForm({
7304
7032
  if (isNotZodObject) {
7305
7033
  return z.object({
7306
7034
  "​": schema2
7307
- });
7308
- }
7309
- return schema2;
7310
- };
7311
- const schemaProvider = new CustomZodProvider(normalizedSchema(schema));
7312
- const formProps = {
7313
- schema: schemaProvider,
7314
- onSubmit: async (values) => {
7315
- await onSubmit?.(isNotZodObject ? values["​"] || {} : values);
7316
- },
7317
- defaultValues: isNotZodObject ? defaultValues ? { "​": defaultValues } : void 0 : defaultValues,
7318
- formProps: {
7319
- className
7320
- },
7321
- uiComponents: {
7322
- SubmitButton: ({ children }) => onSubmit ? /* @__PURE__ */ jsxRuntime.jsx(Button$1, { variant: "light", className: "w-full", size: "lg", disabled: isSubmitLoading, children: isSubmitLoading ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) }) : submitButtonLabel || children }) : null
7323
- },
7324
- formComponents: {
7325
- Label: ({ value }) => /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-normal", children: value })
7326
- },
7327
- withSubmit: true
7328
- };
7329
- return /* @__PURE__ */ jsxRuntime.jsx(AutoForm, { ...formProps, readOnly });
7330
- }
7331
-
7332
- function resolveSerializedZodOutput(obj) {
7333
- return Function("z", `"use strict";return (${obj});`)(z.z);
7334
- }
7335
-
7336
- function CodeBlockDemo({
7337
- code = "",
7338
- language = "ts",
7339
- filename,
7340
- className
7341
- }) {
7342
- return /* @__PURE__ */ jsxRuntime.jsxs(reactCodeBlock.CodeBlock, { code, language, theme: prismReactRenderer.themes.oneDark, children: [
7343
- filename ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute w-full px-6 py-2 pl-4 text-sm rounded bg-mastra-bg-2 text-mastra-el-6/50", children: filename }) : null,
7344
- /* @__PURE__ */ jsxRuntime.jsx(
7345
- reactCodeBlock.CodeBlock.Code,
7346
- {
7347
- className: cn("bg-transparent h-full p-6 rounded-xl whitespace-pre-wrap", filename ? "pt-10" : "", className),
7348
- children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-row", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
7349
- /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineNumber, { className: "table-cell pr-4 text-sm text-right select-none text-gray-500/50" }),
7350
- /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineContent, { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.Token, { className: "font-mono text-sm mastra-token" }) })
7351
- ] }) })
7352
- }
7353
- )
7354
- ] });
7355
- }
7356
-
7357
- const WorkflowCard = ({ header, children, footer }) => {
7358
- const [expanded, setExpanded] = React.useState(false);
7359
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border-sm border-border1 bg-surface4", children: [
7360
- /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "py-1 px-2 flex items-center gap-3 justify-between w-full", onClick: () => setExpanded((s) => !s), children: [
7361
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: header }),
7362
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: cn("text-icon3 transition-transform -rotate-90", expanded && "rotate-0") }) })
7363
- ] }),
7364
- children && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t-sm border-border1", children }),
7365
- footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1 px-2 border-t-sm border-border1", children: footer })
7366
- ] });
7367
- };
7368
-
7369
- const LegacyWorkflowStatus = ({ stepId, pathStatus, path }) => {
7370
- const status = pathStatus === "completed" ? "Completed" : stepId === path ? pathStatus.charAt(0).toUpperCase() + pathStatus.slice(1) : pathStatus === "executing" ? "Executing" : "Completed";
7371
- return /* @__PURE__ */ jsxRuntime.jsx(
7372
- WorkflowCard,
7373
- {
7374
- header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
7375
- /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
7376
- status === "Completed" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
7377
- status === "Failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
7378
- status === "Executing" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-icon3 animate-spin" })
7379
- ] }),
7380
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-lg", className: "text-icon6 font-medium", children: path })
7381
- ] })
7382
- }
7383
- );
7384
- };
7385
-
7386
- const WorkflowResult = ({ jsonResult, sanitizedJsonResult }) => {
7387
- const { handleCopy } = useCopyToClipboard({ text: jsonResult });
7388
- const [expanded, setExpanded] = React.useState(false);
7389
- return /* @__PURE__ */ jsxRuntime.jsx(
7390
- WorkflowCard,
7391
- {
7392
- header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 justify-between w-full", children: [
7393
- /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "text-icon6 flex items-center gap-3 font-medium", children: [
7394
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(DeploymentIcon, {}) }),
7395
- "Workflow Execution (JSON)"
7396
- ] }),
7397
- /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
7398
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
7399
- "button",
7400
- {
7401
- className: "p-2 rounded-lg hover:bg-surface5 transition-colors duration-150 ease-in-out text-icon3 hover:text-icon6",
7402
- onClick: () => handleCopy(),
7403
- children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { size: "sm", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
7404
- }
7405
- ) }),
7406
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: "Copy result" })
7407
- ] })
7408
- ] }),
7409
- footer: /* @__PURE__ */ jsxRuntime.jsx(
7410
- "button",
7411
- {
7412
- className: "w-full h-full text-center text-icon2 hover:text-icon6 text-ui-md",
7413
- onClick: () => setExpanded((s) => !s),
7414
- children: expanded ? "collapse" : "expand"
7415
- }
7416
- ),
7417
- children: expanded ? /* @__PURE__ */ jsxRuntime.jsx(CodeBlockDemo, { className: "w-full overflow-x-auto", code: sanitizedJsonResult || jsonResult, language: "json" }) : null
7418
- }
7419
- );
7420
- };
7421
-
7422
- function LegacyWorkflowTrigger({
7423
- workflowId,
7424
- setRunId
7425
- }) {
7426
- const { legacyResult: result, setLegacyResult: setResult, payload, setPayload } = React.useContext(WorkflowRunContext);
7427
- const { isLoading, legacyWorkflow: workflow } = useLegacyWorkflow(workflowId);
7428
- const { createLegacyWorkflowRun: createWorkflowRun, startLegacyWorkflowRun: startWorkflowRun } = useExecuteWorkflow();
7429
- const {
7430
- watchLegacyWorkflow: watchWorkflow,
7431
- legacyWatchResult: watchResult,
7432
- isWatchingLegacyWorkflow: isWatchingWorkflow
7433
- } = useWatchWorkflow();
7434
- const { resumeLegacyWorkflow: resumeWorkflow, isResumingLegacyWorkflow: isResumingWorkflow } = useResumeWorkflow();
7435
- const [suspendedSteps, setSuspendedSteps] = React.useState([]);
7436
- const [isRunning, setIsRunning] = React.useState(false);
7437
- const triggerSchema = workflow?.triggerSchema;
7438
- const handleExecuteWorkflow = async (data) => {
7439
- try {
7440
- if (!workflow) return;
7441
- setIsRunning(true);
7442
- setResult(null);
7443
- const { runId } = await createWorkflowRun({ workflowId });
7444
- setRunId?.(runId);
7445
- watchWorkflow({ workflowId, runId });
7446
- startWorkflowRun({ workflowId, runId, input: data });
7447
- } catch (err) {
7448
- setIsRunning(false);
7449
- sonner.toast.error("Error executing workflow");
7450
- }
7451
- };
7452
- const handleResumeWorkflow = async (step) => {
7453
- if (!workflow) return;
7454
- const { stepId, runId: prevRunId, context } = step;
7455
- const { runId } = await createWorkflowRun({ workflowId, prevRunId });
7456
- watchWorkflow({ workflowId, runId });
7457
- await resumeWorkflow({
7458
- stepId,
7459
- runId,
7460
- context,
7461
- workflowId
7462
- });
7463
- };
7464
- const watchResultToUse = result ?? watchResult;
7465
- const workflowActivePaths = watchResultToUse?.activePaths ?? {};
7466
- React.useEffect(() => {
7467
- setIsRunning(isWatchingWorkflow);
7468
- }, [isWatchingWorkflow]);
7469
- React.useEffect(() => {
7470
- if (!watchResultToUse?.activePaths || !result?.runId) return;
7471
- const suspended = Object.entries(watchResultToUse.activePaths).filter(([_, { status }]) => status === "suspended").map(([stepId, { suspendPayload }]) => ({
7472
- stepId,
7473
- runId: result.runId,
7474
- suspendPayload
7475
- }));
7476
- setSuspendedSteps(suspended);
7477
- }, [watchResultToUse, result]);
7478
- React.useEffect(() => {
7479
- if (watchResult) {
7480
- setResult(watchResult);
7481
- }
7482
- }, [watchResult]);
7483
- if (isLoading) {
7484
- return /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: "h-[calc(100vh-126px)] pt-2 px-4 pb-4 text-xs", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
7485
- /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-10" }),
7486
- /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-10" })
7487
- ] }) });
7488
- }
7489
- if (!workflow) return null;
7490
- const isSuspendedSteps = suspendedSteps.length > 0;
7491
- const zodInputSchema = triggerSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(triggerSchema))) : null;
7492
- const { sanitizedOutput, ...restResult } = result ?? {};
7493
- const hasWorkflowActivePaths = Object.values(workflowActivePaths).length > 0;
7494
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full px-5 pt-3 pb-12", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
7495
- isResumingWorkflow && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "py-2 px-5 flex items-center gap-2 bg-surface5 -mx-5 -mt-5 border-b-sm border-border1", children: [
7496
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin text-icon6" }) }),
7497
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { children: "Resuming workflow" })
7498
- ] }),
7499
- !isSuspendedSteps && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: zodInputSchema ? /* @__PURE__ */ jsxRuntime.jsx(
7500
- DynamicForm,
7501
- {
7502
- schema: zodInputSchema,
7503
- defaultValues: payload,
7504
- isSubmitLoading: isWatchingWorkflow,
7505
- submitButtonLabel: "Run",
7506
- onSubmit: (data) => {
7507
- setPayload(data);
7508
- handleExecuteWorkflow(data);
7509
- }
7510
- }
7511
- ) : /* @__PURE__ */ jsxRuntime.jsx(
7512
- Button$1,
7513
- {
7514
- className: "w-full",
7515
- variant: "light",
7516
- disabled: isRunning,
7517
- onClick: () => handleExecuteWorkflow(null),
7518
- children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) }) : "Trigger"
7519
- }
7520
- ) }),
7521
- isSuspendedSteps && suspendedSteps?.map((step) => {
7522
- const stepDefinition = workflow.steps[step.stepId];
7523
- const stepSchema = stepDefinition?.inputSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(stepDefinition.inputSchema))) : z.z.record(z.z.string(), z.z.any());
7524
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col px-4", children: [
7525
- /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "secondary", className: "text-mastra-el-3", size: "xs", children: step.stepId }),
7526
- step.suspendPayload && /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
7527
- CodeBlockDemo,
7528
- {
7529
- className: "w-full overflow-x-auto p-2",
7530
- code: JSON.stringify(step.suspendPayload, null, 2),
7531
- language: "json"
7532
- }
7533
- ) }),
7534
- /* @__PURE__ */ jsxRuntime.jsx(
7535
- DynamicForm,
7536
- {
7537
- schema: stepSchema,
7538
- isSubmitLoading: isResumingWorkflow,
7539
- submitButtonLabel: "Resume",
7540
- onSubmit: (data) => {
7541
- handleResumeWorkflow({
7542
- stepId: step.stepId,
7543
- runId: step.runId,
7544
- suspendPayload: step.suspendPayload,
7545
- context: data
7546
- });
7547
- }
7548
- }
7549
- )
7550
- ] });
7551
- }),
7552
- hasWorkflowActivePaths && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7553
- /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
7554
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-4", children: Object.entries(workflowActivePaths)?.map(([stepId, { status: pathStatus, stepPath }]) => {
7555
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1", children: stepPath?.map((path, idx) => {
7556
- return /* @__PURE__ */ jsxRuntime.jsx(LegacyWorkflowStatus, { stepId, pathStatus, path }, idx);
7557
- }) }, stepId);
7558
- }) })
7559
- ] }),
7560
- result && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7561
- /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "border-border1 border-sm my-5" }),
7562
- /* @__PURE__ */ jsxRuntime.jsx(WorkflowResult, { sanitizedJsonResult: sanitizedOutput, jsonResult: JSON.stringify(restResult, null, 2) })
7563
- ] })
7564
- ] }) });
7565
- }
7566
-
7567
- const Slider = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
7568
- SliderPrimitive__namespace.Root,
7569
- {
7570
- ref,
7571
- className: cn("relative flex w-full touch-none select-none items-center", className),
7572
- ...props,
7573
- children: [
7574
- /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20", children: /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Range, { className: "absolute h-full bg-primary/50" }) }),
7575
- /* @__PURE__ */ jsxRuntime.jsx(SliderPrimitive__namespace.Thumb, { className: "block h-4 w-4 rounded-full border border-primary/50 bg-white shadow transition-colors disabled:pointer-events-none disabled:opacity-50" })
7576
- ]
7577
- }
7578
- ));
7579
- Slider.displayName = SliderPrimitive__namespace.Root.displayName;
7580
-
7581
- const ZoomSlider = React.forwardRef(({ className, ...props }) => {
7582
- const { zoom } = react.useViewport();
7583
- const { zoomTo, zoomIn, zoomOut, fitView } = react.useReactFlow();
7584
- return /* @__PURE__ */ jsxRuntime.jsxs(react.Panel, { className: cn("flex gap-1 rounded-md bg-primary-foreground p-1 text-foreground", className), ...props, children: [
7585
- /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomOut({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "h-4 w-4" }) }),
7586
- /* @__PURE__ */ jsxRuntime.jsx(
7587
- Slider,
7588
- {
7589
- className: "w-[140px]",
7590
- value: [zoom],
7591
- min: 0.01,
7592
- max: 1,
7593
- step: 0.01,
7594
- onValueChange: (values) => {
7595
- zoomTo(values[0]);
7596
- }
7597
- }
7598
- ),
7599
- /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomIn({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }) }),
7600
- /* @__PURE__ */ jsxRuntime.jsxs(Button$2, { className: "min-w-20 tabular-nums", variant: "ghost", onClick: () => zoomTo(1, { duration: 300 }), children: [
7601
- (100 * zoom).toFixed(0),
7602
- "%"
7603
- ] }),
7604
- /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => fitView({ duration: 300, maxZoom: 1 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Maximize, { className: "h-4 w-4" }) })
7605
- ] });
7606
- });
7607
- ZoomSlider.displayName = "ZoomSlider";
7608
-
7609
- function WorkflowNestedGraph({
7610
- stepGraph,
7611
- open,
7612
- workflowName,
7613
- onShowTrace,
7614
- onSendEvent
7615
- }) {
7616
- const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
7617
- stepGraph
7618
- });
7619
- const [isMounted, setIsMounted] = React.useState(false);
7620
- const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
7621
- const [edges] = react.useEdgesState(initialEdges);
7622
- const { steps } = useCurrentRun();
7623
- const nodeTypes = {
7624
- "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
7625
- WorkflowDefaultNode,
7626
- {
7627
- parentWorkflowName: workflowName,
7628
- onShowTrace,
7629
- onSendEvent,
7630
- ...props
7631
- }
7632
- ),
7633
- "condition-node": WorkflowConditionNode,
7634
- "after-node": WorkflowAfterNode,
7635
- "loop-result-node": WorkflowLoopResultNode,
7636
- "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
7637
- WorkflowNestedNode,
7638
- {
7639
- parentWorkflowName: workflowName,
7640
- onShowTrace,
7641
- onSendEvent,
7642
- ...props
7643
- }
7644
- )
7645
- };
7646
- React.useEffect(() => {
7647
- if (open) {
7648
- setTimeout(() => {
7649
- setIsMounted(true);
7650
- }, 500);
7651
- }
7652
- }, [open]);
7653
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full relative bg-surface1", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(
7654
- react.ReactFlow,
7655
- {
7656
- nodes,
7657
- edges: edges.map((e) => ({
7658
- ...e,
7659
- style: {
7660
- ...e.style,
7661
- stroke: steps[`${workflowName}.${e.data?.previousStepId}`]?.status === "success" && steps[`${workflowName}.${e.data?.nextStepId}`] ? "#22c55e" : e.data?.conditionNode && !steps[`${workflowName}.${e.data?.previousStepId}`] && Boolean(steps[`${workflowName}.${e.data?.nextStepId}`]?.status) ? "#22c55e" : void 0
7662
- }
7663
- })),
7664
- fitView: true,
7665
- fitViewOptions: {
7666
- maxZoom: 1
7667
- },
7668
- minZoom: 0.01,
7669
- maxZoom: 1,
7670
- nodeTypes,
7671
- onNodesChange,
7672
- children: [
7673
- /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
7674
- /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Lines, gap: 12, size: 0.5 })
7675
- ]
7676
- }
7677
- ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) });
7678
- }
7679
-
7680
- const WorkflowNestedGraphContext = React.createContext(
7681
- {}
7682
- );
7683
- function WorkflowNestedGraphProvider({
7684
- children,
7685
- onShowTrace,
7686
- onSendEvent
7687
- }) {
7688
- const [stepGraph, setStepGraph] = React.useState(null);
7689
- const [parentStepGraphList, setParentStepGraphList] = React.useState([]);
7690
- const [openDialog, setOpenDialog] = React.useState(false);
7691
- const [label, setLabel] = React.useState("");
7692
- const [fullStep, setFullStep] = React.useState("");
7693
- const closeNestedGraph = () => {
7694
- if (parentStepGraphList.length) {
7695
- const lastStepGraph = parentStepGraphList[parentStepGraphList.length - 1];
7696
- setStepGraph(lastStepGraph.stepGraph);
7697
- setLabel(lastStepGraph.label);
7698
- setFullStep(lastStepGraph.fullStep);
7699
- setParentStepGraphList(parentStepGraphList.slice(0, -1));
7700
- } else {
7701
- setOpenDialog(false);
7702
- setStepGraph(null);
7703
- setLabel("");
7704
- setFullStep("");
7705
- }
7706
- };
7707
- const showNestedGraph = ({
7708
- label: newLabel,
7709
- stepGraph: newStepGraph,
7710
- fullStep: newFullStep
7711
- }) => {
7712
- if (stepGraph) {
7713
- setParentStepGraphList([...parentStepGraphList, { stepGraph, label, fullStep }]);
7714
- }
7715
- setLabel(newLabel);
7716
- setFullStep(newFullStep);
7717
- setStepGraph(newStepGraph);
7718
- setOpenDialog(true);
7719
- };
7720
- return /* @__PURE__ */ jsxRuntime.jsxs(
7721
- WorkflowNestedGraphContext.Provider,
7722
- {
7723
- value: {
7724
- showNestedGraph,
7725
- closeNestedGraph
7726
- },
7727
- children: [
7728
- children,
7729
- /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: openDialog, onOpenChange: closeNestedGraph, children: /* @__PURE__ */ jsxRuntime.jsx(DialogPortal, { children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[45rem] h-[45rem] max-w-[unset] bg-[#121212] p-[0.5rem]", children: [
7730
- /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-1.5 absolute top-3 left-3 z-50", children: [
7731
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Workflow, { className: "text-current w-4 h-4" }),
7732
- /* @__PURE__ */ jsxRuntime.jsxs(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: [
7733
- label,
7734
- " workflow"
7735
- ] })
7736
- ] }),
7737
- /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
7738
- WorkflowNestedGraph,
7739
- {
7740
- stepGraph,
7741
- open: openDialog,
7742
- workflowName: fullStep,
7743
- onShowTrace,
7744
- onSendEvent
7745
- }
7746
- ) })
7747
- ] }) }) }, `${label}-${fullStep}`)
7748
- ]
7749
- }
7750
- );
7751
- }
7752
-
7753
- function WorkflowNestedNode({
7754
- data,
7755
- parentWorkflowName,
7756
- onShowTrace,
7757
- onSendEvent
7758
- }) {
7759
- const { steps, runId } = useCurrentRun();
7760
- const { showNestedGraph } = React.useContext(WorkflowNestedGraphContext);
7761
- const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig, event } = data;
7762
- const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
7763
- const step = steps[fullLabel];
7764
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7765
- !withoutTopHandle && /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "target", position: react.Position.Top, style: { visibility: "hidden" } }),
7766
- /* @__PURE__ */ jsxRuntime.jsxs(
7767
- "div",
7768
- {
7769
- className: cn(
7770
- "bg-surface3 rounded-lg w-[274px] border-sm border-border1 pt-2",
7771
- step?.status === "success" && "bg-accent1Darker",
7772
- step?.status === "failed" && "bg-accent2Darker",
7773
- step?.status === "suspended" && "bg-accent3Darker",
7774
- step?.status === "waiting" && "bg-accent5Darker",
7775
- step?.status === "running" && "bg-accent6Darker"
7776
- ),
7777
- children: [
7778
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
7779
- /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
7780
- step?.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
7781
- step?.status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
7782
- step?.status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PauseIcon, { className: "text-accent3" }),
7783
- step?.status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
7784
- step?.status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" }),
7785
- !step && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, { className: "text-icon2" })
7786
- ] }),
7787
- /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "text-icon6 font-medium inline-flex items-center gap-1 justify-between w-full", children: [
7788
- label,
7789
- " ",
7790
- step?.startedAt && /* @__PURE__ */ jsxRuntime.jsx(Clock, { startedAt: step.startedAt, endedAt: step.endedAt })
7791
- ] })
7792
- ] }),
7793
- description && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
7794
- /* @__PURE__ */ jsxRuntime.jsx(
7795
- WorkflowStepActionBar,
7796
- {
7797
- stepName: label,
7798
- input: step?.input,
7799
- resumeData: step?.resumeData,
7800
- output: step?.output,
7801
- error: step?.error,
7802
- mapConfig,
7803
- onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0,
7804
- onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
7805
- onSendEvent,
7806
- event: step?.status === "waiting" ? event : void 0,
7807
- runId,
7808
- status: step?.status
7809
- }
7810
- )
7811
- ]
7812
- }
7813
- ),
7814
- !withoutBottomHandle && /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { visibility: "hidden" } })
7815
- ] });
7816
- }
7817
-
7818
- function WorkflowGraphInner({ workflow, onShowTrace, onSendEvent }) {
7819
- const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
7820
- const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
7821
- const [edges] = react.useEdgesState(initialEdges);
7822
- const { steps, runId } = useCurrentRun();
7823
- const nodeTypes = {
7824
- "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { onShowTrace, onSendEvent, ...props }),
7825
- "condition-node": WorkflowConditionNode,
7826
- "after-node": WorkflowAfterNode,
7827
- "loop-result-node": WorkflowLoopResultNode,
7828
- "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { onShowTrace, onSendEvent, ...props })
7829
- };
7830
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs(
7831
- react.ReactFlow,
7832
- {
7833
- nodes,
7834
- edges: edges.map((e) => ({
7835
- ...e,
7836
- style: {
7837
- ...e.style,
7838
- stroke: steps[e.data?.previousStepId]?.status === "success" && steps[e.data?.nextStepId] ? "#22c55e" : e.data?.conditionNode && !steps[e.data?.previousStepId] && Boolean(steps[e.data?.nextStepId]?.status) ? "#22c55e" : void 0
7839
- }
7840
- })),
7841
- nodeTypes,
7842
- onNodesChange,
7843
- fitView: true,
7844
- fitViewOptions: {
7845
- maxZoom: 1
7846
- },
7847
- minZoom: 0.01,
7848
- maxZoom: 1,
7849
- children: [
7850
- /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
7851
- /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Dots, gap: 12, size: 0.5 })
7852
- ]
7853
- }
7854
- ) });
7855
- }
7856
-
7857
- function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading, onSendEvent }) {
7858
- const { snapshot } = React.useContext(WorkflowRunContext);
7859
- if (isLoading) {
7860
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-full" }) });
7861
- }
7862
- if (!workflow) {
7863
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid h-full place-items-center", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
7864
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, {}),
7865
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
7866
- "We couldn't find ",
7867
- lodashTitleCase(workflowId),
7868
- " workflow."
7869
- ] })
7870
- ] }) });
7871
- }
7872
- return /* @__PURE__ */ jsxRuntime.jsx(
7873
- WorkflowNestedGraphProvider,
7874
- {
7875
- onShowTrace,
7876
- onSendEvent,
7877
- children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
7878
- WorkflowGraphInner,
7879
- {
7880
- workflow: snapshot?.serializedStepGraph ? { stepGraph: snapshot?.serializedStepGraph } : workflow,
7881
- onShowTrace,
7882
- onSendEvent
7883
- }
7884
- ) })
7885
- },
7886
- snapshot?.runId ?? workflowId
7887
- );
7888
- }
7889
-
7890
- const WorkflowStatus = ({ stepId, status, result }) => {
7891
- return /* @__PURE__ */ jsxRuntime.jsx(
7892
- WorkflowCard,
7893
- {
7894
- header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
7895
- /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
7896
- status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
7897
- status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
7898
- status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CirclePause, { className: "text-accent3" }),
7899
- status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
7900
- status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" })
7901
- ] }),
7902
- /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-lg", className: "text-icon6 font-medium", children: stepId.charAt(0).toUpperCase() + stepId.slice(1) })
7903
- ] }),
7904
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md bg-surface4 p-1 font-mono relative", children: [
7905
- /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: JSON.stringify(result, null, 2), className: "absolute top-2 right-2 z-10" }),
7906
- /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: result })
7907
- ] })
7035
+ });
7908
7036
  }
7909
- );
7910
- };
7037
+ return schema2;
7038
+ };
7039
+ const schemaProvider = new CustomZodProvider(normalizedSchema(schema));
7040
+ const formProps = {
7041
+ schema: schemaProvider,
7042
+ onSubmit: async (values) => {
7043
+ await onSubmit?.(isNotZodObject ? values["​"] || {} : values);
7044
+ },
7045
+ defaultValues: isNotZodObject ? defaultValues ? { "​": defaultValues } : void 0 : defaultValues,
7046
+ formProps: {
7047
+ className
7048
+ },
7049
+ uiComponents: {
7050
+ SubmitButton: ({ children }) => onSubmit ? /* @__PURE__ */ jsxRuntime.jsx(Button$1, { variant: "light", className: "w-full", size: "lg", disabled: isSubmitLoading, children: isSubmitLoading ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "animate-spin" }) }) : submitButtonLabel || children }) : null
7051
+ },
7052
+ formComponents: {
7053
+ Label: ({ value }) => /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-normal", children: value })
7054
+ },
7055
+ withSubmit: true
7056
+ };
7057
+ return /* @__PURE__ */ jsxRuntime.jsx(AutoForm, { ...formProps, readOnly });
7058
+ }
7911
7059
 
7912
7060
  const RadioGroup = React__namespace.forwardRef(({ className, ...props }, ref) => {
7913
7061
  return /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Root, { className: cn("grid gap-2", className), ...props, ref });
@@ -8555,18 +7703,15 @@ const columns$3 = [
8555
7703
  id: "stepsCount",
8556
7704
  header: "Steps",
8557
7705
  size: 300,
8558
- cell: ({ row }) => /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end items-center gap-2", children: [
8559
- /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Footprints, {}), className: "!h-button-md", children: [
8560
- row.original.stepsCount,
8561
- " step",
8562
- row.original.stepsCount > 1 ? "s" : ""
8563
- ] }),
8564
- row.original.isLegacy ? /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { className: "!text-foreground/80 !h-button-md", children: "Legacy" }) : null
8565
- ] }) })
7706
+ cell: ({ row }) => /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-end items-center gap-2", children: /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Footprints, {}), className: "!h-button-md", children: [
7707
+ row.original.stepsCount,
7708
+ " step",
7709
+ row.original.stepsCount > 1 ? "s" : ""
7710
+ ] }) }) })
8566
7711
  }
8567
7712
  ];
8568
7713
 
8569
- function WorkflowTable({ workflows, legacyWorkflows, isLoading }) {
7714
+ function WorkflowTable({ workflows, isLoading }) {
8570
7715
  const { navigate, paths } = useLinkComponent();
8571
7716
  const workflowData = React.useMemo(() => {
8572
7717
  const _workflowsData = Object.keys(workflows ?? {}).map((key) => {
@@ -8575,22 +7720,11 @@ function WorkflowTable({ workflows, legacyWorkflows, isLoading }) {
8575
7720
  id: key,
8576
7721
  name: workflow?.name || "N/A",
8577
7722
  stepsCount: Object.keys(workflow?.steps ?? {})?.length,
8578
- isLegacy: false,
8579
- link: paths.workflowLink(key)
8580
- };
8581
- });
8582
- const legacyWorkflowsData = Object.keys(legacyWorkflows ?? {}).map((key) => {
8583
- const workflow = legacyWorkflows?.[key];
8584
- return {
8585
- id: key,
8586
- name: workflow?.name || "N/A",
8587
- stepsCount: Object.keys(workflow?.steps ?? {})?.length,
8588
- isLegacy: true,
8589
7723
  link: paths.workflowLink(key)
8590
7724
  };
8591
7725
  });
8592
- return [..._workflowsData, ...legacyWorkflowsData];
8593
- }, [workflows, legacyWorkflows]);
7726
+ return _workflowsData;
7727
+ }, [workflows]);
8594
7728
  const table = reactTable.useReactTable({
8595
7729
  data: workflowData,
8596
7730
  columns: columns$3,
@@ -8686,6 +7820,19 @@ const useWorkflowStream = (workflowFullState) => {
8686
7820
  }, [workflowFullState]);
8687
7821
  };
8688
7822
 
7823
+ const useWorkflow = (workflowId) => {
7824
+ const client = useMastraClient();
7825
+ const { runtimeContext } = usePlaygroundStore();
7826
+ return reactQuery.useQuery({
7827
+ queryKey: ["workflow", workflowId],
7828
+ queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
7829
+ enabled: Boolean(workflowId),
7830
+ retry: false,
7831
+ refetchOnWindowFocus: false,
7832
+ throwOnError: false
7833
+ });
7834
+ };
7835
+
8689
7836
  const LoadingBadge = () => {
8690
7837
  return /* @__PURE__ */ jsxRuntime.jsx(
8691
7838
  BadgeWrapper,
@@ -9880,212 +9027,185 @@ const handleNetworkMessageFromMemory = (content) => {
9880
9027
  return { role: "assistant", content: [{ type: "text", text: "Unknown response" }] };
9881
9028
  };
9882
9029
 
9883
- const handleStreamChunk = async ({
9884
- chunk,
9885
- setMessages,
9886
- refreshWorkingMemory,
9887
- _sideEffects
9888
- }) => {
9889
- function updater() {
9890
- setMessages((currentConversation) => {
9891
- const message = {
9030
+ const handleStreamChunk = ({ chunk, conversation }) => {
9031
+ switch (chunk.type) {
9032
+ default:
9033
+ return [...conversation];
9034
+ case "text-start": {
9035
+ const newMessage = {
9892
9036
  role: "assistant",
9893
- content: [{ type: "text", text: _sideEffects.content }]
9037
+ content: [{ type: "text", text: "" }]
9894
9038
  };
9895
- if (!_sideEffects.assistantMessageAdded) {
9896
- _sideEffects.assistantMessageAdded = true;
9897
- if (_sideEffects.assistantToolCallAddedForUpdater) {
9898
- _sideEffects.assistantToolCallAddedForUpdater = false;
9899
- }
9900
- return [...currentConversation, message];
9901
- }
9902
- if (_sideEffects.assistantToolCallAddedForUpdater) {
9903
- _sideEffects.assistantToolCallAddedForUpdater = false;
9904
- return [...currentConversation, message];
9905
- }
9906
- return [...currentConversation.slice(0, -1), message];
9907
- });
9908
- }
9909
- switch (chunk.type) {
9039
+ return [...conversation, newMessage];
9040
+ }
9910
9041
  case "text-delta": {
9911
- if (_sideEffects.assistantToolCallAddedForContent) {
9912
- _sideEffects.assistantToolCallAddedForContent = false;
9913
- _sideEffects.content = chunk.payload.text;
9914
- } else {
9915
- _sideEffects.content += chunk.payload.text;
9042
+ const lastMessage = conversation[conversation.length - 1];
9043
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9044
+ const updatedContent = lastMessage.content.map((part) => {
9045
+ if (typeof part === "object" && part.type === "text") {
9046
+ return {
9047
+ ...part,
9048
+ text: part.text + chunk.payload.text
9049
+ };
9050
+ }
9051
+ return part;
9052
+ });
9053
+ const updatedMessage = {
9054
+ ...lastMessage,
9055
+ content: updatedContent
9056
+ };
9057
+ return [...conversation.slice(0, -1), updatedMessage];
9916
9058
  }
9917
- updater();
9918
- break;
9059
+ return [...conversation];
9919
9060
  }
9920
9061
  case "tool-output": {
9921
9062
  if (chunk.payload.output?.type.startsWith("workflow-")) {
9922
- handleWorkflowChunk({ workflowChunk: chunk.payload.output, setMessages, entityName: chunk.payload.toolName });
9923
- } else {
9924
- setMessages((currentConversation) => {
9925
- const lastMessage = currentConversation[currentConversation.length - 1];
9926
- if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9927
- const updatedContent = lastMessage.content.map((part) => {
9928
- if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
9929
- const existingToolOutput = part.args?.__mastraMetadata?.toolOutput || [];
9930
- return {
9931
- ...part,
9932
- args: {
9933
- ...part.args,
9934
- __mastraMetadata: {
9935
- ...part.args?.__mastraMetadata,
9936
- toolOutput: [...existingToolOutput, chunk?.payload?.output]
9937
- }
9938
- }
9939
- };
9063
+ return handleWorkflowChunk({
9064
+ workflowChunk: chunk.payload.output,
9065
+ conversation,
9066
+ entityName: chunk.payload.toolName
9067
+ });
9068
+ }
9069
+ const lastMessage = conversation[conversation.length - 1];
9070
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9071
+ const updatedContent = lastMessage.content.map((part) => {
9072
+ if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
9073
+ const existingToolOutput = part.args?.__mastraMetadata?.toolOutput || [];
9074
+ return {
9075
+ ...part,
9076
+ args: {
9077
+ ...part.args,
9078
+ __mastraMetadata: {
9079
+ ...part.args?.__mastraMetadata,
9080
+ toolOutput: [...existingToolOutput, chunk?.payload?.output]
9081
+ }
9940
9082
  }
9941
- return part;
9942
- });
9943
- const updatedMessage = {
9944
- ...lastMessage,
9945
- content: updatedContent
9946
9083
  };
9947
- return [...currentConversation.slice(0, -1), updatedMessage];
9948
9084
  }
9949
- return currentConversation;
9085
+ return part;
9950
9086
  });
9087
+ const updatedMessage = {
9088
+ ...lastMessage,
9089
+ content: updatedContent
9090
+ };
9091
+ return [...conversation.slice(0, -1), updatedMessage];
9951
9092
  }
9952
- break;
9093
+ return [...conversation];
9953
9094
  }
9954
9095
  case "tool-call": {
9955
- setMessages((currentConversation) => {
9956
- const lastMessage = currentConversation[currentConversation.length - 1];
9957
- if (lastMessage && lastMessage.role === "assistant") {
9958
- const updatedMessage = {
9959
- ...lastMessage,
9960
- content: Array.isArray(lastMessage.content) ? [
9961
- ...lastMessage.content,
9962
- {
9963
- type: "tool-call",
9964
- toolCallId: chunk.payload.toolCallId,
9965
- toolName: chunk.payload.toolName,
9966
- args: {
9967
- ...chunk.payload.args,
9968
- __mastraMetadata: {
9969
- ...chunk.payload.args?.__mastraMetadata,
9970
- isStreaming: true
9971
- }
9972
- }
9973
- }
9974
- ] : [
9975
- ...typeof lastMessage.content === "string" ? [{ type: "text", text: lastMessage.content }] : [],
9976
- {
9977
- type: "tool-call",
9978
- toolCallId: chunk.payload.toolCallId,
9979
- toolName: chunk.payload.toolName,
9980
- args: {
9981
- ...chunk.payload.args,
9982
- __mastraMetadata: {
9983
- ...chunk.payload.args?.__mastraMetadata,
9984
- isStreaming: true
9985
- }
9096
+ const lastMessage = conversation[conversation.length - 1];
9097
+ if (lastMessage && lastMessage.role === "assistant") {
9098
+ const updatedMessage = {
9099
+ ...lastMessage,
9100
+ content: Array.isArray(lastMessage.content) ? [
9101
+ ...lastMessage.content,
9102
+ {
9103
+ type: "tool-call",
9104
+ toolCallId: chunk.payload.toolCallId,
9105
+ toolName: chunk.payload.toolName,
9106
+ args: {
9107
+ ...chunk.payload.args,
9108
+ __mastraMetadata: {
9109
+ ...chunk.payload.args?.__mastraMetadata,
9110
+ isStreaming: true
9986
9111
  }
9987
9112
  }
9988
- ]
9989
- };
9990
- _sideEffects.assistantToolCallAddedForUpdater = true;
9991
- _sideEffects.assistantToolCallAddedForContent = true;
9992
- return [...currentConversation.slice(0, -1), updatedMessage];
9993
- }
9994
- const newMessage = {
9995
- role: "assistant",
9996
- content: [
9997
- { type: "text", text: _sideEffects.content },
9113
+ }
9114
+ ] : [
9115
+ ...typeof lastMessage.content === "string" ? [{ type: "text", text: lastMessage.content }] : [],
9998
9116
  {
9999
9117
  type: "tool-call",
10000
9118
  toolCallId: chunk.payload.toolCallId,
10001
9119
  toolName: chunk.payload.toolName,
10002
9120
  args: {
10003
9121
  ...chunk.payload.args,
10004
- __mastraMetadata: { ...chunk.payload.args?.__mastraMetadata, isStreaming: true }
9122
+ __mastraMetadata: {
9123
+ ...chunk.payload.args?.__mastraMetadata,
9124
+ isStreaming: true
9125
+ }
10005
9126
  }
10006
9127
  }
10007
9128
  ]
10008
9129
  };
10009
- _sideEffects.assistantToolCallAddedForUpdater = true;
10010
- _sideEffects.assistantToolCallAddedForContent = true;
10011
- return [...currentConversation, newMessage];
10012
- });
10013
- _sideEffects.toolCallIdToName.current[chunk.payload.toolCallId] = chunk.payload.toolName;
10014
- break;
9130
+ return [...conversation.slice(0, -1), updatedMessage];
9131
+ }
9132
+ const newMessage = {
9133
+ role: "assistant",
9134
+ content: [
9135
+ {
9136
+ type: "tool-call",
9137
+ toolCallId: chunk.payload.toolCallId,
9138
+ toolName: chunk.payload.toolName,
9139
+ args: {
9140
+ ...chunk.payload.args,
9141
+ __mastraMetadata: {
9142
+ ...chunk.payload.args?.__mastraMetadata,
9143
+ isStreaming: true
9144
+ }
9145
+ }
9146
+ }
9147
+ ]
9148
+ };
9149
+ return [...conversation, newMessage];
10015
9150
  }
10016
9151
  case "tool-result": {
10017
- setMessages((currentConversation) => {
10018
- const lastMessage = currentConversation[currentConversation.length - 1];
10019
- if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
10020
- const updatedContent = lastMessage.content.map((part) => {
10021
- if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
10022
- return {
10023
- ...part,
10024
- result: chunk.payload.result
10025
- };
10026
- }
10027
- return part;
10028
- });
10029
- const updatedMessage = {
10030
- ...lastMessage,
10031
- content: updatedContent
10032
- };
10033
- return [...currentConversation.slice(0, -1), updatedMessage];
10034
- }
10035
- return currentConversation;
10036
- });
10037
- try {
10038
- const toolName = _sideEffects.toolCallIdToName.current[chunk.payload.toolCallId];
10039
- if (toolName === "updateWorkingMemory" && chunk.payload.result?.success) {
10040
- await refreshWorkingMemory?.();
10041
- }
10042
- } finally {
10043
- delete _sideEffects.toolCallIdToName.current[chunk.payload.toolCallId];
9152
+ const lastMessage = conversation[conversation.length - 1];
9153
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9154
+ const updatedContent = lastMessage.content.map((part) => {
9155
+ if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
9156
+ return {
9157
+ ...part,
9158
+ result: chunk.payload.result
9159
+ };
9160
+ }
9161
+ return part;
9162
+ });
9163
+ const updatedMessage = {
9164
+ ...lastMessage,
9165
+ content: updatedContent
9166
+ };
9167
+ return [...conversation.slice(0, -1), updatedMessage];
10044
9168
  }
10045
- break;
9169
+ return [...conversation];
10046
9170
  }
10047
9171
  case "error": {
10048
9172
  if (typeof chunk.payload.error === "string") {
10049
9173
  throw new Error(chunk.payload.error);
10050
9174
  }
10051
- break;
9175
+ return [...conversation];
10052
9176
  }
10053
9177
  case "finish": {
10054
- handleFinishReason$1(chunk.payload.finishReason);
10055
- break;
9178
+ handleFinishReason$1(chunk.payload.stepResult.reason);
9179
+ return [...conversation];
10056
9180
  }
10057
9181
  case "reasoning-delta": {
10058
- setMessages((currentConversation) => {
10059
- const lastMessage = currentConversation[currentConversation.length - 1];
10060
- if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
10061
- const updatedContent = lastMessage.content.map((part) => {
10062
- if (typeof part === "object" && part.type === "reasoning") {
10063
- return {
10064
- ...part,
10065
- text: part.text + chunk.payload.text
10066
- };
10067
- }
10068
- return part;
10069
- });
10070
- const updatedMessage = {
10071
- ...lastMessage,
10072
- content: updatedContent
10073
- };
10074
- return [...currentConversation.slice(0, -1), updatedMessage];
10075
- }
10076
- const newMessage = {
10077
- role: "assistant",
10078
- content: [
10079
- {
10080
- type: "reasoning",
10081
- text: chunk.payload.text
10082
- },
10083
- { type: "text", text: _sideEffects.content }
10084
- ]
9182
+ const lastMessage = conversation[conversation.length - 1];
9183
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9184
+ const updatedContent = lastMessage.content.map((part) => {
9185
+ if (typeof part === "object" && part.type === "reasoning") {
9186
+ return {
9187
+ ...part,
9188
+ text: part.text + chunk.payload.text
9189
+ };
9190
+ }
9191
+ return part;
9192
+ });
9193
+ const updatedMessage = {
9194
+ ...lastMessage,
9195
+ content: updatedContent
10085
9196
  };
10086
- return [...currentConversation, newMessage];
10087
- });
10088
- break;
9197
+ return [...conversation.slice(0, -1), updatedMessage];
9198
+ }
9199
+ const newMessage = {
9200
+ role: "assistant",
9201
+ content: [
9202
+ {
9203
+ type: "reasoning",
9204
+ text: chunk.payload.text
9205
+ }
9206
+ ]
9207
+ };
9208
+ return [...conversation, newMessage];
10089
9209
  }
10090
9210
  }
10091
9211
  };
@@ -10095,15 +9215,179 @@ const handleFinishReason$1 = (finishReason) => {
10095
9215
  throw new Error("Stream finished with reason tool-calls, try increasing maxSteps");
10096
9216
  }
10097
9217
  };
10098
- const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10099
- reactDom.flushSync(() => {
10100
- setMessages((currentConversation) => {
10101
- const lastMessage = currentConversation[currentConversation.length - 1];
9218
+ const handleWorkflowChunk = ({
9219
+ workflowChunk,
9220
+ conversation,
9221
+ entityName
9222
+ }) => {
9223
+ const lastMessage = conversation[conversation.length - 1];
9224
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9225
+ const newMessage = {
9226
+ ...lastMessage,
9227
+ content: contentArray.map((part) => {
9228
+ if (part.type === "tool-call") {
9229
+ return {
9230
+ ...part,
9231
+ toolName: part?.entityName || entityName,
9232
+ args: {
9233
+ ...part.args,
9234
+ __mastraMetadata: {
9235
+ ...part.args?.__mastraMetadata,
9236
+ workflowFullState: mapWorkflowStreamChunkToWatchResult(
9237
+ part.args?.__mastraMetadata?.workflowFullState || {},
9238
+ workflowChunk
9239
+ ),
9240
+ isStreaming: true
9241
+ }
9242
+ }
9243
+ };
9244
+ }
9245
+ return part;
9246
+ })
9247
+ };
9248
+ return [...conversation.slice(0, -1), newMessage];
9249
+ };
9250
+ const handleAgentChunk = ({
9251
+ agentChunk,
9252
+ conversation,
9253
+ entityName
9254
+ }) => {
9255
+ switch (agentChunk.type) {
9256
+ case "tool-result": {
9257
+ const lastMessage = conversation[conversation.length - 1];
9258
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9259
+ const newMessage = {
9260
+ ...lastMessage,
9261
+ content: contentArray.map((part) => {
9262
+ if (part.type === "tool-call") {
9263
+ const messages = part.args?.__mastraMetadata?.messages || [];
9264
+ const next = {
9265
+ ...part,
9266
+ toolName: part?.entityName || entityName,
9267
+ args: {
9268
+ ...part.args,
9269
+ __mastraMetadata: {
9270
+ ...part.args?.__mastraMetadata,
9271
+ isStreaming: true,
9272
+ messages: [
9273
+ ...messages.slice(0, -1),
9274
+ {
9275
+ ...messages[messages.length - 1],
9276
+ type: "tool",
9277
+ toolName: agentChunk.payload.toolName,
9278
+ args: agentChunk.payload.args,
9279
+ toolOutput: agentChunk.payload.result
9280
+ }
9281
+ ]
9282
+ }
9283
+ }
9284
+ };
9285
+ return next;
9286
+ }
9287
+ return part;
9288
+ })
9289
+ };
9290
+ return [...conversation.slice(0, -1), newMessage];
9291
+ }
9292
+ case "tool-call": {
9293
+ const lastMessage = conversation[conversation.length - 1];
9294
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9295
+ const newMessage = {
9296
+ ...lastMessage,
9297
+ content: contentArray.map((part) => {
9298
+ if (part.type === "tool-call") {
9299
+ const messages = part.args?.__mastraMetadata?.messages || [];
9300
+ const next = {
9301
+ ...part,
9302
+ toolName: part?.entityName || entityName,
9303
+ args: {
9304
+ ...part.args,
9305
+ __mastraMetadata: {
9306
+ ...part.args?.__mastraMetadata,
9307
+ isStreaming: true,
9308
+ messages: [
9309
+ ...messages,
9310
+ {
9311
+ type: "tool",
9312
+ toolCallId: agentChunk.payload.toolCallId,
9313
+ toolName: agentChunk.payload.toolName,
9314
+ args: {
9315
+ ...agentChunk.payload.args,
9316
+ __mastraMetadata: {
9317
+ ...agentChunk.payload.args?.__mastraMetadata,
9318
+ isStreaming: true
9319
+ }
9320
+ }
9321
+ }
9322
+ ]
9323
+ }
9324
+ }
9325
+ };
9326
+ return next;
9327
+ }
9328
+ return part;
9329
+ })
9330
+ };
9331
+ return [...conversation.slice(0, -1), newMessage];
9332
+ }
9333
+ case "text-delta": {
9334
+ const lastMessage = conversation[conversation.length - 1];
9335
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9336
+ const newMessage = {
9337
+ ...lastMessage,
9338
+ content: contentArray.map((part) => {
9339
+ if (part.type === "tool-call") {
9340
+ const messages = part.args?.__mastraMetadata?.messages || [];
9341
+ const lastMastraMessage = messages[messages.length - 1];
9342
+ const nextMessages = lastMastraMessage?.type === "text" ? [
9343
+ ...messages.slice(0, -1),
9344
+ { type: "text", content: (lastMastraMessage?.content || "") + agentChunk.payload.text }
9345
+ ] : [...messages, { type: "text", content: agentChunk.payload.text }];
9346
+ return {
9347
+ ...part,
9348
+ toolName: part?.entityName || entityName,
9349
+ args: {
9350
+ ...part.args,
9351
+ __mastraMetadata: {
9352
+ ...part.args?.__mastraMetadata,
9353
+ isStreaming: true,
9354
+ messages: nextMessages
9355
+ }
9356
+ }
9357
+ };
9358
+ }
9359
+ return part;
9360
+ })
9361
+ };
9362
+ return [...conversation.slice(0, -1), newMessage];
9363
+ }
9364
+ case "tool-output": {
9365
+ if (!agentChunk.payload.output.type.startsWith("workflow-")) return [...conversation];
9366
+ const lastMessage = conversation[conversation.length - 1];
10102
9367
  const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10103
9368
  const newMessage = {
10104
9369
  ...lastMessage,
10105
9370
  content: contentArray.map((part) => {
10106
9371
  if (part.type === "tool-call") {
9372
+ const messages = part.args?.__mastraMetadata?.messages || [];
9373
+ const lastMastraMessage = messages[messages.length - 1];
9374
+ const nextMessages = lastMastraMessage?.type === "tool" ? [
9375
+ ...messages.slice(0, -1),
9376
+ {
9377
+ ...lastMastraMessage,
9378
+ args: {
9379
+ ...agentChunk.payload.args,
9380
+ __mastraMetadata: {
9381
+ ...agentChunk.payload.args?.__mastraMetadata,
9382
+ workflowFullState: mapWorkflowStreamChunkToWatchResult(
9383
+ lastMastraMessage.args?.__mastraMetadata?.workflowFullState || {},
9384
+ agentChunk.payload.output
9385
+ ),
9386
+ isStreaming: true
9387
+ }
9388
+ }
9389
+ }
9390
+ ] : messages;
10107
9391
  return {
10108
9392
  ...part,
10109
9393
  toolName: part?.entityName || entityName,
@@ -10111,11 +9395,8 @@ const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10111
9395
  ...part.args,
10112
9396
  __mastraMetadata: {
10113
9397
  ...part.args?.__mastraMetadata,
10114
- workflowFullState: mapWorkflowStreamChunkToWatchResult(
10115
- part.args?.__mastraMetadata?.workflowFullState || {},
10116
- workflowChunk
10117
- ),
10118
- isStreaming: true
9398
+ isStreaming: true,
9399
+ messages: nextMessages
10119
9400
  }
10120
9401
  }
10121
9402
  };
@@ -10123,216 +9404,42 @@ const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10123
9404
  return part;
10124
9405
  })
10125
9406
  };
10126
- return [...currentConversation.slice(0, -1), newMessage];
10127
- });
10128
- });
10129
- };
10130
- const handleAgentChunk = ({ agentChunk, setMessages, entityName }) => {
10131
- switch (agentChunk.type) {
10132
- case "tool-result": {
10133
- setMessages((currentConversation) => {
10134
- const lastMessage = currentConversation[currentConversation.length - 1];
10135
- const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10136
- const newMessage = {
10137
- ...lastMessage,
10138
- content: contentArray.map((part) => {
10139
- if (part.type === "tool-call") {
10140
- const messages = part.args?.__mastraMetadata?.messages || [];
10141
- const next = {
10142
- ...part,
10143
- toolName: part?.entityName || entityName,
10144
- args: {
10145
- ...part.args,
10146
- __mastraMetadata: {
10147
- ...part.args?.__mastraMetadata,
10148
- isStreaming: true,
10149
- messages: [
10150
- ...messages.slice(0, -1),
10151
- {
10152
- ...messages[messages.length - 1],
10153
- type: "tool",
10154
- toolName: agentChunk.payload.toolName,
10155
- args: agentChunk.payload.args,
10156
- toolOutput: agentChunk.payload.result
10157
- }
10158
- ]
10159
- }
10160
- }
10161
- };
10162
- return next;
10163
- }
10164
- return part;
10165
- })
10166
- };
10167
- return [...currentConversation.slice(0, -1), newMessage];
10168
- });
10169
- break;
10170
- }
10171
- case "tool-call": {
10172
- setMessages((currentConversation) => {
10173
- const lastMessage = currentConversation[currentConversation.length - 1];
10174
- const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10175
- const newMessage = {
10176
- ...lastMessage,
10177
- content: contentArray.map((part) => {
10178
- if (part.type === "tool-call") {
10179
- const messages = part.args?.__mastraMetadata?.messages || [];
10180
- const next = {
10181
- ...part,
10182
- toolName: part?.entityName || entityName,
10183
- args: {
10184
- ...part.args,
10185
- __mastraMetadata: {
10186
- ...part.args?.__mastraMetadata,
10187
- isStreaming: true,
10188
- messages: [
10189
- ...messages,
10190
- {
10191
- type: "tool",
10192
- toolCallId: agentChunk.payload.toolCallId,
10193
- toolName: agentChunk.payload.toolName,
10194
- args: {
10195
- ...agentChunk.payload.args,
10196
- __mastraMetadata: {
10197
- ...agentChunk.payload.args?.__mastraMetadata,
10198
- isStreaming: true
10199
- }
10200
- }
10201
- }
10202
- ]
10203
- }
10204
- }
10205
- };
10206
- return next;
10207
- }
10208
- return part;
10209
- })
10210
- };
10211
- return [...currentConversation.slice(0, -1), newMessage];
10212
- });
10213
- break;
10214
- }
10215
- case "text-delta": {
10216
- setMessages((currentConversation) => {
10217
- const lastMessage = currentConversation[currentConversation.length - 1];
10218
- const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10219
- const newMessage = {
10220
- ...lastMessage,
10221
- content: contentArray.map((part) => {
10222
- if (part.type === "tool-call") {
10223
- const messages = part.args?.__mastraMetadata?.messages || [];
10224
- const lastMastraMessage = messages[messages.length - 1];
10225
- const nextMessages = lastMastraMessage?.type === "text" ? [
10226
- ...messages.slice(0, -1),
10227
- { type: "text", content: (lastMastraMessage?.content || "") + agentChunk.payload.text }
10228
- ] : [...messages, { type: "text", content: agentChunk.payload.text }];
10229
- return {
10230
- ...part,
10231
- toolName: part?.entityName || entityName,
10232
- args: {
10233
- ...part.args,
10234
- __mastraMetadata: {
10235
- ...part.args?.__mastraMetadata,
10236
- isStreaming: true,
10237
- messages: nextMessages
10238
- }
10239
- }
10240
- };
10241
- }
10242
- return part;
10243
- })
10244
- };
10245
- return [...currentConversation.slice(0, -1), newMessage];
10246
- });
10247
- break;
10248
- }
10249
- case "tool-output": {
10250
- reactDom.flushSync(() => {
10251
- setMessages((currentConversation) => {
10252
- if (!agentChunk.payload.output.type.startsWith("workflow-")) return currentConversation;
10253
- const lastMessage = currentConversation[currentConversation.length - 1];
10254
- const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10255
- const newMessage = {
10256
- ...lastMessage,
10257
- content: contentArray.map((part) => {
10258
- if (part.type === "tool-call") {
10259
- const messages = part.args?.__mastraMetadata?.messages || [];
10260
- const lastMastraMessage = messages[messages.length - 1];
10261
- const nextMessages = lastMastraMessage?.type === "tool" ? [
10262
- ...messages.slice(0, -1),
10263
- {
10264
- ...lastMastraMessage,
10265
- args: {
10266
- ...agentChunk.payload.args,
10267
- __mastraMetadata: {
10268
- ...agentChunk.payload.args?.__mastraMetadata,
10269
- workflowFullState: mapWorkflowStreamChunkToWatchResult(
10270
- lastMastraMessage.args?.__mastraMetadata?.workflowFullState || {},
10271
- agentChunk.payload.output
10272
- ),
10273
- isStreaming: true
10274
- }
10275
- }
10276
- }
10277
- ] : messages;
10278
- return {
10279
- ...part,
10280
- toolName: part?.entityName || entityName,
10281
- args: {
10282
- ...part.args,
10283
- __mastraMetadata: {
10284
- ...part.args?.__mastraMetadata,
10285
- isStreaming: true,
10286
- messages: nextMessages
10287
- }
10288
- }
10289
- };
10290
- }
10291
- return part;
10292
- })
10293
- };
10294
- return [...currentConversation.slice(0, -1), newMessage];
10295
- });
10296
- });
10297
- break;
9407
+ return [...conversation.slice(0, -1), newMessage];
10298
9408
  }
9409
+ default:
9410
+ case "agent-execution-end":
9411
+ return [...conversation];
10299
9412
  }
10300
9413
  };
10301
9414
  const createRootToolAssistantMessage = ({
10302
9415
  chunk,
10303
9416
  entityName,
10304
- setMessages,
9417
+ conversation,
10305
9418
  runId,
10306
- _sideEffects,
10307
9419
  from,
10308
9420
  networkMetadata
10309
9421
  }) => {
10310
- setMessages((currentConversation) => {
10311
- if (!entityName || !runId) return currentConversation;
10312
- const newMessage = {
10313
- role: "assistant",
10314
- content: [
10315
- { type: "text", text: _sideEffects.content },
10316
- {
10317
- type: "tool-call",
10318
- toolCallId: runId,
10319
- toolName: entityName,
10320
- args: {
10321
- ...chunk?.payload?.args,
10322
- __mastraMetadata: {
10323
- from,
10324
- networkMetadata,
10325
- ...chunk.payload.args?.__mastraMetadata,
10326
- isStreaming: true
10327
- }
9422
+ if (!entityName || !runId) return [...conversation];
9423
+ const newMessage = {
9424
+ role: "assistant",
9425
+ content: [
9426
+ {
9427
+ type: "tool-call",
9428
+ toolCallId: runId,
9429
+ toolName: entityName,
9430
+ args: {
9431
+ ...chunk?.payload?.args,
9432
+ __mastraMetadata: {
9433
+ from,
9434
+ networkMetadata,
9435
+ ...chunk.payload.args?.__mastraMetadata,
9436
+ isStreaming: true
10328
9437
  }
10329
9438
  }
10330
- ]
10331
- };
10332
- _sideEffects.assistantToolCallAddedForUpdater = true;
10333
- _sideEffects.assistantToolCallAddedForContent = true;
10334
- return [...currentConversation, newMessage];
10335
- });
9439
+ }
9440
+ ]
9441
+ };
9442
+ return [...conversation, newMessage];
10336
9443
  };
10337
9444
 
10338
9445
  const convertMessage$1 = (message) => {
@@ -10381,6 +9488,60 @@ const convertToAIAttachments = async (attachments) => {
10381
9488
  });
10382
9489
  return Promise.all(promises);
10383
9490
  };
9491
+ const initializeMessageState = (initialMessages) => {
9492
+ const convertedMessages = initialMessages?.map((message) => {
9493
+ let content;
9494
+ try {
9495
+ content = JSON.parse(message.content);
9496
+ if (content.isNetwork) {
9497
+ return handleNetworkMessageFromMemory(content);
9498
+ }
9499
+ } catch (e) {
9500
+ }
9501
+ const attachmentsAsContentParts = (message.experimental_attachments || []).map((image) => ({
9502
+ type: image.contentType.startsWith(`image/`) ? "image" : image.contentType.startsWith(`audio/`) ? "audio" : "file",
9503
+ mimeType: image.contentType,
9504
+ image: image.url
9505
+ }));
9506
+ const formattedParts = (message.parts || []).map((part) => {
9507
+ if (part.type === "reasoning") {
9508
+ return {
9509
+ type: "reasoning",
9510
+ text: part.reasoning || part?.details?.filter((detail) => detail.type === "text")?.map((detail) => detail.text).join(" ")
9511
+ };
9512
+ }
9513
+ if (part.type === "tool-invocation") {
9514
+ if (part.toolInvocation.state === "result") {
9515
+ return {
9516
+ type: "tool-call",
9517
+ toolCallId: part.toolInvocation.toolCallId,
9518
+ toolName: part.toolInvocation.toolName,
9519
+ args: part.toolInvocation.args,
9520
+ result: part.toolInvocation.result
9521
+ };
9522
+ }
9523
+ }
9524
+ if (part.type === "file") {
9525
+ return {
9526
+ type: "file",
9527
+ mimeType: part.mimeType,
9528
+ data: part.data
9529
+ };
9530
+ }
9531
+ if (part.type === "text") {
9532
+ return {
9533
+ type: "text",
9534
+ text: part.text
9535
+ };
9536
+ }
9537
+ }).filter(Boolean);
9538
+ return {
9539
+ ...message,
9540
+ content: [...formattedParts, ...attachmentsAsContentParts]
9541
+ };
9542
+ }).filter(Boolean);
9543
+ return convertedMessages;
9544
+ };
10384
9545
  function MastraRuntimeProvider({
10385
9546
  children,
10386
9547
  agentId,
@@ -10393,8 +9554,17 @@ function MastraRuntimeProvider({
10393
9554
  modelVersion
10394
9555
  }) {
10395
9556
  const [isRunning, setIsRunning] = React.useState(false);
10396
- const [messages, setMessages] = React.useState([]);
10397
- const [currentThreadId, setCurrentThreadId] = React.useState(threadId);
9557
+ const {
9558
+ messages,
9559
+ setMessages,
9560
+ streamVNext,
9561
+ network,
9562
+ cancelRun,
9563
+ isRunning: isRunningStreamVNext
9564
+ } = reactHooks.useMastraChat({
9565
+ agentId,
9566
+ initializeMessages: () => memory ? initializeMessageState(initialMessages || []) : []
9567
+ });
10398
9568
  const { refetch: refreshWorkingMemory } = useWorkingMemory();
10399
9569
  const abortControllerRef = React.useRef(null);
10400
9570
  const {
@@ -10417,76 +9587,23 @@ function MastraRuntimeProvider({
10417
9587
  Object.entries(runtimeContext ?? {}).forEach(([key, value]) => {
10418
9588
  runtimeContextInstance.set(key, value);
10419
9589
  });
10420
- React.useEffect(() => {
10421
- const hasNewInitialMessages = initialMessages && initialMessages?.length > messages?.length;
10422
- if (messages.length === 0 || currentThreadId !== threadId || hasNewInitialMessages && currentThreadId === threadId) {
10423
- if (initialMessages && threadId && memory) {
10424
- const convertedMessages = initialMessages?.map((message) => {
10425
- let content;
10426
- try {
10427
- content = JSON.parse(message.content);
10428
- if (content.isNetwork) {
10429
- return handleNetworkMessageFromMemory(content);
10430
- }
10431
- } catch (e) {
10432
- }
10433
- const attachmentsAsContentParts = (message.experimental_attachments || []).map((image) => ({
10434
- type: image.contentType.startsWith(`image/`) ? "image" : image.contentType.startsWith(`audio/`) ? "audio" : "file",
10435
- mimeType: image.contentType,
10436
- image: image.url
10437
- }));
10438
- const formattedParts = (message.parts || []).map((part) => {
10439
- if (part.type === "reasoning") {
10440
- return {
10441
- type: "reasoning",
10442
- text: part.reasoning || part?.details?.filter((detail) => detail.type === "text")?.map((detail) => detail.text).join(" ")
10443
- };
10444
- }
10445
- if (part.type === "tool-invocation") {
10446
- if (part.toolInvocation.state === "result") {
10447
- return {
10448
- type: "tool-call",
10449
- toolCallId: part.toolInvocation.toolCallId,
10450
- toolName: part.toolInvocation.toolName,
10451
- args: part.toolInvocation.args,
10452
- result: part.toolInvocation.result
10453
- };
10454
- }
10455
- }
10456
- if (part.type === "file") {
10457
- return {
10458
- type: "file",
10459
- mimeType: part.mimeType,
10460
- data: part.data
10461
- };
10462
- }
10463
- if (part.type === "text") {
10464
- return {
10465
- type: "text",
10466
- text: part.text
10467
- };
10468
- }
10469
- }).filter(Boolean);
10470
- return {
10471
- ...message,
10472
- content: [...formattedParts, ...attachmentsAsContentParts]
10473
- };
10474
- }).filter(Boolean);
10475
- setMessages(convertedMessages);
10476
- setCurrentThreadId(threadId);
10477
- }
10478
- }
10479
- }, [initialMessages, threadId, memory]);
9590
+ const modelSettingsArgs = {
9591
+ frequencyPenalty,
9592
+ presencePenalty,
9593
+ maxRetries,
9594
+ temperature,
9595
+ topK,
9596
+ topP,
9597
+ maxTokens,
9598
+ instructions,
9599
+ providerOptions
9600
+ };
10480
9601
  const baseClient = useMastraClient();
10481
9602
  const onNew = async (message) => {
10482
9603
  if (message.content[0]?.type !== "text") throw new Error("Only text messages are supported");
10483
9604
  const attachments = await convertToAIAttachments(message.attachments);
10484
9605
  const input = message.content[0].text;
10485
- setMessages((currentConversation) => [
10486
- ...currentConversation,
10487
- { role: "user", content: input, attachments: message.attachments }
10488
- ]);
10489
- setIsRunning(true);
9606
+ setMessages((s) => [...s, { role: "user", content: input, attachments: message.attachments }]);
10490
9607
  const controller = new AbortController();
10491
9608
  abortControllerRef.current = controller;
10492
9609
  const clientWithAbort = new clientJs.MastraClient({
@@ -10496,7 +9613,7 @@ function MastraRuntimeProvider({
10496
9613
  const agent = clientWithAbort.getAgent(agentId);
10497
9614
  try {
10498
9615
  let handleGenerateResponse = function(generatedResponse) {
10499
- if (generatedResponse.response && "messages" in generatedResponse.response) {
9616
+ if (generatedResponse.response && "messages" in generatedResponse.response && generatedResponse.response.messages) {
10500
9617
  const latestMessage = generatedResponse.response.messages.reduce(
10501
9618
  (acc, message2) => {
10502
9619
  const _content = Array.isArray(acc.content) ? acc.content : [];
@@ -10577,86 +9694,72 @@ function MastraRuntimeProvider({
10577
9694
  };
10578
9695
  if (modelVersion === "v2") {
10579
9696
  if (chatWithNetwork) {
10580
- const response = await agent.network({
10581
- messages: [
9697
+ let currentEntityId;
9698
+ await network({
9699
+ coreUserMessages: [
10582
9700
  {
10583
9701
  role: "user",
10584
9702
  content: input
10585
- }
9703
+ },
9704
+ ...attachments
10586
9705
  ],
10587
- maxSteps,
10588
- modelSettings: {
10589
- frequencyPenalty,
10590
- presencePenalty,
10591
- maxRetries,
10592
- maxOutputTokens: maxTokens,
10593
- temperature,
10594
- topK,
10595
- topP
10596
- },
10597
- runId: agentId,
10598
9706
  runtimeContext: runtimeContextInstance,
10599
- ...memory ? { thread: threadId, resourceId: agentId } : {}
10600
- });
10601
- const _sideEffects = {
10602
- assistantMessageAdded: false,
10603
- assistantToolCallAddedForUpdater: false,
10604
- assistantToolCallAddedForContent: false,
10605
- content: "",
10606
- toolCallIdToName
10607
- };
10608
- let currentEntityId;
10609
- await response.processDataStream({
10610
- onChunk: async (chunk) => {
9707
+ threadId,
9708
+ modelSettings: modelSettingsArgs,
9709
+ signal: controller.signal,
9710
+ onNetworkChunk: (chunk, conversation) => {
10611
9711
  if (chunk.type.startsWith("agent-execution-event-")) {
10612
9712
  const agentChunk = chunk.payload;
10613
- if (!currentEntityId) return;
10614
- await handleAgentChunk({ agentChunk, setMessages, entityName: currentEntityId });
9713
+ if (!currentEntityId) return conversation;
9714
+ return handleAgentChunk({ agentChunk, conversation, entityName: currentEntityId });
10615
9715
  } else if (chunk.type === "tool-execution-start") {
10616
- await handleStreamChunk({
9716
+ const { args: argsData } = chunk.payload;
9717
+ const nestedArgs = argsData.args || {};
9718
+ const mastraMetadata = argsData.__mastraMetadata || {};
9719
+ const selectionReason = argsData.selectionReason || "";
9720
+ return handleStreamChunk({
10617
9721
  chunk: {
10618
9722
  ...chunk,
10619
9723
  type: "tool-call",
10620
9724
  payload: {
10621
- ...chunk?.payload,
10622
- toolCallId: chunk?.payload?.args?.toolCallId,
10623
- toolName: chunk?.payload?.args?.toolName,
9725
+ ...chunk.payload,
9726
+ toolCallId: argsData.toolCallId || "unknown",
9727
+ toolName: argsData.toolName || "unknown",
10624
9728
  args: {
10625
- ...chunk?.payload?.args?.args,
9729
+ ...nestedArgs,
10626
9730
  __mastraMetadata: {
10627
- ...chunk?.payload?.args?.__mastraMetadata,
9731
+ ...mastraMetadata,
10628
9732
  networkMetadata: {
10629
- selectionReason: chunk?.payload?.args?.selectionReason || "",
10630
- input: chunk?.payload?.args?.args
9733
+ selectionReason,
9734
+ input: nestedArgs
10631
9735
  }
10632
9736
  }
10633
9737
  }
10634
9738
  }
10635
9739
  },
10636
- setMessages,
10637
- refreshWorkingMemory,
10638
- _sideEffects
9740
+ conversation
10639
9741
  });
10640
9742
  } else if (chunk.type === "tool-execution-end") {
10641
- await handleStreamChunk({
9743
+ const next = handleStreamChunk({
10642
9744
  chunk: { ...chunk, type: "tool-result" },
10643
- setMessages,
10644
- refreshWorkingMemory,
10645
- _sideEffects
9745
+ conversation
10646
9746
  });
9747
+ if (chunk.payload?.toolName === "updateWorkingMemory" && typeof chunk.payload.result === "object" && "success" in chunk.payload.result && chunk.payload.result?.success) {
9748
+ refreshWorkingMemory?.();
9749
+ }
9750
+ return next;
10647
9751
  } else if (chunk.type.startsWith("workflow-execution-event-")) {
10648
9752
  const workflowChunk = chunk.payload;
10649
- if (!currentEntityId) return;
10650
- await handleWorkflowChunk({ workflowChunk, setMessages, entityName: currentEntityId });
9753
+ if (!currentEntityId) return conversation;
9754
+ return handleWorkflowChunk({ workflowChunk, conversation, entityName: currentEntityId });
10651
9755
  } else if (chunk.type === "workflow-execution-start" || chunk.type === "agent-execution-start") {
10652
9756
  currentEntityId = chunk.payload?.args?.resourceId;
10653
9757
  const runId = chunk.payload.runId;
10654
- if (!currentEntityId || !runId) return;
10655
- createRootToolAssistantMessage({
9758
+ if (!currentEntityId || !runId) return conversation;
9759
+ return createRootToolAssistantMessage({
10656
9760
  entityName: currentEntityId,
10657
- setMessages,
9761
+ conversation,
10658
9762
  runId,
10659
- _sideEffects,
10660
9763
  chunk,
10661
9764
  from: chunk.type === "agent-execution-start" ? "AGENT" : "WORKFLOW",
10662
9765
  networkMetadata: {
@@ -10664,21 +9767,19 @@ function MastraRuntimeProvider({
10664
9767
  input: chunk?.payload?.args?.prompt
10665
9768
  }
10666
9769
  });
10667
- _sideEffects.toolCallIdToName.current[runId] = currentEntityId;
10668
9770
  } else if (chunk.type === "network-execution-event-step-finish") {
10669
- setMessages((currentConversation) => {
10670
- return [
10671
- ...currentConversation,
10672
- { role: "assistant", content: [{ type: "text", text: chunk?.payload?.result || "" }] }
10673
- ];
10674
- });
9771
+ return [
9772
+ ...conversation,
9773
+ { role: "assistant", content: [{ type: "text", text: chunk?.payload?.result || "" }] }
9774
+ ];
10675
9775
  } else {
10676
- await handleStreamChunk({ chunk, setMessages, refreshWorkingMemory, _sideEffects });
9776
+ return handleStreamChunk({ chunk, conversation });
10677
9777
  }
10678
9778
  }
10679
9779
  });
10680
9780
  } else {
10681
9781
  if (chatWithGenerateVNext) {
9782
+ setIsRunning(true);
10682
9783
  const response = await agent.generateVNext({
10683
9784
  messages: [
10684
9785
  {
@@ -10706,50 +9807,32 @@ function MastraRuntimeProvider({
10706
9807
  setIsRunning(false);
10707
9808
  return;
10708
9809
  } else {
10709
- const response = await agent.streamVNext({
10710
- messages: [
9810
+ await streamVNext({
9811
+ coreUserMessages: [
10711
9812
  {
10712
9813
  role: "user",
10713
9814
  content: input
10714
9815
  },
10715
9816
  ...attachments
10716
9817
  ],
10717
- runId: agentId,
10718
- modelSettings: {
10719
- frequencyPenalty,
10720
- presencePenalty,
10721
- maxRetries,
10722
- maxOutputTokens: maxTokens,
10723
- temperature,
10724
- topK,
10725
- topP
10726
- },
10727
- instructions,
10728
9818
  runtimeContext: runtimeContextInstance,
10729
- ...memory ? { threadId, resourceId: agentId } : {},
10730
- providerOptions
10731
- });
10732
- if (!response.body) {
10733
- throw new Error("No response body");
10734
- }
10735
- const _sideEffects = {
10736
- assistantMessageAdded: false,
10737
- assistantToolCallAddedForUpdater: false,
10738
- assistantToolCallAddedForContent: false,
10739
- content: "",
10740
- toolCallIdToName
10741
- };
10742
- await response.processDataStream({
10743
- onChunk: async (chunk) => {
10744
- await handleStreamChunk({ chunk, setMessages, refreshWorkingMemory, _sideEffects });
10745
- }
9819
+ threadId,
9820
+ modelSettings: modelSettingsArgs,
9821
+ onChunk: (chunk, conversation) => {
9822
+ const next = handleStreamChunk({ chunk, conversation });
9823
+ if (chunk.type === "tool-result" && chunk.payload?.toolName === "updateWorkingMemory" && typeof chunk.payload.result === "object" && "success" in chunk.payload.result && chunk.payload.result?.success) {
9824
+ refreshWorkingMemory?.();
9825
+ }
9826
+ return next;
9827
+ },
9828
+ signal: controller.signal
10746
9829
  });
10747
- setIsRunning(false);
10748
9830
  return;
10749
9831
  }
10750
9832
  }
10751
9833
  } else {
10752
9834
  if (chatWithGenerate) {
9835
+ setIsRunning(true);
10753
9836
  const generateResponse = await agent.generate({
10754
9837
  messages: [
10755
9838
  {
@@ -10864,6 +9947,7 @@ function MastraRuntimeProvider({
10864
9947
  return [...currentConversation.slice(0, -1), message2];
10865
9948
  });
10866
9949
  };
9950
+ setIsRunning(true);
10867
9951
  const response = await agent.stream({
10868
9952
  messages: [
10869
9953
  {
@@ -11043,11 +10127,12 @@ function MastraRuntimeProvider({
11043
10127
  abortControllerRef.current.abort();
11044
10128
  abortControllerRef.current = null;
11045
10129
  setIsRunning(false);
10130
+ cancelRun?.();
11046
10131
  }
11047
10132
  };
11048
10133
  const { adapters, isReady } = useAdapters(agentId);
11049
10134
  const runtime = react$2.useExternalStoreRuntime({
11050
- isRunning,
10135
+ isRunning: isRunning || isRunningStreamVNext,
11051
10136
  messages,
11052
10137
  convertMessage: convertMessage$1,
11053
10138
  onNew,
@@ -12268,6 +11353,7 @@ const MistralIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
12268
11353
 
12269
11354
  const providerMapToIcon = {
12270
11355
  "openai.chat": /* @__PURE__ */ jsxRuntime.jsx(OpenaiChatIcon, {}),
11356
+ "openai.responses": /* @__PURE__ */ jsxRuntime.jsx(OpenaiChatIcon, {}),
12271
11357
  "anthropic.chat": /* @__PURE__ */ jsxRuntime.jsx(AnthropicChatIcon, {}),
12272
11358
  "anthropic.messages": /* @__PURE__ */ jsxRuntime.jsx(AnthropicMessagesIcon, {}),
12273
11359
  AZURE: /* @__PURE__ */ jsxRuntime.jsx(AzureIcon, {}),
@@ -12299,17 +11385,34 @@ const columns$2 = [
12299
11385
  {
12300
11386
  header: "Model",
12301
11387
  accessorKey: "model",
12302
- size: 160,
11388
+ size: 300,
12303
11389
  cell: ({ row }) => {
12304
- return /* @__PURE__ */ jsxRuntime.jsx(Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
12305
- Badge$1,
12306
- {
12307
- variant: "default",
12308
- icon: providerMapToIcon[row.original.provider] || /* @__PURE__ */ jsxRuntime.jsx(OpenAIIcon, {}),
12309
- className: "truncate",
12310
- children: row.original.modelId || "N/A"
12311
- }
12312
- ) });
11390
+ return /* @__PURE__ */ jsxRuntime.jsxs(Cell, { children: [
11391
+ /* @__PURE__ */ jsxRuntime.jsx(
11392
+ Badge$1,
11393
+ {
11394
+ variant: "default",
11395
+ icon: providerMapToIcon[row.original.provider] || /* @__PURE__ */ jsxRuntime.jsx(OpenAIIcon, {}),
11396
+ className: "truncate",
11397
+ children: row.original.modelId || "N/A"
11398
+ }
11399
+ ),
11400
+ row.original.modelList && row.original.modelList.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
11401
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { variant: "info", className: "ml-2", children: [
11402
+ "+ ",
11403
+ row.original.modelList.length - 1,
11404
+ " more"
11405
+ ] }) }),
11406
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { className: "bg-surface5 flex flex-col gap-2", children: row.original.modelList.slice(1).map((mdl) => /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
11407
+ Badge$1,
11408
+ {
11409
+ variant: "default",
11410
+ icon: providerMapToIcon[mdl.model.provider],
11411
+ children: mdl.model.modelId
11412
+ }
11413
+ ) }, mdl.id)) })
11414
+ ] }) : null
11415
+ ] });
12313
11416
  }
12314
11417
  },
12315
11418
  {
@@ -12342,7 +11445,8 @@ function AgentsTable({ agents, isLoading }) {
12342
11445
  repoUrl: void 0,
12343
11446
  tools: agent.tools,
12344
11447
  modelId: agent.modelId,
12345
- link: paths.agentLink(key)
11448
+ link: paths.agentLink(key),
11449
+ modelList: agent.modelList
12346
11450
  };
12347
11451
  }),
12348
11452
  [agents]
@@ -12358,10 +11462,10 @@ function AgentsTable({ agents, isLoading }) {
12358
11462
  if (rows.length === 0) {
12359
11463
  return /* @__PURE__ */ jsxRuntime.jsx(EmptyAgentsTable, {});
12360
11464
  }
12361
- return /* @__PURE__ */ jsxRuntime.jsx(ScrollableContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
11465
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollableContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
12362
11466
  /* @__PURE__ */ jsxRuntime.jsx(Thead, { className: "sticky top-0", children: ths.headers.map((header) => /* @__PURE__ */ jsxRuntime.jsx(Th, { style: { width: header.index === 0 ? "auto" : header.column.getSize() }, children: reactTable.flexRender(header.column.columnDef.header, header.getContext()) }, header.id)) }),
12363
11467
  /* @__PURE__ */ jsxRuntime.jsx(Tbody, { children: rows.map((row) => /* @__PURE__ */ jsxRuntime.jsx(Row, { onClick: () => navigate(row.original.link), children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id)) }, row.id)) })
12364
- ] }) });
11468
+ ] }) }) });
12365
11469
  }
12366
11470
  const AgentsTableSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
12367
11471
  /* @__PURE__ */ jsxRuntime.jsxs(Thead, { children: [
@@ -14489,6 +13593,126 @@ const AgentMetadataModelSwitcher = ({
14489
13593
  ] });
14490
13594
  };
14491
13595
 
13596
+ const Switch = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
13597
+ SwitchPrimitives__namespace.Root,
13598
+ {
13599
+ className: cn(
13600
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-mastra-bg-7 data-[state=unchecked]:bg-input",
13601
+ className
13602
+ ),
13603
+ ...props,
13604
+ ref,
13605
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13606
+ SwitchPrimitives__namespace.Thumb,
13607
+ {
13608
+ className: cn(
13609
+ "pointer-events-none block h-4 w-4 rounded-full bg-white shadow-lg transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
13610
+ )
13611
+ }
13612
+ )
13613
+ }
13614
+ ));
13615
+ Switch.displayName = SwitchPrimitives__namespace.Root.displayName;
13616
+
13617
+ const AgentMetadataModelList = ({
13618
+ modelList,
13619
+ modelProviders,
13620
+ updateModelInModelList,
13621
+ reorderModelList
13622
+ }) => {
13623
+ const [modelConfigs, setModelConfigs] = React.useState(() => modelList);
13624
+ const handleDragEnd = (result) => {
13625
+ if (!result.destination) {
13626
+ return;
13627
+ }
13628
+ const items = Array.from(modelConfigs);
13629
+ const [reorderedItem] = items.splice(result.source.index, 1);
13630
+ items.splice(result.destination.index, 0, reorderedItem);
13631
+ setModelConfigs(items);
13632
+ reorderModelList({ reorderedModelIds: items.map((item) => item.id) });
13633
+ };
13634
+ const updateModel = (params) => {
13635
+ setModelConfigs(
13636
+ (prev) => prev.map(
13637
+ (modelConfig) => modelConfig.id === params.modelConfigId ? {
13638
+ ...modelConfig,
13639
+ enabled: params.enabled ?? modelConfig.enabled,
13640
+ maxRetries: params.maxRetries ?? modelConfig.maxRetries,
13641
+ model: {
13642
+ modelId: params.model?.modelId ?? modelConfig.model.modelId,
13643
+ provider: params.model?.provider ?? modelConfig.model.provider,
13644
+ modelVersion: modelConfig.model.modelVersion
13645
+ }
13646
+ } : modelConfig
13647
+ )
13648
+ );
13649
+ return updateModelInModelList(params);
13650
+ };
13651
+ return /* @__PURE__ */ jsxRuntime.jsx(dnd.DragDropContext, { onDragEnd: handleDragEnd, children: /* @__PURE__ */ jsxRuntime.jsx(dnd.Droppable, { droppableId: "model-list", children: (provided) => /* @__PURE__ */ jsxRuntime.jsxs("div", { ...provided.droppableProps, ref: provided.innerRef, className: "flex flex-col gap-2", children: [
13652
+ modelConfigs.map((modelConfig, index) => /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: modelConfig.id, index, children: (provided2) => /* @__PURE__ */ jsxRuntime.jsx(
13653
+ "div",
13654
+ {
13655
+ ref: provided2.innerRef,
13656
+ ...provided2.draggableProps,
13657
+ ...provided2.dragHandleProps,
13658
+ style: provided2.draggableProps.style,
13659
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13660
+ AgentMetadataModelListItem,
13661
+ {
13662
+ modelConfig,
13663
+ modelProviders,
13664
+ updateModelInModelList: updateModel
13665
+ }
13666
+ )
13667
+ }
13668
+ ) }, modelConfig.id)),
13669
+ provided.placeholder
13670
+ ] }) }) });
13671
+ };
13672
+ const AgentMetadataModelListItem = ({
13673
+ modelConfig,
13674
+ modelProviders,
13675
+ updateModelInModelList
13676
+ }) => {
13677
+ const [isEditingModel, setIsEditingModel] = React.useState(false);
13678
+ const [enabled, setEnabled] = React.useState(() => modelConfig.enabled);
13679
+ const providerIcon = providerMapToIcon[modelConfig.model.provider || "openai.chat"];
13680
+ return isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
13681
+ AgentMetadataModelSwitcher,
13682
+ {
13683
+ defaultProvider: modelConfig.model.provider,
13684
+ defaultModel: modelConfig.model.modelId,
13685
+ updateModel: (params) => updateModelInModelList({ modelConfigId: modelConfig.id, model: params }),
13686
+ closeEditor: () => setIsEditingModel(false),
13687
+ modelProviders
13688
+ }
13689
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 p-2 rounded-lg bg-background hover:bg-muted/50 transition-colors", children: [
13690
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon3 cursor-grab active:cursor-grabbing", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, {}) }) }),
13691
+ /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: providerIcon, className: "font-medium", children: modelConfig.model.modelId || "N/A" }),
13692
+ /* @__PURE__ */ jsxRuntime.jsx(
13693
+ Switch,
13694
+ {
13695
+ checked: enabled,
13696
+ onCheckedChange: (checked) => {
13697
+ setEnabled(checked);
13698
+ updateModelInModelList({ modelConfigId: modelConfig.id, enabled: checked });
13699
+ }
13700
+ }
13701
+ ),
13702
+ /* @__PURE__ */ jsxRuntime.jsx(
13703
+ "button",
13704
+ {
13705
+ onClick: () => setIsEditingModel(true),
13706
+ className: "text-icon3 hover:text-icon6",
13707
+ title: "Edit model",
13708
+ type: "button",
13709
+ "aria-label": "Edit model",
13710
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EditIcon, {}) })
13711
+ }
13712
+ )
13713
+ ] });
13714
+ };
13715
+
14492
13716
  const AgentMetadataNetworkList = ({ agents }) => {
14493
13717
  const { Link, paths } = useLinkComponent();
14494
13718
  if (agents.length === 0) {
@@ -14502,7 +13726,9 @@ const AgentMetadata = ({
14502
13726
  promptSlot,
14503
13727
  hasMemoryEnabled,
14504
13728
  updateModel,
14505
- modelProviders
13729
+ modelProviders,
13730
+ updateModelInModelList,
13731
+ reorderModelList
14506
13732
  }) => {
14507
13733
  const [isEditingModel, setIsEditingModel] = React.useState(false);
14508
13734
  const providerIcon = providerMapToIcon[agent.provider || "openai.chat"];
@@ -14513,7 +13739,15 @@ const AgentMetadata = ({
14513
13739
  const agentWorkflows = agent.workflows ?? {};
14514
13740
  const workflows = Object.keys(agentWorkflows).map((key) => ({ id: key, ...agentWorkflows[key] }));
14515
13741
  return /* @__PURE__ */ jsxRuntime.jsxs(AgentMetadataWrapper, { children: [
14516
- /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Model", children: isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
13742
+ agent.modelList ? /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Models", children: /* @__PURE__ */ jsxRuntime.jsx(
13743
+ AgentMetadataModelList,
13744
+ {
13745
+ modelList: agent.modelList,
13746
+ modelProviders,
13747
+ updateModelInModelList,
13748
+ reorderModelList
13749
+ }
13750
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Model", children: isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
14517
13751
  AgentMetadataModelSwitcher,
14518
13752
  {
14519
13753
  defaultProvider: agent.provider,
@@ -19302,8 +18536,6 @@ exports.JudgeIcon = JudgeIcon;
19302
18536
  exports.Kbd = Kbd;
19303
18537
  exports.KeyValueList = KeyValueList;
19304
18538
  exports.LatencyIcon = LatencyIcon;
19305
- exports.LegacyWorkflowGraph = LegacyWorkflowGraph;
19306
- exports.LegacyWorkflowTrigger = LegacyWorkflowTrigger;
19307
18539
  exports.LinkComponentProvider = LinkComponentProvider;
19308
18540
  exports.LogsIcon = LogsIcon;
19309
18541
  exports.MainContentContent = MainContentContent;
@@ -19421,21 +18653,17 @@ exports.spanTypePrefixes = spanTypePrefixes;
19421
18653
  exports.transformKey = transformKey;
19422
18654
  exports.useAgentSettings = useAgentSettings;
19423
18655
  exports.useCurrentRun = useCurrentRun;
19424
- exports.useExecuteWorkflow = useExecuteWorkflow;
19425
18656
  exports.useInView = useInView;
19426
- exports.useLegacyWorkflow = useLegacyWorkflow;
19427
18657
  exports.useLinkComponent = useLinkComponent;
19428
18658
  exports.useMastraClient = useMastraClient;
19429
18659
  exports.usePlaygroundStore = usePlaygroundStore;
19430
18660
  exports.usePolling = usePolling;
19431
- exports.useResumeWorkflow = useResumeWorkflow;
19432
18661
  exports.useScorer = useScorer;
19433
18662
  exports.useScorers = useScorers;
19434
18663
  exports.useScoresByEntityId = useScoresByEntityId;
19435
18664
  exports.useScoresByScorerId = useScoresByScorerId;
19436
18665
  exports.useSpeechRecognition = useSpeechRecognition;
19437
18666
  exports.useThreadInput = useThreadInput;
19438
- exports.useWatchWorkflow = useWatchWorkflow;
19439
18667
  exports.useWorkflow = useWorkflow;
19440
18668
  exports.useWorkflowRuns = useWorkflowRuns;
19441
18669
  exports.useWorkingMemory = useWorkingMemory;