@mastra/playground-ui 6.2.2 → 6.2.3-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/index.cjs.js +1370 -2120
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +1275 -2019
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/components/assistant-ui/messages/assistant-message.d.ts +2 -1
  7. package/dist/src/components/assistant-ui/thread.d.ts +2 -1
  8. package/dist/src/components/ui/button.d.ts +1 -1
  9. package/dist/src/components/ui/command.d.ts +2 -2
  10. package/dist/src/components/ui/resizable.d.ts +1 -1
  11. package/dist/src/domains/agents/components/agent-chat.d.ts +1 -1
  12. package/dist/src/domains/agents/components/agent-metadata/agent-metadata-model-list.d.ts +17 -0
  13. package/dist/src/domains/agents/components/agent-metadata/agent-metadata.d.ts +4 -1
  14. package/dist/src/domains/agents/components/agent-table/types.d.ts +2 -1
  15. package/dist/src/domains/agents/components/provider-map-icon.d.ts +1 -0
  16. package/dist/src/domains/workflows/components/workflow-table/types.d.ts +0 -1
  17. package/dist/src/domains/workflows/components/workflow-table/workflow-table.d.ts +2 -3
  18. package/dist/src/domains/workflows/context/workflow-run-context.d.ts +0 -3
  19. package/dist/src/domains/workflows/index.d.ts +0 -2
  20. package/dist/src/domains/workflows/workflow/utils.d.ts +0 -10
  21. package/dist/src/hooks/use-workflows.d.ts +1 -45
  22. package/dist/src/index.d.ts +1 -1
  23. package/dist/src/services/stream-chunk-message.d.ts +9 -18
  24. package/dist/src/types.d.ts +9 -1
  25. package/package.json +9 -7
  26. package/dist/src/contexts/mastra-client-context.d.ts +0 -8
  27. package/dist/src/domains/workflows/context/legacy-workflow-nested-graph-context.d.ts +0 -13
  28. package/dist/src/domains/workflows/workflow/legacy-workflow-graph-inner.d.ts +0 -4
  29. package/dist/src/domains/workflows/workflow/legacy-workflow-graph.d.ts +0 -3
  30. package/dist/src/domains/workflows/workflow/legacy-workflow-nested-graph.d.ts +0 -5
  31. package/dist/src/domains/workflows/workflow/legacy-workflow-nested-node.d.ts +0 -11
  32. package/dist/src/domains/workflows/workflow/legacy-workflow-status.d.ts +0 -6
  33. package/dist/src/domains/workflows/workflow/legacy-workflow-trigger.d.ts +0 -4
package/dist/index.cjs.js CHANGED
@@ -3,10 +3,9 @@
3
3
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
 
5
5
  require('./index.css');const jsxRuntime = require('react/jsx-runtime');
6
- const React = require('react');
7
- const clientJs = require('@mastra/client-js');
8
- const react$2 = require('@assistant-ui/react');
6
+ const react$3 = require('@assistant-ui/react');
9
7
  const lucideReact = require('lucide-react');
8
+ const React = require('react');
10
9
  const reactSlot = require('@radix-ui/react-slot');
11
10
  const TooltipPrimitive = require('@radix-ui/react-tooltip');
12
11
  const AvatarPrimitive = require('@radix-ui/react-avatar');
@@ -21,26 +20,27 @@ const codemirrorThemeDracula = require('@uiw/codemirror-theme-dracula');
21
20
  const CodeMirror = require('@uiw/react-codemirror');
22
21
  const sonner = require('sonner');
23
22
  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
23
  const react = require('@xyflow/react');
29
24
  require('@xyflow/react/dist/style.css');
30
25
  const Dagre = require('@dagrejs/dagre');
31
26
  const prismReactRenderer = require('prism-react-renderer');
32
27
  const CollapsiblePrimitive = require('@radix-ui/react-collapsible');
33
28
  const ScrollAreaPrimitive = require('@radix-ui/react-scroll-area');
29
+ const colors = require('./colors-DLwJ7rFA.cjs');
34
30
  const prettier = require('prettier');
35
31
  const prettierPluginBabel = require('prettier/plugins/babel');
36
32
  const prettierPluginEstree = require('prettier/plugins/estree');
37
- const colors = require('./colors-DLwJ7rFA.cjs');
33
+ const SliderPrimitive = require('@radix-ui/react-slider');
38
34
  const jsonSchemaToZod = require('json-schema-to-zod');
39
35
  const superjson = require('superjson');
40
36
  const z = require('zod');
37
+ const reactCodeBlock = require('react-code-block');
38
+ const zustand = require('zustand');
39
+ const middleware = require('zustand/middleware');
41
40
  const react$1 = require('@autoform/react');
42
41
  const CheckboxPrimitive = require('@radix-ui/react-checkbox');
43
42
  const dateFns = require('date-fns');
43
+ const useDebounce = require('use-debounce');
44
44
  const reactDayPicker = require('react-day-picker');
45
45
  const PopoverPrimitive = require('@radix-ui/react-popover');
46
46
  const SelectPrimitive = require('@radix-ui/react-select');
@@ -48,18 +48,20 @@ const uuid = require('@lukeed/uuid');
48
48
  const LabelPrimitive = require('@radix-ui/react-label');
49
49
  const v4 = require('@autoform/zod/v4');
50
50
  const v3 = require('zod/v3');
51
- const reactCodeBlock = require('react-code-block');
52
- const SliderPrimitive = require('@radix-ui/react-slider');
53
51
  const RadioGroupPrimitive = require('@radix-ui/react-radio-group');
52
+ const react$2 = require('@mastra/react');
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');
59
- const react$3 = require('motion/react');
58
+ const clientJs = require('@mastra/client-js');
59
+ const react$4 = 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,43 +90,19 @@ 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
 
103
- const createMastraClient = (baseUrl, mastraClientHeaders = {}) => {
104
- return new clientJs.MastraClient({
105
- baseUrl: baseUrl || "",
106
- // only add the header if the baseUrl is not provided i.e it's a local dev environment
107
- headers: !baseUrl ? { ...mastraClientHeaders, "x-mastra-dev-playground": "true" } : mastraClientHeaders
108
- });
109
- };
110
-
111
- const MastraClientContext = React.createContext(void 0);
112
- const MastraClientProvider = ({
113
- children,
114
- baseUrl,
115
- headers
116
- }) => {
117
- const client = createMastraClient(baseUrl, headers);
118
- return /* @__PURE__ */ jsxRuntime.jsx(MastraClientContext.Provider, { value: { client }, children });
119
- };
120
- const useMastraClient = () => {
121
- const context = React.useContext(MastraClientContext);
122
- if (context === void 0) {
123
- throw new Error("useMastraClient must be used within a MastraClientProvider");
124
- }
125
- return context.client;
126
- };
127
-
128
106
  function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
129
107
 
130
108
  const falsyToString = (value)=>typeof value === "boolean" ? `${value}` : value === 0 ? "0" : value;
@@ -4538,244 +4516,254 @@ const ToolBadge = ({ toolName, args, result, networkMetadata, toolOutput }) => {
4538
4516
  );
4539
4517
  };
