@mastra/playground-ui 2.0.1-alpha.0 → 2.0.1-alpha.2

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/dist/components/ui/data-table.d.ts +5 -1
  2. package/dist/components/ui/resizable.d.ts +1 -1
  3. package/dist/components/ui/text.d.ts +1 -1
  4. package/dist/domains/resizable-panel.d.ts +12 -0
  5. package/dist/domains/workflows/context/workflow-run-context.d.ts +3 -1
  6. package/dist/domains/workflows/workflow/utils.d.ts +5 -4
  7. package/dist/domains/workflows/workflow/workflow-after-node.d.ts +6 -0
  8. package/dist/domains/workflows/workflow/workflow-loop-result-node.d.ts +6 -0
  9. package/dist/hooks/use-resize-column.d.ts +2 -1
  10. package/dist/hooks/use-traces.d.ts +1 -1
  11. package/dist/hooks/use-workflows.d.ts +10 -3
  12. package/dist/index.css +4 -0
  13. package/dist/index.d.ts +1 -1
  14. package/dist/index.es.js +521 -1199
  15. package/dist/index.es.js.map +1 -1
  16. package/dist/lib/polls.d.ts +5 -1
  17. package/package.json +3 -3
  18. package/dist/chat-ui/chat-items.d.ts +0 -52
  19. package/dist/chat-ui/chat-message.d.ts +0 -30
  20. package/dist/chat-ui/chat.d.ts +0 -3
  21. package/dist/chat-ui/copy-button.d.ts +0 -7
  22. package/dist/chat-ui/file-preview.d.ts +0 -8
  23. package/dist/chat-ui/hooks/use-auto-scroll.d.ts +0 -7
  24. package/dist/chat-ui/hooks/use-autosize-textarea.d.ts +0 -8
  25. package/dist/chat-ui/hooks/use-copy-to-clipboard.d.ts +0 -10
  26. package/dist/chat-ui/markdown-renderer.d.ts +0 -88
  27. package/dist/chat-ui/markdown.d.ts +0 -4
  28. package/dist/chat-ui/message-input.d.ts +0 -22
  29. package/dist/chat-ui/message-list.d.ts +0 -11
  30. package/dist/chat-ui/prompt-suggestions.d.ts +0 -11
  31. package/dist/chat-ui/syntax-highlighter.d.ts +0 -1
  32. package/dist/chat-ui/types.d.ts +0 -14
  33. package/dist/chat-ui/typing-indicator.d.ts +0 -1
package/dist/index.es.js CHANGED
@@ -1,24 +1,21 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { MessagePrimitive, ActionBarPrimitive, BranchPickerPrimitive, ThreadPrimitive, ComposerPrimitive, useExternalStoreRuntime, AssistantRuntimeProvider } from '@assistant-ui/react';
3
+ import { CheckIcon, CopyIcon, ChevronLeftIcon, ChevronRightIcon, ArrowUp, Copy, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Braces, Clock1, ChevronDown, XIcon, Footprints, CircleCheck, CircleX, AlertCircleIcon, X, Plus, CalendarIcon, Check, Loader2 } from 'lucide-react';
2
4
  import * as React from 'react';
3
- import React__default, { useState, useRef, useCallback, useEffect, useLayoutEffect, Suspense, useMemo, forwardRef, memo, createContext, useContext, Fragment as Fragment$1 } from 'react';
4
- import { useSWRConfig } from 'swr';
5
- import { MastraClient } from '@mastra/client-js';
6
- import { Check, Copy, X, FileIcon, Paperclip, Square, ArrowUp, Dot, ArrowDown, CheckIcon, CopyIcon, ChevronLeftIcon, ChevronRightIcon, Search, RefreshCcwIcon, ChevronRight, SortAsc, SortDesc, Braces, Clock1, ChevronDown, XIcon, Footprints, AlertCircleIcon, Plus, CalendarIcon, Loader2 } from 'lucide-react';
5
+ import React__default, { forwardRef, memo, useState, useEffect, createContext, useContext, useRef, useMemo, useCallback, Fragment as Fragment$1 } from 'react';
7
6
  import { Slot } from '@radix-ui/react-slot';
8
- import { omit } from 'remeda';
9
- import { motion, AnimatePresence } from 'motion/react';
10
- import Markdown from 'react-markdown';
11
- import remarkGfm from 'remark-gfm';
12
- import { MessagePrimitive, ActionBarPrimitive, BranchPickerPrimitive, ThreadPrimitive, ComposerPrimitive, useExternalStoreRuntime, AssistantRuntimeProvider } from '@assistant-ui/react';
13
7
  import * as TooltipPrimitive from '@radix-ui/react-tooltip';
14
8
  import * as AvatarPrimitive from '@radix-ui/react-avatar';
15
9
  import { unstable_memoizeMarkdownComponents, useIsMarkdownCodeBlock, MarkdownTextPrimitive } from '@assistant-ui/react-markdown';
16
10
  import '@assistant-ui/react-markdown/styles/dot.css';
11
+ import remarkGfm from 'remark-gfm';
17
12
  import { makePrismAsyncSyntaxHighlighter } from '@assistant-ui/react-syntax-highlighter';
18
13
  import { coldarkDark } from 'react-syntax-highlighter/dist/cjs/styles/prism';
14
+ import { MastraClient } from '@mastra/client-js';
19
15
  import { format, formatDistanceToNow, isValid } from 'date-fns';
20
16
  import * as TabsPrimitive from '@radix-ui/react-tabs';
21
17
  import { toast } from 'sonner';
18
+ import { AnimatePresence } from 'motion/react';
22
19
  import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
23
20
  import { jsonLanguage } from '@codemirror/lang-json';
24
21
  import { tags } from '@lezer/highlight';
@@ -44,7 +41,7 @@ import { DayPicker } from 'react-day-picker';
44
41
  import * as SelectPrimitive from '@radix-ui/react-select';
45
42
  import * as LabelPrimitive from '@radix-ui/react-label';
46
43
  import { v4 } from '@lukeed/uuid';
47
- import { CodeBlock as CodeBlock$1 } from 'react-code-block';
44
+ import { CodeBlock } from 'react-code-block';
48
45
 
49
46
  import './index.css';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}
50
47
 
@@ -2837,877 +2834,6 @@ const Button = React.forwardRef(
2837
2834
  );
2838
2835
  Button.displayName = "Button";
2839
2836
 