4540
4518
 
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"
4519
+ function convertWorkflowRunStateToWatchResult(runState) {
4520
+ const runId = runState.runId;
4521
+ const steps = {};
4522
+ const context = runState.context || {};
4523
+ Object.entries(context).forEach(([stepId, stepResult]) => {
4524
+ if (stepId !== "input" && "status" in stepResult) {
4525
+ const result = stepResult;
4526
+ steps[stepId] = {
4527
+ status: result.status,
4528
+ output: "output" in result ? result.output : void 0,
4529
+ payload: "payload" in result ? result.payload : void 0,
4530
+ resumePayload: "resumePayload" in result ? result.resumePayload : void 0,
4531
+ error: "error" in result ? result.error : void 0,
4532
+ startedAt: "startedAt" in result ? result.startedAt : Date.now(),
4533
+ endedAt: "endedAt" in result ? result.endedAt : void 0,
4534
+ suspendedAt: "suspendedAt" in result ? result.suspendedAt : void 0,
4535
+ resumedAt: "resumedAt" in result ? result.resumedAt : void 0
4536
+ };
4553
4537
  }
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
4538
  });
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;
4539
+ const status = determineWorkflowStatus(steps);
4540
+ return {
4541
+ type: "watch",
4542
+ payload: {
4543
+ workflowState: {
4544
+ status,
4545
+ steps,
4546
+ result: runState.value,
4547
+ payload: context.input,
4548
+ error: void 0
4549
+ }
4550
+ },
4551
+ eventTimestamp: new Date(runState.timestamp),
4552
+ runId
4553
+ };
4554
+ }
4555
+ function determineWorkflowStatus(steps) {
4556
+ const stepStatuses = Object.values(steps).map((step) => step.status);
4557
+ if (stepStatuses.includes("failed")) {
4558
+ return "failed";
4559
+ }
4560
+ if (stepStatuses.includes("suspended")) {
4561
+ return "suspended";
4562
+ }
4563
+ if (stepStatuses.every((status) => status === "success")) {
4564
+ return "success";
4565
+ }
4566
+ return "running";
4567
+ }
4568
+ const mapWorkflowStreamChunkToWatchResult = (prev, chunk) => {
4569
+ if (chunk.type === "workflow-start") {
4570
+ return {
4571
+ ...prev,
4572
+ runId: chunk.runId,
4573
+ eventTimestamp: /* @__PURE__ */ new Date(),
4574
+ payload: {
4575
+ ...prev?.payload || {},
4576
+ workflowState: {
4577
+ ...prev?.payload?.workflowState,
4578
+ status: "running",
4579
+ steps: {}
4589
4580
  }
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
4581
  }
4610
4582
  };
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
- );
4583
+ }
4584
+ if (chunk.type === "workflow-step-start") {
4585
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4586
+ return {
4587
+ ...prev,
4588
+ payload: {
4589
+ ...prev.payload,
4590
+ currentStep: {
4591
+ id: chunk.payload.id,
4592
+ ...chunk.payload
4593
+ },
4594
+ workflowState: {
4595
+ ...prev?.payload?.workflowState,
4596
+ steps: {
4597
+ ...prev?.payload?.workflowState?.steps,
4598
+ [chunk.payload.id]: {
4599
+ ...current || {},
4600
+ ...chunk.payload
4601
+ }
4602
+ }
4662
4603
  }
4663
- acc[key] = { ...value, output };
4664
- return acc;
4665
4604
  },
4666
- {}
4667
- );
4668
- const sanitizedRecord = {
4669
- ...record,
4670
- sanitizedOutput: record ? JSON.stringify({ ...record, results: formattedResults }, null, 2).slice(0, 5e4) : null
4605
+ eventTimestamp: /* @__PURE__ */ new Date()
4671
4606
  };
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
- };
4721
- 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");
4607
+ }
4608
+ if (chunk.type === "workflow-step-suspended") {
4609
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4610
+ return {
4611
+ ...prev,
4612
+ payload: {
4613
+ ...prev?.payload,
4614
+ currentStep: {
4615
+ id: chunk.payload.id,
4616
+ ...prev?.payload?.currentStep,
4617
+ ...chunk.payload
4618
+ },
4619
+ workflowState: {
4620
+ ...prev?.payload?.workflowState,
4621
+ status: "suspended",
4622
+ steps: {
4623
+ ...prev?.payload?.workflowState?.steps,
4624
+ [chunk.payload.id]: {
4625
+ ...current || {},
4626
+ ...chunk.payload
4627
+ }
4628
+ }
4758
4629
  }
4759
- }
4760
- if ("or" in group2) {
4761
- for (const subGroup of group2.or) {
4762
- recurse({ ...subGroup }, "or");
4630
+ },
4631
+ eventTimestamp: /* @__PURE__ */ new Date()
4632
+ };
4633
+ }
4634
+ if (chunk.type === "workflow-step-waiting") {
4635
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4636
+ return {
4637
+ ...prev,
4638
+ payload: {
4639
+ ...prev?.payload,
4640
+ currentStep: {
4641
+ id: chunk.payload.id,
4642
+ ...prev?.payload?.currentStep || {},
4643
+ ...chunk.payload
4644
+ },
4645
+ workflowState: {
4646
+ ...prev?.payload?.workflowState,
4647
+ status: "waiting",
4648
+ steps: {
4649
+ ...prev?.payload?.workflowState?.steps,
4650
+ [chunk.payload.id]: {
4651
+ ...current,
4652
+ ...chunk.payload
4653
+ }
4654
+ }
4763
4655
  }
4764
- }
4765
- if ("not" in group2) {
4766
- recurse({ ...group2.not }, "not");
4767
- }
4768
- }
4656
+ },
4657
+ eventTimestamp: /* @__PURE__ */ new Date()
4658
+ };
4769
4659
  }
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, {
4660
+ if (chunk.type === "workflow-step-result") {
4661
+ const status = chunk.payload.status;
4662
+ const current = prev?.payload?.workflowState?.steps?.[chunk.payload.id] || {};
4663
+ const next = {
4664
+ ...prev,
4665
+ payload: {
4666
+ ...prev?.payload,
4667
+ currentStep: {
4668
+ id: chunk.payload.id,
4669
+ ...prev?.payload?.currentStep || {},
4670
+ ...chunk.payload
4671
+ },
4672
+ workflowState: {
4673
+ ...prev?.payload?.workflowState,
4674
+ status,
4675
+ steps: {
4676
+ ...prev?.payload?.workflowState?.steps,
4677
+ [chunk.payload.id]: {
4678
+ ...current,
4679
+ ...chunk.payload
4680
+ }
4681
+ }
4682
+ }
4683
+ },
4684
+ eventTimestamp: /* @__PURE__ */ new Date()
4685
+ };
4686
+ return next;
4687
+ }
4688
+ if (chunk.type === "workflow-canceled") {
4689
+ return {
4690
+ ...prev,
4691
+ payload: {
4692
+ ...prev?.payload,
4693
+ workflowState: {
4694
+ ...prev?.payload?.workflowState,
4695
+ status: "canceled"
4696
+ }
4697
+ },
4698
+ eventTimestamp: /* @__PURE__ */ new Date()
4699
+ };
4700
+ }
4701
+ if (chunk.type === "workflow-finish") {
4702
+ return {
4703
+ ...prev,
4704
+ payload: {
4705
+ ...prev?.payload,
4706
+ currentStep: void 0,
4707
+ workflowState: {
4708
+ ...prev?.payload?.workflowState,
4709
+ status: chunk.payload.workflowStatus
4710
+ }
4711
+ },
4712
+ eventTimestamp: /* @__PURE__ */ new Date()
4713
+ };
4714
+ }
4715
+ return prev;
4716
+ };
4717
+
4718
+ const WorkflowRunContext = React.createContext({});
4719
+ function WorkflowRunProvider({
4720
+ children,
4721
+ snapshot
4722
+ }) {
4723
+ const [result, setResult] = React.useState(
4724
+ () => snapshot ? convertWorkflowRunStateToWatchResult(snapshot) : null
4725
+ );
4726
+ const [payload, setPayload] = React.useState(null);
4727
+ const clearData = () => {
4728
+ setResult(null);
4729
+ setPayload(null);
4730
+ };
4731
+ React.useEffect(() => {
4732
+ if (snapshot?.runId) {
4733
+ setResult(convertWorkflowRunStateToWatchResult(snapshot));
4734
+ }
4735
+ }, [snapshot]);
4736
+ return /* @__PURE__ */ jsxRuntime.jsx(
4737
+ WorkflowRunContext.Provider,
4738
+ {
4739
+ value: {
4740
+ result,
4741
+ setResult,
4742
+ payload,
4743
+ setPayload,
4744
+ clearData,
4745
+ snapshot
4746
+ },
4747
+ children
4748
+ }
4749
+ );
4750
+ }
4751
+
4752
+ function Skeleton({ className, ...props }) {
4753
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("animate-pulse rounded-md bg-muted/50", className), ...props });
4754
+ }
4755
+
4756
+ const lodashTitleCase = (str) => {
4757
+ const camelCased = str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : "").replace(/^(.)/, (char) => char.toLowerCase());
4758
+ return camelCased.replace(/([A-Z])/g, " $1").replace(/^./, (str2) => str2.toUpperCase()).trim();
4759
+ };
4760
+
4761
+ const getLayoutedElements = (nodes, edges) => {
4762
+ const g = new Dagre.graphlib.Graph().setDefaultEdgeLabel(() => ({}));
4763
+ g.setGraph({ rankdir: "TB" });
4764
+ edges.forEach((edge) => g.setEdge(edge.source, edge.target));
4765
+ nodes.forEach(
4766
+ (node) => g.setNode(node.id, {
4779
4767
  ...node,
4780
4768
  width: node.measured?.width ?? 274,
4781
4769
  height: node.measured?.height ?? (node?.data?.isLarge ? 260 : 100)
@@ -4807,281 +4795,6 @@ const defaultEdgeOptions = {
4807
4795
  color: "#8e8e8e"
4808
4796
  }
4809
4797
  };
4810
- const contructLegacyNodesAndEdges = ({
4811
- stepGraph,
4812
- stepSubscriberGraph,
4813
- steps: mainSteps = {}
4814
- }) => {
4815
- if (!stepGraph) {
4816
- return { nodes: [], edges: [] };
4817
- }
4818
- const { initial, ...stepsList } = stepGraph;
4819
- if (!initial.length) {
4820
- return { nodes: [], edges: [] };
4821
- }
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
4882
- }
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 };
4898
- }
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;
4935
- }
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
- }
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;
4969
- }
4970
- }
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
- }
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
5009
- }
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
- }
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
5052
- }
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
- }
5080
- }
5081
- }
5082
- const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(nodes, edges);
5083
- return { nodes: layoutedNodes, edges: layoutedEdges };
5084
- };
5085
4798
  const getStepNodeAndEdge = ({
5086
4799
  stepFlow,
5087
4800
  xIndex,
@@ -5518,257 +5231,20 @@ const ScrollBar = React__namespace.forwardRef(({ className, orientation = "verti
5518
5231
  ));
5519
5232
  ScrollBar.displayName = ScrollAreaPrimitive__namespace.ScrollAreaScrollbar.displayName;
5520
5233
 
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") {
5234
+ const useCurrentRun = () => {
5235
+ const context = React.useContext(WorkflowRunContext);
5236
+ const workflowCurrentSteps = context.result?.payload?.workflowState?.steps ?? {};
5237
+ const steps = Object.entries(workflowCurrentSteps).reduce((acc, [key, value]) => {
5572
5238
  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
5239
+ ...acc,
5240
+ [key]: {
5241
+ error: value.error,
5242
+ startedAt: value.startedAt,
5243
+ endedAt: value.endedAt,
5244
+ status: value.status,
5245
+ output: value.output,
5246
+ input: value.payload,
5247
+ resumeData: value.resumePayload
5772
5248
  }
5773
5249
  };
5774
5250
  }, {});
@@ -6323,23 +5799,84 @@ function Spinner({ color = "#fff", className }) {
6323
5799
  );
6324
5800
  }
6325
5801
 
6326
- function LegacyWorkflowNestedGraph({
5802
+ const Slider = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
5803
+ SliderPrimitive__namespace.Root,
5804
+ {
5805
+ ref,
5806
+ className: cn("relative flex w-full touch-none select-none items-center", className),
5807
+ ...props,
5808
+ children: [
5809
+ /* @__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" }) }),
5810
+ /* @__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" })
5811
+ ]
5812
+ }
5813
+ ));
5814
+ Slider.displayName = SliderPrimitive__namespace.Root.displayName;
5815
+
5816
+ const ZoomSlider = React.forwardRef(({ className, ...props }) => {
5817
+ const { zoom } = react.useViewport();
5818
+ const { zoomTo, zoomIn, zoomOut, fitView } = react.useReactFlow();
5819
+ return /* @__PURE__ */ jsxRuntime.jsxs(react.Panel, { className: cn("flex gap-1 rounded-md bg-primary-foreground p-1 text-foreground", className), ...props, children: [
5820
+ /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomOut({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Minus, { className: "h-4 w-4" }) }),
5821
+ /* @__PURE__ */ jsxRuntime.jsx(
5822
+ Slider,
5823
+ {
5824
+ className: "w-[140px]",
5825
+ value: [zoom],
5826
+ min: 0.01,
5827
+ max: 1,
5828
+ step: 0.01,
5829
+ onValueChange: (values) => {
5830
+ zoomTo(values[0]);
5831
+ }
5832
+ }
5833
+ ),
5834
+ /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", size: "icon", onClick: () => zoomIn({ duration: 300 }), children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }) }),
5835
+ /* @__PURE__ */ jsxRuntime.jsxs(Button$2, { className: "min-w-20 tabular-nums", variant: "ghost", onClick: () => zoomTo(1, { duration: 300 }), children: [
5836
+ (100 * zoom).toFixed(0),
5837
+ "%"
5838
+ ] }),
5839
+ /* @__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" }) })
5840
+ ] });
5841
+ });
5842
+ ZoomSlider.displayName = "ZoomSlider";
5843
+
5844
+ function WorkflowNestedGraph({
6327
5845
  stepGraph,
6328
- stepSubscriberGraph,
6329
- open
5846
+ open,
5847
+ workflowName,
5848
+ onShowTrace,
5849
+ onSendEvent
6330
5850
  }) {
6331
- const { nodes: initialNodes, edges: initialEdges } = contructLegacyNodesAndEdges({
6332
- stepGraph,
6333
- stepSubscriberGraph
5851
+ const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges({
5852
+ stepGraph
6334
5853
  });
6335
5854
  const [isMounted, setIsMounted] = React.useState(false);
6336
5855
  const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
6337
5856
  const [edges] = react.useEdgesState(initialEdges);
5857
+ const { steps } = useCurrentRun();
6338
5858
  const nodeTypes = {
6339
- "default-node": WorkflowDefaultNode,
5859
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
5860
+ WorkflowDefaultNode,
5861
+ {
5862
+ parentWorkflowName: workflowName,
5863
+ onShowTrace,
5864
+ onSendEvent,
5865
+ ...props
5866
+ }
5867
+ ),
6340
5868
  "condition-node": WorkflowConditionNode,
6341
5869
  "after-node": WorkflowAfterNode,
6342
- "loop-result-node": WorkflowLoopResultNode
5870
+ "loop-result-node": WorkflowLoopResultNode,
5871
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(
5872
+ WorkflowNestedNode,
5873
+ {
5874
+ parentWorkflowName: workflowName,
5875
+ onShowTrace,
5876
+ onSendEvent,
5877
+ ...props
5878
+ }
5879
+ )
6343
5880
  };
6344
5881
  React.useEffect(() => {
6345
5882
  if (open) {
@@ -6348,49 +5885,75 @@ function LegacyWorkflowNestedGraph({
6348
5885
  }, 500);
6349
5886
  }
6350
5887
  }, [open]);
6351
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full relative", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(
5888
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full relative bg-surface1", children: isMounted ? /* @__PURE__ */ jsxRuntime.jsxs(
6352
5889
  react.ReactFlow,
6353
5890
  {
6354
5891
  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 })
5892
+ edges: edges.map((e) => ({
5893
+ ...e,
5894
+ style: {
5895
+ ...e.style,
5896
+ 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
5897
+ }
5898
+ })),
5899
+ fitView: true,
5900
+ fitViewOptions: {
5901
+ maxZoom: 1
5902
+ },
5903
+ minZoom: 0.01,
5904
+ maxZoom: 1,
5905
+ nodeTypes,
5906
+ onNodesChange,
5907
+ children: [
5908
+ /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
5909
+ /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Lines, gap: 12, size: 0.5 })
6363
5910
  ]
6364
5911
  }
6365
5912
  ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) });
6366
5913
  }
6367
5914
 
6368
- const LegacyWorkflowNestedGraphContext = React.createContext(
5915
+ const WorkflowNestedGraphContext = React.createContext(
6369
5916
  {}
6370
5917
  );
6371
- function LegacyWorkflowNestedGraphProvider({ children }) {
5918
+ function WorkflowNestedGraphProvider({
5919
+ children,
5920
+ onShowTrace,
5921
+ onSendEvent
5922
+ }) {
6372
5923
  const [stepGraph, setStepGraph] = React.useState(null);
6373
- const [stepSubscriberGraph, setStepSubscriberGraph] = React.useState(null);
5924
+ const [parentStepGraphList, setParentStepGraphList] = React.useState([]);
6374
5925
  const [openDialog, setOpenDialog] = React.useState(false);
6375
5926
  const [label, setLabel] = React.useState("");
5927
+ const [fullStep, setFullStep] = React.useState("");
6376
5928
  const closeNestedGraph = () => {
6377
- setOpenDialog(false);
6378
- setStepGraph(null);
6379
- setStepSubscriberGraph(null);
6380
- setLabel("");
5929
+ if (parentStepGraphList.length) {
5930
+ const lastStepGraph = parentStepGraphList[parentStepGraphList.length - 1];
5931
+ setStepGraph(lastStepGraph.stepGraph);
5932
+ setLabel(lastStepGraph.label);
5933
+ setFullStep(lastStepGraph.fullStep);
5934
+ setParentStepGraphList(parentStepGraphList.slice(0, -1));
5935
+ } else {
5936
+ setOpenDialog(false);
5937
+ setStepGraph(null);
5938
+ setLabel("");
5939
+ setFullStep("");
5940
+ }
6381
5941
  };
6382
5942
  const showNestedGraph = ({
6383
- label: label2,
6384
- stepGraph: stepGraph2,
6385
- stepSubscriberGraph: stepSubscriberGraph2
5943
+ label: newLabel,
5944
+ stepGraph: newStepGraph,
5945
+ fullStep: newFullStep
6386
5946
  }) => {
6387
- setLabel(label2);
6388
- setStepGraph(stepGraph2);
6389
- setStepSubscriberGraph(stepSubscriberGraph2);
5947
+ if (stepGraph) {
5948
+ setParentStepGraphList([...parentStepGraphList, { stepGraph, label, fullStep }]);
5949
+ }
5950
+ setLabel(newLabel);
5951
+ setFullStep(newFullStep);
5952
+ setStepGraph(newStepGraph);
6390
5953
  setOpenDialog(true);
6391
5954
  };
6392
5955
  return /* @__PURE__ */ jsxRuntime.jsxs(
6393
- LegacyWorkflowNestedGraphContext.Provider,
5956
+ WorkflowNestedGraphContext.Provider,
6394
5957
  {
6395
5958
  value: {
6396
5959
  showNestedGraph,
@@ -6398,8 +5961,8 @@ function LegacyWorkflowNestedGraphProvider({ children }) {
6398
5961
  },
6399
5962
  children: [
6400
5963
  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: [
5964
+ /* @__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: [
5965
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: "flex items-center gap-1.5 absolute top-3 left-3 z-50", children: [
6403
5966
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Workflow, { className: "text-current w-4 h-4" }),
6404
5967
  /* @__PURE__ */ jsxRuntime.jsxs(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: [
6405
5968
  label,
@@ -6407,77 +5970,131 @@ function LegacyWorkflowNestedGraphProvider({ children }) {
6407
5970
  ] })
6408
5971
  ] }),
6409
5972
  /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
6410
- LegacyWorkflowNestedGraph,
5973
+ WorkflowNestedGraph,
6411
5974
  {
6412
5975
  stepGraph,
6413
5976
  open: openDialog,
6414
- stepSubscriberGraph
5977
+ workflowName: fullStep,
5978
+ onShowTrace,
5979
+ onSendEvent
6415
5980
  }
6416
5981
  ) })
6417
- ] }) }) })
5982
+ ] }) }) }, `${label}-${fullStep}`)
6418
5983
  ]
6419
5984
  }
6420
5985
  );
6421
5986
  }
6422
5987
 
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: [
5988
+ function WorkflowNestedNode({
5989
+ data,
5990
+ parentWorkflowName,
5991
+ onShowTrace,
5992
+ onSendEvent
5993
+ }) {
5994
+ const { steps, runId } = useCurrentRun();
5995
+ const { showNestedGraph } = React.useContext(WorkflowNestedGraphContext);
5996
+ const { label, description, withoutTopHandle, withoutBottomHandle, stepGraph, mapConfig, event } = data;
5997
+ const fullLabel = parentWorkflowName ? `${parentWorkflowName}.${label}` : label;
5998
+ const step = steps[fullLabel];
5999
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6427
6000
  !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
- ] }) }),
6001
+ /* @__PURE__ */ jsxRuntime.jsxs(
6002
+ "div",
6003
+ {
6004
+ className: cn(
6005
+ "bg-surface3 rounded-lg w-[274px] border-sm border-border1 pt-2",
6006
+ step?.status === "success" && "bg-accent1Darker",
6007
+ step?.status === "failed" && "bg-accent2Darker",
6008
+ step?.status === "suspended" && "bg-accent3Darker",
6009
+ step?.status === "waiting" && "bg-accent5Darker",
6010
+ step?.status === "running" && "bg-accent6Darker"
6011
+ ),
6012
+ children: [
6013
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-2 px-3", !description && "pb-2"), children: [
6014
+ /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
6015
+ step?.status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
6016
+ step?.status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
6017
+ step?.status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PauseIcon, { className: "text-accent3" }),
6018
+ step?.status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
6019
+ step?.status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" }),
6020
+ !step && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleDashed, { className: "text-icon2" })
6021
+ ] }),
6022
+ /* @__PURE__ */ jsxRuntime.jsxs(Txt, { variant: "ui-lg", className: "text-icon6 font-medium inline-flex items-center gap-1 justify-between w-full", children: [
6023
+ label,
6024
+ " ",
6025
+ step?.startedAt && /* @__PURE__ */ jsxRuntime.jsx(Clock, { startedAt: step.startedAt, endedAt: step.endedAt })
6026
+ ] })
6027
+ ] }),
6028
+ description && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-icon3 px-3 pb-2", children: description }),
6029
+ /* @__PURE__ */ jsxRuntime.jsx(
6030
+ WorkflowStepActionBar,
6031
+ {
6032
+ stepName: label,
6033
+ input: step?.input,
6034
+ resumeData: step?.resumeData,
6035
+ output: step?.output,
6036
+ error: step?.error,
6037
+ mapConfig,
6038
+ onShowTrace: runId && onShowTrace ? () => onShowTrace?.({ runId, stepName: fullLabel }) : void 0,
6039
+ onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
6040
+ onSendEvent,
6041
+ event: step?.status === "waiting" ? event : void 0,
6042
+ runId,
6043
+ status: step?.status
6044
+ }
6045
+ )
6046
+ ]
6047
+ }
6048
+ ),
6432
6049
  !withoutBottomHandle && /* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { visibility: "hidden" } })
6433
6050
  ] });
6434
6051
  }
6435
6052
 
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
- });
6053
+ function WorkflowGraphInner({ workflow, onShowTrace, onSendEvent }) {
6054
+ const { nodes: initialNodes, edges: initialEdges } = constructNodesAndEdges(workflow);
6442
6055
  const [nodes, _, onNodesChange] = react.useNodesState(initialNodes);
6443
6056
  const [edges] = react.useEdgesState(initialEdges);
6057
+ const { steps, runId } = useCurrentRun();
6444
6058
  const nodeTypes = {
6445
- "default-node": WorkflowDefaultNode,
6059
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { onShowTrace, onSendEvent, ...props }),
6446
6060
  "condition-node": WorkflowConditionNode,
6447
6061
  "after-node": WorkflowAfterNode,
6448
6062
  "loop-result-node": WorkflowLoopResultNode,
6449
- "nested-node": LegacyWorkflowNestedNode
6063
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { onShowTrace, onSendEvent, ...props })
6450
6064
  };
6451
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full", children: /* @__PURE__ */ jsxRuntime.jsxs(
6065
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs(
6452
6066
  react.ReactFlow,
6453
6067
  {
6454
6068
  nodes,
6455
- edges,
6069
+ edges: edges.map((e) => ({
6070
+ ...e,
6071
+ style: {
6072
+ ...e.style,
6073
+ 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
6074
+ }
6075
+ })),
6456
6076
  nodeTypes,
6457
6077
  onNodesChange,
6458
6078
  fitView: true,
6459
6079
  fitViewOptions: {
6460
- maxZoom: 0.85
6080
+ maxZoom: 1
6461
6081
  },
6082
+ minZoom: 0.01,
6083
+ maxZoom: 1,
6462
6084
  children: [
6463
- /* @__PURE__ */ jsxRuntime.jsx(react.Controls, {}),
6085
+ /* @__PURE__ */ jsxRuntime.jsx(ZoomSlider, { position: "bottom-left" }),
6464
6086
  /* @__PURE__ */ jsxRuntime.jsx(react.Background, { variant: react.BackgroundVariant.Dots, gap: 12, size: 0.5 })
6465
6087
  ]
6466
6088
  }
6467
6089
  ) });
6468
6090
  }
6469
6091
 
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);
6092
+ function WorkflowGraph({ workflowId, onShowTrace, workflow, isLoading, onSendEvent }) {
6093
+ const { snapshot } = React.useContext(WorkflowRunContext);
6477
6094
  if (isLoading) {
6478
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-[600px]" }) });
6095
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-full" }) });
6479
6096
  }
6480
- if (!legacyWorkflow) {
6097
+ if (!workflow) {
6481
6098
  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
6099
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, {}),
6483
6100
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
@@ -6487,9 +6104,95 @@ function LegacyWorkflowGraph({ workflowId }) {
6487
6104
  ] })
6488
6105
  ] }) });
6489
6106
  }
6490
- return /* @__PURE__ */ jsxRuntime.jsx(LegacyWorkflowNestedGraphProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(LegacyWorkflowGraphInner, { workflow: legacyWorkflow }) }) });
6107
+ return /* @__PURE__ */ jsxRuntime.jsx(
6108
+ WorkflowNestedGraphProvider,
6109
+ {
6110
+ onShowTrace,
6111
+ onSendEvent,
6112
+ children: /* @__PURE__ */ jsxRuntime.jsx(react.ReactFlowProvider, { children: /* @__PURE__ */ jsxRuntime.jsx(
6113
+ WorkflowGraphInner,
6114
+ {
6115
+ workflow: snapshot?.serializedStepGraph ? { stepGraph: snapshot?.serializedStepGraph } : workflow,
6116
+ onShowTrace,
6117
+ onSendEvent
6118
+ }
6119
+ ) })
6120
+ },
6121
+ snapshot?.runId ?? workflowId
6122
+ );
6123
+ }
6124
+
6125
+ function resolveSerializedZodOutput(obj) {
6126
+ return Function("z", `"use strict";return (${obj});`)(z.z);
6127
+ }
6128
+
6129
+ function CodeBlockDemo({
6130
+ code = "",
6131
+ language = "ts",
6132
+ filename,
6133
+ className
6134
+ }) {
6135
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactCodeBlock.CodeBlock, { code, language, theme: prismReactRenderer.themes.oneDark, children: [
6136
+ 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,
6137
+ /* @__PURE__ */ jsxRuntime.jsx(
6138
+ reactCodeBlock.CodeBlock.Code,
6139
+ {
6140
+ className: cn("bg-transparent h-full p-6 rounded-xl whitespace-pre-wrap", filename ? "pt-10" : "", className),
6141
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "table-row", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center", children: [
6142
+ /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineNumber, { className: "table-cell pr-4 text-sm text-right select-none text-gray-500/50" }),
6143
+ /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.LineContent, { className: "flex", children: /* @__PURE__ */ jsxRuntime.jsx(reactCodeBlock.CodeBlock.Token, { className: "font-mono text-sm mastra-token" }) })
6144
+ ] }) })
6145
+ }
6146
+ )
6147
+ ] });
6491
6148
  }
6492
6149
 
6150
+ const usePlaygroundStore = zustand.create()(
6151
+ middleware.persist(
6152
+ (set) => ({
6153
+ runtimeContext: {},
6154
+ setRuntimeContext: (runtimeContext) => set({ runtimeContext })
6155
+ }),
6156
+ {
6157
+ name: "mastra-playground-store"
6158
+ }
6159
+ )
6160
+ );
6161
+
6162
+ const WorkflowCard = ({ header, children, footer }) => {
6163
+ const [expanded, setExpanded] = React.useState(false);
6164
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border-sm border-border1 bg-surface4", children: [
6165
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "py-1 px-2 flex items-center gap-3 justify-between w-full", onClick: () => setExpanded((s) => !s), children: [
6166
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full", children: header }),
6167
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: cn("text-icon3 transition-transform -rotate-90", expanded && "rotate-0") }) })
6168
+ ] }),
6169
+ children && expanded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t-sm border-border1", children }),
6170
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-1 px-2 border-t-sm border-border1", children: footer })
6171
+ ] });
6172
+ };
6173
+
6174
+ const WorkflowStatus = ({ stepId, status, result }) => {
6175
+ return /* @__PURE__ */ jsxRuntime.jsx(
6176
+ WorkflowCard,
6177
+ {
6178
+ header: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
6179
+ /* @__PURE__ */ jsxRuntime.jsxs(Icon, { children: [
6180
+ status === "success" && /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "text-accent1" }),
6181
+ status === "failed" && /* @__PURE__ */ jsxRuntime.jsx(CrossIcon, { className: "text-accent2" }),
6182
+ status === "suspended" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CirclePause, { className: "text-accent3" }),
6183
+ status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.HourglassIcon, { className: "text-accent5" }),
6184
+ status === "running" && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2, { className: "text-accent6 animate-spin" })
6185
+ ] }),
6186
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-lg", className: "text-icon6 font-medium", children: stepId.charAt(0).toUpperCase() + stepId.slice(1) })
6187
+ ] }),
6188
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md bg-surface4 p-1 font-mono relative", children: [
6189
+ /* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: JSON.stringify(result, null, 2), className: "absolute top-2 right-2 z-10" }),
6190
+ /* @__PURE__ */ jsxRuntime.jsx(SyntaxHighlighter$1, { data: result })
6191
+ ] })
6192
+ }
6193
+ );
6194
+ };
6195
+
6493
6196
  const Form = React.forwardRef(({ children, ...props }, ref) => {
6494
6197
  return /* @__PURE__ */ jsxRuntime.jsx("form", { ref, className: "space-y-4", ...props, children });
6495
6198
  });
@@ -7322,592 +7025,12 @@ function DynamicForm({
7322
7025
  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
7026
  },
7324
7027
  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
- ] })
7908
- }
7909
- );
7910
- };
7028
+ Label: ({ value }) => /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-sm font-normal", children: value })
7029
+ },
7030
+ withSubmit: true
7031
+ };
7032
+ return /* @__PURE__ */ jsxRuntime.jsx(AutoForm, { ...formProps, readOnly });
7033
+ }
7911
7034
 
7912
7035
  const RadioGroup = React__namespace.forwardRef(({ className, ...props }, ref) => {
7913
7036
  return /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Root, { className: cn("grid gap-2", className), ...props, ref });
@@ -8208,7 +7331,7 @@ const WorkflowJsonDialog = ({ result }) => {
8208
7331
  };
8209
7332
 
8210
7333
  const useWorkflowRuns = (workflowId, { enabled = true } = {}) => {
8211
- const client = useMastraClient();
7334
+ const client = react$2.useMastraClient();
8212
7335
  return reactQuery.useQuery({
8213
7336
  queryKey: ["workflow-runs", workflowId],
8214
7337
  queryFn: () => client.getWorkflow(workflowId).runs({ limit: 50 }),
@@ -8555,18 +7678,15 @@ const columns$3 = [
8555
7678
  id: "stepsCount",
8556
7679
  header: "Steps",
8557
7680
  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
- ] }) })
7681
+ 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: [
7682
+ row.original.stepsCount,
7683
+ " step",
7684
+ row.original.stepsCount > 1 ? "s" : ""
7685
+ ] }) }) })
8566
7686
  }
8567
7687
  ];
8568
7688
 
8569
- function WorkflowTable({ workflows, legacyWorkflows, isLoading }) {
7689
+ function WorkflowTable({ workflows, isLoading }) {
8570
7690
  const { navigate, paths } = useLinkComponent();
8571
7691
  const workflowData = React.useMemo(() => {
8572
7692
  const _workflowsData = Object.keys(workflows ?? {}).map((key) => {
@@ -8575,22 +7695,11 @@ function WorkflowTable({ workflows, legacyWorkflows, isLoading }) {
8575
7695
  id: key,
8576
7696
  name: workflow?.name || "N/A",
8577
7697
  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
7698
  link: paths.workflowLink(key)
8590
7699
  };
8591
7700
  });
8592
- return [..._workflowsData, ...legacyWorkflowsData];
8593
- }, [workflows, legacyWorkflows]);
7701
+ return _workflowsData;
7702
+ }, [workflows]);
8594
7703
  const table = reactTable.useReactTable({
8595
7704
  data: workflowData,
8596
7705
  columns: columns$3,
@@ -8686,6 +7795,19 @@ const useWorkflowStream = (workflowFullState) => {
8686
7795
  }, [workflowFullState]);
8687
7796
  };
8688
7797
 
7798
+ const useWorkflow = (workflowId) => {
7799
+ const client = react$2.useMastraClient();
7800
+ const { runtimeContext } = usePlaygroundStore();
7801
+ return reactQuery.useQuery({
7802
+ queryKey: ["workflow", workflowId],
7803
+ queryFn: () => workflowId ? client.getWorkflow(workflowId).details(runtimeContext) : null,
7804
+ enabled: Boolean(workflowId),
7805
+ retry: false,
7806
+ refetchOnWindowFocus: false,
7807
+ throwOnError: false
7808
+ });
7809
+ };
7810
+
8689
7811
  const LoadingBadge = () => {
8690
7812
  return /* @__PURE__ */ jsxRuntime.jsx(
8691
7813
  BadgeWrapper,
@@ -8791,13 +7913,15 @@ const Reasoning = ({ text }) => {
8791
7913
  ] });
8792
7914
  };
8793
7915
 
8794
- const AssistantMessage = ({ ToolFallback: ToolFallbackCustom }) => {
8795
- const data = react$2.useMessage();
7916
+ const AssistantMessage = ({ ToolFallback: ToolFallbackCustom, hasModelList }) => {
7917
+ const data = react$3.useMessage();
8796
7918
  const messageId = data.id;
8797
7919
  const isToolCallAndOrReasoning = data.content.every(({ type }) => type === "tool-call" || type === "reasoning");
8798
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.MessagePrimitive.Root, { className: "max-w-full", "data-message-id": messageId, children: [
7920
+ const modelMetadata = data.metadata?.custom?.modelMetadata;
7921
+ const showModelUsed = hasModelList && modelMetadata;
7922
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.MessagePrimitive.Root, { className: "max-w-full", "data-message-id": messageId, children: [
8799
7923
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon6 text-ui-lg leading-ui-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
8800
- react$2.MessagePrimitive.Parts,
7924
+ react$3.MessagePrimitive.Parts,
8801
7925
  {
8802
7926
  components: {
8803
7927
  Text: MarkdownText,
@@ -8806,23 +7930,33 @@ const AssistantMessage = ({ ToolFallback: ToolFallbackCustom }) => {
8806
7930
  }
8807
7931
  }
8808
7932
  ) }),
8809
- !isToolCallAndOrReasoning && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 pt-1", children: /* @__PURE__ */ jsxRuntime.jsx(AssistantActionBar$1, {}) })
7933
+ !isToolCallAndOrReasoning && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("h-6 pt-1 flex gap-2 items-center", { "pb-1": showModelUsed }), children: [
7934
+ showModelUsed && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7935
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.BrainIcon, { className: "size-4" }),
7936
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-sm leading-ui-sm text-icon6", children: [
7937
+ modelMetadata.modelProvider,
7938
+ "/",
7939
+ modelMetadata.modelId
7940
+ ] })
7941
+ ] }),
7942
+ /* @__PURE__ */ jsxRuntime.jsx(AssistantActionBar$1, {})
7943
+ ] })
8810
7944
  ] });
8811
7945
  };
8812
7946
  const AssistantActionBar$1 = () => {
8813
7947
  return /* @__PURE__ */ jsxRuntime.jsxs(
8814
- react$2.ActionBarPrimitive.Root,
7948
+ react$3.ActionBarPrimitive.Root,
8815
7949
  {
8816
7950
  hideWhenRunning: true,
8817
7951
  autohide: "always",
8818
7952
  autohideFloat: "single-branch",
8819
7953
  className: "flex gap-1 items-center transition-all relative",
8820
7954
  children: [
8821
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { speaking: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ActionBarPrimitive.Speak, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Read aloud", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AudioLinesIcon, {}) }) }) }),
8822
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { speaking: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ActionBarPrimitive.StopSpeaking, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Stop", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.StopCircleIcon, {}) }) }) }),
8823
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", className: "bg-transparent text-icon3 hover:text-icon6", children: [
8824
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { copied: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) }),
8825
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { copied: false, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
7955
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { speaking: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ActionBarPrimitive.Speak, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Read aloud", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AudioLinesIcon, {}) }) }) }),
7956
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { speaking: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ActionBarPrimitive.StopSpeaking, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Stop", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.StopCircleIcon, {}) }) }) }),
7957
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", className: "bg-transparent text-icon3 hover:text-icon6", children: [
7958
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { copied: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) }),
7959
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { copied: false, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
8826
7960
  ] }) })
8827
7961
  ]
8828
7962
  }
@@ -8846,7 +7980,7 @@ const useFileSrc = (file) => {
8846
7980
  };
8847
7981
 
8848
7982
  const useAttachmentSrc = () => {
8849
- const { file, src } = react$2.useAttachment(
7983
+ const { file, src } = react$3.useAttachment(
8850
7984
  shallow.useShallow((a) => {
8851
7985
  if (a.file) {
8852
7986
  const isURL = a.file.name.startsWith("https://");
@@ -8906,11 +8040,11 @@ const TxtPreviewDialog = ({ data, open, onOpenChange }) => {
8906
8040
  };
8907
8041
 
8908
8042
  const InMessageContextWrapper = () => {
8909
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Root, { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[366px] px-5 py-3 text-icon6 text-ui-lg leading-ui-lg rounded-lg bg-surface3", children: /* @__PURE__ */ jsxRuntime.jsx(InMessageAttachmentWrapper, {}) }) });
8043
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Root, { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[366px] px-5 py-3 text-icon6 text-ui-lg leading-ui-lg rounded-lg bg-surface3", children: /* @__PURE__ */ jsxRuntime.jsx(InMessageAttachmentWrapper, {}) }) });
8910
8044
  };
8911
8045
  const InMessageAttachmentWrapper = () => {
8912
8046
  const src = useAttachmentSrc();
8913
- const attachment = react$2.useAttachment((a) => a);
8047
+ const attachment = react$3.useAttachment((a) => a);
8914
8048
  const isUrl = attachment?.name?.startsWith("https://");
8915
8049
  if (attachment.type === "image") {
8916
8050
  const actualSrc = isUrl ? attachment?.name : src;
@@ -8919,7 +8053,7 @@ const InMessageAttachmentWrapper = () => {
8919
8053
  {
8920
8054
  type: "image",
8921
8055
  contentType: void 0,
8922
- nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Name, {}),
8056
+ nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Name, {}),
8923
8057
  src: actualSrc,
8924
8058
  data: void 0
8925
8059
  }
@@ -8932,7 +8066,7 @@ const InMessageAttachmentWrapper = () => {
8932
8066
  {
8933
8067
  type: "document",
8934
8068
  contentType: attachment.contentType,
8935
- nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Name, {}),
8069
+ nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Name, {}),
8936
8070
  src: isUrl ? attachment?.name : src,
8937
8071
  data: `data:application/pdf;base64,${pdfText}`
8938
8072
  }
@@ -8943,7 +8077,7 @@ const InMessageAttachmentWrapper = () => {
8943
8077
  {
8944
8078
  type: attachment.type,
8945
8079
  contentType: attachment.contentType,
8946
- nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Name, {}),
8080
+ nameSlot: /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Name, {}),
8947
8081
  src,
8948
8082
  data: attachment.content?.[0]?.text
8949
8083
  }
@@ -8956,14 +8090,14 @@ const InMessageAttachment = ({ type, contentType, nameSlot, src, data }) => {
8956
8090
  ] }) });
8957
8091
  };
8958
8092
  const UserMessageAttachments = () => {
8959
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.Attachments, { components: { Attachment: InMessageContextWrapper } });
8093
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.Attachments, { components: { Attachment: InMessageContextWrapper } });
8960
8094
  };