2840
- function useCopyToClipboard$2({ text, copyMessage = "Copied to clipboard!" }) {
2841
- const [isCopied, setIsCopied] = useState(false);
2842
- const [error, setError] = useState("");
2843
- const timeoutRef = useRef(null);
2844
- const handleCopy = useCallback(() => {
2845
- navigator.clipboard.writeText(text).then(() => {
2846
- setIsCopied(true);
2847
- if (timeoutRef.current) {
2848
- clearTimeout(timeoutRef.current);
2849
- timeoutRef.current = null;
2850
- }
2851
- timeoutRef.current = setTimeout(() => {
2852
- setIsCopied(false);
2853
- }, 2e3);
2854
- }).catch(() => {
2855
- setError("Failed to copy to clipboard.");
2856
- });
2857
- }, [text, copyMessage]);
2858
- return { isCopied, handleCopy, error };
2859
- }
2860
-
2861
- function CopyButton$1({ content, copyMessage, classname }) {
2862
- const { isCopied, handleCopy } = useCopyToClipboard$2({
2863
- text: content,
2864
- copyMessage
2865
- });
2866
- return /* @__PURE__ */ jsxs("button", { className: cn("relative h-6 w-6", classname), "aria-label": "Copy to clipboard", onClick: handleCopy, children: [
2867
- /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: /* @__PURE__ */ jsx(Check, { className: cn("h-4 w-4 transition-transform ease-in-out", isCopied ? "scale-100" : "scale-0") }) }),
2868
- /* @__PURE__ */ jsx(Copy, { className: cn("h-4 w-4 transition-transform ease-in-out", isCopied ? "scale-0" : "scale-100") })
2869
- ] });
2870
- }
2871
-
2872
- const ACTIVATION_THRESHOLD = 50;
2873
- function useAutoScroll(dependencies) {
2874
- const containerRef = useRef(null);
2875
- const previousScrollTop = useRef(null);
2876
- const [shouldAutoScroll, setShouldAutoScroll] = useState(true);
2877
- const scrollToBottom = () => {
2878
- if (containerRef.current) {
2879
- containerRef.current.scrollTop = containerRef.current.scrollHeight;
2880
- }
2881
- };
2882
- const handleScroll = () => {
2883
- if (containerRef.current) {
2884
- const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
2885
- const isScrollingUp = previousScrollTop.current ? scrollTop < previousScrollTop.current : false;
2886
- if (isScrollingUp) {
2887
- setShouldAutoScroll(false);
2888
- } else {
2889
- const isScrolledToBottom = Math.abs(scrollHeight - scrollTop - clientHeight) < ACTIVATION_THRESHOLD;
2890
- setShouldAutoScroll(isScrolledToBottom);
2891
- }
2892
- previousScrollTop.current = scrollTop;
2893
- }
2894
- };
2895
- const handleTouchStart = () => {
2896
- setShouldAutoScroll(false);
2897
- };
2898
- useEffect(() => {
2899
- if (containerRef.current) {
2900
- previousScrollTop.current = containerRef.current.scrollTop;
2901
- }
2902
- }, []);
2903
- useEffect(() => {
2904
- if (shouldAutoScroll) {
2905
- scrollToBottom();
2906
- }
2907
- }, dependencies);
2908
- return {
2909
- containerRef,
2910
- scrollToBottom,
2911
- handleScroll,
2912
- shouldAutoScroll,
2913
- handleTouchStart
2914
- };
2915
- }
2916
-
2917
- const FilePreview = React__default.forwardRef((props, ref) => {
2918
- if (props.file.type.startsWith("image/")) {
2919
- return /* @__PURE__ */ jsx(ImageFilePreview, { ...props, ref });
2920
- }
2921
- if (props.file.type.startsWith("text/") || props.file.name.endsWith(".txt") || props.file.name.endsWith(".md")) {
2922
- return /* @__PURE__ */ jsx(TextFilePreview, { ...props, ref });
2923
- }
2924
- return /* @__PURE__ */ jsx(GenericFilePreview, { ...props, ref });
2925
- });
2926
- FilePreview.displayName = "FilePreview";
2927
- const ImageFilePreview = React__default.forwardRef(({ file, onRemove }, ref) => {
2928
- return /* @__PURE__ */ jsxs(
2929
- motion.div,
2930
- {
2931
- ref,
2932
- className: "relative flex max-w-[200px] rounded-md border p-1.5 pr-2 text-xs",
2933
- layout: true,
2934
- initial: { opacity: 0, y: "100%" },
2935
- animate: { opacity: 1, y: 0 },
2936
- exit: { opacity: 0, y: "100%" },
2937
- children: [
2938
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center space-x-2", children: [
2939
- /* @__PURE__ */ jsx(
2940
- "img",
2941
- {
2942
- alt: `Attachment ${file.name}`,
2943
- className: "bg-muted grid h-10 w-10 shrink-0 place-items-center rounded-sm border object-cover",
2944
- src: URL.createObjectURL(file)
2945
- }
2946
- ),
2947
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground w-full truncate", children: file.name })
2948
- ] }),
2949
- onRemove ? /* @__PURE__ */ jsx(
2950
- "button",
2951
- {
2952
- className: "bg-background absolute -right-2 -top-2 flex h-4 w-4 items-center justify-center rounded-full border",
2953
- type: "button",
2954
- onClick: onRemove,
2955
- "aria-label": "Remove attachment",
2956
- children: /* @__PURE__ */ jsx(X, { className: "h-2.5 w-2.5" })
2957
- }
2958
- ) : null
2959
- ]
2960
- }
2961
- );
2962
- });
2963
- ImageFilePreview.displayName = "ImageFilePreview";
2964
- const TextFilePreview = React__default.forwardRef(({ file, onRemove }, ref) => {
2965
- const [preview, setPreview] = React__default.useState("");
2966
- useEffect(() => {
2967
- const reader = new FileReader();
2968
- reader.onload = (e) => {
2969
- const text = e.target?.result;
2970
- setPreview(text.slice(0, 50) + (text.length > 50 ? "..." : ""));
2971
- };
2972
- reader.readAsText(file);
2973
- }, [file]);
2974
- return /* @__PURE__ */ jsxs(
2975
- motion.div,
2976
- {
2977
- ref,
2978
- className: "relative flex max-w-[200px] rounded-md border p-1.5 pr-2 text-xs",
2979
- layout: true,
2980
- initial: { opacity: 0, y: "100%" },
2981
- animate: { opacity: 1, y: 0 },
2982
- exit: { opacity: 0, y: "100%" },
2983
- children: [
2984
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center space-x-2", children: [
2985
- /* @__PURE__ */ jsx("div", { className: "bg-muted grid h-10 w-10 shrink-0 place-items-center rounded-sm border p-0.5", children: /* @__PURE__ */ jsx("div", { className: "text-muted-foreground h-full w-full overflow-hidden text-[6px] leading-none", children: preview || "Loading..." }) }),
2986
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground w-full truncate", children: file.name })
2987
- ] }),
2988
- onRemove ? /* @__PURE__ */ jsx(
2989
- "button",
2990
- {
2991
- className: "bg-background absolute -right-2 -top-2 flex h-4 w-4 items-center justify-center rounded-full border",
2992
- type: "button",
2993
- onClick: onRemove,
2994
- "aria-label": "Remove attachment",
2995
- children: /* @__PURE__ */ jsx(X, { className: "h-2.5 w-2.5" })
2996
- }
2997
- ) : null
2998
- ]
2999
- }
3000
- );
3001
- });
3002
- TextFilePreview.displayName = "TextFilePreview";
3003
- const GenericFilePreview = React__default.forwardRef(({ file, onRemove }, ref) => {
3004
- return /* @__PURE__ */ jsxs(
3005
- motion.div,
3006
- {
3007
- ref,
3008
- className: "relative flex max-w-[200px] rounded-md border p-1.5 pr-2 text-xs",
3009
- layout: true,
3010
- initial: { opacity: 0, y: "100%" },
3011
- animate: { opacity: 1, y: 0 },
3012
- exit: { opacity: 0, y: "100%" },
3013
- children: [
3014
- /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center space-x-2", children: [
3015
- /* @__PURE__ */ jsx("div", { className: "bg-muted grid h-10 w-10 shrink-0 place-items-center rounded-sm border", children: /* @__PURE__ */ jsx(FileIcon, { className: "text-foreground h-6 w-6" }) }),
3016
- /* @__PURE__ */ jsx("span", { className: "text-muted-foreground w-full truncate", children: file.name })
3017
- ] }),
3018
- onRemove ? /* @__PURE__ */ jsx(
3019
- "button",
3020
- {
3021
- className: "bg-background absolute -right-2 -top-2 flex h-4 w-4 items-center justify-center rounded-full border",
3022
- type: "button",
3023
- onClick: onRemove,
3024
- "aria-label": "Remove attachment",
3025
- children: /* @__PURE__ */ jsx(X, { className: "h-2.5 w-2.5" })
3026
- }
3027
- ) : null
3028
- ]
3029
- }
3030
- );
3031
- });
3032
- GenericFilePreview.displayName = "GenericFilePreview";
3033
-
3034
- function useAutosizeTextArea({
3035
- ref,
3036
- maxHeight = Number.MAX_SAFE_INTEGER,
3037
- borderWidth = 0,
3038
- dependencies
3039
- }) {
3040
- const originalHeight = useRef(null);
3041
- useLayoutEffect(() => {
3042
- if (!ref.current) return;
3043
- const currentRef = ref.current;
3044
- const borderAdjustment = borderWidth * 2;
3045
- if (originalHeight.current === null) {
3046
- originalHeight.current = currentRef.scrollHeight - borderAdjustment;
3047
- }
3048
- currentRef.style.removeProperty("height");
3049
- const scrollHeight = currentRef.scrollHeight;
3050
- const clampedToMax = Math.min(scrollHeight, maxHeight);
3051
- const clampedToMin = Math.max(clampedToMax, originalHeight.current);
3052
- currentRef.style.height = `${clampedToMin + borderAdjustment}px`;
3053
- }, [maxHeight, ref, ...dependencies]);
3054
- }
3055
-
3056
- function MessageInput({
3057
- placeholder = "Ask AI...",
3058
- className,
3059
- onKeyDown: onKeyDownProp,
3060
- submitOnEnter = true,
3061
- stop,
3062
- isGenerating,
3063
- ...props
3064
- }) {
3065
- const [isDragging, setIsDragging] = useState(false);
3066
- const addFiles = (files) => {
3067
- if (props.allowAttachments) {
3068
- props.setFiles((currentFiles) => {
3069
- if (currentFiles === null) {
3070
- return files;
3071
- }
3072
- if (files === null) {
3073
- return currentFiles;
3074
- }
3075
- return [...currentFiles, ...files];
3076
- });
3077
- }
3078
- };
3079
- const onDragOver = (event) => {
3080
- if (props.allowAttachments !== true) return;
3081
- event.preventDefault();
3082
- setIsDragging(true);
3083
- };
3084
- const onDragLeave = (event) => {
3085
- if (props.allowAttachments !== true) return;
3086
- event.preventDefault();
3087
- setIsDragging(false);
3088
- };
3089
- const onDrop = (event) => {
3090
- setIsDragging(false);
3091
- if (props.allowAttachments !== true) return;
3092
- event.preventDefault();
3093
- const dataTransfer = event.dataTransfer;
3094
- if (dataTransfer.files.length) {
3095
- addFiles(Array.from(dataTransfer.files));
3096
- }
3097
- };
3098
- const onPaste = (event) => {
3099
- const items = event.clipboardData?.items;
3100
- if (!items) return;
3101
- const files = Array.from(items).map((item) => item.getAsFile()).filter((file) => file !== null);
3102
- if (props.allowAttachments && files.length > 0) {
3103
- addFiles(files);
3104
- }
3105
- };
3106
- const onKeyDown = (event) => {
3107
- if (submitOnEnter && event.key === "Enter" && !event.shiftKey) {
3108
- event.preventDefault();
3109
- event.currentTarget.form?.requestSubmit();
3110
- }
3111
- onKeyDownProp?.(event);
3112
- };
3113
- const textAreaRef = useRef(null);
3114
- const showFileList = props.allowAttachments && props.files && props.files.length > 0;
3115
- useAutosizeTextArea({
3116
- ref: textAreaRef,
3117
- maxHeight: 240,
3118
- borderWidth: 1,
3119
- dependencies: [props.value, showFileList]
3120
- });
3121
- return /* @__PURE__ */ jsxs("div", { className: "relative mx-auto flex w-full", onDragOver, onDragLeave, onDrop, children: [
3122
- /* @__PURE__ */ jsx(
3123
- "textarea",
3124
- {
3125
- "aria-label": "Write your prompt here",
3126
- placeholder,
3127
- ref: textAreaRef,
3128
- onPaste,
3129
- onKeyDown,
3130
- className: cn(
3131
- "ring-offset-background placeholder:text-muted-foreground focus-visible:border-primary h-[98px] w-full grow resize-none rounded-2xl border-[0.5px] border-[#424242] bg-[#141414] p-3 pr-24 text-sm shadow-[0px_2px_8.1px_0px_rgba(0,0,0,0.20);] transition-[border] focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
3132
- showFileList && "pb-16",
3133
- className
3134
- ),
3135
- ...props.allowAttachments ? omit(props, ["allowAttachments", "files", "setFiles"]) : omit(props, ["allowAttachments"])
3136
- }
3137
- ),
3138
- props.allowAttachments && /* @__PURE__ */ jsx("div", { className: "absolute inset-x-3 bottom-0 overflow-x-scroll py-3", children: /* @__PURE__ */ jsx("div", { className: "flex space-x-3", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", children: props.files?.map((file) => {
3139
- return /* @__PURE__ */ jsx(
3140
- FilePreview,
3141
- {
3142
- file,
3143
- onRemove: () => {
3144
- props.setFiles((files) => {
3145
- if (!files) return null;
3146
- const filtered = Array.from(files).filter((f) => f !== file);
3147
- if (filtered.length === 0) return null;
3148
- return filtered;
3149
- });
3150
- }
3151
- },
3152
- file.name + String(file.lastModified)
3153
- );
3154
- }) }) }) }),
3155
- /* @__PURE__ */ jsxs("div", { className: "absolute bottom-3 right-3 flex gap-2", children: [
3156
- props.allowAttachments && /* @__PURE__ */ jsx(
3157
- Button,
3158
- {
3159
- type: "button",
3160
- size: "icon",
3161
- variant: "outline",
3162
- className: "h-8 w-8",
3163
- "aria-label": "Attach a file",
3164
- onClick: async () => {
3165
- const files = await showFileUploadDialog();
3166
- addFiles(files);
3167
- },
3168
- children: /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" })
3169
- }
3170
- ),
3171
- isGenerating && stop ? /* @__PURE__ */ jsx(Button, { type: "button", size: "icon", className: "h-8 w-8", "aria-label": "Stop generating", onClick: stop, children: /* @__PURE__ */ jsx(Square, { className: "h-3 w-3 animate-pulse", fill: "currentColor" }) }) : /* @__PURE__ */ jsx(
3172
- Button,
3173
- {
3174
- type: "submit",
3175
- variant: "secondary",
3176
- size: "icon",
3177
- className: "mt-0 h-8 w-8 rounded-full transition-opacity",
3178
- "aria-label": "Send message",
3179
- disabled: props.value === "" || isGenerating,
3180
- children: /* @__PURE__ */ jsx(ArrowUp, { className: "h-6 w-6" })
3181
- }
3182
- )
3183
- ] }),
3184
- props.allowAttachments && /* @__PURE__ */ jsx(FileUploadOverlay, { isDragging })
3185
- ] });
3186
- }
3187
- MessageInput.displayName = "MessageInput";
3188
- function FileUploadOverlay({ isDragging }) {
3189
- return /* @__PURE__ */ jsx(AnimatePresence, { children: isDragging && /* @__PURE__ */ jsxs(
3190
- motion.div,
3191
- {
3192
- className: "border-border bg-background text-muted-foreground pointer-events-none absolute inset-0 flex items-center justify-center space-x-2 rounded-xl border border-dashed text-sm",
3193
- initial: { opacity: 0 },
3194
- animate: { opacity: 1 },
3195
- exit: { opacity: 0 },
3196
- transition: { duration: 0.2 },
3197
- "aria-hidden": true,
3198
- children: [
3199
- /* @__PURE__ */ jsx(Paperclip, { className: "h-4 w-4" }),
3200
- /* @__PURE__ */ jsx("span", { children: "Drop your files here to attach them." })
3201
- ]
3202
- }
3203
- ) });
3204
- }
3205
- function showFileUploadDialog() {
3206
- const input = document.createElement("input");
3207
- input.type = "file";
3208
- input.multiple = true;
3209
- input.accept = "*/*";
3210
- input.click();
3211
- return new Promise((resolve) => {
3212
- input.onchange = (e) => {
3213
- const files = e.currentTarget.files;
3214
- if (files) {
3215
- resolve(Array.from(files));
3216
- return;
3217
- }
3218
- resolve(null);
3219
- };
3220
- });
3221
- }
3222
-
3223
- async function highlight(code, language) {
3224
- const { codeToTokens, bundledLanguages } = await import('shiki');
3225
- if (!(language in bundledLanguages)) return null;
3226
- const { tokens } = await codeToTokens(code, {
3227
- lang: language,
3228
- defaultColor: false,
3229
- themes: {
3230
- light: "github-light",
3231
- dark: "github-dark"
3232
- }
3233
- });
3234
- return tokens;
3235
- }
3236
-
3237
- function MarkdownRenderer({ children }) {
3238
- const processedText = children?.replace(/\\n/g, "\n");
3239
- return /* @__PURE__ */ jsx(Markdown, { remarkPlugins: [remarkGfm], components: COMPONENTS, className: "space-y-3", children: processedText });
3240
- }
3241
- const HighlightedPre = React__default.memo(({ children, language, ...props }) => {
3242
- const [tokens, setTokens] = useState([]);
3243
- useEffect(() => {
3244
- highlight(children, language).then((tokens2) => {
3245
- if (tokens2) setTokens(tokens2);
3246
- });
3247
- }, [children, language]);
3248
- if (!tokens.length) {
3249
- return /* @__PURE__ */ jsx("pre", { ...props, children });
3250
- }
3251
- return /* @__PURE__ */ jsx("pre", { ...props, children: /* @__PURE__ */ jsx("code", { children: tokens.map((line, lineIndex) => /* @__PURE__ */ jsxs(Fragment, { children: [
3252
- /* @__PURE__ */ jsx("span", { children: line.map((token, tokenIndex) => {
3253
- const style = typeof token.htmlStyle === "string" ? void 0 : token.htmlStyle;
3254
- return /* @__PURE__ */ jsx(
3255
- "span",
3256
- {
3257
- className: "text-shiki-light bg-shiki-light-bg dark:text-shiki-dark dark:bg-shiki-dark-bg",
3258
- style,
3259
- children: token.content
3260
- },
3261
- tokenIndex
3262
- );
3263
- }) }, lineIndex),
3264
- lineIndex !== tokens.length - 1 && "\n"
3265
- ] })) }) });
3266
- });
3267
- HighlightedPre.displayName = "HighlightedCode";
3268
- const CodeBlock = ({ children, className, language, ...restProps }) => {
3269
- const code = typeof children === "string" ? children : childrenTakeAllStringContents(children);
3270
- const preClass = cn(
3271
- "overflow-x-scroll rounded-md border bg-background/50 p-4 font-mono text-sm [scrollbar-width:none]",
3272
- className
3273
- );
3274
- return /* @__PURE__ */ jsxs("div", { className: "group/code relative mb-4", children: [
3275
- /* @__PURE__ */ jsx(
3276
- Suspense,
3277
- {
3278
- fallback: /* @__PURE__ */ jsx("pre", { className: preClass, ...restProps, children }),
3279
- children: /* @__PURE__ */ jsx(HighlightedPre, { language, className: preClass, children: code })
3280
- }
3281
- ),
3282
- /* @__PURE__ */ jsx("div", { className: "invisible absolute right-2 top-2 flex space-x-1 rounded-lg p-1 opacity-0 transition-all duration-200 group-hover/code:visible group-hover/code:opacity-100", children: /* @__PURE__ */ jsx(CopyButton$1, { content: code, copyMessage: "Copied code to clipboard" }) })
3283
- ] });
3284
- };
3285
- function childrenTakeAllStringContents(element) {
3286
- if (typeof element === "string") {
3287
- return element;
3288
- }
3289
- if (element && typeof element === "object" && "props" in element) {
3290
- const el = element;
3291
- const children = el.props.children;
3292
- if (Array.isArray(children)) {
3293
- return children.map((child) => childrenTakeAllStringContents(child)).join("");
3294
- } else {
3295
- return childrenTakeAllStringContents(children);
3296
- }
3297
- }
3298
- return "";
3299
- }
3300
- const COMPONENTS = {
3301
- h1: withClass("h1", "text-2xl font-semibold"),
3302
- h2: withClass("h2", "font-semibold text-xl"),
3303
- h3: withClass("h3", "font-semibold text-lg"),
3304
- h4: withClass("h4", "font-semibold text-base"),
3305
- h5: withClass("h5", "font-medium"),
3306
- strong: withClass("strong", "font-semibold"),
3307
- a: withClass("a", "text-primary underline underline-offset-2"),
3308
- blockquote: withClass("blockquote", "border-l-2 border-primary pl-4"),
3309
- code: ({ children, className, ...rest }) => {
3310
- const match = /language-(\w+)/.exec(className || "");
3311
- return match ? /* @__PURE__ */ jsx(CodeBlock, { className, language: match[1], ...rest, children }) : /* @__PURE__ */ jsx(
3312
- "code",
3313
- {
3314
- className: cn(
3315
- "[:not(pre)>&]:bg-background/50 font-mono [:not(pre)>&]:rounded-md [:not(pre)>&]:px-1 [:not(pre)>&]:py-0.5"
3316
- ),
3317
- ...rest,
3318
- children
3319
- }
3320
- );
3321
- },
3322
- pre: ({ children }) => children,
3323
- ol: withClass("ol", "list-decimal space-y-2 pl-6"),
3324
- ul: withClass("ul", "list-disc space-y-2 pl-6"),
3325
- li: withClass("li", "my-1.5"),
3326
- table: withClass("table", "w-full border-collapse overflow-y-auto rounded-md border border-foreground/20"),
3327
- th: withClass(
3328
- "th",
3329
- "border border-foreground/20 px-4 py-2 text-left font-bold [&[align=center]]:text-center [&[align=right]]:text-right"
3330
- ),
3331
- td: withClass(
3332
- "td",
3333
- "border border-foreground/20 px-4 py-2 text-left [&[align=center]]:text-center [&[align=right]]:text-right"
3334
- ),
3335
- tr: withClass("tr", "m-0 border-t p-0 even:bg-muted"),
3336
- p: withClass("p", "whitespace-pre-wrap leading-relaxed"),
3337
- hr: withClass("hr", "border-foreground/20")
3338
- };
3339
- function withClass(Tag, classes) {
3340
- const Component = ({ node, ...props }) => /* @__PURE__ */ jsx(Tag, { className: classes, ...props });
3341
- Component.displayName = Tag;
3342
- return Component;
3343
- }
3344
-
3345
- const chatBubbleVariants = cva("group/message relative break-words rounded-xl px-3 py-2 text-sm sm:max-w-[70%]", {
3346
- variants: {
3347
- isUser: {
3348
- true: "bg-primary text-primary-foreground",
3349
- false: "bg-muted text-foreground"
3350
- },
3351
- isError: {
3352
- true: "bg-red-100 dark:bg-red-900/20",
3353
- false: ""
3354
- },
3355
- animation: {
3356
- none: "",
3357
- slide: "duration-300 animate-in fade-in-0",
3358
- scale: "duration-300 animate-in fade-in-0 zoom-in-75",
3359
- fade: "duration-500 animate-in fade-in-0"
3360
- }
3361
- },
3362
- compoundVariants: [
3363
- {
3364
- isUser: true,
3365
- animation: "slide",
3366
- class: "slide-in-from-right"
3367
- },
3368
- {
3369
- isUser: false,
3370
- animation: "slide",
3371
- class: "slide-in-from-left"
3372
- },
3373
- {
3374
- isUser: true,
3375
- animation: "scale",
3376
- class: "origin-bottom-right"
3377
- },
3378
- {
3379
- isUser: false,
3380
- animation: "scale",
3381
- class: "origin-bottom-left"
3382
- }
3383
- ]
3384
- });
3385
- const ChatMessage = ({
3386
- role,
3387
- content,
3388
- createdAt,
3389
- showTimeStamp = false,
3390
- animation = "scale",
3391
- actions,
3392
- className,
3393
- experimental_attachments,
3394
- isError = false
3395
- }) => {
3396
- const isUser = role === "user";
3397
- const files = useMemo(() => {
3398
- return experimental_attachments?.map((attachment) => {
3399
- const dataArray = dataUrlToUint8Array(attachment.url);
3400
- const file = new File([dataArray], attachment.name ?? "Unknown");
3401
- return file;
3402
- });
3403
- }, [experimental_attachments]);
3404
- const formattedTime = createdAt?.toLocaleTimeString("en-US", {
3405
- hour: "2-digit",
3406
- minute: "2-digit"
3407
- });
3408
- return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col", isUser ? "items-end" : "items-start"), children: [
3409
- files ? /* @__PURE__ */ jsx("div", { className: "mb-1 flex flex-wrap gap-2", children: files.map((file, index) => {
3410
- return /* @__PURE__ */ jsx(FilePreview, { file }, index);
3411
- }) }) : null,
3412
- /* @__PURE__ */ jsxs("div", { className: cn(chatBubbleVariants({ isUser, isError, animation: "none" }), className), children: [
3413
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(MarkdownRenderer, { children: content }) }),
3414
- role === "assistant" && actions ? /* @__PURE__ */ jsx("div", { className: "bg-background text-foreground absolute -bottom-4 right-2 flex space-x-1 rounded-lg border p-1 opacity-0 transition-opacity group-hover/message:opacity-100", children: actions }) : null
3415
- ] }),
3416
- showTimeStamp && createdAt ? /* @__PURE__ */ jsx(
3417
- "time",
3418
- {
3419
- dateTime: createdAt.toISOString(),
3420
- className: cn(
3421
- "mt-1 block px-1 text-xs opacity-50",
3422
- animation !== "none" && "animate-in fade-in-0 duration-500"
3423
- ),
3424
- children: formattedTime
3425
- }
3426
- ) : null
3427
- ] });
3428
- };
3429
- function dataUrlToUint8Array(data) {
3430
- const base64 = data.split(",")[1];
3431
- const buf = Buffer.from(base64 ?? "", "base64");
3432
- return new Uint8Array(buf);
3433
- }
3434
-
3435
- function TypingIndicator() {
3436
- return /* @__PURE__ */ jsx("div", { className: "justify-left flex space-x-1", children: /* @__PURE__ */ jsx("div", { className: "bg-muted flex items-center gap-1 rounded-lg px-2 py-3", children: /* @__PURE__ */ jsxs("div", { className: "flex -space-x-2.5", children: [
3437
- /* @__PURE__ */ jsx(Dot, { className: "animate-typing-dot-bounce h-5 w-5" }),
3438
- /* @__PURE__ */ jsx(Dot, { className: "animate-typing-dot-bounce h-5 w-5 delay-200" }),
3439
- /* @__PURE__ */ jsx(Dot, { className: "animate-typing-dot-bounce h-5 w-5 delay-500" })
3440
- ] }) }) });
3441
- }
3442
-
3443
- function MessageList({ messages, showTimeStamps = true, isTyping = false, messageOptions }) {
3444
- return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-3xl space-y-4 px-3 pt-3", children: [
3445
- messages.map((message, index) => {
3446
- const additionalOptions = typeof messageOptions === "function" ? messageOptions(message) : messageOptions;
3447
- if (message.role === "assistant" && !message.content.trim()) {
3448
- return null;
3449
- }
3450
- return /* @__PURE__ */ jsx(ChatMessage, { showTimeStamp: showTimeStamps, ...message, ...additionalOptions }, index);
3451
- }),
3452
- isTyping && /* @__PURE__ */ jsx(TypingIndicator, {})
3453
- ] });
3454
- }
3455
-
3456
- function PromptSuggestions({ append, suggestions, memoryIsPresent }) {
3457
- return /* @__PURE__ */ jsx("div", { className: "flex gap-6 text-sm", children: suggestions.map((suggestion) => /* @__PURE__ */ jsx(
3458
- "button",
3459
- {
3460
- type: "button",
3461
- onClick: () => append({ role: "user", content: suggestion }),
3462
- className: "h-max rounded-[0.4rem] bg-[#141414] p-4 py-[0.6rem]",
3463
- children: /* @__PURE__ */ jsx(
3464
- "span",
3465
- {
3466
- className: cn("text-[#939393] transition-colors hover:text-white", memoryIsPresent ? "text-xs" : "text-sm"),
3467
- children: suggestion
3468
- }
3469
- )
3470
- },
3471
- suggestion
3472
- )) });
3473
- }
3474
-
3475
- function ChatMessages({
3476
- messages,
3477
- children
3478
- }) {
3479
- const { scrollToBottom, shouldAutoScroll } = useAutoScroll([messages]);
3480
- return /* @__PURE__ */ jsxs("div", { className: "h-full overflow-y-scroll pb-4", children: [
3481
- children,
3482
- /* @__PURE__ */ jsx("div", { className: "flex flex-1 items-end justify-end [grid-column:1/1] [grid-row:1/1]", children: !shouldAutoScroll && /* @__PURE__ */ jsx("div", { className: "sticky bottom-0 left-0 flex w-full justify-end", children: /* @__PURE__ */ jsx(
3483
- Button,
3484
- {
3485
- onClick: scrollToBottom,
3486
- className: "animate-in fade-in-0 slide-in-from-bottom-1 h-8 w-8 rounded-full ease-in-out",
3487
- size: "icon",
3488
- variant: "ghost",
3489
- children: /* @__PURE__ */ jsx(ArrowDown, { className: "h-4 w-4" })
3490
- }
3491
- ) }) })
3492
- ] });
3493
- }
3494
- const ChatContainer = forwardRef(
3495
- ({ className, ...props }, ref) => {
3496
- return /* @__PURE__ */ jsx("div", { ref, className: cn("w-full", className), ...props });
3497
- }
3498
- );
3499
- ChatContainer.displayName = "ChatContainer";
3500
- const ChatForm = forwardRef(
3501
- ({ children, handleSubmit, isPending, className }, ref) => {
3502
- const [files, setFiles] = useState(null);
3503
- const onSubmit = (event) => {
3504
- if (isPending) {
3505
- event.preventDefault();
3506
- return;
3507
- }
3508
- if (!files) {
3509
- handleSubmit(event);
3510
- return;
3511
- }
3512
- const fileList = createFileList(files);
3513
- handleSubmit(event, { experimental_attachments: fileList });
3514
- setFiles(null);
3515
- };
3516
- return /* @__PURE__ */ jsx("form", { ref, onSubmit, className, children: children({ files, setFiles }) });
3517
- }
3518
- );
3519
- ChatForm.displayName = "ChatForm";
3520
- function createFileList(files) {
3521
- const dataTransfer = new DataTransfer();
3522
- for (const file of Array.from(files)) {
3523
- dataTransfer.items.add(file);
3524
- }
3525
- return dataTransfer.files;
3526
- }
3527
-
3528
- function Chat({ agentId, initialMessages = [], agentName, threadId, memory, buildUrl }) {
3529
- const [messages, setMessages] = useState(initialMessages);
3530
- const [input, setInput] = useState("");
3531
- const [isLoading, setIsLoading] = useState(false);
3532
- const { mutate } = useSWRConfig();
3533
- const { containerRef, handleScroll, handleTouchStart } = useAutoScroll([messages]);
3534
- useEffect(() => {
3535
- setMessages(initialMessages);
3536
- }, [initialMessages]);
3537
- const handleInputChange = useCallback((e) => {
3538
- setInput(e.target.value);
3539
- }, []);
3540
- const handleSubmit = useCallback(
3541
- async (event) => {
3542
- event?.preventDefault?.();
3543
- if (!input.trim() || isLoading) return;
3544
- const userMessage = input;
3545
- setInput("");
3546
- setIsLoading(true);
3547
- const newUserMessage = {
3548
- id: Date.now().toString(),
3549
- role: "user",
3550
- content: userMessage
3551
- };
3552
- const newAssistantMessage = {
3553
- id: (Date.now() + 1).toString(),
3554
- role: "assistant",
3555
- content: ""
3556
- };
3557
- setMessages((prev) => [...prev, newUserMessage, newAssistantMessage]);
3558
- const newThreadId = threadId ? threadId : crypto.randomUUID();
3559
- try {
3560
- const client = new MastraClient({
3561
- baseUrl: buildUrl || ""
3562
- });
3563
- const response = await client.getAgent(agentId).stream({
3564
- messages: [userMessage],
3565
- threadId: newThreadId,
3566
- resourceId: agentId
3567
- });
3568
- if (!response.body) return;
3569
- if (response.status !== 200) {
3570
- const error = await response.json();
3571
- setMessages((prev) => [
3572
- ...prev.slice(0, -1),
3573
- {
3574
- ...prev[prev.length - 1],
3575
- content: error.error,
3576
- isError: true
3577
- }
3578
- ]);
3579
- return;
3580
- }
3581
- await mutate(`${buildUrl}/api/memory/threads?resourceid=${agentId}`);
3582
- const reader = response.body.getReader();
3583
- const decoder = new TextDecoder();
3584
- let buffer = "";
3585
- let assistantMessage = "";
3586
- while (true) {
3587
- const { done, value } = await reader.read();
3588
- if (done) {
3589
- break;
3590
- }
3591
- const chunk = decoder.decode(value);
3592
- buffer += chunk;
3593
- if (buffer?.toLocaleLowerCase()?.includes("an error occurred")) {
3594
- setMessages((prev) => [
3595
- ...prev.slice(0, -1),
3596
- {
3597
- ...prev[prev.length - 1],
3598
- content: "An error occurred while processing your request.",
3599
- isError: true
3600
- }
3601
- ]);
3602
- return;
3603
- }
3604
- const matches = buffer.matchAll(/0:"([^"]*)"/g);
3605
- for (const match of matches) {
3606
- const content = match[1];
3607
- assistantMessage += content;
3608
- setMessages((prev) => [...prev.slice(0, -1), { ...prev[prev.length - 1], content: assistantMessage }]);
3609
- }
3610
- buffer = "";
3611
- }
3612
- } catch (error) {
3613
- console.error("Error:", error);
3614
- setMessages((prev) => [
3615
- ...prev.slice(0, -1),
3616
- {
3617
- ...prev[prev.length - 1],
3618
- content: "An error occurred while processing your request.",
3619
- isError: true
3620
- }
3621
- ]);
3622
- } finally {
3623
- setIsLoading(false);
3624
- }
3625
- },
3626
- [input, isLoading, buildUrl, agentId, threadId, mutate]
3627
- );
3628
- const lastMessage = messages.at(-1);
3629
- const isEmpty = messages.length === 0;
3630
- const isTyping = isLoading && lastMessage?.role === "assistant" && !lastMessage?.content.trim();
3631
- const append = useCallback(
3632
- (message) => {
3633
- setInput(message.content);
3634
- handleSubmit();
3635
- },
3636
- [handleSubmit]
3637
- );
3638
- const suggestions = ["What capabilities do you have?", "How can you help me?", "Tell me about yourself"];
3639
- return /* @__PURE__ */ jsxs(ChatContainer, { className: "relative flex h-full w-full flex-col overflow-y-clip pb-9", children: [
3640
- /* @__PURE__ */ jsx(
3641
- "div",
3642
- {
3643
- ref: containerRef,
3644
- onScroll: handleScroll,
3645
- onTouchStart: handleTouchStart,
3646
- className: "h-full overflow-y-clip bg-transparent pb-[calc(98px+2rem)]",
3647
- children: /* @__PURE__ */ jsx(ChatMessages, { messages, children: /* @__PURE__ */ jsx(MessageList, { messages, isTyping }) })
3648
- }
3649
- ),
3650
- /* @__PURE__ */ jsxs("div", { className: "absolute bottom-8 left-1/2 flex w-full max-w-3xl -translate-x-1/2 flex-col gap-2 bg-[#0f0f0f] pb-3", children: [
3651
- isEmpty ? /* @__PURE__ */ jsx("div", { className: "mx-auto max-w-2xl", children: /* @__PURE__ */ jsx(
3652
- PromptSuggestions,
3653
- {
3654
- memoryIsPresent: memory,
3655
- label: `Chat with ${agentName}`,
3656
- append,
3657
- suggestions
3658
- }
3659
- ) }) : null,
3660
- /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(ChatForm, { isPending: isLoading || isTyping, handleSubmit, children: ({ files, setFiles }) => /* @__PURE__ */ jsx(
3661
- MessageInput,
3662
- {
3663
- value: input,
3664
- onChange: handleInputChange,
3665
- files,
3666
- setFiles,
3667
- isGenerating: isLoading,
3668
- placeholder: `Enter your message...`
3669
- }
3670
- ) }) }),
3671
- !memory && /* @__PURE__ */ jsxs("div", { className: "text-mastra-el-5 flex items-center gap-1 text-sm", children: [
3672
- /* @__PURE__ */ jsxs(
3673
- "svg",
3674
- {
3675
- xmlns: "http://www.w3.org/2000/svg",
3676
- width: "14",
3677
- height: "14",
3678
- viewBox: "0 0 24 24",
3679
- fill: "none",
3680
- stroke: "currentColor",
3681
- strokeWidth: "2",
3682
- strokeLinecap: "round",
3683
- strokeLinejoin: "round",
3684
- className: "text-purple-400",
3685
- children: [
3686
- /* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "10" }),
3687
- /* @__PURE__ */ jsx("path", { d: "M12 16v-4" }),
3688
- /* @__PURE__ */ jsx("path", { d: "M12 8h.01" })
3689
- ]
3690
- }
3691
- ),
3692
- /* @__PURE__ */ jsxs("span", { className: "text-xs text-gray-300/60", children: [
3693
- "Agent will not remember previous messages. To enable memory for agent see",
3694
- " ",
3695
- /* @__PURE__ */ jsx(
3696
- "a",
3697
- {
3698
- href: "https://mastra.ai/docs/agents/01-agent-memory",
3699
- target: "_blank",
3700
- rel: "noopener",
3701
- className: "text-gray-300/60 underline hover:text-gray-100",
3702
- children: "docs."
3703
- }
3704
- )
3705
- ] })
3706
- ] })
3707
- ] })
3708
- ] });
3709
- }
3710
-
3711
2837
  const TooltipProvider = TooltipPrimitive.Provider;