8961
8095
  const UserMessage = () => {
8962
- const message = react$2.useMessage();
8096
+ const message = react$3.useMessage();
8963
8097
  const messageId = message?.id;
8964
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.MessagePrimitive.Root, { className: "w-full flex items-end pb-4 flex-col", "data-message-id": messageId, children: [
8098
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.MessagePrimitive.Root, { className: "w-full flex items-end pb-4 flex-col", "data-message-id": messageId, children: [
8965
8099
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[366px] px-5 py-3 text-icon6 text-ui-lg leading-ui-lg rounded-lg bg-surface3", children: /* @__PURE__ */ jsxRuntime.jsx(
8966
- react$2.MessagePrimitive.Parts,
8100
+ react$3.MessagePrimitive.Parts,
8967
8101
  {
8968
8102
  components: {
8969
8103
  File: (p) => {
@@ -9028,7 +8162,7 @@ const useSpeechRecognition = ({
9028
8162
  language = "en-US",
9029
8163
  agentId
9030
8164
  }) => {
9031
- const client = useMastraClient();
8165
+ const client = react$2.useMastraClient();
9032
8166
  const [agent, setAgent] = React.useState(null);
9033
8167
  const { runtimeContext } = usePlaygroundStore();
9034
8168
  React.useEffect(() => {
@@ -9152,7 +8286,7 @@ const useMastraSpeechToText = ({ agent }) => {
9152
8286
  };
9153
8287
 
9154
8288
  const useHasAttachments = () => {
9155
- const composer = react$2.useComposerRuntime();
8289
+ const composer = react$3.useComposerRuntime();
9156
8290
  const [hasAttachments, setHasAttachments] = React.useState(false);
9157
8291
  React.useEffect(() => {
9158
8292
  composer.subscribe(() => {
@@ -9221,22 +8355,22 @@ const ComposerPdfAttachment = ({ document }) => {
9221
8355
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full w-full", children: state.isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: "animate-spin" }) : /* @__PURE__ */ jsxRuntime.jsx(PdfEntry, { data: state.text, url: isUrl ? document.file?.name : void 0 }) });
9222
8356
  };
9223
8357
  const AttachmentThumbnail = () => {
9224
- const isImage = react$2.useAttachment((a) => a.type === "image");
9225
- const document = react$2.useAttachment((a) => a.type === "document" ? a : void 0);
8358
+ const isImage = react$3.useAttachment((a) => a.type === "image");
8359
+ const document = react$3.useAttachment((a) => a.type === "document" ? a : void 0);
9226
8360
  const src = useAttachmentSrc();
9227
- const canRemove = react$2.useAttachment((a) => a.source !== "message");
8361
+ const canRemove = react$3.useAttachment((a) => a.source !== "message");
9228
8362
  const isUrl = document?.file?.name.startsWith("https://");
9229
8363
  const actualSrc = isUrl ? document?.file?.name : src;
9230
8364
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
9231
8365
  /* @__PURE__ */ jsxRuntime.jsx(TooltipPrimitive.TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
9232
- /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden size-16 rounded-lg bg-surface3 border-sm border-border1 ", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx(ImageEntry, { src: actualSrc ?? "" }) : document?.contentType === "application/pdf" ? /* @__PURE__ */ jsxRuntime.jsx(ComposerPdfAttachment, { document }) : document ? /* @__PURE__ */ jsxRuntime.jsx(ComposerTxtAttachment, { document }) : null }) }) }),
9233
- /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Name, {}) })
8366
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Root, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-hidden size-16 rounded-lg bg-surface3 border-sm border-border1 ", children: isImage ? /* @__PURE__ */ jsxRuntime.jsx(ImageEntry, { src: actualSrc ?? "" }) : document?.contentType === "application/pdf" ? /* @__PURE__ */ jsxRuntime.jsx(ComposerPdfAttachment, { document }) : document ? /* @__PURE__ */ jsxRuntime.jsx(ComposerTxtAttachment, { document }) : null }) }) }),
8367
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", children: /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Name, {}) })
9234
8368
  ] }) }),
9235
8369
  canRemove && /* @__PURE__ */ jsxRuntime.jsx(AttachmentRemove, {})
9236
8370
  ] }) });
9237
8371
  };
9238
8372
  const AttachmentRemove = () => {
9239
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.AttachmentPrimitive.Remove, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
8373
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.AttachmentPrimitive.Remove, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
9240
8374
  TooltipIconButton,
9241
8375
  {
9242
8376
  tooltip: "Remove file",
@@ -9249,15 +8383,15 @@ const AttachmentRemove = () => {
9249
8383
  const ComposerAttachments = () => {
9250
8384
  const hasAttachments = useHasAttachments();
9251
8385
  if (!hasAttachments) return null;
9252
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-row items-center gap-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Attachments, { components: { Attachment: AttachmentThumbnail } }) });
8386
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex w-full flex-row items-center gap-4 pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Attachments, { components: { Attachment: AttachmentThumbnail } }) });
9253
8387
  };
9254
8388
 
9255
8389
  const useComposerAddAttachment = ({
9256
8390
  multiple = true,
9257
8391
  onChange
9258
8392
  } = {}) => {
9259
- const disabled = react$2.useComposer((c) => !c.isEditing);
9260
- const composerRuntime = react$2.useComposerRuntime();
8393
+ const disabled = react$3.useComposer((c) => !c.isEditing);
8394
+ const composerRuntime = react$3.useComposerRuntime();
9261
8395
  const callback = React.useCallback(() => {
9262
8396
  const input = document.createElement("input");
9263
8397
  input.type = "file";
@@ -9324,7 +8458,7 @@ const getFileContentType = async (url) => {
9324
8458
  };
9325
8459
 
9326
8460
  const AttachFileDialog = ({ onOpenChange, open }) => {
9327
- const composerRuntime = react$2.useComposerRuntime();
8461
+ const composerRuntime = react$3.useComposerRuntime();
9328
8462
  const addFilInputAttachment = useComposerAddAttachment({
9329
8463
  onChange: () => onOpenChange(false)
9330
8464
  });
@@ -9392,17 +8526,17 @@ const useThreadInput = () => {
9392
8526
  return React.useContext(ThreadInputContext);
9393
8527
  };
9394
8528
 
9395
- const Thread = ({ ToolFallback, agentName, agentId, hasMemory }) => {
8529
+ const Thread = ({ ToolFallback, agentName, agentId, hasMemory, hasModelList }) => {
9396
8530
  const areaRef = React.useRef(null);
9397
8531
  useAutoscroll(areaRef, { enabled: true });
9398
8532
  const WrappedAssistantMessage = (props) => {
9399
- return /* @__PURE__ */ jsxRuntime.jsx(AssistantMessage, { ...props, ToolFallback });
8533
+ return /* @__PURE__ */ jsxRuntime.jsx(AssistantMessage, { ...props, ToolFallback, hasModelList });
9400
8534
  };
9401
8535
  return /* @__PURE__ */ jsxRuntime.jsxs(ThreadWrapper$1, { children: [
9402
- /* @__PURE__ */ jsxRuntime.jsxs(react$2.ThreadPrimitive.Viewport, { ref: areaRef, autoScroll: false, className: "overflow-y-scroll scroll-smooth h-full", children: [
8536
+ /* @__PURE__ */ jsxRuntime.jsxs(react$3.ThreadPrimitive.Viewport, { ref: areaRef, autoScroll: false, className: "overflow-y-scroll scroll-smooth h-full", children: [
9403
8537
  /* @__PURE__ */ jsxRuntime.jsx(ThreadWelcome$1, { agentName }),
9404
8538
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[568px] w-full mx-auto px-4 pb-7", children: /* @__PURE__ */ jsxRuntime.jsx(
9405
- react$2.ThreadPrimitive.Messages,
8539
+ react$3.ThreadPrimitive.Messages,
9406
8540
  {
9407
8541
  components: {
9408
8542
  UserMessage,
@@ -9411,13 +8545,13 @@ const Thread = ({ ToolFallback, agentName, agentId, hasMemory }) => {
9411
8545
  }
9412
8546
  }
9413
8547
  ) }),
9414
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { empty: false, children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) })
8548
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { empty: false, children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) })
9415
8549
  ] }),
9416
8550
  /* @__PURE__ */ jsxRuntime.jsx(Composer$1, { hasMemory, agentId })
9417
8551
  ] });
9418
8552
  };
9419
8553
  const ThreadWrapper$1 = ({ children }) => {
9420
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.Root, { className: "grid grid-rows-[1fr_auto] h-full overflow-y-auto", children });
8554
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.Root, { className: "grid grid-rows-[1fr_auto] h-full overflow-y-auto", children });
9421
8555
  };
9422
8556
  const ThreadWelcome$1 = ({ agentName }) => {
9423
8557
  const safeAgentName = agentName ?? "";
@@ -9430,7 +8564,7 @@ const ThreadWelcome$1 = ({ agentName }) => {
9430
8564
  } else {
9431
8565
  initials = "A";
9432
8566
  }
9433
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.Empty, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-grow flex-col items-center justify-center", children: [
8567
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.Empty, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-grow flex-col items-center justify-center", children: [
9434
8568
  /* @__PURE__ */ jsxRuntime.jsx(Avatar, { children: /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: initials }) }),
9435
8569
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 font-medium", children: "How can I help you today?" })
9436
8570
  ] }) });
@@ -9438,10 +8572,10 @@ const ThreadWelcome$1 = ({ agentName }) => {
9438
8572
  const Composer$1 = ({ hasMemory, agentId }) => {
9439
8573
  const { setThreadInput } = useThreadInput();
9440
8574
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mx-4", children: [
9441
- /* @__PURE__ */ jsxRuntime.jsxs(react$2.ComposerPrimitive.Root, { children: [
8575
+ /* @__PURE__ */ jsxRuntime.jsxs(react$3.ComposerPrimitive.Root, { children: [
9442
8576
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-w-[568px] w-full mx-auto pb-2", children: /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachments, {}) }),
9443
8577
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-surface3 rounded-lg border-sm border-border1 py-4 mt-auto max-w-[568px] w-full mx-auto px-4 focus-within:outline focus-within:outline-accent1 -outline-offset-2", children: [
9444
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Input, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
8578
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Input, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
9445
8579
  "textarea",
9446
8580
  {
9447
8581
  className: "text-ui-lg leading-ui-lg placeholder:text-icon3 text-icon6 bg-transparent focus:outline-none resize-none outline-none",
@@ -9465,7 +8599,7 @@ const Composer$1 = ({ hasMemory, agentId }) => {
9465
8599
  ] });
9466
8600
  };
9467
8601
  const SpeechInput$1 = ({ agentId }) => {
9468
- const composerRuntime = react$2.useComposerRuntime();
8602
+ const composerRuntime = react$3.useComposerRuntime();
9469
8603
  const { start, stop, isListening, transcript } = useSpeechRecognition({ agentId });
9470
8604
  React.useEffect(() => {
9471
8605
  if (!transcript) return;
@@ -9498,7 +8632,7 @@ const ComposerAction$1 = () => {
9498
8632
  }
9499
8633
  ),
9500
8634
  /* @__PURE__ */ jsxRuntime.jsx(AttachFileDialog, { open: isAddAttachmentDialogOpen, onOpenChange: setIsAddAttachmentDialogOpen }),
9501
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { running: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
8635
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { running: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
9502
8636
  TooltipIconButton,
9503
8637
  {
9504
8638
  tooltip: "Send",
@@ -9507,15 +8641,15 @@ const ComposerAction$1 = () => {
9507
8641
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-6 w-6 text-[#898989] hover:text-[#fff]" })
9508
8642
  }
9509
8643
  ) }) }),
9510
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { running: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Cancel", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsx(CircleStopIcon$1, {}) }) }) })
8644
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { running: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Cancel", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsx(CircleStopIcon$1, {}) }) }) })
9511
8645
  ] });
9512
8646
  };
9513
8647
  const EditComposer$1 = () => {
9514
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.ComposerPrimitive.Root, { children: [
9515
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Input, {}),
8648
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.ComposerPrimitive.Root, { children: [
8649
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Input, {}),
9516
8650
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
9517
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", children: "Cancel" }) }),
9518
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { children: "Send" }) })
8651
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", children: "Cancel" }) }),
8652
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { children: "Send" }) })
9519
8653
  ] })
9520
8654
  ] });
9521
8655
  };
@@ -9531,7 +8665,7 @@ function parseJsonString(jsonString) {
9531
8665
  }
9532
8666
  }
9533
8667
  function useAgentWorkingMemory(agentId, threadId, resourceId) {
9534
- const client = useMastraClient();
8668
+ const client = react$2.useMastraClient();
9535
8669
  const [threadExists, setThreadExists] = React.useState(false);
9536
8670
  const [workingMemoryData, setWorkingMemoryData] = React.useState(null);
9537
8671
  const [workingMemorySource, setWorkingMemorySource] = React.useState("thread");
@@ -9749,7 +8883,7 @@ class PDFAttachmentAdapter {
9749
8883
  const useAdapters = (agentId) => {
9750
8884
  const [isReady, setIsReady] = React.useState(false);
9751
8885
  const [speechAdapter, setSpeechAdapter] = React.useState(void 0);
9752
- const baseClient = useMastraClient();
8886
+ const baseClient = react$2.useMastraClient();
9753
8887
  const { runtimeContext } = usePlaygroundStore();
9754
8888
  React.useEffect(() => {
9755
8889
  const check = async () => {
@@ -9759,7 +8893,7 @@ const useAdapters = (agentId) => {
9759
8893
  setSpeechAdapter(new VoiceAttachmentAdapter(agent));
9760
8894
  setIsReady(true);
9761
8895
  } catch {
9762
- setSpeechAdapter(new react$2.WebSpeechSynthesisAdapter());
8896
+ setSpeechAdapter(new react$3.WebSpeechSynthesisAdapter());
9763
8897
  setIsReady(true);
9764
8898
  }
9765
8899
  };
@@ -9768,9 +8902,9 @@ const useAdapters = (agentId) => {
9768
8902
  return {
9769
8903
  isReady,
9770
8904
  adapters: {
9771
- attachments: new react$2.CompositeAttachmentAdapter([
9772
- new react$2.SimpleImageAttachmentAdapter(),
9773
- new react$2.SimpleTextAttachmentAdapter(),
8905
+ attachments: new react$3.CompositeAttachmentAdapter([
8906
+ new react$3.SimpleImageAttachmentAdapter(),
8907
+ new react$3.SimpleTextAttachmentAdapter(),
9774
8908
  new PDFAttachmentAdapter()
9775
8909
  ]),
9776
8910
  speech: speechAdapter
@@ -9779,14 +8913,14 @@ const useAdapters = (agentId) => {
9779
8913
  };
9780
8914
 
9781
8915
  const handleNetworkMessageFromMemory = (content) => {
9782
- if (content.resourceType === "workflow") {
8916
+ if (content.primitiveType === "workflow") {
9783
8917
  return {
9784
8918
  role: "assistant",
9785
8919
  content: [
9786
8920
  {
9787
8921
  type: "tool-call",
9788
8922
  toolCallId: content.finalResult.runId,
9789
- toolName: content.resourceId,
8923
+ toolName: content.primitiveId,
9790
8924
  result: { runId: content.finalResult.runId },
9791
8925
  args: {
9792
8926
  __mastraMetadata: {
@@ -9801,7 +8935,7 @@ const handleNetworkMessageFromMemory = (content) => {
9801
8935
  ]
9802
8936
  };
9803
8937
  }
9804
- if (content.resourceType === "agent") {
8938
+ if (content.primitiveType === "agent") {
9805
8939
  const badgeMessages = [];
9806
8940
  let toolCalls = {};
9807
8941
  const messages = content.finalResult.messages.slice(1);
@@ -9839,7 +8973,7 @@ const handleNetworkMessageFromMemory = (content) => {
9839
8973
  {
9840
8974
  type: "tool-call",
9841
8975
  toolCallId: content.finalResult.runId,
9842
- toolName: content.resourceId,
8976
+ toolName: content.primitiveId,
9843
8977
  result: { runId: content.finalResult.runId },
9844
8978
  args: {
9845
8979
  __mastraMetadata: {
@@ -9855,14 +8989,14 @@ const handleNetworkMessageFromMemory = (content) => {
9855
8989
  ]
9856
8990
  };
9857
8991
  }
9858
- if (content.resourceType === "tool") {
8992
+ if (content.primitiveType === "tool") {
9859
8993
  return {
9860
8994
  role: "assistant",
9861
8995
  content: [
9862
8996
  {
9863
8997
  type: "tool-call",
9864
8998
  toolCallId: content.finalResult.toolCallId,
9865
- toolName: content.resourceId,
8999
+ toolName: content.primitiveId,
9866
9000
  result: content.finalResult.result,
9867
9001
  args: {
9868
9002
  ...content?.input,
@@ -9880,213 +9014,211 @@ const handleNetworkMessageFromMemory = (content) => {
9880
9014
  return { role: "assistant", content: [{ type: "text", text: "Unknown response" }] };
9881
9015
  };
9882
9016
 
9883
- const handleStreamChunk = async ({
9884
- chunk,
9885
- setMessages,
9886
- refreshWorkingMemory,
9887
- _sideEffects
9888
- }) => {
9889
- function updater() {
9890
- setMessages((currentConversation) => {
9891
- const message = {
9017
+ const handleStreamChunk = ({ chunk, conversation }) => {
9018
+ switch (chunk.type) {
9019
+ case "start": {
9020
+ const newMessage = {
9892
9021
  role: "assistant",
9893
- content: [{ type: "text", text: _sideEffects.content }]
9022
+ content: []
9894
9023
  };
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) {
9024
+ return [...conversation, newMessage];
9025
+ }
9026
+ case "text-start":
9910
9027
  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;
9028
+ const lastMessage = conversation[conversation.length - 1];
9029
+ if (!lastMessage) return conversation;
9030
+ if (lastMessage.role === "assistant" && typeof lastMessage.content !== `string` && (!lastMessage.content || lastMessage.content.length === 0 || lastMessage.content[lastMessage.content.length - 1]?.type !== `text`)) {
9031
+ return [
9032
+ ...conversation.slice(0, -1),
9033
+ {
9034
+ ...lastMessage,
9035
+ content: [...lastMessage.content || [], { type: "text", text: "" }]
9036
+ }
9037
+ ];
9038
+ }
9039
+ if (chunk.type === `text-start`) return conversation;
9040
+ if (typeof lastMessage.content === `string`) {
9041
+ return [
9042
+ ...conversation.slice(0, -1),
9043
+ {
9044
+ ...lastMessage,
9045
+ content: lastMessage.content + chunk.payload.text
9046
+ }
9047
+ ];
9916
9048
  }
9917
- updater();
9918
- break;
9049
+ const lastPart = lastMessage.content?.[lastMessage.content.length - 1];
9050
+ if (!lastPart || lastPart.type !== `text`) return conversation;
9051
+ return [
9052
+ ...conversation.slice(0, -1),
9053
+ {
9054
+ ...lastMessage,
9055
+ content: [...lastMessage.content.slice(0, -1), { ...lastPart, text: lastPart.text + chunk.payload.text }]
9056
+ }
9057
+ ];
9919
9058
  }
9920
9059
  case "tool-output": {
9921
9060
  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
- };
9061
+ return handleWorkflowChunk({
9062
+ workflowChunk: chunk.payload.output,
9063
+ conversation,
9064
+ entityName: chunk.payload.toolName
9065
+ });
9066
+ }
9067
+ const lastMessage = conversation[conversation.length - 1];
9068
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9069
+ const updatedContent = lastMessage.content.map((part) => {
9070
+ if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
9071
+ const existingToolOutput = part.args?.__mastraMetadata?.toolOutput || [];
9072
+ return {
9073
+ ...part,
9074
+ args: {
9075
+ ...part.args,
9076
+ __mastraMetadata: {
9077
+ ...part.args?.__mastraMetadata,
9078
+ toolOutput: [...existingToolOutput, chunk?.payload?.output]
9079
+ }
9940
9080
  }
9941
- return part;
9942
- });
9943
- const updatedMessage = {
9944
- ...lastMessage,
9945
- content: updatedContent
9946
9081
  };
9947
- return [...currentConversation.slice(0, -1), updatedMessage];
9948
9082
  }
9949
- return currentConversation;
9083
+ return part;
9950
9084
  });
9085
+ const updatedMessage = {
9086
+ ...lastMessage,
9087
+ content: updatedContent
9088
+ };
9089
+ return [...conversation.slice(0, -1), updatedMessage];
9951
9090
  }
9952
- break;
9091
+ return [...conversation];
9953
9092
  }
9954
9093
  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
- }
9094
+ const lastMessage = conversation[conversation.length - 1];
9095
+ if (lastMessage && lastMessage.role === "assistant") {
9096
+ const updatedMessage = {
9097
+ ...lastMessage,
9098
+ content: Array.isArray(lastMessage.content) ? [
9099
+ ...lastMessage.content,
9100
+ {
9101
+ type: "tool-call",
9102
+ toolCallId: chunk.payload.toolCallId,
9103
+ toolName: chunk.payload.toolName,
9104
+ args: {
9105
+ ...chunk.payload.args,
9106
+ __mastraMetadata: {
9107
+ ...chunk.payload.args?.__mastraMetadata,
9108
+ isStreaming: true
9986
9109
  }
9987
9110
  }
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 },
9111
+ }
9112
+ ] : [
9113
+ ...typeof lastMessage.content === "string" ? [{ type: "text", text: lastMessage.content }] : [],
9998
9114
  {
9999
9115
  type: "tool-call",
10000
9116
  toolCallId: chunk.payload.toolCallId,
10001
9117
  toolName: chunk.payload.toolName,
10002
9118
  args: {
10003
9119
  ...chunk.payload.args,
10004
- __mastraMetadata: { ...chunk.payload.args?.__mastraMetadata, isStreaming: true }
9120
+ __mastraMetadata: {
9121
+ ...chunk.payload.args?.__mastraMetadata,
9122
+ isStreaming: true
9123
+ }
10005
9124
  }
10006
9125
  }
10007
9126
  ]
10008
9127
  };
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;
9128
+ return [...conversation.slice(0, -1), updatedMessage];
9129
+ }
9130
+ const newMessage = {
9131
+ role: "assistant",
9132
+ content: [
9133
+ {
9134
+ type: "tool-call",
9135
+ toolCallId: chunk.payload.toolCallId,
9136
+ toolName: chunk.payload.toolName,
9137
+ args: {
9138
+ ...chunk.payload.args,
9139
+ __mastraMetadata: {
9140
+ ...chunk.payload.args?.__mastraMetadata,
9141
+ isStreaming: true
9142
+ }
9143
+ }
9144
+ }
9145
+ ]
9146
+ };
9147
+ return [...conversation, newMessage];
10015
9148
  }
10016
9149
  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];
9150
+ const lastMessage = conversation[conversation.length - 1];
9151
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9152
+ const updatedContent = lastMessage.content.map((part) => {
9153
+ if (typeof part === "object" && part.type === "tool-call" && part.toolCallId === chunk.payload.toolCallId) {
9154
+ return {
9155
+ ...part,
9156
+ result: chunk.payload.result
9157
+ };
9158
+ }
9159
+ return part;
9160
+ });
9161
+ const updatedMessage = {
9162
+ ...lastMessage,
9163
+ content: updatedContent
9164
+ };
9165
+ return [...conversation.slice(0, -1), updatedMessage];
10044
9166
  }
10045
- break;
9167
+ return [...conversation];
10046
9168
  }
10047
9169
  case "error": {
10048
9170
  if (typeof chunk.payload.error === "string") {
10049
9171
  throw new Error(chunk.payload.error);
10050
9172
  }
10051
- break;
9173
+ return [...conversation];
10052
9174
  }
10053
9175
  case "finish": {
10054
- handleFinishReason$1(chunk.payload.finishReason);
10055
- break;
9176
+ const lastMessage = conversation[conversation.length - 1];
9177
+ handleFinishReason$1(chunk.payload.stepResult.reason);
9178
+ if (lastMessage && lastMessage.role === "assistant") {
9179
+ const updatedMessage = {
9180
+ ...lastMessage,
9181
+ metadata: {
9182
+ custom: {
9183
+ modelMetadata: chunk.payload.metadata.modelMetadata
9184
+ }
9185
+ }
9186
+ };
9187
+ return [...conversation.slice(0, -1), updatedMessage];
9188
+ }
9189
+ return [...conversation];
10056
9190
  }
10057
9191
  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
- ]
9192
+ const lastMessage = conversation[conversation.length - 1];
9193
+ if (lastMessage && lastMessage.role === "assistant" && Array.isArray(lastMessage.content)) {
9194
+ const updatedContent = lastMessage.content.map((part) => {
9195
+ if (typeof part === "object" && part.type === "reasoning") {
9196
+ return {
9197
+ ...part,
9198
+ text: part.text + chunk.payload.text
9199
+ };
9200
+ }
9201
+ return part;
9202
+ });
9203
+ const updatedMessage = {
9204
+ ...lastMessage,
9205
+ content: updatedContent
10085
9206
  };
10086
- return [...currentConversation, newMessage];
10087
- });
10088
- break;
9207
+ return [...conversation.slice(0, -1), updatedMessage];
9208
+ }
9209
+ const newMessage = {
9210
+ role: "assistant",
9211
+ content: [
9212
+ {
9213
+ type: "reasoning",
9214
+ text: chunk.payload.text
9215
+ }
9216
+ ]
9217
+ };
9218
+ return [...conversation, newMessage];
10089
9219
  }
9220
+ default:
9221
+ return [...conversation];
10090
9222
  }
10091
9223
  };
10092
9224
  const handleFinishReason$1 = (finishReason) => {
@@ -10095,15 +9227,179 @@ const handleFinishReason$1 = (finishReason) => {
10095
9227
  throw new Error("Stream finished with reason tool-calls, try increasing maxSteps");
10096
9228
  }
10097
9229
  };
10098
- const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10099
- reactDom.flushSync(() => {
10100
- setMessages((currentConversation) => {
10101
- const lastMessage = currentConversation[currentConversation.length - 1];
9230
+ const handleWorkflowChunk = ({
9231
+ workflowChunk,
9232
+ conversation,
9233
+ entityName
9234
+ }) => {
9235
+ const lastMessage = conversation[conversation.length - 1];
9236
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9237
+ const newMessage = {
9238
+ ...lastMessage,
9239
+ content: contentArray.map((part) => {
9240
+ if (part.type === "tool-call") {
9241
+ return {
9242
+ ...part,
9243
+ toolName: part?.entityName || entityName,
9244
+ args: {
9245
+ ...part.args,
9246
+ __mastraMetadata: {
9247
+ ...part.args?.__mastraMetadata,
9248
+ workflowFullState: mapWorkflowStreamChunkToWatchResult(
9249
+ part.args?.__mastraMetadata?.workflowFullState || {},
9250
+ workflowChunk
9251
+ ),
9252
+ isStreaming: true
9253
+ }
9254
+ }
9255
+ };
9256
+ }
9257
+ return part;
9258
+ })
9259
+ };
9260
+ return [...conversation.slice(0, -1), newMessage];
9261
+ };
9262
+ const handleAgentChunk = ({
9263
+ agentChunk,
9264
+ conversation,
9265
+ entityName
9266
+ }) => {
9267
+ switch (agentChunk.type) {
9268
+ case "tool-result": {
9269
+ const lastMessage = conversation[conversation.length - 1];
9270
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9271
+ const newMessage = {
9272
+ ...lastMessage,
9273
+ content: contentArray.map((part) => {
9274
+ if (part.type === "tool-call") {
9275
+ const messages = part.args?.__mastraMetadata?.messages || [];
9276
+ const next = {
9277
+ ...part,
9278
+ toolName: part?.entityName || entityName,
9279
+ args: {
9280
+ ...part.args,
9281
+ __mastraMetadata: {
9282
+ ...part.args?.__mastraMetadata,
9283
+ isStreaming: true,
9284
+ messages: [
9285
+ ...messages.slice(0, -1),
9286
+ {
9287
+ ...messages[messages.length - 1],
9288
+ type: "tool",
9289
+ toolName: agentChunk.payload.toolName,
9290
+ args: agentChunk.payload.args,
9291
+ toolOutput: agentChunk.payload.result
9292
+ }
9293
+ ]
9294
+ }
9295
+ }
9296
+ };
9297
+ return next;
9298
+ }
9299
+ return part;
9300
+ })
9301
+ };
9302
+ return [...conversation.slice(0, -1), newMessage];
9303
+ }
9304
+ case "tool-call": {
9305
+ const lastMessage = conversation[conversation.length - 1];
9306
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9307
+ const newMessage = {
9308
+ ...lastMessage,
9309
+ content: contentArray.map((part) => {
9310
+ if (part.type === "tool-call") {
9311
+ const messages = part.args?.__mastraMetadata?.messages || [];
9312
+ const next = {
9313
+ ...part,
9314
+ toolName: part?.entityName || entityName,
9315
+ args: {
9316
+ ...part.args,
9317
+ __mastraMetadata: {
9318
+ ...part.args?.__mastraMetadata,
9319
+ isStreaming: true,
9320
+ messages: [
9321
+ ...messages,
9322
+ {
9323
+ type: "tool",
9324
+ toolCallId: agentChunk.payload.toolCallId,
9325
+ toolName: agentChunk.payload.toolName,
9326
+ args: {
9327
+ ...agentChunk.payload.args,
9328
+ __mastraMetadata: {
9329
+ ...agentChunk.payload.args?.__mastraMetadata,
9330
+ isStreaming: true
9331
+ }
9332
+ }
9333
+ }
9334
+ ]
9335
+ }
9336
+ }
9337
+ };
9338
+ return next;
9339
+ }
9340
+ return part;
9341
+ })
9342
+ };
9343
+ return [...conversation.slice(0, -1), newMessage];
9344
+ }
9345
+ case "text-delta": {
9346
+ const lastMessage = conversation[conversation.length - 1];
9347
+ const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
9348
+ const newMessage = {
9349
+ ...lastMessage,
9350
+ content: contentArray.map((part) => {
9351
+ if (part.type === "tool-call") {
9352
+ const messages = part.args?.__mastraMetadata?.messages || [];
9353
+ const lastMastraMessage = messages[messages.length - 1];
9354
+ const nextMessages = lastMastraMessage?.type === "text" ? [
9355
+ ...messages.slice(0, -1),
9356
+ { type: "text", content: (lastMastraMessage?.content || "") + agentChunk.payload.text }
9357
+ ] : [...messages, { type: "text", content: agentChunk.payload.text }];
9358
+ return {
9359
+ ...part,
9360
+ toolName: part?.entityName || entityName,
9361
+ args: {
9362
+ ...part.args,
9363
+ __mastraMetadata: {
9364
+ ...part.args?.__mastraMetadata,
9365
+ isStreaming: true,
9366
+ messages: nextMessages
9367
+ }
9368
+ }
9369
+ };
9370
+ }
9371
+ return part;
9372
+ })
9373
+ };
9374
+ return [...conversation.slice(0, -1), newMessage];
9375
+ }
9376
+ case "tool-output": {
9377
+ if (!agentChunk.payload.output.type.startsWith("workflow-")) return [...conversation];
9378
+ const lastMessage = conversation[conversation.length - 1];
10102
9379
  const contentArray = Array.isArray(lastMessage.content) ? lastMessage.content : [{ type: "text", text: lastMessage.content }];
10103
9380
  const newMessage = {
10104
9381
  ...lastMessage,
10105
9382
  content: contentArray.map((part) => {
10106
9383
  if (part.type === "tool-call") {
9384
+ const messages = part.args?.__mastraMetadata?.messages || [];
9385
+ const lastMastraMessage = messages[messages.length - 1];
9386
+ const nextMessages = lastMastraMessage?.type === "tool" ? [
9387
+ ...messages.slice(0, -1),
9388
+ {
9389
+ ...lastMastraMessage,
9390
+ args: {
9391
+ ...agentChunk.payload.args,
9392
+ __mastraMetadata: {
9393
+ ...agentChunk.payload.args?.__mastraMetadata,
9394
+ workflowFullState: mapWorkflowStreamChunkToWatchResult(
9395
+ lastMastraMessage.args?.__mastraMetadata?.workflowFullState || {},
9396
+ agentChunk.payload.output
9397
+ ),
9398
+ isStreaming: true
9399
+ }
9400
+ }
9401
+ }
9402
+ ] : messages;
10107
9403
  return {
10108
9404
  ...part,
10109
9405
  toolName: part?.entityName || entityName,
@@ -10111,11 +9407,8 @@ const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10111
9407
  ...part.args,
10112
9408
  __mastraMetadata: {
10113
9409
  ...part.args?.__mastraMetadata,
10114
- workflowFullState: mapWorkflowStreamChunkToWatchResult(
10115
- part.args?.__mastraMetadata?.workflowFullState || {},
10116
- workflowChunk
10117
- ),
10118
- isStreaming: true
9410
+ isStreaming: true,
9411
+ messages: nextMessages
10119
9412
  }
10120
9413
  }
10121
9414
  };
@@ -10123,216 +9416,42 @@ const handleWorkflowChunk = ({ workflowChunk, setMessages, entityName }) => {
10123
9416
  return part;
10124
9417
  })
10125
9418
  };
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;
9419
+ return [...conversation.slice(0, -1), newMessage];
10298
9420
  }
9421
+ default:
9422
+ case "agent-execution-end":
9423
+ return [...conversation];
10299
9424
  }
10300
9425
  };
10301
9426
  const createRootToolAssistantMessage = ({
10302
9427
  chunk,
10303
9428
  entityName,
10304
- setMessages,
9429
+ conversation,
10305
9430
  runId,
10306
- _sideEffects,
10307
9431
  from,
10308
9432
  networkMetadata
10309
9433
  }) => {
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
- }
9434
+ if (!entityName || !runId) return [...conversation];
9435
+ const newMessage = {
9436
+ role: "assistant",
9437
+ content: [
9438
+ {
9439
+ type: "tool-call",
9440
+ toolCallId: runId,
9441
+ toolName: entityName,
9442
+ args: {
9443
+ ...chunk?.payload?.args,
9444
+ __mastraMetadata: {
9445
+ from,
9446
+ networkMetadata,
9447
+ ...chunk.payload.args?.__mastraMetadata,
9448
+ isStreaming: true
10328
9449
  }
10329
9450
  }
10330
- ]
10331
- };
10332
- _sideEffects.assistantToolCallAddedForUpdater = true;
10333
- _sideEffects.assistantToolCallAddedForContent = true;
10334
- return [...currentConversation, newMessage];
10335
- });
9451
+ }
9452
+ ]
9453
+ };
9454
+ return [...conversation, newMessage];
10336
9455
  };
10337
9456
 
10338
9457
  const convertMessage$1 = (message) => {
@@ -10381,6 +9500,60 @@ const convertToAIAttachments = async (attachments) => {
10381
9500
  });
10382
9501
  return Promise.all(promises);
10383
9502
  };
9503
+ const initializeMessageState = (initialMessages) => {
9504
+ const convertedMessages = initialMessages?.map((message) => {
9505
+ let content;
9506
+ try {
9507
+ content = JSON.parse(message.content);
9508
+ if (content.isNetwork) {
9509
+ return handleNetworkMessageFromMemory(content);
9510
+ }
9511
+ } catch (e) {
9512
+ }
9513
+ const attachmentsAsContentParts = (message.experimental_attachments || []).map((image) => ({
9514
+ type: image.contentType.startsWith(`image/`) ? "image" : image.contentType.startsWith(`audio/`) ? "audio" : "file",
9515
+ mimeType: image.contentType,
9516
+ image: image.url
9517
+ }));
9518
+ const formattedParts = (message.parts || []).map((part) => {
9519
+ if (part.type === "reasoning") {
9520
+ return {
9521
+ type: "reasoning",
9522
+ text: part.reasoning || part?.details?.filter((detail) => detail.type === "text")?.map((detail) => detail.text).join(" ")
9523
+ };
9524
+ }
9525
+ if (part.type === "tool-invocation") {
9526
+ if (part.toolInvocation.state === "result") {
9527
+ return {
9528
+ type: "tool-call",
9529
+ toolCallId: part.toolInvocation.toolCallId,
9530
+ toolName: part.toolInvocation.toolName,
9531
+ args: part.toolInvocation.args,
9532
+ result: part.toolInvocation.result
9533
+ };
9534
+ }
9535
+ }
9536
+ if (part.type === "file") {
9537
+ return {
9538
+ type: "file",
9539
+ mimeType: part.mimeType,
9540
+ data: part.data
9541
+ };
9542
+ }
9543
+ if (part.type === "text") {
9544
+ return {
9545
+ type: "text",
9546
+ text: part.text
9547
+ };
9548
+ }
9549
+ }).filter(Boolean);
9550
+ return {
9551
+ ...message,
9552
+ content: [...formattedParts, ...attachmentsAsContentParts]
9553
+ };
9554
+ }).filter(Boolean);
9555
+ return convertedMessages;
9556
+ };
10384
9557
  function MastraRuntimeProvider({
10385
9558
  children,
10386
9559
  agentId,
@@ -10393,8 +9566,17 @@ function MastraRuntimeProvider({
10393
9566
  modelVersion
10394
9567
  }) {
10395
9568
  const [isRunning, setIsRunning] = React.useState(false);
10396
- const [messages, setMessages] = React.useState([]);
10397
- const [currentThreadId, setCurrentThreadId] = React.useState(threadId);
9569
+ const {
9570
+ messages,
9571
+ setMessages,
9572
+ streamVNext,
9573
+ network,
9574
+ cancelRun,
9575
+ isRunning: isRunningStreamVNext
9576
+ } = react$2.useChat({
9577
+ agentId,
9578
+ initializeMessages: () => memory ? initializeMessageState(initialMessages || []) : []
9579
+ });
10398
9580
  const { refetch: refreshWorkingMemory } = useWorkingMemory();
10399
9581
  const abortControllerRef = React.useRef(null);
10400
9582
  const {
@@ -10417,76 +9599,23 @@ function MastraRuntimeProvider({
10417
9599
  Object.entries(runtimeContext ?? {}).forEach(([key, value]) => {
10418
9600
  runtimeContextInstance.set(key, value);
10419
9601
  });
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]);
10480
- const baseClient = useMastraClient();
9602
+ const modelSettingsArgs = {
9603
+ frequencyPenalty,
9604
+ presencePenalty,
9605
+ maxRetries,
9606
+ temperature,
9607
+ topK,
9608
+ topP,
9609
+ maxTokens,
9610
+ instructions,
9611
+ providerOptions
9612
+ };
9613
+ const baseClient = react$2.useMastraClient();
10481
9614
  const onNew = async (message) => {
10482
9615
  if (message.content[0]?.type !== "text") throw new Error("Only text messages are supported");
10483
9616
  const attachments = await convertToAIAttachments(message.attachments);
10484
9617
  const input = message.content[0].text;
10485
- setMessages((currentConversation) => [
10486
- ...currentConversation,
10487
- { role: "user", content: input, attachments: message.attachments }
10488
- ]);
10489
- setIsRunning(true);
9618
+ setMessages((s) => [...s, { role: "user", content: input, attachments: message.attachments }]);
10490
9619
  const controller = new AbortController();
10491
9620
  abortControllerRef.current = controller;
10492
9621
  const clientWithAbort = new clientJs.MastraClient({
@@ -10496,7 +9625,7 @@ function MastraRuntimeProvider({
10496
9625
  const agent = clientWithAbort.getAgent(agentId);
10497
9626
  try {
10498
9627
  let handleGenerateResponse = function(generatedResponse) {
10499
- if (generatedResponse.response && "messages" in generatedResponse.response) {
9628
+ if (generatedResponse.response && "messages" in generatedResponse.response && generatedResponse.response.messages) {
10500
9629
  const latestMessage = generatedResponse.response.messages.reduce(
10501
9630
  (acc, message2) => {
10502
9631
  const _content = Array.isArray(acc.content) ? acc.content : [];
@@ -10569,7 +9698,17 @@ function MastraRuntimeProvider({
10569
9698
  },
10570
9699
  { role: "assistant", content: [] }
10571
9700
  );
10572
- setMessages((currentConversation) => [...currentConversation, latestMessage]);
9701
+ setMessages((currentConversation) => [
9702
+ ...currentConversation,
9703
+ {
9704
+ ...latestMessage,
9705
+ metadata: {
9706
+ custom: {
9707
+ modelMetadata: generatedResponse.response.modelMetadata
9708
+ }
9709
+ }
9710
+ }
9711
+ ]);
10573
9712
  if (generatedResponse.finishReason) {
10574
9713
  handleFinishReason(generatedResponse.finishReason);
10575
9714
  }
@@ -10577,86 +9716,72 @@ function MastraRuntimeProvider({
10577
9716
  };
10578
9717
  if (modelVersion === "v2") {
10579
9718
  if (chatWithNetwork) {
10580
- const response = await agent.network({
10581
- messages: [
9719
+ let currentEntityId;
9720
+ await network({
9721
+ coreUserMessages: [
10582
9722
  {
10583
9723
  role: "user",
10584
9724
  content: input
10585
- }
9725
+ },
9726
+ ...attachments
10586
9727
  ],
10587
- maxSteps,
10588
- modelSettings: {
10589
- frequencyPenalty,
10590
- presencePenalty,
10591
- maxRetries,
10592
- maxOutputTokens: maxTokens,
10593
- temperature,
10594
- topK,
10595
- topP
10596
- },
10597
- runId: agentId,
10598
9728
  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) => {
9729
+ threadId,
9730
+ modelSettings: modelSettingsArgs,
9731
+ signal: controller.signal,
9732
+ onNetworkChunk: (chunk, conversation) => {
10611
9733
  if (chunk.type.startsWith("agent-execution-event-")) {
10612
9734
  const agentChunk = chunk.payload;
10613
- if (!currentEntityId) return;
10614
- await handleAgentChunk({ agentChunk, setMessages, entityName: currentEntityId });
9735
+ if (!currentEntityId) return conversation;
9736
+ return handleAgentChunk({ agentChunk, conversation, entityName: currentEntityId });
10615
9737
  } else if (chunk.type === "tool-execution-start") {
10616
- await handleStreamChunk({
9738
+ const { args: argsData } = chunk.payload;
9739
+ const nestedArgs = argsData.args || {};
9740
+ const mastraMetadata = argsData.__mastraMetadata || {};
9741
+ const selectionReason = argsData.selectionReason || "";
9742
+ return handleStreamChunk({
10617
9743
  chunk: {
10618
9744
  ...chunk,
10619
9745
  type: "tool-call",
10620
9746
  payload: {
10621
- ...chunk?.payload,
10622
- toolCallId: chunk?.payload?.args?.toolCallId,
10623
- toolName: chunk?.payload?.args?.toolName,
9747
+ ...chunk.payload,
9748
+ toolCallId: argsData.toolCallId || "unknown",
9749
+ toolName: argsData.toolName || "unknown",
10624
9750
  args: {
10625
- ...chunk?.payload?.args?.args,
9751
+ ...nestedArgs,
10626
9752
  __mastraMetadata: {
10627
- ...chunk?.payload?.args?.__mastraMetadata,
9753
+ ...mastraMetadata,
10628
9754
  networkMetadata: {
10629
- selectionReason: chunk?.payload?.args?.selectionReason || "",
10630
- input: chunk?.payload?.args?.args
9755
+ selectionReason,
9756
+ input: nestedArgs
10631
9757
  }
10632
9758
  }
10633
9759
  }
10634
9760
  }
10635
9761
  },
10636
- setMessages,
10637
- refreshWorkingMemory,
10638
- _sideEffects
9762
+ conversation
10639
9763
  });
10640
9764
  } else if (chunk.type === "tool-execution-end") {
10641
- await handleStreamChunk({
9765
+ const next = handleStreamChunk({
10642
9766
  chunk: { ...chunk, type: "tool-result" },
10643
- setMessages,
10644
- refreshWorkingMemory,
10645
- _sideEffects
9767
+ conversation
10646
9768
  });
9769
+ if (chunk.payload?.toolName === "updateWorkingMemory" && typeof chunk.payload.result === "object" && "success" in chunk.payload.result && chunk.payload.result?.success) {
9770
+ refreshWorkingMemory?.();
9771
+ }
9772
+ return next;
10647
9773
  } else if (chunk.type.startsWith("workflow-execution-event-")) {
10648
9774
  const workflowChunk = chunk.payload;
10649
- if (!currentEntityId) return;
10650
- await handleWorkflowChunk({ workflowChunk, setMessages, entityName: currentEntityId });
9775
+ if (!currentEntityId) return conversation;
9776
+ return handleWorkflowChunk({ workflowChunk, conversation, entityName: currentEntityId });
10651
9777
  } else if (chunk.type === "workflow-execution-start" || chunk.type === "agent-execution-start") {
10652
- currentEntityId = chunk.payload?.args?.resourceId;
9778
+ currentEntityId = chunk.payload?.args?.primitiveId;
10653
9779
  const runId = chunk.payload.runId;
10654
- if (!currentEntityId || !runId) return;
10655
- createRootToolAssistantMessage({
9780
+ if (!currentEntityId || !runId) return conversation;
9781
+ return createRootToolAssistantMessage({
10656
9782
  entityName: currentEntityId,
10657
- setMessages,
9783
+ conversation,
10658
9784
  runId,
10659
- _sideEffects,
10660
9785
  chunk,
10661
9786
  from: chunk.type === "agent-execution-start" ? "AGENT" : "WORKFLOW",
10662
9787
  networkMetadata: {
@@ -10664,21 +9789,19 @@ function MastraRuntimeProvider({
10664
9789
  input: chunk?.payload?.args?.prompt
10665
9790
  }
10666
9791
  });
10667
- _sideEffects.toolCallIdToName.current[runId] = currentEntityId;
10668
9792
  } 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
- });
9793
+ return [
9794
+ ...conversation,
9795
+ { role: "assistant", content: [{ type: "text", text: chunk?.payload?.result || "" }] }
9796
+ ];
10675
9797
  } else {
10676
- await handleStreamChunk({ chunk, setMessages, refreshWorkingMemory, _sideEffects });
9798
+ return handleStreamChunk({ chunk, conversation });
10677
9799
  }
10678
9800
  }
10679
9801
  });
10680
9802
  } else {
10681
9803
  if (chatWithGenerateVNext) {
9804
+ setIsRunning(true);
10682
9805
  const response = await agent.generateVNext({
10683
9806
  messages: [
10684
9807
  {
@@ -10706,50 +9829,32 @@ function MastraRuntimeProvider({
10706
9829
  setIsRunning(false);
10707
9830
  return;
10708
9831
  } else {
10709
- const response = await agent.streamVNext({
10710
- messages: [
9832
+ await streamVNext({
9833
+ coreUserMessages: [
10711
9834
  {
10712
9835
  role: "user",
10713
9836
  content: input
10714
9837
  },
10715
9838
  ...attachments
10716
9839
  ],
10717
- runId: agentId,
10718
- modelSettings: {
10719
- frequencyPenalty,
10720
- presencePenalty,
10721
- maxRetries,
10722
- maxOutputTokens: maxTokens,
10723
- temperature,
10724
- topK,
10725
- topP
10726
- },
10727
- instructions,
10728
9840
  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
- }
9841
+ threadId,
9842
+ modelSettings: modelSettingsArgs,
9843
+ onChunk: (chunk, conversation) => {
9844
+ const next = handleStreamChunk({ chunk, conversation });
9845
+ if (chunk.type === "tool-result" && chunk.payload?.toolName === "updateWorkingMemory" && typeof chunk.payload.result === "object" && "success" in chunk.payload.result && chunk.payload.result?.success) {
9846
+ refreshWorkingMemory?.();
9847
+ }
9848
+ return next;
9849
+ },
9850
+ signal: controller.signal
10746
9851
  });
10747
- setIsRunning(false);
10748
9852
  return;
10749
9853
  }
10750
9854
  }
10751
9855
  } else {
10752
9856
  if (chatWithGenerate) {
9857
+ setIsRunning(true);
10753
9858
  const generateResponse = await agent.generate({
10754
9859
  messages: [
10755
9860
  {
@@ -10864,6 +9969,7 @@ function MastraRuntimeProvider({
10864
9969
  return [...currentConversation.slice(0, -1), message2];
10865
9970
  });
10866
9971
  };
9972
+ setIsRunning(true);
10867
9973
  const response = await agent.stream({
10868
9974
  messages: [
10869
9975
  {
@@ -11043,11 +10149,12 @@ function MastraRuntimeProvider({
11043
10149
  abortControllerRef.current.abort();
11044
10150
  abortControllerRef.current = null;
11045
10151
  setIsRunning(false);
10152
+ cancelRun?.();
11046
10153
  }
11047
10154
  };
11048
10155
  const { adapters, isReady } = useAdapters(agentId);
11049
- const runtime = react$2.useExternalStoreRuntime({
11050
- isRunning,
10156
+ const runtime = react$3.useExternalStoreRuntime({
10157
+ isRunning: isRunning || isRunningStreamVNext,
11051
10158
  messages,
11052
10159
  convertMessage: convertMessage$1,
11053
10160
  onNew,
@@ -11055,7 +10162,7 @@ function MastraRuntimeProvider({
11055
10162
  adapters: isReady ? adapters : void 0
11056
10163
  });
11057
10164
  if (!isReady) return null;
11058
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.AssistantRuntimeProvider, { runtime, children: [
10165
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.AssistantRuntimeProvider, { runtime, children: [
11059
10166
  " ",
11060
10167
  children,
11061
10168
  " "
@@ -11129,7 +10236,8 @@ const AgentChat = ({
11129
10236
  initialMessages,
11130
10237
  memory,
11131
10238
  refreshThreadList,
11132
- modelVersion
10239
+ modelVersion,
10240
+ modelList
11133
10241
  }) => {
11134
10242
  const { settings } = useAgentSettings();
11135
10243
  const { runtimeContext } = usePlaygroundStore();
@@ -11145,7 +10253,7 @@ const AgentChat = ({
11145
10253
  refreshThreadList,
11146
10254
  settings,
11147
10255
  runtimeContext,
11148
- children: /* @__PURE__ */ jsxRuntime.jsx(Thread, { agentName: agentName ?? "", hasMemory: memory, agentId })
10256
+ children: /* @__PURE__ */ jsxRuntime.jsx(Thread, { agentName: agentName ?? "", hasMemory: memory, agentId, hasModelList: Boolean(modelList) })
11149
10257
  }
11150
10258
  );
11151
10259
  };
@@ -11399,7 +10507,7 @@ function EvalTable({ evals, isCIMode = false, onRefresh }) {
11399
10507
  ] }) }),
11400
10508
  /* @__PURE__ */ jsxRuntime.jsx(TableHead, { className: "w-48 text-mastra-el-3", children: "Evaluations" })
11401
10509
  ] }) }),
11402
- /* @__PURE__ */ jsxRuntime.jsx(TableBody, { className: "border-b border-gray-6 relative", children: /* @__PURE__ */ jsxRuntime.jsx(react$3.AnimatePresence, { mode: "wait", presenceAffectsLayout: false, children: groupEvals(evals).length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
10510
+ /* @__PURE__ */ jsxRuntime.jsx(TableBody, { className: "border-b border-gray-6 relative", children: /* @__PURE__ */ jsxRuntime.jsx(react$4.AnimatePresence, { mode: "wait", presenceAffectsLayout: false, children: groupEvals(evals).length === 0 ? /* @__PURE__ */ jsxRuntime.jsxs(TableRow, { children: [
11403
10511
  /* @__PURE__ */ jsxRuntime.jsx(TableCell, { className: "h-12 w-16" }),
11404
10512
  /* @__PURE__ */ jsxRuntime.jsx(TableCell, { colSpan: 4, className: "h-32 px-4 text-center text-mastra-el-3", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center gap-2", children: [
11405
10513
  /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Search, { className: "size-5" }),
@@ -12268,6 +11376,7 @@ const MistralIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
12268
11376
 
12269
11377
  const providerMapToIcon = {
12270
11378
  "openai.chat": /* @__PURE__ */ jsxRuntime.jsx(OpenaiChatIcon, {}),
11379
+ "openai.responses": /* @__PURE__ */ jsxRuntime.jsx(OpenaiChatIcon, {}),
12271
11380
  "anthropic.chat": /* @__PURE__ */ jsxRuntime.jsx(AnthropicChatIcon, {}),
12272
11381
  "anthropic.messages": /* @__PURE__ */ jsxRuntime.jsx(AnthropicMessagesIcon, {}),
12273
11382
  AZURE: /* @__PURE__ */ jsxRuntime.jsx(AzureIcon, {}),
@@ -12299,17 +11408,34 @@ const columns$2 = [
12299
11408
  {
12300
11409
  header: "Model",
12301
11410
  accessorKey: "model",
12302
- size: 160,
11411
+ size: 300,
12303
11412
  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
- ) });
11413
+ return /* @__PURE__ */ jsxRuntime.jsxs(Cell, { children: [
11414
+ /* @__PURE__ */ jsxRuntime.jsx(
11415
+ Badge$1,
11416
+ {
11417
+ variant: "default",
11418
+ icon: providerMapToIcon[row.original.provider] || /* @__PURE__ */ jsxRuntime.jsx(OpenAIIcon, {}),
11419
+ className: "truncate",
11420
+ children: row.original.modelId || "N/A"
11421
+ }
11422
+ ),
11423
+ row.original.modelList && row.original.modelList.length > 1 ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
11424
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Badge$1, { variant: "info", className: "ml-2", children: [
11425
+ "+ ",
11426
+ row.original.modelList.length - 1,
11427
+ " more"
11428
+ ] }) }),
11429
+ /* @__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(
11430
+ Badge$1,
11431
+ {
11432
+ variant: "default",
11433
+ icon: providerMapToIcon[mdl.model.provider],
11434
+ children: mdl.model.modelId
11435
+ }
11436
+ ) }, mdl.id)) })
11437
+ ] }) : null
11438
+ ] });
12313
11439
  }
12314
11440
  },
12315
11441
  {
@@ -12342,7 +11468,8 @@ function AgentsTable({ agents, isLoading }) {
12342
11468
  repoUrl: void 0,
12343
11469
  tools: agent.tools,
12344
11470
  modelId: agent.modelId,
12345
- link: paths.agentLink(key)
11471
+ link: paths.agentLink(key),
11472
+ modelList: agent.modelList
12346
11473
  };
12347
11474
  }),
12348
11475
  [agents]
@@ -12358,10 +11485,10 @@ function AgentsTable({ agents, isLoading }) {
12358
11485
  if (rows.length === 0) {
12359
11486
  return /* @__PURE__ */ jsxRuntime.jsx(EmptyAgentsTable, {});
12360
11487
  }
12361
- return /* @__PURE__ */ jsxRuntime.jsx(ScrollableContainer, { children: /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
11488
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollableContainer, { children: /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
12362
11489
  /* @__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
11490
  /* @__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
- ] }) });
11491
+ ] }) }) });
12365
11492
  }
12366
11493
  const AgentsTableSkeleton = () => /* @__PURE__ */ jsxRuntime.jsxs(Table$1, { children: [
12367
11494
  /* @__PURE__ */ jsxRuntime.jsxs(Thead, { children: [
@@ -13995,7 +13122,7 @@ function ScoresTools({ onEntityChange, onReset, selectedEntity, entityOptions, i
13995
13122
  }
13996
13123
 
13997
13124
  const useScoresByEntityId = (entityId, entityType, page = 0) => {
13998
- const client = useMastraClient();
13125
+ const client = react$2.useMastraClient();
13999
13126
  const [scores, setScores] = React.useState(null);
14000
13127
  const [isLoading, setIsLoading] = React.useState(true);
14001
13128
  React.useEffect(() => {
@@ -14020,7 +13147,7 @@ const useScoresByEntityId = (entityId, entityType, page = 0) => {
14020
13147
  return { scores, isLoading };
14021
13148
  };
14022
13149
  const useScoresByScorerId = ({ scorerId, page = 0, entityId, entityType }) => {
14023
- const client = useMastraClient();
13150
+ const client = react$2.useMastraClient();
14024
13151
  return reactQuery.useQuery({
14025
13152
  queryKey: ["scores", scorerId, page, entityId, entityType],
14026
13153
  queryFn: () => client.getScoresByScorerId({ scorerId, page, entityId, entityType, perPage: 10 }),
@@ -14028,7 +13155,7 @@ const useScoresByScorerId = ({ scorerId, page = 0, entityId, entityType }) => {
14028
13155
  });
14029
13156
  };
14030
13157
  const useScorer = (scorerId) => {
14031
- const client = useMastraClient();
13158
+ const client = react$2.useMastraClient();
14032
13159
  const [scorer, setScorer] = React.useState(null);
14033
13160
  const [isLoading, setIsLoading] = React.useState(true);
14034
13161
  React.useEffect(() => {
@@ -14050,7 +13177,7 @@ const useScorer = (scorerId) => {
14050
13177
  return { scorer, isLoading };
14051
13178
  };
14052
13179
  const useScorers = () => {
14053
- const client = useMastraClient();
13180
+ const client = react$2.useMastraClient();
14054
13181
  return reactQuery.useQuery({
14055
13182
  queryKey: ["scorers"],
14056
13183
  queryFn: () => client.getScorers(),
@@ -14489,6 +13616,126 @@ const AgentMetadataModelSwitcher = ({
14489
13616
  ] });
14490
13617
  };
14491
13618
 
13619
+ const Switch = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
13620
+ SwitchPrimitives__namespace.Root,
13621
+ {
13622
+ className: cn(
13623
+ "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",
13624
+ className
13625
+ ),
13626
+ ...props,
13627
+ ref,
13628
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13629
+ SwitchPrimitives__namespace.Thumb,
13630
+ {
13631
+ className: cn(
13632
+ "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"
13633
+ )
13634
+ }
13635
+ )
13636
+ }
13637
+ ));
13638
+ Switch.displayName = SwitchPrimitives__namespace.Root.displayName;
13639
+
13640
+ const AgentMetadataModelList = ({
13641
+ modelList,
13642
+ modelProviders,
13643
+ updateModelInModelList,
13644
+ reorderModelList
13645
+ }) => {
13646
+ const [modelConfigs, setModelConfigs] = React.useState(() => modelList);
13647
+ const handleDragEnd = (result) => {
13648
+ if (!result.destination) {
13649
+ return;
13650
+ }
13651
+ const items = Array.from(modelConfigs);
13652
+ const [reorderedItem] = items.splice(result.source.index, 1);
13653
+ items.splice(result.destination.index, 0, reorderedItem);
13654
+ setModelConfigs(items);
13655
+ reorderModelList({ reorderedModelIds: items.map((item) => item.id) });
13656
+ };
13657
+ const updateModel = (params) => {
13658
+ setModelConfigs(
13659
+ (prev) => prev.map(
13660
+ (modelConfig) => modelConfig.id === params.modelConfigId ? {
13661
+ ...modelConfig,
13662
+ enabled: params.enabled ?? modelConfig.enabled,
13663
+ maxRetries: params.maxRetries ?? modelConfig.maxRetries,
13664
+ model: {
13665
+ modelId: params.model?.modelId ?? modelConfig.model.modelId,
13666
+ provider: params.model?.provider ?? modelConfig.model.provider,
13667
+ modelVersion: modelConfig.model.modelVersion
13668
+ }
13669
+ } : modelConfig
13670
+ )
13671
+ );
13672
+ return updateModelInModelList(params);
13673
+ };
13674
+ 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: [
13675
+ modelConfigs.map((modelConfig, index) => /* @__PURE__ */ jsxRuntime.jsx(dnd.Draggable, { draggableId: modelConfig.id, index, children: (provided2) => /* @__PURE__ */ jsxRuntime.jsx(
13676
+ "div",
13677
+ {
13678
+ ref: provided2.innerRef,
13679
+ ...provided2.draggableProps,
13680
+ ...provided2.dragHandleProps,
13681
+ style: provided2.draggableProps.style,
13682
+ children: /* @__PURE__ */ jsxRuntime.jsx(
13683
+ AgentMetadataModelListItem,
13684
+ {
13685
+ modelConfig,
13686
+ modelProviders,
13687
+ updateModelInModelList: updateModel
13688
+ }
13689
+ )
13690
+ }
13691
+ ) }, modelConfig.id)),
13692
+ provided.placeholder
13693
+ ] }) }) });
13694
+ };
13695
+ const AgentMetadataModelListItem = ({
13696
+ modelConfig,
13697
+ modelProviders,
13698
+ updateModelInModelList
13699
+ }) => {
13700
+ const [isEditingModel, setIsEditingModel] = React.useState(false);
13701
+ const [enabled, setEnabled] = React.useState(() => modelConfig.enabled);
13702
+ const providerIcon = providerMapToIcon[modelConfig.model.provider || "openai.chat"];
13703
+ return isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
13704
+ AgentMetadataModelSwitcher,
13705
+ {
13706
+ defaultProvider: modelConfig.model.provider,
13707
+ defaultModel: modelConfig.model.modelId,
13708
+ updateModel: (params) => updateModelInModelList({ modelConfigId: modelConfig.id, model: params }),
13709
+ closeEditor: () => setIsEditingModel(false),
13710
+ modelProviders
13711
+ }
13712
+ ) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 p-2 rounded-lg bg-background hover:bg-muted/50 transition-colors", children: [
13713
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon3 cursor-grab active:cursor-grabbing", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.GripVertical, {}) }) }),
13714
+ /* @__PURE__ */ jsxRuntime.jsx(Badge$1, { icon: providerIcon, className: "font-medium", children: modelConfig.model.modelId || "N/A" }),
13715
+ /* @__PURE__ */ jsxRuntime.jsx(
13716
+ Switch,
13717
+ {
13718
+ checked: enabled,
13719
+ onCheckedChange: (checked) => {
13720
+ setEnabled(checked);
13721
+ updateModelInModelList({ modelConfigId: modelConfig.id, enabled: checked });
13722
+ }
13723
+ }
13724
+ ),
13725
+ /* @__PURE__ */ jsxRuntime.jsx(
13726
+ "button",
13727
+ {
13728
+ onClick: () => setIsEditingModel(true),
13729
+ className: "text-icon3 hover:text-icon6",
13730
+ title: "Edit model",
13731
+ type: "button",
13732
+ "aria-label": "Edit model",
13733
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.EditIcon, {}) })
13734
+ }
13735
+ )
13736
+ ] });
13737
+ };
13738
+
14492
13739
  const AgentMetadataNetworkList = ({ agents }) => {
14493
13740
  const { Link, paths } = useLinkComponent();
14494
13741
  if (agents.length === 0) {
@@ -14502,7 +13749,9 @@ const AgentMetadata = ({
14502
13749
  promptSlot,
14503
13750
  hasMemoryEnabled,
14504
13751
  updateModel,
14505
- modelProviders
13752
+ modelProviders,
13753
+ updateModelInModelList,
13754
+ reorderModelList
14506
13755
  }) => {
14507
13756
  const [isEditingModel, setIsEditingModel] = React.useState(false);
14508
13757
  const providerIcon = providerMapToIcon[agent.provider || "openai.chat"];
@@ -14513,7 +13762,15 @@ const AgentMetadata = ({
14513
13762
  const agentWorkflows = agent.workflows ?? {};
14514
13763
  const workflows = Object.keys(agentWorkflows).map((key) => ({ id: key, ...agentWorkflows[key] }));
14515
13764
  return /* @__PURE__ */ jsxRuntime.jsxs(AgentMetadataWrapper, { children: [
14516
- /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Model", children: isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
13765
+ agent.modelList ? /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Models", children: /* @__PURE__ */ jsxRuntime.jsx(
13766
+ AgentMetadataModelList,
13767
+ {
13768
+ modelList: agent.modelList,
13769
+ modelProviders,
13770
+ updateModelInModelList,
13771
+ reorderModelList
13772
+ }
13773
+ ) }) : /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataSection, { title: "Model", children: isEditingModel ? /* @__PURE__ */ jsxRuntime.jsx(
14517
13774
  AgentMetadataModelSwitcher,
14518
13775
  {
14519
13776
  defaultProvider: agent.provider,
@@ -14603,7 +13860,7 @@ const AgentMetadataScorerList = ({ entityId, entityType }) => {
14603
13860
  const scorerList = Object.keys(scorers).filter((scorerKey) => {
14604
13861
  const scorer = scorers[scorerKey];
14605
13862
  if (entityType === "AGENT") {
14606
- return scorer.agentNames.includes(entityId);
13863
+ return scorer.agentNames?.includes?.(entityId);
14607
13864
  }
14608
13865
  return scorer.workflowIds.includes(entityId);
14609
13866
  }).map((scorerKey) => ({ ...scorers[scorerKey], id: scorerKey }));
@@ -14932,7 +14189,7 @@ const LabelMappings = {
14932
14189
  const StepDropdown = () => {
14933
14190
  const [isExpanded, setIsExpanded] = React.useState(false);
14934
14191
  const { state } = useVNextNetworkChat();
14935
- const message = react$2.useMessage();
14192
+ const message = react$3.useMessage();
14936
14193
  const id = message?.metadata?.custom?.id;
14937
14194
  if (!id) return /* @__PURE__ */ jsxRuntime.jsx("div", { children: "Something is wrong" });
14938
14195
  const currentState = state[id];
@@ -15070,7 +14327,7 @@ const StepClock = ({ step }) => {
15070
14327
  const NextAssistantMessage = ({
15071
14328
  ToolFallback: ToolFallbackCustom
15072
14329
  }) => {
15073
- const data = react$2.useMessage();
14330
+ const data = react$3.useMessage();
15074
14331
  const isSolelyToolCall = data.content.length === 1 && data.content[0].type === "tool-call";
15075
14332
  const content = data.content[0];
15076
14333
  if (!content) {
@@ -15080,9 +14337,9 @@ const NextAssistantMessage = ({
15080
14337
  if (textContent === "start") {
15081
14338
  return /* @__PURE__ */ jsxRuntime.jsx(StepDropdown, {});
15082
14339
  }
15083
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.MessagePrimitive.Root, { className: "max-w-full", children: [
14340
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.MessagePrimitive.Root, { className: "max-w-full", children: [
15084
14341
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-icon6 text-ui-lg leading-ui-lg", children: /* @__PURE__ */ jsxRuntime.jsx(
15085
- react$2.MessagePrimitive.Parts,
14342
+ react$3.MessagePrimitive.Parts,
15086
14343
  {
15087
14344
  components: {
15088
14345
  Text: MarkdownText,
@@ -15095,15 +14352,15 @@ const NextAssistantMessage = ({
15095
14352
  };
15096
14353
  const AssistantActionBar = () => {
15097
14354
  return /* @__PURE__ */ jsxRuntime.jsx(
15098
- react$2.ActionBarPrimitive.Root,
14355
+ react$3.ActionBarPrimitive.Root,
15099
14356
  {
15100
14357
  hideWhenRunning: true,
15101
14358
  autohide: "always",
15102
14359
  autohideFloat: "single-branch",
15103
14360
  className: "flex gap-1 items-center transition-all",
15104
- children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", className: "bg-transparent text-icon3 hover:text-icon6", children: [
15105
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { copied: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) }),
15106
- /* @__PURE__ */ jsxRuntime.jsx(react$2.MessagePrimitive.If, { copied: false, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
14361
+ children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ActionBarPrimitive.Copy, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(TooltipIconButton, { tooltip: "Copy", className: "bg-transparent text-icon3 hover:text-icon6", children: [
14362
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { copied: true, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckIcon, {}) }),
14363
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.MessagePrimitive.If, { copied: false, children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CopyIcon, {}) })
15107
14364
  ] }) })
15108
14365
  }
15109
14366
  );
@@ -15116,11 +14373,11 @@ const NetworkThread = ({ ToolFallback, networkName, hasMemory }) => {
15116
14373
  return /* @__PURE__ */ jsxRuntime.jsx(NextAssistantMessage, { ...props, ToolFallback });
15117
14374
  };
15118
14375
  return /* @__PURE__ */ jsxRuntime.jsxs(ThreadWrapper, { children: [
15119
- /* @__PURE__ */ jsxRuntime.jsxs(react$2.ThreadPrimitive.Viewport, { className: "py-10 overflow-y-auto scroll-smooth h-full", ref: areaRef, autoScroll: false, children: [
14376
+ /* @__PURE__ */ jsxRuntime.jsxs(react$3.ThreadPrimitive.Viewport, { className: "py-10 overflow-y-auto scroll-smooth h-full", ref: areaRef, autoScroll: false, children: [
15120
14377
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15121
14378
  /* @__PURE__ */ jsxRuntime.jsx(ThreadWelcome, { networkName }),
15122
14379
  /* @__PURE__ */ jsxRuntime.jsx(
15123
- react$2.ThreadPrimitive.Messages,
14380
+ react$3.ThreadPrimitive.Messages,
15124
14381
  {
15125
14382
  components: {
15126
14383
  UserMessage,
@@ -15130,7 +14387,7 @@ const NetworkThread = ({ ToolFallback, networkName, hasMemory }) => {
15130
14387
  }
15131
14388
  )
15132
14389
  ] }),
15133
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { empty: false, children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) })
14390
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { empty: false, children: /* @__PURE__ */ jsxRuntime.jsx("div", {}) })
15134
14391
  ] }),
15135
14392
  /* @__PURE__ */ jsxRuntime.jsx(Composer, { hasMemory })
15136
14393
  ] });
@@ -15138,7 +14395,7 @@ const NetworkThread = ({ ToolFallback, networkName, hasMemory }) => {
15138
14395
  const ThreadWrapper = ({ children }) => {
15139
14396
  const hasAttachments = useHasAttachments();
15140
14397
  return /* @__PURE__ */ jsxRuntime.jsx(
15141
- react$2.ThreadPrimitive.Root,
14398
+ react$3.ThreadPrimitive.Root,
15142
14399
  {
15143
14400
  className: clsx(
15144
14401
  "max-w-[568px] w-full mx-auto px-4",
@@ -15159,17 +14416,17 @@ const ThreadWelcome = ({ networkName }) => {
15159
14416
  } else {
15160
14417
  initials = "A";
15161
14418
  }
15162
- return /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.Empty, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-grow flex-col items-center justify-center", children: [
14419
+ return /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.Empty, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex w-full flex-grow flex-col items-center justify-center", children: [
15163
14420
  /* @__PURE__ */ jsxRuntime.jsx(Avatar, { children: /* @__PURE__ */ jsxRuntime.jsx(AvatarFallback, { children: initials }) }),
15164
14421
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-4 font-medium", children: "How can I help you today?" })
15165
14422
  ] }) });
15166
14423
  };
15167
14424
  const Composer = ({ hasMemory }) => {
15168
14425
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15169
- /* @__PURE__ */ jsxRuntime.jsxs(react$2.ComposerPrimitive.Root, { children: [
14426
+ /* @__PURE__ */ jsxRuntime.jsxs(react$3.ComposerPrimitive.Root, { children: [
15170
14427
  /* @__PURE__ */ jsxRuntime.jsx(ComposerAttachments, {}),
15171
14428
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full bg-surface3 rounded-lg border-sm border-border1 px-3 py-4 mt-auto h-[100px]", children: [
15172
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Input, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
14429
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Input, { asChild: true, className: "w-full", children: /* @__PURE__ */ jsxRuntime.jsx(
15173
14430
  "textarea",
15174
14431
  {
15175
14432
  className: "text-ui-lg leading-ui-lg placeholder:text-icon3 text-icon6 bg-transparent resize-none",
@@ -15192,7 +14449,7 @@ const Composer = ({ hasMemory }) => {
15192
14449
  ] });
15193
14450
  };
15194
14451
  const SpeechInput = () => {
15195
- const composerRuntime = react$2.useComposerRuntime();
14452
+ const composerRuntime = react$3.useComposerRuntime();
15196
14453
  const { start, stop, isListening, transcript } = useSpeechRecognition({});
15197
14454
  React.useEffect(() => {
15198
14455
  if (!transcript) return;
@@ -15212,8 +14469,8 @@ const SpeechInput = () => {
15212
14469
  };
15213
14470
  const ComposerAction = () => {
15214
14471
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
15215
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Add attachment", variant: "ghost", className: "rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "h-6 w-6 text-[#898989] hover:text-[#fff]" }) }) }),
15216
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { running: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
14472
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.AddAttachment, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Add attachment", variant: "ghost", className: "rounded-full", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PlusIcon, { className: "h-6 w-6 text-[#898989] hover:text-[#fff]" }) }) }),
14473
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { running: false, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
15217
14474
  TooltipIconButton,
15218
14475
  {
15219
14476
  tooltip: "Send",
@@ -15222,15 +14479,15 @@ const ComposerAction = () => {
15222
14479
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUp, { className: "h-6 w-6 text-[#898989] hover:text-[#fff]" })
15223
14480
  }
15224
14481
  ) }) }),
15225
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ThreadPrimitive.If, { running: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Cancel", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsx(CircleStopIcon, {}) }) }) })
14482
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ThreadPrimitive.If, { running: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(TooltipIconButton, { tooltip: "Cancel", variant: "default", children: /* @__PURE__ */ jsxRuntime.jsx(CircleStopIcon, {}) }) }) })
15226
14483
  ] });
15227
14484
  };
15228
14485
  const EditComposer = () => {
15229
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.ComposerPrimitive.Root, { children: [
15230
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Input, {}),
14486
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.ComposerPrimitive.Root, { children: [
14487
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Input, {}),
15231
14488
  /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
15232
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", children: "Cancel" }) }),
15233
- /* @__PURE__ */ jsxRuntime.jsx(react$2.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { children: "Send" }) })
14489
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Cancel, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { variant: "ghost", children: "Cancel" }) }),
14490
+ /* @__PURE__ */ jsxRuntime.jsx(react$3.ComposerPrimitive.Send, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$2, { children: "Send" }) })
15234
14491
  ] })
15235
14492
  ] });
15236
14493
  };
@@ -15548,7 +14805,7 @@ ${formatted}\`\`\``;
15548
14805
  }
15549
14806
  }
15550
14807
  }, [initialMessages, threadId, memory, messages]);
15551
- const mastra = useMastraClient();
14808
+ const mastra = react$2.useMastraClient();
15552
14809
  const network = mastra.getVNextNetwork(networkId);
15553
14810
  const onNew = async (message) => {
15554
14811
  runIdRef.current = void 0;
@@ -15722,13 +14979,13 @@ ${formatted}\`\`\``;
15722
14979
  setIsRunning(false);
15723
14980
  }
15724
14981
  };
15725
- const runtime = react$2.useExternalStoreRuntime({
14982
+ const runtime = react$3.useExternalStoreRuntime({
15726
14983
  isRunning,
15727
14984
  messages,
15728
14985
  convertMessage,
15729
14986
  onNew
15730
14987
  });
15731
- return /* @__PURE__ */ jsxRuntime.jsxs(react$2.AssistantRuntimeProvider, { runtime, children: [
14988
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$3.AssistantRuntimeProvider, { runtime, children: [
15732
14989
  " ",
15733
14990
  children,
15734
14991
  " "
@@ -18279,7 +17536,7 @@ Dropdown.SubTrigger = DropdownMenuSubTrigger;
18279
17536
  Dropdown.RadioGroup = DropdownMenuRadioGroup;
18280
17537
 
18281
17538
  const useTriggerScorer = (onScorerTriggered) => {
18282
- const client = useMastraClient();
17539
+ const client = react$2.useMastraClient();
18283
17540
  return reactQuery.useMutation({
18284
17541
  mutationFn: async ({ scorerName, traceId, spanId }) => {
18285
17542
  const response = await client.score({
@@ -19302,13 +18559,10 @@ exports.JudgeIcon = JudgeIcon;
19302
18559
  exports.Kbd = Kbd;
19303
18560
  exports.KeyValueList = KeyValueList;
19304
18561
  exports.LatencyIcon = LatencyIcon;
19305
- exports.LegacyWorkflowGraph = LegacyWorkflowGraph;
19306
- exports.LegacyWorkflowTrigger = LegacyWorkflowTrigger;
19307
18562
  exports.LinkComponentProvider = LinkComponentProvider;
19308
18563
  exports.LogsIcon = LogsIcon;
19309
18564
  exports.MainContentContent = MainContentContent;
19310
18565
  exports.MainContentLayout = MainContentLayout;
19311
- exports.MastraClientProvider = MastraClientProvider;
19312
18566
  exports.MastraResizablePanel = MastraResizablePanel;
19313
18567
  exports.McpCoinIcon = McpCoinIcon;
19314
18568
  exports.McpServerIcon = McpServerIcon;
@@ -19375,6 +18629,7 @@ exports.ThreadLink = ThreadLink;
19375
18629
  exports.ThreadList = ThreadList;
19376
18630
  exports.Threads = Threads;
19377
18631
  exports.ToolCoinIcon = ToolCoinIcon;
18632
+ exports.ToolFallback = ToolFallback;
19378
18633
  exports.ToolList = ToolList;
19379
18634
  exports.ToolListEmpty = ToolListEmpty;
19380
18635
  exports.ToolListSkeleton = ToolListSkeleton;
@@ -19421,21 +18676,16 @@ exports.spanTypePrefixes = spanTypePrefixes;
19421
18676
  exports.transformKey = transformKey;
19422
18677
  exports.useAgentSettings = useAgentSettings;
19423
18678
  exports.useCurrentRun = useCurrentRun;
19424
- exports.useExecuteWorkflow = useExecuteWorkflow;
19425
18679
  exports.useInView = useInView;
19426
- exports.useLegacyWorkflow = useLegacyWorkflow;
19427
18680
  exports.useLinkComponent = useLinkComponent;
19428
- exports.useMastraClient = useMastraClient;
19429
18681
  exports.usePlaygroundStore = usePlaygroundStore;
19430
18682
  exports.usePolling = usePolling;
19431
- exports.useResumeWorkflow = useResumeWorkflow;
19432
18683
  exports.useScorer = useScorer;
19433
18684
  exports.useScorers = useScorers;
19434
18685
  exports.useScoresByEntityId = useScoresByEntityId;
19435
18686
  exports.useScoresByScorerId = useScoresByScorerId;
19436
18687
  exports.useSpeechRecognition = useSpeechRecognition;
19437
18688
  exports.useThreadInput = useThreadInput;
19438
- exports.useWatchWorkflow = useWatchWorkflow;
19439
18689
  exports.useWorkflow = useWorkflow;
19440
18690
  exports.useWorkflowRuns = useWorkflowRuns;
19441
18691
  exports.useWorkingMemory = useWorkingMemory;