3712
2838
  const Tooltip = TooltipPrimitive.Root;
3713
2839
  const TooltipTrigger = TooltipPrimitive.Trigger;
@@ -4378,7 +3504,7 @@ function MastraRuntimeProvider({
4378
3504
  refreshThreadList?.();
4379
3505
  }
4380
3506
  } catch (error) {
4381
- console.error("Error occured in MastraRuntimeProvider", error);
3507
+ console.error("Error occurred in MastraRuntimeProvider", error);
4382
3508
  setIsRunning(false);
4383
3509
  }
4384
3510
  };
@@ -4523,7 +3649,7 @@ const Table = React.forwardRef(
4523
3649
  );
4524
3650
  Table.displayName = "Table";
4525
3651
  const TableHeader = React.forwardRef(
4526
- ({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b", className), ...props })
3652
+ ({ className, ...props }, ref) => /* @__PURE__ */ jsx("thead", { ref, className: cn("[&_tr]:border-b-[0.5px]", className), ...props })
4527
3653
  );
4528
3654
  TableHeader.displayName = "TableHeader";
4529
3655
  const TableBody = React.forwardRef(
@@ -4616,7 +3742,7 @@ const useEvalsByAgentId = (agentId, type, baseUrl) => {
4616
3742
  };
4617
3743
 
4618
3744
  const AgentEvalsContext = createContext({ handleRefresh: () => {
4619
- }, isLoading: false });
3745
+ }, isLoading: true });
4620
3746
  const scrollableContentClass = cn(
4621
3747
  "relative overflow-y-auto overflow-x-hidden invisible hover:visible focus:visible",
4622
3748
  "[&::-webkit-scrollbar]:w-1",
@@ -4648,6 +3774,13 @@ function AgentEvals({ agentId, baseUrl }) {
4648
3774
  handleRefresh,
4649
3775
  isLoading: activeTab === "live" ? isLiveLoading : isCiLoading
4650
3776
  };
3777
+ function handleRefresh() {
3778
+ if (activeTab === "live") {
3779
+ refetchLiveEvals();
3780
+ } else {
3781
+ refetchCiEvals();
3782
+ }
3783
+ }
4651
3784
  return /* @__PURE__ */ jsx(AgentEvalsContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
4652
3785
  Tabs,
4653
3786
  {
@@ -4655,7 +3788,7 @@ function AgentEvals({ agentId, baseUrl }) {
4655
3788
  onValueChange: (value) => setActiveTab(value),
4656
3789
  className: "grid grid-rows-[auto_1fr] h-full min-h-0 pb-2",
4657
3790
  children: [
4658
- /* @__PURE__ */ jsx("div", { className: "bg-mastra-bg-2 border-b border-mastra-border/10", children: /* @__PURE__ */ jsxs(TabsList, { className: "bg-transparent border-0 h-auto mx-4 pt-5", children: [
3791
+ /* @__PURE__ */ jsx("div", { className: "border-b border-mastra-border/10", children: /* @__PURE__ */ jsxs(TabsList, { className: "bg-transparent border-0 h-auto mx-4", children: [
4659
3792
  /* @__PURE__ */ jsx(TabsTrigger, { value: "live", className: tabIndicatorClass, children: "Live" }),
4660
3793
  /* @__PURE__ */ jsx(TabsTrigger, { value: "ci", className: tabIndicatorClass, children: "CI" })
4661
3794
  ] }) }),
@@ -4664,32 +3797,14 @@ function AgentEvals({ agentId, baseUrl }) {
4664
3797
  ]
4665
3798
  }
4666
3799
  ) });
4667
- function handleRefresh() {
4668
- if (activeTab === "live") {
4669
- refetchLiveEvals();
4670
- } else {
4671
- refetchCiEvals();
4672
- }
4673
- }
4674
3800
  }
4675
3801
  function EvalTable({ evals, isCIMode = false }) {
4676
3802
  const { handleRefresh, isLoading: isTableLoading } = useContext(AgentEvalsContext);
4677
3803
  const [expandedMetrics, setExpandedMetrics] = useState(/* @__PURE__ */ new Set());
4678
3804
  const [searchTerm, setSearchTerm] = useState("");
4679
3805
  const [sortConfig, setSortConfig] = useState({ field: "metricName", direction: "asc" });
4680
- const [showLoading, setShowLoading] = useState(false);
4681
- useEffect(() => {
4682
- if (isTableLoading) {
4683
- const timer = setTimeout(() => {
4684
- setShowLoading(true);
4685
- }, 200);
4686
- return () => clearTimeout(timer);
4687
- } else {
4688
- setShowLoading(false);
4689
- }
4690
- }, [isTableLoading]);
4691
3806
  return /* @__PURE__ */ jsxs("div", { className: "min-h-0 grid grid-rows-[auto_1fr]", children: [
4692
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 p-4 bg-mastra-bg-2 rounded-lg", children: [
3807
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 p-4 rounded-lg", children: [
4693
3808
  /* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
4694
3809
  /* @__PURE__ */ jsx(Search, { className: "absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-mastra-el-3" }),
4695
3810
  /* @__PURE__ */ jsx(
@@ -4707,11 +3822,11 @@ function EvalTable({ evals, isCIMode = false }) {
4707
3822
  evals.length,
4708
3823
  " Total Evaluations"
4709
3824
  ] }),
4710
- /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", onClick: handleRefresh, disabled: showLoading, className: "h-9 w-9", children: showLoading ? /* @__PURE__ */ jsx(RefreshCcwIcon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(RefreshCcwIcon, { className: "h-4 w-4" }) })
3825
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon", onClick: handleRefresh, disabled: isTableLoading, className: "h-9 w-9", children: isTableLoading ? /* @__PURE__ */ jsx(RefreshCcwIcon, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(RefreshCcwIcon, { className: "h-4 w-4" }) })
4711
3826
  ] }),
4712
3827
  /* @__PURE__ */ jsx("div", { className: "overflow-auto", children: /* @__PURE__ */ jsxs(Table, { className: "w-full", children: [
4713
- /* @__PURE__ */ jsx(TableHeader, { className: "bg-mastra-bg-2 sticky top-0 z-10", children: /* @__PURE__ */ jsxs(TableRow, { className: "border-gray-6 border-b-[0.1px] text-[0.8125rem]", children: [
4714
- /* @__PURE__ */ jsx(TableHead, { className: "w-12" }),
3828
+ /* @__PURE__ */ jsx(TableHeader, { className: "bg-mastra-bg-2 h-[var(--table-header-height)] sticky top-0 z-10", children: /* @__PURE__ */ jsxs(TableRow, { className: "border-gray-6 border-b-[0.1px] text-[0.8125rem]", children: [
3829
+ /* @__PURE__ */ jsx(TableHead, { className: "w-12 h-12" }),
4715
3830
  /* @__PURE__ */ jsx(
4716
3831
  TableHead,
4717
3832
  {
@@ -4730,17 +3845,20 @@ function EvalTable({ evals, isCIMode = false }) {
4730
3845
  ] }) }),
4731
3846
  /* @__PURE__ */ jsx(TableHead, { className: "w-48 text-mastra-el-3", children: "Evaluations" })
4732
3847
  ] }) }),
4733
- /* @__PURE__ */ jsx(TableBody, { className: "border-b border-gray-6 relative", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", presenceAffectsLayout: false, children: showLoading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs(TableRow, { className: "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", children: [
4734
- /* @__PURE__ */ jsx(TableCell, { className: "w-12", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-8 rounded-full" }) }),
4735
- /* @__PURE__ */ jsx(TableCell, { className: "min-w-[200px]", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }) }),
3848
+ /* @__PURE__ */ jsx(TableBody, { className: "border-b border-gray-6 relative", children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", presenceAffectsLayout: false, children: isTableLoading ? Array.from({ length: 3 }).map((_, i) => /* @__PURE__ */ jsxs(TableRow, { className: "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", children: [
3849
+ /* @__PURE__ */ jsx(TableCell, { className: "w-12 h-12", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-8 rounded-full" }) }),
3850
+ /* @__PURE__ */ jsx(TableCell, { className: "min-w-[200px] max-w-[30%]", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-3/4" }) }),
4736
3851
  /* @__PURE__ */ jsx(TableCell, { className: "flex-1", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-full" }) }),
4737
3852
  /* @__PURE__ */ jsx(TableCell, { className: "w-48", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }) }),
4738
- /* @__PURE__ */ jsx(TableCell, { className: "w-48", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-16" }) })
4739
- ] }, i)) : groupEvals(evals).length === 0 ? /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 5, className: "h-32 text-center text-mastra-el-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
4740
- /* @__PURE__ */ jsx(Search, { className: "h-8 w-8" }),
4741
- /* @__PURE__ */ jsx("p", { children: "No evaluations found" }),
4742
- searchTerm && /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Try adjusting your search terms" })
4743
- ] }) }) }) : groupEvals(evals).map((group) => /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
3853
+ /* @__PURE__ */ jsx(TableCell, { className: "w-48", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-20" }) })
3854
+ ] }, i)) : groupEvals(evals).length === 0 ? /* @__PURE__ */ jsxs(TableRow, { children: [
3855
+ /* @__PURE__ */ jsx(TableCell, { className: "h-12 w-16" }),
3856
+ /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "h-32 px-4 text-center text-mastra-el-3", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2", children: [
3857
+ /* @__PURE__ */ jsx(Search, { className: "size-5" }),
3858
+ /* @__PURE__ */ jsx("p", { children: "No evaluations found" }),
3859
+ searchTerm && /* @__PURE__ */ jsx("p", { className: "text-sm", children: "Try adjusting your search terms" })
3860
+ ] }) })
3861
+ ] }) : groupEvals(evals).map((group) => /* @__PURE__ */ jsxs(React__default.Fragment, { children: [
4744
3862
  /* @__PURE__ */ jsxs(
4745
3863
  TableRow,
4746
3864
  {
@@ -4859,20 +3977,103 @@ function EvalTable({ evals, isCIMode = false }) {
4859
3977
  )
4860
3978
  );
4861
3979
  }
4862
- groups.sort((a, b) => {
4863
- const direction = sortConfig.direction === "asc" ? 1 : -1;
4864
- switch (sortConfig.field) {
4865
- case "metricName":
4866
- return direction * a.metricName.localeCompare(b.metricName);
4867
- case "averageScore":
4868
- return direction * (a.averageScore - b.averageScore);
4869
- default:
4870
- return 0;
3980
+ groups.sort((a, b) => {
3981
+ const direction = sortConfig.direction === "asc" ? 1 : -1;
3982
+ switch (sortConfig.field) {
3983
+ case "metricName":
3984
+ return direction * a.metricName.localeCompare(b.metricName);
3985
+ case "averageScore":
3986
+ return direction * (a.averageScore - b.averageScore);
3987
+ default:
3988
+ return 0;
3989
+ }
3990
+ });
3991
+ return groups;
3992
+ }
3993
+ }
3994
+
3995
+ const useResizeColumn = ({
3996
+ defaultWidth,
3997
+ minimumWidth,
3998
+ maximumWidth,
3999
+ setCurrentWidth
4000
+ }) => {
4001
+ const [isDragging, setIsDragging] = useState(false);
4002
+ const [sidebarWidth, setSidebarWidth] = useState(defaultWidth);
4003
+ const containerRef = useRef(null);
4004
+ const dragStartXRef = useRef(0);
4005
+ const initialWidthRef = useRef(0);
4006
+ const handleMouseDown = (e) => {
4007
+ e.preventDefault();
4008
+ setIsDragging(true);
4009
+ dragStartXRef.current = e.clientX;
4010
+ initialWidthRef.current = sidebarWidth;
4011
+ };
4012
+ useEffect(() => {
4013
+ setSidebarWidth(defaultWidth);
4014
+ setCurrentWidth?.(defaultWidth);
4015
+ }, [defaultWidth]);
4016
+ useEffect(() => {
4017
+ const handleMouseMove = (e) => {
4018
+ if (!isDragging || !containerRef.current) return;
4019
+ const containerWidth = containerRef.current.offsetWidth;
4020
+ const deltaX = dragStartXRef.current - e.clientX;
4021
+ const deltaPercentage = deltaX / containerWidth * 100;
4022
+ const newWidth = Math.min(Math.max(initialWidthRef.current + deltaPercentage, minimumWidth), maximumWidth);
4023
+ setSidebarWidth(newWidth);
4024
+ setCurrentWidth?.(newWidth);
4025
+ };
4026
+ const handleMouseUp = () => {
4027
+ setIsDragging(false);
4028
+ };
4029
+ if (isDragging) {
4030
+ window.addEventListener("mousemove", handleMouseMove);
4031
+ window.addEventListener("mouseup", handleMouseUp);
4032
+ }
4033
+ return () => {
4034
+ window.removeEventListener("mousemove", handleMouseMove);
4035
+ window.removeEventListener("mouseup", handleMouseUp);
4036
+ };
4037
+ }, [isDragging]);
4038
+ return { sidebarWidth, isDragging, handleMouseDown, containerRef };
4039
+ };
4040
+
4041
+ const MastraResizablePanel = ({
4042
+ children,
4043
+ defaultWidth,
4044
+ minimumWidth,
4045
+ maximumWidth,
4046
+ className,
4047
+ disabled = false,
4048
+ setCurrentWidth,
4049
+ dividerPosition = "left"
4050
+ }) => {
4051
+ const { sidebarWidth, isDragging, handleMouseDown, containerRef } = useResizeColumn({
4052
+ defaultWidth: disabled ? 100 : defaultWidth,
4053
+ minimumWidth,
4054
+ maximumWidth,
4055
+ setCurrentWidth
4056
+ });
4057
+ return /* @__PURE__ */ jsxs("div", { className: cn("w-full h-full relative", className), ref: containerRef, style: { width: `${sidebarWidth}%` }, children: [
4058
+ !disabled && dividerPosition === "left" ? /* @__PURE__ */ jsx(
4059
+ "div",
4060
+ {
4061
+ className: `w-1 bg-mastra-bg-1 bg-[#121212] h-full cursor-col-resize hover:w-1.5 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
4062
+ ${isDragging ? "bg-mastra-border-2 bg-[#424242] w-1.5 cursor- col-resize" : ""}`,
4063
+ onMouseDown: handleMouseDown
4871
4064
  }
4872
- });
4873
- return groups;
4874
- }
4875
- }
4065
+ ) : null,
4066
+ children,
4067
+ !disabled && dividerPosition === "right" ? /* @__PURE__ */ jsx(
4068
+ "div",
4069
+ {
4070
+ className: `w-1 bg-mastra-bg-1 bg-[#121212] h-full cursor-col-resize hover:w-1.5 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
4071
+ ${isDragging ? "bg-mastra-border-2 bg-[#424242] w-1.5 cursor- col-resize" : ""}`,
4072
+ onMouseDown: handleMouseDown
4073
+ }
4074
+ ) : null
4075
+ ] });
4076
+ };
4876
4077
 
4877
4078
  const ScrollArea = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(ScrollAreaPrimitive.Root, { ref, className: cn("relative overflow-hidden", className), ...props, children: [
4878
4079
  /* @__PURE__ */ jsx(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit]", children }),
@@ -5052,11 +4253,18 @@ const allowedAiSpanAttributes = [
5052
4253
  ];
5053
4254
 
5054
4255
  function Traces({ traces }) {
5055
- const { setTraces, trace: currentTrace } = useContext(TraceContext);
5056
- const currentTraceParentSpan = currentTrace?.find((span) => span.parentSpanId === void 0) || currentTrace?.[0];
4256
+ const { trace: currentTrace } = useContext(TraceContext);
4257
+ const [prevTracesId, setPrevTracesId] = useState(/* @__PURE__ */ new Set());
5057
4258
  useEffect(() => {
5058
- setTraces(traces);
4259
+ if (!prevTracesId.size && traces) {
4260
+ setPrevTracesId(new Set(traces.map((trace) => trace.traceId)));
4261
+ }
5059
4262
  }, [traces]);
4263
+ const isNew = (traceId) => {
4264
+ if (!prevTracesId.size) return false;
4265
+ return !prevTracesId.has(traceId);
4266
+ };
4267
+ const currentTraceParentSpan = currentTrace?.find((span) => span.parentSpanId === void 0) || currentTrace?.[0];
5060
4268
  return /* @__PURE__ */ jsx("div", { className: "h-full w-[calc(100%_-_400px)]", children: /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", children: /* @__PURE__ */ jsxs(Table, { children: [
5061
4269
  /* @__PURE__ */ jsx(TableHeader, { className: "sticky top-0 z-10 bg-[#0F0F0F]", style: { outline: "1px solid 0_0%_20.4%" }, children: /* @__PURE__ */ jsxs(TableRow, { className: "border-gray-6 border-b-[0.1px] text-[0.8125rem]", children: [
5062
4270
  /* @__PURE__ */ jsx(TableHead, { className: "text-mastra-el-3 h-10", children: "Trace" }),
@@ -5070,9 +4278,13 @@ function Traces({ traces }) {
5070
4278
  /* @__PURE__ */ jsx(TableBody, { className: "border-b border-gray-6", children: !traces.length ? /* @__PURE__ */ jsx(TableRow, { className: "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "h-24 text-center", children: "No traces found" }) }) : traces.map((trace, index) => /* @__PURE__ */ jsxs(
5071
4279
  TableRow,
5072
4280
  {
5073
- className: cn("border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", {
5074
- "bg-muted/50": currentTraceParentSpan?.traceId === trace.traceId
5075
- }),
4281
+ className: cn(
4282
+ "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]",
4283
+ isNew(trace.traceId) ? "animate-fade-in" : "not-new",
4284
+ {
4285
+ "bg-muted/50": currentTraceParentSpan?.traceId === trace.traceId
4286
+ }
4287
+ ),
5076
4288
  children: [
5077
4289
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
5078
4290
  TraceButton,
@@ -5461,59 +4673,14 @@ function AttributesValues({ attributes, depth = 0 }) {
5461
4673
  return /* @__PURE__ */ jsx("span", { className: "text-gray-400", children: String(processedValue) });
5462
4674
  }
5463
4675
 
5464
- const useResizeColumn = ({
5465
- defaultWidth,
5466
- minimumWidth,
5467
- maximumWidth
5468
- }) => {
5469
- const [isDragging, setIsDragging] = useState(false);
5470
- const [sidebarWidth, setSidebarWidth] = useState(defaultWidth);
5471
- const { isOpen } = useContext(TraceContext);
5472
- const containerRef = useRef(null);
5473
- const dragStartXRef = useRef(0);
5474
- const initialWidthRef = useRef(0);
5475
- const handleMouseDown = (e) => {
5476
- e.preventDefault();
5477
- setIsDragging(true);
5478
- dragStartXRef.current = e.clientX;
5479
- initialWidthRef.current = sidebarWidth;
5480
- };
5481
- useEffect(() => {
5482
- if (!isOpen) {
5483
- setSidebarWidth(defaultWidth);
5484
- }
5485
- }, [isOpen]);
5486
- useEffect(() => {
5487
- const handleMouseMove = (e) => {
5488
- if (!isDragging || !containerRef.current) return;
5489
- const containerWidth = containerRef.current.offsetWidth;
5490
- const deltaX = dragStartXRef.current - e.clientX;
5491
- const deltaPercentage = deltaX / containerWidth * 100;
5492
- const newWidth = Math.min(Math.max(initialWidthRef.current + deltaPercentage, minimumWidth), maximumWidth);
5493
- setSidebarWidth(newWidth);
5494
- };
5495
- const handleMouseUp = () => {
5496
- setIsDragging(false);
5497
- };
5498
- if (isDragging) {
5499
- window.addEventListener("mousemove", handleMouseMove);
5500
- window.addEventListener("mouseup", handleMouseUp);
5501
- }
5502
- return () => {
5503
- window.removeEventListener("mousemove", handleMouseMove);
5504
- window.removeEventListener("mouseup", handleMouseUp);
5505
- };
5506
- }, [isDragging]);
5507
- return { sidebarWidth, isDragging, handleMouseDown, containerRef };
5508
- };
5509
-
5510
4676
  function usePolling({
5511
4677
  fetchFn,
5512
4678
  interval = 3e3,
5513
4679
  enabled = false,
5514
4680
  onSuccess,
5515
4681
  onError,
5516
- shouldContinue = () => true
4682
+ shouldContinue = () => true,
4683
+ restartPolling = false
5517
4684
  }) {
5518
4685
  const [isPolling, setIsPolling] = useState(enabled);
5519
4686
  const [error, setError] = useState(null);
@@ -5522,6 +4689,7 @@ function usePolling({
5522
4689
  const [firstCallLoading, setFirstCallLoading] = useState(false);
5523
4690
  const timeoutRef = useRef(null);
5524
4691
  const mountedRef = useRef(true);
4692
+ const [restart, setRestart] = useState(restartPolling);
5525
4693
  const cleanup = useCallback(() => {
5526
4694
  console.log("cleanup");
5527
4695
  if (timeoutRef.current) {
@@ -5540,17 +4708,15 @@ function usePolling({
5540
4708
  setError(null);
5541
4709
  }, []);
5542
4710
  const executePoll = useCallback(
5543
- async (fistCall = false) => {
4711
+ async (refetch2 = true) => {
5544
4712
  if (!mountedRef.current) return;
5545
4713
  setIsLoading(true);
5546
- setFirstCallLoading(fistCall);
5547
4714
  try {
5548
4715
  const result = await fetchFn();
5549
4716
  setData(result);
5550
4717
  setError(null);
5551
4718
  onSuccess?.(result);
5552
- setFirstCallLoading(false);
5553
- if (shouldContinue(result)) {
4719
+ if (shouldContinue(result) && refetch2) {
5554
4720
  timeoutRef.current = setTimeout(executePoll, interval);
5555
4721
  } else {
5556
4722
  stopPolling();
@@ -5569,6 +4735,18 @@ function usePolling({
5569
4735
  },
5570
4736
  [fetchFn, interval, onSuccess, onError, shouldContinue, stopPolling]
5571
4737
  );
4738
+ const refetch = useCallback(
4739
+ (withPolling = false) => {
4740
+ console.log("refetch", { withPolling });
4741
+ if (withPolling) {
4742
+ setIsPolling(true);
4743
+ } else {
4744
+ executePoll(false);
4745
+ }
4746
+ setError(null);
4747
+ },
4748
+ [executePoll]
4749
+ );
5572
4750
  useEffect(() => {
5573
4751
  mountedRef.current = true;
5574
4752
  if (enabled && isPolling) {
@@ -5580,6 +4758,16 @@ function usePolling({
5580
4758
  cleanup();
5581
4759
  };
5582
4760
  }, [enabled, isPolling, executePoll, cleanup]);
4761
+ useEffect(() => {
4762
+ setRestart(restartPolling);
4763
+ }, [restartPolling]);
4764
+ useEffect(() => {
4765
+ if (restart && !isPolling) {
4766
+ setIsPolling(true);
4767
+ executePoll();
4768
+ setRestart(false);
4769
+ }
4770
+ }, [restart]);
5583
4771
  return {
5584
4772
  isPolling,
5585
4773
  isLoading,
@@ -5587,15 +4775,19 @@ function usePolling({
5587
4775
  data,
5588
4776
  startPolling,
5589
4777
  stopPolling,
5590
- firstCallLoading
4778
+ firstCallLoading,
4779
+ refetch
5591
4780
  };
5592
4781
  }
5593
4782
 
5594
4783
  const useTraces = (componentName, baseUrl, isWorkflow = false) => {
5595
- const [traces, setTraces] = useState(null);
5596
- const client = new MastraClient({
5597
- baseUrl: baseUrl || ""
5598
- });
4784
+ const [traces, setTraces] = useState([]);
4785
+ const client = useMemo(
4786
+ () => new MastraClient({
4787
+ baseUrl: baseUrl || ""
4788
+ }),
4789
+ [baseUrl]
4790
+ );
5599
4791
  const fetchFn = useCallback(async () => {
5600
4792
  try {
5601
4793
  const res = await client.getTelemetry({
@@ -5611,7 +4803,7 @@ const useTraces = (componentName, baseUrl, isWorkflow = false) => {
5611
4803
  } catch (error2) {
5612
4804
  throw error2;
5613
4805
  }
5614
- }, [componentName]);
4806
+ }, [client, componentName, isWorkflow]);
5615
4807
  const onSuccess = useCallback((newTraces) => {
5616
4808
  if (newTraces.length > 0) {
5617
4809
  setTraces(() => newTraces);
@@ -5620,8 +4812,8 @@ const useTraces = (componentName, baseUrl, isWorkflow = false) => {
5620
4812
  const onError = useCallback((error2) => {
5621
4813
  toast.error(error2.message);
5622
4814
  }, []);
5623
- const shouldContinue = useCallback(() => {
5624
- return true;
4815
+ const shouldContinue = useCallback((result) => {
4816
+ return result.length > 0;
5625
4817
  }, []);
5626
4818
  const { firstCallLoading, error } = usePolling({
5627
4819
  fetchFn,
@@ -5648,11 +4840,6 @@ function AgentTracesInner({
5648
4840
  }) {
5649
4841
  const { traces, error, firstCallLoading } = useTraces(agentName, baseUrl);
5650
4842
  const { isOpen: open } = useContext(TraceContext);
5651
- const { sidebarWidth, isDragging, handleMouseDown, containerRef } = useResizeColumn({
5652
- defaultWidth: 60,
5653
- minimumWidth: 50,
5654
- maximumWidth: 90
5655
- });
5656
4843
  if (firstCallLoading) {
5657
4844
  return /* @__PURE__ */ jsxs("main", { className: "flex-1 relative overflow-hidden h-full", children: [
5658
4845
  /* @__PURE__ */ jsx("div", { className: "h-full w-[calc(100%_-_400px)]", children: /* @__PURE__ */ jsxs(Table, { children: [
@@ -5672,7 +4859,7 @@ function AgentTracesInner({
5672
4859
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }) })
5673
4860
  ] }) })
5674
4861
  ] }) }),
5675
- /* @__PURE__ */ jsx(SidebarItems$1, { sidebarChild })
4862
+ /* @__PURE__ */ jsx(SidebarItems$1, { sidebarChild, className: "min-w-[400px]" })
5676
4863
  ] });
5677
4864
  }
5678
4865
  if (!traces || traces.length === 0) {
@@ -5689,59 +4876,28 @@ function AgentTracesInner({
5689
4876
  ] }) }),
5690
4877
  /* @__PURE__ */ jsx(TableBody, { className: "border-b border-gray-6", children: /* @__PURE__ */ jsx(TableRow, { className: "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "h-24 text-center", children: error?.message || "No traces found" }) }) })
5691
4878
  ] }) }),
5692
- /* @__PURE__ */ jsx(SidebarItems$1, { sidebarChild })
4879
+ /* @__PURE__ */ jsx(SidebarItems$1, { sidebarChild, className: "min-w-[400px]" })
5693
4880
  ] });
5694
4881
  }
5695
- return /* @__PURE__ */ jsxs("main", { className: "flex-1 h-full relative overflow-hidden", ref: containerRef, children: [
4882
+ return /* @__PURE__ */ jsxs("main", { className: "flex-1 h-full relative overflow-hidden", children: [
5696
4883
  /* @__PURE__ */ jsx(Traces, { traces }),
5697
- /* @__PURE__ */ jsx(
5698
- SidebarItems$1,
5699
- {
5700
- sidebarWidth,
5701
- className: cn(open ? "grid grid-cols-2 w-[60%]" : ""),
5702
- isDragging,
5703
- handleMouseDown,
5704
- sidebarChild
5705
- }
5706
- )
4884
+ /* @__PURE__ */ jsx(SidebarItems$1, { sidebarChild, className: cn(open ? "grid grid-cols-2 w-[60%]" : "min-w-[400px]") })
5707
4885
  ] });
5708
4886
  }
5709
- function SidebarItems$1({
5710
- sidebarChild,
5711
- className,
5712
- sidebarWidth,
5713
- isDragging,
5714
- handleMouseDown
5715
- }) {
4887
+ function SidebarItems$1({ sidebarChild, className }) {
5716
4888
  const { openDetail, isOpen: open } = useContext(TraceContext);
5717
- const {
5718
- sidebarWidth: rightSidebarWidth,
5719
- isDragging: innerIsDragging,
5720
- handleMouseDown: handleInnerMouseDown,
5721
- containerRef: innerContainerRef
5722
- } = useResizeColumn({
5723
- defaultWidth: 50,
5724
- minimumWidth: 30,
5725
- maximumWidth: 80
5726
- });
4889
+ const [rightSidebarWidth, setRightSidebarWidth] = useState(40);
5727
4890
  return /* @__PURE__ */ jsxs(
5728
- "aside",
4891
+ MastraResizablePanel,
5729
4892
  {
5730
4893
  className: cn(
5731
- "absolute right-0 top-0 h-full w-[400px] z-20 overflow-x-scroll border-l-[0.5px] bg-mastra-bg-1 bg-[#121212]",
4894
+ "absolute right-0 top-0 h-full z-20 overflow-x-scroll border-l-[0.5px] bg-mastra-bg-1 bg-[#121212]",
5732
4895
  className
5733
4896
  ),
5734
- style: { width: open ? `${sidebarWidth}%` : void 0 },
5735
- ref: innerContainerRef,
4897
+ defaultWidth: open ? 60 : 30,
4898
+ minimumWidth: open ? 50 : 30,
4899
+ maximumWidth: open ? 90 : 50,
5736
4900
  children: [
5737
- open ? /* @__PURE__ */ jsx(
5738
- "div",
5739
- {
5740
- className: `w-1 bg-mastra-bg-1 bg-[#121212] h-full cursor-col-resize hover:w-2 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
5741
- ${isDragging ? "bg-mastra-border-2 bg-[#424242] w-2 cursor-col-resize" : ""}`,
5742
- onMouseDown: handleMouseDown
5743
- }
5744
- ) : null,
5745
4901
  open && /* @__PURE__ */ jsx(
5746
4902
  "div",
5747
4903
  {
@@ -5750,22 +4906,19 @@ function SidebarItems$1({
5750
4906
  children: /* @__PURE__ */ jsx(TraceDetails, {})
5751
4907
  }
5752
4908
  ),
5753
- /* @__PURE__ */ jsxs(
5754
- "div",
4909
+ /* @__PURE__ */ jsx(
4910
+ MastraResizablePanel,
5755
4911
  {
5756
- className: "h-full overflow-y-hidden border-l-[0.5px] absolute right-0 top-0 z-20 bg-mastra-bg-1 bg-[#121212]",
5757
- style: { width: `${openDetail ? rightSidebarWidth : 100}%` },
5758
- children: [
5759
- openDetail ? /* @__PURE__ */ jsx(
5760
- "div",
5761
- {
5762
- className: `w-1 h-full bg-mastra-bg-1 bg-[#121212] cursor-col-resize hover:w-2 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
5763
- ${innerIsDragging ? "bg-mastra-border-2 bg-[#424242] w-2 cursor-col-resize" : ""}`,
5764
- onMouseDown: handleInnerMouseDown
5765
- }
5766
- ) : null,
5767
- /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-scroll", children: !openDetail ? sidebarChild : /* @__PURE__ */ jsx(SpanDetail, {}) })
5768
- ]
4912
+ defaultWidth: 50,
4913
+ minimumWidth: 30,
4914
+ maximumWidth: 80,
4915
+ className: cn("h-full overflow-y-hidden border-l-[0.5px] right-0 top-0 z-20 bg-mastra-bg-1 bg-[#121212]", {
4916
+ absolute: open,
4917
+ "unset-position": !open
4918
+ }),
4919
+ disabled: !open,
4920
+ setCurrentWidth: setRightSidebarWidth,
4921
+ children: /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-scroll", children: !openDetail ? sidebarChild : /* @__PURE__ */ jsx(SpanDetail, {}) })
5769
4922
  }
5770
4923
  )
5771
4924
  ]
@@ -5823,7 +4976,8 @@ const DataTable = ({
5823
4976
  emptyStateHeight,
5824
4977
  getRowId,
5825
4978
  selectedRowId,
5826
- isLoading
4979
+ isLoading,
4980
+ emptyText
5827
4981
  }) => {
5828
4982
  const [sorting, setSorting] = useState([]);
5829
4983
  const [{ pageIndex, pageSize }, setPagination] = useState({
@@ -5898,7 +5052,10 @@ const DataTable = ({
5898
5052
  },
5899
5053
  cell.id
5900
5054
  ))
5901
- ] }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: columns.length, className: cn("h-24 text-center", emptyStateHeight), children: "No results." }) }) })
5055
+ ] }, row.id)) : /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsxs(TableCell, { colSpan: columns.length, className: cn("h-24 text-center", emptyStateHeight), children: [
5056
+ "No ",
5057
+ emptyText || "results"
5058
+ ] }) }) })
5902
5059
  ] }) }),
5903
5060
  pagination && /* @__PURE__ */ jsxs("div", { className: "mt-4 flex items-center justify-between px-2", children: [
5904
5061
  /* @__PURE__ */ jsxs("div", { className: "text-muted-foreground text-sm", children: [
@@ -5928,6 +5085,7 @@ const AgentsTable = ({
5928
5085
  return /* @__PURE__ */ jsx(
5929
5086
  DataTable,
5930
5087
  {
5088
+ emptyText: "Agents",
5931
5089
  title,
5932
5090
  isLoading,
5933
5091
  withoutBorder: true,
@@ -5935,7 +5093,7 @@ const AgentsTable = ({
5935
5093
  icon: /* @__PURE__ */ jsx(AgentIcon, { className: "h-4 w-4" }),
5936
5094
  columns,
5937
5095
  data: agentsList,
5938
- className: "border-t-0' border-[0.5px] border-x-0"
5096
+ className: "!border-t-0 border-[0.5px] border-x-0"
5939
5097
  }
5940
5098
  );
5941
5099
  };
@@ -5954,11 +5112,6 @@ function WorkflowTracesInner({
5954
5112
  }) {
5955
5113
  const { traces, error, firstCallLoading } = useTraces(workflowName, baseUrl, true);
5956
5114
  const { isOpen: open } = useContext(TraceContext);
5957
- const { sidebarWidth, isDragging, handleMouseDown, containerRef } = useResizeColumn({
5958
- defaultWidth: 60,
5959
- minimumWidth: 50,
5960
- maximumWidth: 90
5961
- });
5962
5115
  if (firstCallLoading) {
5963
5116
  return /* @__PURE__ */ jsxs("main", { className: "flex-1 h-full relative overflow-hidden", children: [
5964
5117
  /* @__PURE__ */ jsx("div", { className: "h-full w-[calc(100%_-_400px)]", children: /* @__PURE__ */ jsxs(Table, { children: [
@@ -5978,7 +5131,7 @@ function WorkflowTracesInner({
5978
5131
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }) })
5979
5132
  ] }) })
5980
5133
  ] }) }),
5981
- /* @__PURE__ */ jsx(SidebarItems, { sidebarChild })
5134
+ /* @__PURE__ */ jsx(SidebarItems, { sidebarChild, className: "min-w-[400px]" })
5982
5135
  ] });
5983
5136
  }
5984
5137
  if (!traces || traces.length === 0) {
@@ -5995,59 +5148,28 @@ function WorkflowTracesInner({
5995
5148
  ] }) }),
5996
5149
  /* @__PURE__ */ jsx(TableBody, { className: "border-b border-gray-6", children: /* @__PURE__ */ jsx(TableRow, { className: "border-b-gray-6 border-b-[0.1px] text-[0.8125rem]", children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "h-24 text-center", children: error?.message || "No traces found" }) }) })
5997
5150
  ] }) }),
5998
- /* @__PURE__ */ jsx(SidebarItems, { sidebarChild })
5151
+ /* @__PURE__ */ jsx(SidebarItems, { sidebarChild, className: "min-w-[400px]" })
5999
5152
  ] });
6000
5153
  }
6001
- return /* @__PURE__ */ jsxs("main", { className: "flex-1 h-full relative overflow-hidden", ref: containerRef, children: [
5154
+ return /* @__PURE__ */ jsxs("main", { className: "flex-1 h-full relative overflow-hidden", children: [
6002
5155
  /* @__PURE__ */ jsx(Traces, { traces }),
6003
- /* @__PURE__ */ jsx(
6004
- SidebarItems,
6005
- {
6006
- sidebarWidth,
6007
- className: cn(open ? "grid grid-cols-2 w-[60%]" : ""),
6008
- isDragging,
6009
- handleMouseDown,
6010
- sidebarChild
6011
- }
6012
- )
5156
+ /* @__PURE__ */ jsx(SidebarItems, { className: cn(open ? "grid grid-cols-2 w-[60%]" : "min-w-[400px]"), sidebarChild })
6013
5157
  ] });
6014
5158
  }
6015
- function SidebarItems({
6016
- sidebarChild,
6017
- className,
6018
- sidebarWidth,
6019
- isDragging,
6020
- handleMouseDown
6021
- }) {
5159
+ function SidebarItems({ sidebarChild, className }) {
6022
5160
  const { openDetail, isOpen: open } = useContext(TraceContext);
6023
- const {
6024
- sidebarWidth: rightSidebarWidth,
6025
- isDragging: innerIsDragging,
6026
- handleMouseDown: handleInnerMouseDown,
6027
- containerRef: innerContainerRef
6028
- } = useResizeColumn({
6029
- defaultWidth: 50,
6030
- minimumWidth: 30,
6031
- maximumWidth: 80
6032
- });
5161
+ const [rightSidebarWidth, setRightSidebarWidth] = useState(40);
6033
5162
  return /* @__PURE__ */ jsxs(
6034
- "aside",
5163
+ MastraResizablePanel,
6035
5164
  {
6036
5165
  className: cn(
6037
- "absolute right-0 top-0 h-full w-[400px] z-20 overflow-x-scroll border-l-[0.5px] bg-mastra-bg-1 bg-[#121212]",
5166
+ "absolute right-0 top-0 h-full z-20 overflow-x-scroll border-l-[0.5px] bg-mastra-bg-1 bg-[#121212]",
6038
5167
  className
6039
5168
  ),
6040
- style: { width: open ? `${sidebarWidth}%` : void 0 },
6041
- ref: innerContainerRef,
5169
+ defaultWidth: open ? 60 : 30,
5170
+ minimumWidth: open ? 50 : 30,
5171
+ maximumWidth: open ? 90 : 50,
6042
5172
  children: [
6043
- open ? /* @__PURE__ */ jsx(
6044
- "div",
6045
- {
6046
- className: `w-1 bg-mastra-bg-1 bg-[#121212] h-full cursor-col-resize hover:w-2 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
6047
- ${isDragging ? "bg-mastra-border-2 bg-[#424242] w-2 cursor-col-resize" : ""}`,
6048
- onMouseDown: handleMouseDown
6049
- }
6050
- ) : null,
6051
5173
  open && /* @__PURE__ */ jsx(
6052
5174
  "div",
6053
5175
  {
@@ -6056,22 +5178,19 @@ function SidebarItems({
6056
5178
  children: /* @__PURE__ */ jsx(TraceDetails, {})
6057
5179
  }
6058
5180
  ),
6059
- /* @__PURE__ */ jsxs(
6060
- "div",
5181
+ /* @__PURE__ */ jsx(
5182
+ MastraResizablePanel,
6061
5183
  {
6062
- className: "h-full overflow-y-hidden border-l-[0.5px] absolute right-0 top-0 z-20 bg-mastra-bg-1 bg-[#121212]",
6063
- style: { width: `${openDetail ? rightSidebarWidth : 100}%` },
6064
- children: [
6065
- openDetail ? /* @__PURE__ */ jsx(
6066
- "div",
6067
- {
6068
- className: `w-1 h-full bg-mastra-bg-1 bg-[#121212] cursor-col-resize hover:w-2 hover:bg-mastra-border-2 hover:bg-[#424242] active:bg-mastra-border-3 active:bg-[#3e3e3e] transition-colors absolute inset-y-0 -left-1 -right-1 z-10
6069
- ${innerIsDragging ? "bg-mastra-border-2 bg-[#424242] w-2 cursor-col-resize" : ""}`,
6070
- onMouseDown: handleInnerMouseDown
6071
- }
6072
- ) : null,
6073
- /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-scroll", children: !openDetail ? sidebarChild : /* @__PURE__ */ jsx(SpanDetail, {}) })
6074
- ]
5184
+ defaultWidth: 50,
5185
+ minimumWidth: 30,
5186
+ maximumWidth: 80,
5187
+ className: cn("h-full overflow-y-hidden border-l-[0.5px] right-0 top-0 z-20 bg-mastra-bg-1 bg-[#121212]", {
5188
+ absolute: open,
5189
+ "unset-position": !open
5190
+ }),
5191
+ disabled: !open,
5192
+ setCurrentWidth: setRightSidebarWidth,
5193
+ children: /* @__PURE__ */ jsx("div", { className: "h-full overflow-y-scroll", children: !openDetail ? sidebarChild : /* @__PURE__ */ jsx(SpanDetail, {}) })
6075
5194
  }
6076
5195
  )
6077
5196
  ]
@@ -6131,16 +5250,26 @@ const useExecuteWorkflow = (baseUrl) => {
6131
5250
  setIsExecutingWorkflow(false);
6132
5251
  }
6133
5252
  };
6134
- const createWorkflowRun = async ({ workflowId, input }) => {
5253
+ const createWorkflowRun = async ({ workflowId, prevRunId }) => {
6135
5254
  try {
6136
- const response = await client.getWorkflow(workflowId).startRun(input || {});
6137
- return response;
5255
+ const workflow = client.getWorkflow(workflowId);
5256
+ const { runId: newRunId } = await workflow.createRun({ runId: prevRunId });
5257
+ return { runId: newRunId };
6138
5258
  } catch (error) {
6139
5259
  console.error("Error creating workflow run:", error);
6140
5260
  throw error;
6141
5261
  }
6142
5262
  };
6143
- return { executeWorkflow, createWorkflowRun, isExecutingWorkflow };
5263
+ const startWorkflowRun = async ({ workflowId, runId, input }) => {
5264
+ try {
5265
+ const workflow = client.getWorkflow(workflowId);
5266
+ await workflow.start({ runId, triggerData: input || {} });
5267
+ } catch (error) {
5268
+ console.error("Error starting workflow run:", error);
5269
+ throw error;
5270
+ }
5271
+ };
5272
+ return { executeWorkflow, startWorkflowRun, createWorkflowRun, isExecutingWorkflow };
6144
5273
  };
6145
5274
  const useWatchWorkflow = (baseUrl) => {
6146
5275
  const [isWatchingWorkflow, setIsWatchingWorkflow] = useState(false);
@@ -6151,13 +5280,10 @@ const useWatchWorkflow = (baseUrl) => {
6151
5280
  const client = new MastraClient({
6152
5281
  baseUrl
6153
5282
  });
6154
- const watchSubscription = client.getWorkflow(workflowId).watch({ runId });
6155
- if (!watchSubscription) {
6156
- throw new Error("Error watching workflow");
6157
- }
6158
- for await (const record of watchSubscription) {
5283
+ const workflow = client.getWorkflow(workflowId);
5284
+ workflow.watch({ runId }, (record) => {
6159
5285
  setWatchResult(record);
6160
- }
5286
+ });
6161
5287
  } catch (error) {
6162
5288
  console.error("Error watching workflow:", error);
6163
5289
  throw error;
@@ -6230,6 +5356,9 @@ function extractConditions(group, type) {
6230
5356
  recurse({ ...subGroup }, "or");
6231
5357
  }
6232
5358
  }
5359
+ if ("not" in group2) {
5360
+ recurse({ ...group2.not }, "not");
5361
+ }
6233
5362
  }
6234
5363
  }
6235
5364
  recurse(group);
@@ -6279,19 +5408,21 @@ const contructNodesAndEdges = ({
6279
5408
  }
6280
5409
  let nodes = [];
6281
5410
  let edges = [];
5411
+ let allSteps = [];
6282
5412
  for (const [_index, _step] of initial.entries()) {
6283
5413
  const step = _step.step;
6284
5414
  const stepId = step.id;
6285
5415
  const steps = [_step, ...stepsList?.[stepId] || []]?.reduce((acc, step2, i) => {
6286
- const newStep = {
5416
+ let newStep = {
6287
5417
  ...step2.step,
6288
5418
  label: step2.step.id,
5419
+ originalId: step2.step.id,
6289
5420
  type: "default-node",
6290
5421
  id: nodes.some((node) => node.id === step2.step.id) ? `${step2.step.id}-${i}` : step2.step.id
6291
5422
  };
6292
5423
  let conditionType = "when";
6293
5424
  if (step2.config?.serializedWhen) {
6294
- conditionType = step2.step.id === "__start_if" ? "if" : step2.step.id === "__start_else" ? "else" : "when";
5425
+ conditionType = step2.step.id?.endsWith("_if") ? "if" : step2.step.id?.endsWith("_else") ? "else" : "when";
6295
5426
  const conditions = extractConditions(step2.config.serializedWhen, conditionType);
6296
5427
  const conditionStep = {
6297
5428
  id: crypto.randomUUID(),
@@ -6301,11 +5432,20 @@ const contructNodesAndEdges = ({
6301
5432
  };
6302
5433
  acc.push(conditionStep);
6303
5434
  }
6304
- if (conditionType === "when") {
6305
- acc.push(newStep);
5435
+ if (conditionType === "if" || conditionType === "else") {
5436
+ newStep = {
5437
+ ...newStep,
5438
+ label: conditionType === "if" ? "start if" : "start else"
5439
+ };
6306
5440
  }
5441
+ newStep = {
5442
+ ...newStep,
5443
+ label: step2.config?.loopLabel || newStep.label
5444
+ };
5445
+ acc.push(newStep);
6307
5446
  return acc;
6308
5447
  }, []);
5448
+ allSteps = [...allSteps, ...steps];
6309
5449
  const newNodes = [...steps].map((step2, index) => {
6310
5450
  const subscriberGraph = stepSubscriberGraph?.[step2.id];
6311
5451
  return {
@@ -6338,21 +5478,26 @@ const contructNodesAndEdges = ({
6338
5478
  }
6339
5479
  for (const [connectingStepId, stepInfoGraph] of Object.entries(stepSubscriberGraph)) {
6340
5480
  const { initial: initial2, ...stepsList2 } = stepInfoGraph;
5481
+ let untilOrWhileConditionId;
5482
+ const loopResultSteps = [];
5483
+ let finishedLoopStep;
5484
+ let otherLoopStep;
6341
5485
  if (initial2.length) {
6342
5486
  for (const [_index, _step] of initial2.entries()) {
6343
5487
  const step = _step.step;
6344
5488
  const stepId = step.id;
6345
- const originalSteps = [_step, ...stepsList2?.[stepId] || []]?.map((step2) => step2.step);
6346
5489
  const steps = [_step, ...stepsList2?.[stepId] || []]?.reduce((acc, step2, i) => {
6347
- const newStep = {
5490
+ let newStep = {
6348
5491
  ...step2.step,
5492
+ originalId: step2.step.id,
6349
5493
  label: step2.step.id,
6350
5494
  type: "default-node",
6351
5495
  id: nodes.some((node) => node.id === step2.step.id) ? `${step2.step.id}-${i}` : step2.step.id
6352
5496
  };
6353
5497
  let conditionType = "when";
6354
- if (step2.config?.serializedWhen) {
6355
- conditionType = step2.step.id === "__start_if" ? "if" : step2.step.id === "__start_else" ? "else" : "when";
5498
+ const isFinishedLoop = step2.config?.loopLabel?.endsWith("loop finished");
5499
+ if (step2.config?.serializedWhen && !isFinishedLoop) {
5500
+ conditionType = step2.step.id?.endsWith("_if") ? "if" : step2.step.id?.endsWith("_else") ? "else" : step2.config?.loopType ?? "when";
6356
5501
  const conditions = extractConditions(step2.config.serializedWhen, conditionType);
6357
5502
  const conditionStep = {
6358
5503
  id: crypto.randomUUID(),
@@ -6360,15 +5505,67 @@ const contructNodesAndEdges = ({
6360
5505
  type: "condition-node",
6361
5506
  isLarge: (conditions?.length > 1 || conditions.some(({ fnString }) => !!fnString)) && conditionType !== "else"
6362
5507
  };
5508
+ if (conditionType === "until" || conditionType === "while") {
5509
+ untilOrWhileConditionId = conditionStep.id;
5510
+ }
6363
5511
  acc.push(conditionStep);
6364
5512
  }
6365
- if (conditionType === "when") {
6366
- acc.push(newStep);
5513
+ if (isFinishedLoop) {
5514
+ const loopResultStep = {
5515
+ id: crypto.randomUUID(),
5516
+ type: "loop-result-node",
5517
+ loopType: "finished",
5518
+ loopResult: step2.config.loopType === "until" ? true : false
5519
+ };
5520
+ loopResultSteps.push(loopResultStep);
5521
+ acc.push(loopResultStep);
5522
+ }
5523
+ if (!isFinishedLoop && step2.config?.loopType) {
5524
+ const loopResultStep = {
5525
+ id: crypto.randomUUID(),
5526
+ type: "loop-result-node",
5527
+ loopType: step2.config.loopType,
5528
+ loopResult: step2.config.loopType === "until" ? false : true
5529
+ };
5530
+ loopResultSteps.push(loopResultStep);
5531
+ acc.push(loopResultStep);
5532
+ }
5533
+ if (conditionType === "if" || conditionType === "else") {
5534
+ newStep = {
5535
+ ...newStep,
5536
+ label: conditionType === "if" ? "start if" : "start else"
5537
+ };
6367
5538
  }
5539
+ if (step2.config.loopType) {
5540
+ if (isFinishedLoop) {
5541
+ finishedLoopStep = newStep;
5542
+ } else {
5543
+ otherLoopStep = newStep;
5544
+ }
5545
+ }
5546
+ newStep = {
5547
+ ...newStep,
5548
+ loopType: isFinishedLoop ? "finished" : step2.config.loopType,
5549
+ label: step2.config?.loopLabel || newStep.label
5550
+ };
5551
+ acc.push(newStep);
6368
5552
  return acc;
6369
5553
  }, []);
6370
- const newNodes = [...steps].map((step2, index) => {
5554
+ let afterStep = [];
5555
+ let afterStepStepList = connectingStepId?.includes("&&") ? connectingStepId.split("&&") : [];
5556
+ if (connectingStepId?.includes("&&")) {
5557
+ afterStep = [
5558
+ {
5559
+ id: connectingStepId,
5560
+ label: connectingStepId,
5561
+ type: "after-node",
5562
+ steps: afterStepStepList
5563
+ }
5564
+ ];
5565
+ }
5566
+ const newNodes = [...steps, ...afterStep].map((step2, index) => {
6371
5567
  const subscriberGraph = stepSubscriberGraph?.[step2.id];
5568
+ const withBottomHandle = step2.originalId === connectingStepId || subscriberGraph;
6372
5569
  return {
6373
5570
  id: step2.id,
6374
5571
  position: { x: _index * 300 + 300, y: index * 100 + 100 },
@@ -6377,19 +5574,37 @@ const contructNodesAndEdges = ({
6377
5574
  conditions: step2.conditions,
6378
5575
  label: step2.label,
6379
5576
  description: step2.description,
6380
- withoutBottomHandle: originalSteps.some(({ id }) => id === step2.label && id !== step2.id) || subscriberGraph ? false : index === steps.length - 1,
5577
+ result: step2.loopResult,
5578
+ loopType: step2.loopType,
5579
+ steps: step2.steps,
5580
+ withoutBottomHandle: withBottomHandle ? false : index === steps.length - 1,
6381
5581
  isLarge: step2.isLarge
6382
5582
  }
6383
5583
  };
6384
5584
  });
6385
- nodes = [...nodes, ...newNodes];
5585
+ nodes = [...nodes, ...newNodes].map((node) => ({
5586
+ ...node,
5587
+ data: {
5588
+ ...node.data,
5589
+ withoutBottomHandle: afterStepStepList.includes(node.id) ? false : node.data.withoutBottomHandle
5590
+ }
5591
+ }));
6386
5592
  const edgeSteps = [...steps].slice(0, -1);
5593
+ const afterEdges = afterStepStepList.map((step2) => ({
5594
+ id: `e${step2}-${connectingStepId}`,
5595
+ source: step2,
5596
+ target: connectingStepId,
5597
+ ...defaultEdgeOptions
5598
+ }));
5599
+ const finishedLoopResult = loopResultSteps?.find((step2) => step2.loopType === "finished");
6387
5600
  const newEdges = edgeSteps.map((step2, index) => ({
6388
5601
  id: `e${step2.id}-${steps[index + 1].id}`,
6389
5602
  source: step2.id,
6390
5603
  target: steps[index + 1].id,
5604
+ remove: finishedLoopResult?.id === steps[index + 1].id,
5605
+ //remove if target is a finished loop result
6391
5606
  ...defaultEdgeOptions
6392
- }));
5607
+ }))?.filter((edge) => !edge.remove);
6393
5608
  const firstEdgeStep = steps[0];
6394
5609
  const lastEdgeStep = steps[steps.length - 1];
6395
5610
  const connectingEdge = connectingStepId === firstEdgeStep.id ? [] : [
@@ -6397,10 +5612,11 @@ const contructNodesAndEdges = ({
6397
5612
  id: `e${connectingStepId}-${firstEdgeStep.id}`,
6398
5613
  source: connectingStepId,
6399
5614
  target: firstEdgeStep.id,
5615
+ remove: finishedLoopResult?.id === firstEdgeStep.id,
6400
5616
  ...defaultEdgeOptions
6401
5617
  }
6402
- ];
6403
- const lastEdge = originalSteps.some(({ id }) => id === lastEdgeStep.label && id !== lastEdgeStep.id) ? [
5618
+ ]?.filter((edge) => !edge.remove);
5619
+ const lastEdge = lastEdgeStep.originalId === connectingStepId ? [
6404
5620
  {
6405
5621
  id: `e${lastEdgeStep.id}-${connectingStepId}`,
6406
5622
  source: lastEdgeStep.id,
@@ -6408,7 +5624,31 @@ const contructNodesAndEdges = ({
6408
5624
  ...defaultEdgeOptions
6409
5625
  }
6410
5626
  ] : [];
6411
- edges = [...edges, ...connectingEdge, ...newEdges, ...lastEdge];
5627
+ edges = [...edges, ...afterEdges, ...connectingEdge, ...newEdges, ...lastEdge];
5628
+ allSteps = [...allSteps, ...steps];
5629
+ }
5630
+ if (untilOrWhileConditionId && loopResultSteps.length && finishedLoopStep && otherLoopStep) {
5631
+ const loopResultStepsEdges = loopResultSteps.map((step) => ({
5632
+ id: `e${untilOrWhileConditionId}-${step.id}`,
5633
+ source: untilOrWhileConditionId,
5634
+ target: step.id,
5635
+ ...defaultEdgeOptions
5636
+ }));
5637
+ const finishedLoopResult = loopResultSteps?.find((res) => res.loopType === "finished");
5638
+ const otherLoopResult = loopResultSteps?.find((res) => res.loopType !== "finished");
5639
+ const otherLoopEdge = {
5640
+ id: `e${otherLoopResult?.id}-${otherLoopStep?.id}`,
5641
+ source: otherLoopResult?.id,
5642
+ target: otherLoopStep.id,
5643
+ ...defaultEdgeOptions
5644
+ };
5645
+ const finishedLoopEdge = {
5646
+ id: `e${finishedLoopResult?.id}-${finishedLoopStep?.id}`,
5647
+ source: finishedLoopResult?.id,
5648
+ target: finishedLoopStep.id,
5649
+ ...defaultEdgeOptions
5650
+ };
5651
+ edges = [...edges, ...loopResultStepsEdges, otherLoopEdge, finishedLoopEdge];
6412
5652
  }
6413
5653
  }
6414
5654
  }
@@ -6476,7 +5716,7 @@ function WorkflowConditionNode({ data }) {
6476
5716
  size: "xs",
6477
5717
  weight: "medium",
6478
5718
  className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px] w-fit",
6479
- children: type.toUpperCase()
5719
+ children: type?.toUpperCase()
6480
5720
  }
6481
5721
  ),
6482
5722
  isCollapsible && /* @__PURE__ */ jsx(
@@ -6537,14 +5777,72 @@ function WorkflowDefaultNode({ data }) {
6537
5777
  ] });
6538
5778
  }
6539
5779
 
5780
+ function WorkflowAfterNode({ data }) {
5781
+ const { steps } = data;
5782
+ const [open, setOpen] = useState(true);
5783
+ return /* @__PURE__ */ jsxs(
5784
+ Collapsible,
5785
+ {
5786
+ open,
5787
+ onOpenChange: setOpen,
5788
+ className: cn("bg-mastra-bg-3 rounded-md w-[274px] flex flex-col p-2 gap-2"),
5789
+ children: [
5790
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
5791
+ /* @__PURE__ */ jsxs(CollapsibleTrigger, { className: "flex items-center justify-between w-full", children: [
5792
+ /* @__PURE__ */ jsx(
5793
+ Text,
5794
+ {
5795
+ size: "xs",
5796
+ weight: "medium",
5797
+ className: "text-mastra-el-3 bg-mastra-bg-11 my-auto block rounded-[0.125rem] px-2 py-1 text-[10px] w-fit",
5798
+ children: "AFTER"
5799
+ }
5800
+ ),
5801
+ /* @__PURE__ */ jsx(
5802
+ ChevronDown,
5803
+ {
5804
+ className: cn("w-4 h-4 transition-transform", {
5805
+ "transform rotate-180": open
5806
+ })
5807
+ }
5808
+ )
5809
+ ] }),
5810
+ /* @__PURE__ */ jsx(CollapsibleContent, { className: "flex flex-col gap-2", children: steps.map((step) => /* @__PURE__ */ jsxs("div", { className: "text-sm bg-mastra-bg-9 flex items-center gap-[6px] rounded-sm p-2", children: [
5811
+ /* @__PURE__ */ jsx(Footprints, { className: "text-current w-4 h-4" }),
5812
+ /* @__PURE__ */ jsx(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: step })
5813
+ ] }, step)) }),
5814
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: { visibility: "hidden" } })
5815
+ ]
5816
+ }
5817
+ );
5818
+ }
5819
+
5820
+ function WorkflowLoopResultNode({ data }) {
5821
+ const { result } = data;
5822
+ return /* @__PURE__ */ jsxs("div", { className: cn("bg-mastra-bg-8 rounded-md w-[274px]"), children: [
5823
+ /* @__PURE__ */ jsx(Handle, { type: "target", position: Position.Top, style: { visibility: "hidden" } }),
5824
+ /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsxs("div", { className: "text-sm bg-mastra-bg-9 flex items-center gap-[6px] rounded-sm p-2", children: [
5825
+ result ? /* @__PURE__ */ jsx(CircleCheck, { className: "text-current w-4 h-4" }) : /* @__PURE__ */ jsx(CircleX, { className: "text-current w-4 h-4" }),
5826
+ /* @__PURE__ */ jsx(Text, { size: "xs", weight: "medium", className: "text-mastra-el-6 capitalize", children: String(result) })
5827
+ ] }) }),
5828
+ /* @__PURE__ */ jsx(Handle, { type: "source", position: Position.Bottom, style: { visibility: "hidden" } })
5829
+ ] });
5830
+ }
5831
+
6540
5832
  function WorkflowGraphInner({ workflow }) {
6541
- const { nodes: initialNodes, edges: initialEdges } = contructNodesAndEdges(workflow);
5833
+ const { nodes: initialNodes, edges: initialEdges } = contructNodesAndEdges({
5834
+ stepGraph: workflow.serializedStepGraph,
5835
+ stepSubscriberGraph: workflow.serializedStepSubscriberGraph
5836
+ });
6542
5837
  const [nodes, _, onNodesChange] = useNodesState(initialNodes);
6543
5838
  const [edges] = useEdgesState(initialEdges);
6544
5839
  const nodeTypes = {
6545
5840
  "default-node": WorkflowDefaultNode,
6546
- "condition-node": WorkflowConditionNode
5841
+ "condition-node": WorkflowConditionNode,
5842
+ "after-node": WorkflowAfterNode,
5843
+ "loop-result-node": WorkflowLoopResultNode
6547
5844
  };
5845
+ console.log("nodes===>", nodes);
6548
5846
  return /* @__PURE__ */ jsx("div", { className: "w-full h-full", children: /* @__PURE__ */ jsxs(
6549
5847
  ReactFlow,
6550
5848
  {
@@ -6623,6 +5921,7 @@ const WorkflowsTable = ({
6623
5921
  return /* @__PURE__ */ jsx(
6624
5922
  DataTable,
6625
5923
  {
5924
+ emptyText: "Workflows",
6626
5925
  title,
6627
5926
  withoutBorder: true,
6628
5927
  withoutRadius: true,
@@ -7885,15 +7184,15 @@ function CodeBlockDemo({
7885
7184
  filename,
7886
7185
  className
7887
7186
  }) {
7888
- return /* @__PURE__ */ jsxs(CodeBlock$1, { code, language, theme: themes.oneDark, children: [
7187
+ return /* @__PURE__ */ jsxs(CodeBlock, { code, language, theme: themes.oneDark, children: [
7889
7188
  filename ? /* @__PURE__ */ 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,
7890
7189
  /* @__PURE__ */ jsx(
7891
- CodeBlock$1.Code,
7190
+ CodeBlock.Code,
7892
7191
  {
7893
7192
  className: cn("bg-transparent h-full p-6 rounded-xl whitespace-pre-wrap", filename ? "pt-10" : "", className),
7894
7193
  children: /* @__PURE__ */ jsx("div", { className: "table-row", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center", children: [
7895
- /* @__PURE__ */ jsx(CodeBlock$1.LineNumber, { className: "table-cell pr-4 text-sm text-right select-none text-gray-500/50" }),
7896
- /* @__PURE__ */ jsx(CodeBlock$1.LineContent, { className: "flex", children: /* @__PURE__ */ jsx(CodeBlock$1.Token, { className: "font-mono text-sm mastra-token" }) })
7194
+ /* @__PURE__ */ jsx(CodeBlock.LineNumber, { className: "table-cell pr-4 text-sm text-right select-none text-gray-500/50" }),
7195
+ /* @__PURE__ */ jsx(CodeBlock.LineContent, { className: "flex", children: /* @__PURE__ */ jsx(CodeBlock.Token, { className: "font-mono text-sm mastra-token" }) })
7897
7196
  ] }) })
7898
7197
  }
7899
7198
  )
@@ -7972,36 +7271,49 @@ function WorkflowTrigger({
7972
7271
  }) {
7973
7272
  const { result, setResult, payload, setPayload } = useContext(WorkflowRunContext);
7974
7273
  const { isLoading, workflow } = useWorkflow(workflowId, baseUrl);
7975
- const { createWorkflowRun } = useExecuteWorkflow(baseUrl);
7274
+ const { createWorkflowRun, startWorkflowRun } = useExecuteWorkflow(baseUrl);
7976
7275
  const { watchWorkflow, watchResult, isWatchingWorkflow } = useWatchWorkflow(baseUrl);
7977
7276
  const { resumeWorkflow, isResumingWorkflow } = useResumeWorkflow(baseUrl);
7978
7277
  const [suspendedSteps, setSuspendedSteps] = useState([]);
7278
+ const [isRunning, setIsRunning] = useState(false);
7979
7279
  const triggerSchema = workflow?.triggerSchema;
7980
7280
  const handleExecuteWorkflow = async (data) => {
7981
- if (!workflow) return;
7982
- setResult(null);
7983
- const { runId } = await createWorkflowRun({ workflowId, input: data });
7984
- setRunId?.(runId);
7985
- watchWorkflow({ workflowId, runId });
7281
+ try {
7282
+ if (!workflow) return;
7283
+ setIsRunning(true);
7284
+ setResult(null);
7285
+ const { runId } = await createWorkflowRun({ workflowId });
7286
+ setRunId?.(runId);
7287
+ watchWorkflow({ workflowId, runId });
7288
+ startWorkflowRun({ workflowId, runId, input: data });
7289
+ } catch (err) {
7290
+ setIsRunning(false);
7291
+ toast.error("Error executing workflow");
7292
+ }
7986
7293
  };
7987
7294
  const handleResumeWorkflow = async (step) => {
7988
7295
  if (!workflow) return;
7989
- const { stepId, runId, context } = step;
7990
- resumeWorkflow({
7296
+ const { stepId, runId: prevRunId, context } = step;
7297
+ const { runId } = await createWorkflowRun({ workflowId, prevRunId });
7298
+ watchWorkflow({ workflowId, runId });
7299
+ await resumeWorkflow({
7991
7300
  stepId,
7992
7301
  runId,
7993
7302
  context,
7994
7303
  workflowId
7995
7304
  });
7996
- watchWorkflow({ workflowId, runId });
7997
7305
  };
7998
7306
  const watchResultToUse = result ?? watchResult;
7999
7307
  const workflowActivePaths = watchResultToUse?.activePaths ?? [];
7308
+ useEffect(() => {
7309
+ setIsRunning(isWatchingWorkflow);
7310
+ }, [isWatchingWorkflow]);
8000
7311
  useEffect(() => {
8001
7312
  if (!watchResultToUse?.activePaths || !result?.runId) return;
8002
7313
  const suspended = watchResultToUse.activePaths.filter((path) => watchResultToUse.context?.steps?.[path.stepId]?.status === "suspended").map((path) => ({
8003
7314
  stepId: path.stepId,
8004
- runId: result.runId
7315
+ runId: result.runId,
7316
+ suspendPayload: watchResultToUse.context?.steps?.[path.stepId]?.suspendPayload
8005
7317
  }));
8006
7318
  setSuspendedSteps(suspended);
8007
7319
  }, [watchResultToUse, result]);
@@ -8018,14 +7330,14 @@ function WorkflowTrigger({
8018
7330
  }
8019
7331
  if (!workflow) return null;
8020
7332
  if (!triggerSchema) {
8021
- return /* @__PURE__ */ jsx(ScrollArea, { className: "h-[calc(100vh-126px)] pt-2 px-4 pb-4 text-xs w-[400px]", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
8022
- /* @__PURE__ */ jsx("div", { className: "space-y-4 px-4", children: /* @__PURE__ */ jsx(Button, { className: "w-full", disabled: isWatchingWorkflow, onClick: () => handleExecuteWorkflow(null), children: isWatchingWorkflow ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : "Trigger" }) }),
7333
+ return /* @__PURE__ */ jsx(ScrollArea, { className: "h-[calc(100vh-126px)] pt-2 px-4 pb-4 text-xs w-full", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
7334
+ /* @__PURE__ */ jsx("div", { className: "px-4 space-y-4", children: /* @__PURE__ */ jsx(Button, { className: "w-full", disabled: isRunning, onClick: () => handleExecuteWorkflow(null), children: isRunning ? /* @__PURE__ */ jsx(Loader2, { className: "w-4 h-4 animate-spin" }) : "Trigger" }) }),
8023
7335
  /* @__PURE__ */ jsxs("div", { children: [
8024
- /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3 px-4", size: "xs", children: "Output" }),
7336
+ /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "px-4 text-mastra-el-3", size: "xs", children: "Output" }),
8025
7337
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx(
8026
7338
  CopyButton,
8027
7339
  {
8028
- classname: "absolute z-40 top-4 right-4 w-8 h-8 p-0 opacity-0 group-hover:opacity-100 transition-opacity duration-150 ease-in-out",
7340
+ classname: "absolute z-40 w-8 h-8 p-0 transition-opacity duration-150 ease-in-out opacity-0 top-4 right-4 group-hover:opacity-100",
8029
7341
  content: JSON.stringify(result ?? {}, null, 2)
8030
7342
  }
8031
7343
  ) }),
@@ -8041,30 +7353,13 @@ function WorkflowTrigger({
8041
7353
  ] }) });
8042
7354
  }
8043
7355
  const zodInputSchema = resolveSerializedZodOutput(jsonSchemaToZod(parse(triggerSchema)));
8044
- return /* @__PURE__ */ jsx(ScrollArea, { className: "h-[calc(100vh-126px)] pt-2 px-4 pb-4 text-xs w-[400px]", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
8045
- /* @__PURE__ */ jsxs("div", { children: [
8046
- suspendedSteps.length > 0 ? suspendedSteps?.map((step) => /* @__PURE__ */ jsxs("div", { className: "px-4", children: [
8047
- /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3", size: "xs", children: step.stepId }),
8048
- /* @__PURE__ */ jsx(
8049
- DynamicForm,
8050
- {
8051
- schema: z$1.record(z$1.string(), z$1.any()),
8052
- isSubmitLoading: isResumingWorkflow,
8053
- submitButtonLabel: "Resume",
8054
- onSubmit: (data) => {
8055
- handleResumeWorkflow({
8056
- stepId: step.stepId,
8057
- runId: step.runId,
8058
- context: data
8059
- });
8060
- }
8061
- }
8062
- )
8063
- ] })) : /* @__PURE__ */ jsx(Fragment, {}),
7356
+ const isSuspendedSteps = suspendedSteps.length > 0;
7357
+ return /* @__PURE__ */ jsx(ScrollArea, { className: "h-[calc(100vh-126px)] pt-2 px-4 pb-4 text-xs w-full", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
7358
+ !isSuspendedSteps && /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
8064
7359
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between w-full", children: [
8065
- /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3 px-4", size: "xs", children: "Input" }),
7360
+ /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "px-4 text-mastra-el-3", size: "xs", children: "Input" }),
8066
7361
  isResumingWorkflow ? /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
8067
- /* @__PURE__ */ jsx(Loader2, { className: "animate-spin w-3 h-3 text-mastra-el-accent" }),
7362
+ /* @__PURE__ */ jsx(Loader2, { className: "w-3 h-3 animate-spin text-mastra-el-accent" }),
8068
7363
  " Resuming workflow"
8069
7364
  ] }) : /* @__PURE__ */ jsx(Fragment, {})
8070
7365
  ] }),
@@ -8081,12 +7376,12 @@ function WorkflowTrigger({
8081
7376
  }
8082
7377
  )
8083
7378
  ] }),
8084
- workflowActivePaths.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
8085
- /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3 px-4", size: "xs", children: "Status" }),
7379
+ workflowActivePaths.length > 0 && /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
7380
+ /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "px-4 text-mastra-el-3", size: "xs", children: "Status" }),
8086
7381
  /* @__PURE__ */ jsx("div", { className: "px-4", children: workflowActivePaths?.map((activePath, idx) => {
8087
- return /* @__PURE__ */ jsx("div", { className: "flex flex-col mt-2 border overflow-hidden", children: activePath?.stepPath?.map((sp, idx2) => {
7382
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col mt-2 overflow-hidden border", children: activePath?.stepPath?.map((sp, idx2) => {
8088
7383
  const status = activePath?.status === "completed" ? "Completed" : sp === activePath?.stepId ? activePath?.status.charAt(0).toUpperCase() + activePath?.status.slice(1) : "Completed";
8089
- const statusIcon = status === "Completed" ? /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-green-500 rounded-full" }) : /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-yellow-500 animate-pulse rounded-full" });
7384
+ const statusIcon = status === "Completed" ? /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-green-500 rounded-full" }) : /* @__PURE__ */ jsx("div", { className: "w-2 h-2 bg-yellow-500 rounded-full animate-pulse" });
8090
7385
  return /* @__PURE__ */ jsxs(
8091
7386
  "div",
8092
7387
  {
@@ -8108,12 +7403,39 @@ function WorkflowTrigger({
8108
7403
  }) }, idx);
8109
7404
  }) })
8110
7405
  ] }),
8111
- result && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
8112
- /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3 px-4", size: "xs", children: "Output" }),
7406
+ isSuspendedSteps && suspendedSteps?.map((step) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col px-4", children: [
7407
+ /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "text-mastra-el-3", size: "xs", children: step.stepId }),
7408
+ step.suspendPayload && /* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(
7409
+ CodeBlockDemo,
7410
+ {
7411
+ className: "w-[300px] overflow-x-auto",
7412
+ code: JSON.stringify(step.suspendPayload, null, 2),
7413
+ language: "json"
7414
+ }
7415
+ ) }),
7416
+ /* @__PURE__ */ jsx(
7417
+ DynamicForm,
7418
+ {
7419
+ schema: z$1.record(z$1.string(), z$1.any()),
7420
+ isSubmitLoading: isResumingWorkflow,
7421
+ submitButtonLabel: "Resume",
7422
+ onSubmit: (data) => {
7423
+ handleResumeWorkflow({
7424
+ stepId: step.stepId,
7425
+ runId: step.runId,
7426
+ suspendPayload: step.suspendPayload,
7427
+ context: data
7428
+ });
7429
+ }
7430
+ }
7431
+ )
7432
+ ] })),
7433
+ result && /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
7434
+ /* @__PURE__ */ jsx(Text, { variant: "secondary", className: "px-4 text-mastra-el-3", size: "xs", children: "Output" }),
8113
7435
  /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: /* @__PURE__ */ jsx(
8114
7436
  CopyButton,
8115
7437
  {
8116
- classname: "absolute z-40 top-4 right-4 w-8 h-8 p-0 opacity-0 group-hover:opacity-100 transition-opacity duration-150 ease-in-out",
7438
+ classname: "absolute z-40 w-8 h-8 p-0 transition-opacity duration-150 ease-in-out opacity-0 top-4 right-4 group-hover:opacity-100",
8117
7439
  content: JSON.stringify(result, null, 2)
8118
7440
  }
8119
7441
  ) }),
@@ -8129,5 +7451,5 @@ function WorkflowTrigger({
8129
7451
  ] }) });
8130
7452
  }
8131
7453
 
8132
- export { AgentChat, AgentEvals, AgentTraces, AgentsTable, Chat, WorkflowGraph, WorkflowRunContext, WorkflowRunProvider, WorkflowTraces, WorkflowTrigger, WorkflowsTable };
7454
+ export { AgentChat, AgentEvals, AgentTraces, AgentsTable, MastraResizablePanel, WorkflowGraph, WorkflowRunContext, WorkflowRunProvider, WorkflowTraces, WorkflowTrigger, WorkflowsTable };
8133
7455
  //# sourceMappingURL=index.es.js.map