@mastra/playground-ui 7.0.0-beta.5 → 7.0.0-beta.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -51,7 +51,7 @@ const RadioGroupPrimitive = require('@radix-ui/react-radio-group');
51
51
  const prettier = require('prettier');
52
52
  const prettierPluginBabel = require('prettier/plugins/babel');
53
53
  const prettierPluginEstree = require('prettier/plugins/estree');
54
- const jsonSchemaToZod = require('json-schema-to-zod');
54
+ const jsonToZod = require('@mastra/schema-compat/json-to-zod');
55
55
  const superjson = require('superjson');
56
56
  const SliderPrimitive = require('@radix-ui/react-slider');
57
57
  const reactCodeBlock = require('react-code-block');
@@ -4893,6 +4893,50 @@ toast.promise = ({
4893
4893
  });
4894
4894
  };
4895
4895
 
4896
+ function useTracingSettingsState({ entityId, entityType }) {
4897
+ const [settings, setSettingsState] = React.useState(void 0);
4898
+ const LOCAL_STORAGE_KEY = `tracing-options-${entityType}:${entityId}`;
4899
+ React.useEffect(() => {
4900
+ try {
4901
+ const stored = localStorage.getItem(LOCAL_STORAGE_KEY);
4902
+ if (stored) {
4903
+ const parsed = JSON.parse(stored);
4904
+ setSettingsState(parsed || void 0);
4905
+ }
4906
+ } catch (e) {
4907
+ console.error(e);
4908
+ }
4909
+ }, [LOCAL_STORAGE_KEY]);
4910
+ const setSettings = (settingsValue) => {
4911
+ setSettingsState((prev) => ({ ...prev, ...settingsValue }));
4912
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify({ ...settingsValue, entityId, entityType }));
4913
+ };
4914
+ const resetAll = () => {
4915
+ setSettingsState(void 0);
4916
+ localStorage.removeItem(LOCAL_STORAGE_KEY);
4917
+ };
4918
+ return {
4919
+ settings,
4920
+ setSettings,
4921
+ resetAll
4922
+ };
4923
+ }
4924
+
4925
+ const TracingSettingsContext = React.createContext({
4926
+ setSettings: () => {
4927
+ },
4928
+ resetAll: () => {
4929
+ },
4930
+ settings: void 0
4931
+ });
4932
+ const TracingSettingsProvider = ({ children, entityId, entityType }) => {
4933
+ const state = useTracingSettingsState({ entityId, entityType });
4934
+ return /* @__PURE__ */ jsxRuntime.jsx(TracingSettingsContext.Provider, { value: state, children });
4935
+ };
4936
+ const useTracingSettings = () => {
4937
+ return React.useContext(TracingSettingsContext);
4938
+ };
4939
+
4896
4940
  const useExecuteWorkflow = () => {
4897
4941
  const client = react$1.useMastraClient();
4898
4942
  const createWorkflowRun = reactQuery.useMutation({
@@ -4956,6 +5000,7 @@ const useExecuteWorkflow = () => {
4956
5000
  };
4957
5001
  const useStreamWorkflow = () => {
4958
5002
  const client = react$1.useMastraClient();
5003
+ const { settings } = useTracingSettings();
4959
5004
  const [streamResult, setStreamResult] = React.useState({});
4960
5005
  const [isStreaming, setIsStreaming] = React.useState(false);
4961
5006
  const readerRef = React.useRef(null);
@@ -5032,7 +5077,13 @@ const useStreamWorkflow = () => {
5032
5077
  requestContext$1.set(key, value);
5033
5078
  });
5034
5079
  const workflow = client.getWorkflow(workflowId);
5035
- const stream = await workflow.streamVNext({ runId, inputData, requestContext: requestContext$1, closeOnSuspend: true });
5080
+ const stream = await workflow.streamVNext({
5081
+ runId,
5082
+ inputData,
5083
+ requestContext: requestContext$1,
5084
+ closeOnSuspend: true,
5085
+ tracingOptions: settings?.tracingOptions
5086
+ });
5036
5087
  if (!stream) {
5037
5088
  return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
5038
5089
  }
@@ -5147,7 +5198,13 @@ const useStreamWorkflow = () => {
5147
5198
  Object.entries(playgroundRequestContext).forEach(([key, value]) => {
5148
5199
  requestContext$1.set(key, value);
5149
5200
  });
5150
- const stream = await workflow.resumeStreamVNext({ runId, step, resumeData, requestContext: requestContext$1 });
5201
+ const stream = await workflow.resumeStreamVNext({
5202
+ runId,
5203
+ step,
5204
+ resumeData,
5205
+ requestContext: requestContext$1,
5206
+ tracingOptions: settings?.tracingOptions
5207
+ });
5151
5208
  if (!stream) {
5152
5209
  return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
5153
5210
  }
@@ -5203,7 +5260,11 @@ const useStreamWorkflow = () => {
5203
5260
  Object.entries(playgroundRequestContext).forEach(([key, value]) => {
5204
5261
  requestContext$1.set(key, value);
5205
5262
  });
5206
- const stream = await workflow.timeTravelStream({ ...params, requestContext: requestContext$1 });
5263
+ const stream = await workflow.timeTravelStream({
5264
+ ...params,
5265
+ requestContext: requestContext$1,
5266
+ tracingOptions: settings?.tracingOptions
5267
+ });
5207
5268
  if (!stream) {
5208
5269
  return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
5209
5270
  }
@@ -5328,16 +5389,35 @@ const useWorkflow = (workflowId) => {
5328
5389
  });
5329
5390
  };
5330
5391
 
5392
+ const PER_PAGE = 20;
5331
5393
  const useWorkflowRuns = (workflowId, { enabled = true } = {}) => {
5332
5394
  const client = react$1.useMastraClient();
5333
- return reactQuery.useQuery({
5395
+ const { inView: isEndOfListInView, setRef: setEndOfListElement } = useInView();
5396
+ const query = reactQuery.useInfiniteQuery({
5334
5397
  queryKey: ["workflow-runs", workflowId],
5335
- queryFn: () => client.getWorkflow(workflowId).runs({ perPage: 50, page: 0 }),
5398
+ queryFn: ({ pageParam }) => client.getWorkflow(workflowId).runs({ limit: PER_PAGE, offset: pageParam * PER_PAGE }),
5399
+ initialPageParam: 0,
5400
+ getNextPageParam: (lastPage, _, lastPageParam) => {
5401
+ if (lastPage.runs.length < PER_PAGE) {
5402
+ return void 0;
5403
+ }
5404
+ return lastPageParam + 1;
5405
+ },
5406
+ select: (data) => {
5407
+ return data.pages.flatMap((page) => page.runs);
5408
+ },
5409
+ retry: false,
5336
5410
  enabled,
5337
5411
  refetchInterval: 5e3,
5338
5412
  gcTime: 0,
5339
5413
  staleTime: 0
5340
5414
  });
5415
+ React.useEffect(() => {
5416
+ if (isEndOfListInView && query.hasNextPage && !query.isFetchingNextPage) {
5417
+ query.fetchNextPage();
5418
+ }
5419
+ }, [isEndOfListInView, query.hasNextPage, query.isFetchingNextPage]);
5420
+ return { ...query, setEndOfListElement };
5341
5421
  };
5342
5422
  const useWorkflowRunExecutionResult = (workflowId, runId, refetchInterval) => {
5343
5423
  const client = react$1.useMastraClient();
@@ -6580,7 +6660,7 @@ const SelectContent = React__namespace.forwardRef(({ className, children, positi
6580
6660
  {
6581
6661
  ref,
6582
6662
  className: cn(
6583
- "relative z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
6663
+ "relative z-50 min-w-[8rem] max-h-dropdown-max-height overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
6584
6664
  position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
6585
6665
  className
6586
6666
  ),
@@ -6930,6 +7010,41 @@ const DiscriminatedUnionField = ({ field, path }) => {
6930
7010
  ] }, field.key);
6931
7011
  };
6932
7012
 
7013
+ react$3.buildZodFieldConfig();
7014
+ function removeEmptyValues(values) {
7015
+ const result = {};
7016
+ for (const key in values) {
7017
+ const value = values[key];
7018
+ if ([null, void 0, "", [], {}].includes(value)) {
7019
+ continue;
7020
+ }
7021
+ if (Array.isArray(value)) {
7022
+ const newArray = value.map((item) => {
7023
+ if (typeof item === "object") {
7024
+ const cleanedItem = removeEmptyValues(item);
7025
+ if (Object.keys(cleanedItem).length > 0) {
7026
+ return cleanedItem;
7027
+ }
7028
+ return null;
7029
+ }
7030
+ return item;
7031
+ });
7032
+ const filteredArray = newArray.filter((item) => item !== null);
7033
+ if (filteredArray.length > 0) {
7034
+ result[key] = filteredArray;
7035
+ }
7036
+ } else if (typeof value === "object") {
7037
+ const cleanedValue = removeEmptyValues(value);
7038
+ if (Object.keys(cleanedValue).length > 0) {
7039
+ result[key] = cleanedValue;
7040
+ }
7041
+ } else {
7042
+ result[key] = value;
7043
+ }
7044
+ }
7045
+ return result;
7046
+ }
7047
+
6933
7048
  function CustomAutoForm({
6934
7049
  schema,
6935
7050
  onSubmit = () => {
@@ -6958,7 +7073,7 @@ function CustomAutoForm({
6958
7073
  }
6959
7074
  }, [onFormInit, methods]);
6960
7075
  const handleSubmit = async (dataRaw) => {
6961
- const data = core.removeEmptyValues(dataRaw);
7076
+ const data = removeEmptyValues(dataRaw);
6962
7077
  const validationResult = schema.validateSchema(data);
6963
7078
  if (validationResult.success) {
6964
7079
  await onSubmit(validationResult.data, methods);
@@ -7038,41 +7153,6 @@ function AutoForm({
7038
7153
  );
7039
7154
  }
7040
7155
 
7041
- react$3.buildZodFieldConfig();
7042
- function removeEmptyValues(values) {
7043
- const result = {};
7044
- for (const key in values) {
7045
- const value = values[key];
7046
- if ([null, void 0, "", [], {}].includes(value)) {
7047
- continue;
7048
- }
7049
- if (Array.isArray(value)) {
7050
- const newArray = value.map((item) => {
7051
- if (typeof item === "object") {
7052
- const cleanedItem = removeEmptyValues(item);
7053
- if (Object.keys(cleanedItem).length > 0) {
7054
- return cleanedItem;
7055
- }
7056
- return null;
7057
- }
7058
- return item;
7059
- });
7060
- const filteredArray = newArray.filter((item) => item !== null);
7061
- if (filteredArray.length > 0) {
7062
- result[key] = filteredArray;
7063
- }
7064
- } else if (typeof value === "object") {
7065
- const cleanedValue = removeEmptyValues(value);
7066
- if (Object.keys(cleanedValue).length > 0) {
7067
- result[key] = cleanedValue;
7068
- }
7069
- } else {
7070
- result[key] = value;
7071
- }
7072
- }
7073
- return result;
7074
- }
7075
-
7076
7156
  const labelVariants = cva("text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70");
7077
7157
  const Label = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(LabelPrimitive__namespace.Root, { ref, className: clsx(labelVariants(), className), ...props }));
7078
7158
  Label.displayName = LabelPrimitive__namespace.Root.displayName;
@@ -7113,6 +7193,9 @@ function inferFieldType(schema, fieldConfig) {
7113
7193
  }
7114
7194
  return "union";
7115
7195
  }
7196
+ if (schema instanceof z.z.ZodDiscriminatedUnion) {
7197
+ return "discriminated-union";
7198
+ }
7116
7199
  return "string";
7117
7200
  }
7118
7201
 
@@ -7241,8 +7324,22 @@ class CustomZodProvider extends v4.ZodProvider {
7241
7324
  }
7242
7325
  validateSchema(values) {
7243
7326
  const cleanedValues = removeEmptyValues(values);
7244
- const result = super.validateSchema(cleanedValues);
7245
- return result;
7327
+ try {
7328
+ const validationResult = this._schema.safeParse(cleanedValues);
7329
+ if (validationResult.success) {
7330
+ return { success: true, data: validationResult.data };
7331
+ } else {
7332
+ return {
7333
+ success: false,
7334
+ errors: validationResult.error.issues.map((error) => ({
7335
+ path: error.path,
7336
+ message: error.message
7337
+ }))
7338
+ };
7339
+ }
7340
+ } catch (error) {
7341
+ throw error;
7342
+ }
7246
7343
  }
7247
7344
  parseSchema() {
7248
7345
  return parseSchema(this._schema);
@@ -7607,7 +7704,7 @@ const WorkflowTimeTravelForm = ({ stepKey, closeModal }) => {
7607
7704
  }
7608
7705
  try {
7609
7706
  const parsed = superjson.parse(stepDefinition.inputSchema);
7610
- return { schema: resolveSerializedZodOutput(jsonSchemaToZod(parsed)), schemaError: null };
7707
+ return { schema: resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(parsed)), schemaError: null };
7611
7708
  } catch (err) {
7612
7709
  console.error("Failed to parse step schema", err);
7613
7710
  return { schema: z.z.record(z.z.string(), z.z.any()) };
@@ -7737,7 +7834,7 @@ const WorkflowStepActionBar = ({
7737
7834
  const { withoutTimeTravel } = React.useContext(WorkflowRunContext);
7738
7835
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
7739
7836
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
7740
- const showTimeTravel = !withoutTimeTravel && stepKey;
7837
+ const showTimeTravel = !withoutTimeTravel && stepKey && !mapConfig;
7741
7838
  return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (input || output || error || mapConfig || resumeData || onShowNestedGraph || showTimeTravel) && /* @__PURE__ */ jsxRuntime.jsxs(
7742
7839
  "div",
7743
7840
  {
@@ -8602,7 +8699,7 @@ function WorkflowTrigger({
8602
8699
  }
8603
8700
  if (!workflow) return null;
8604
8701
  const isSuspendedSteps = suspendedSteps.length > 0;
8605
- const zodInputSchema = triggerSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(triggerSchema))) : null;
8702
+ const zodInputSchema = triggerSchema ? resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(superjson.parse(triggerSchema))) : null;
8606
8703
  const workflowActivePaths = streamResultToUse?.steps ?? {};
8607
8704
  const hasWorkflowActivePaths = Object.values(workflowActivePaths).length > 0;
8608
8705
  const doneStatuses = ["success", "failed", "canceled"];
@@ -8638,7 +8735,7 @@ function WorkflowTrigger({
8638
8735
  !isStreamingWorkflow && isSuspendedSteps && suspendedSteps?.map((step) => {
8639
8736
  const stepDefinition = workflow.allSteps[step.stepId];
8640
8737
  if (!stepDefinition || stepDefinition.isWorkflow) return null;
8641
- const stepSchema = stepDefinition?.resumeSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(stepDefinition.resumeSchema))) : z.z.record(z.z.string(), z.z.any());
8738
+ const stepSchema = stepDefinition?.resumeSchema ? resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(superjson.parse(stepDefinition.resumeSchema))) : z.z.record(z.z.string(), z.z.any());
8642
8739
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col px-4", children: [
8643
8740
  /* @__PURE__ */ jsxRuntime.jsx(Text, { variant: "secondary", className: "text-mastra-el-3", size: "xs", children: step.stepId }),
8644
8741
  step.suspendPayload && /* @__PURE__ */ jsxRuntime.jsx("div", { "data-testid": "suspended-payload", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -9216,6 +9313,104 @@ const EntityHeader = ({ icon, title, isLoading, children }) => {
9216
9313
  ] });
9217
9314
  };
9218
9315
 
9316
+ const Tabs$1 = TabsPrimitive__namespace.Root;
9317
+ const TabsList = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
9318
+ TabsPrimitive__namespace.List,
9319
+ {
9320
+ ref,
9321
+ className: clsx("bg-muted text-muted-foreground inline-flex items-center bg-transparent", className),
9322
+ ...props
9323
+ }
9324
+ ));
9325
+ TabsList.displayName = TabsPrimitive__namespace.List.displayName;
9326
+ const TabsTrigger = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
9327
+ TabsPrimitive__namespace.Trigger,
9328
+ {
9329
+ ref,
9330
+ className: cn(
9331
+ "-outline-offset-2 data-[state=active]:bg-background data-[state=active]:text-foreground whitespace-nowrap text-ui-lg text-icon3 -mb-[0.5px] inline-flex items-center justify-center border-b-2 border-transparent p-3 font-medium disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-b-2 data-[state=active]:border-white data-[state=active]:shadow",
9332
+ className
9333
+ ),
9334
+ ...props
9335
+ }
9336
+ ));
9337
+ TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
9338
+ const TabsContent = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Content, { ref, className: cn("mt-2 -outline-offset-2", className), ...props }));
9339
+ TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
9340
+
9341
+ const PlaygroundTabs = ({
9342
+ children,
9343
+ defaultTab,
9344
+ value,
9345
+ onValueChange,
9346
+ className
9347
+ }) => {
9348
+ const [internalTab, setInternalTab] = React.useState(defaultTab);
9349
+ const isControlled = value !== void 0 && onValueChange !== void 0;
9350
+ const currentTab = isControlled ? value : internalTab;
9351
+ const handleTabChange = (newValue) => {
9352
+ const typedValue = newValue;
9353
+ if (isControlled) {
9354
+ onValueChange(typedValue);
9355
+ } else {
9356
+ setInternalTab(typedValue);
9357
+ }
9358
+ };
9359
+ return /* @__PURE__ */ jsxRuntime.jsx(Tabs$1, { value: currentTab, onValueChange: handleTabChange, className: cn("h-full", className), children });
9360
+ };
9361
+ const TabList$1 = ({ children, className }) => {
9362
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full overflow-x-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx(TabsList, { className: "border-b border-border1 flex min-w-full shrink-0", children }) });
9363
+ };
9364
+ const Tab$1 = ({ children, value, onClick }) => {
9365
+ return /* @__PURE__ */ jsxRuntime.jsx(
9366
+ TabsTrigger,
9367
+ {
9368
+ value,
9369
+ className: "text-xs p-3 text-mastra-el-3 data-[state=active]:text-mastra-el-5 data-[state=active]:border-b-2 whitespace-nowrap flex-shrink-0",
9370
+ onClick,
9371
+ children
9372
+ }
9373
+ );
9374
+ };
9375
+ const TabContent$1 = ({ children, value }) => {
9376
+ return /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value, className: "h-full overflow-hidden flex flex-col", children });
9377
+ };
9378
+
9379
+ const TracingRunOptions = () => {
9380
+ const theme = useCodemirrorTheme$1();
9381
+ const { settings, setSettings } = useTracingSettings();
9382
+ const handleChange = (value) => {
9383
+ if (!value) {
9384
+ return setSettings({ ...settings, tracingOptions: void 0 });
9385
+ }
9386
+ try {
9387
+ const parsed = JSON.parse(value);
9388
+ if (typeof parsed === "object" && parsed !== null) {
9389
+ setSettings({ ...settings, tracingOptions: parsed });
9390
+ }
9391
+ } catch {
9392
+ }
9393
+ };
9394
+ let strValue = "{}";
9395
+ try {
9396
+ strValue = JSON.stringify(settings?.tracingOptions, null, 2);
9397
+ } catch {
9398
+ }
9399
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 px-5 py-2", children: [
9400
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h3", variant: "ui-md", className: "text-icon3", children: "Tracing Options" }),
9401
+ /* @__PURE__ */ jsxRuntime.jsx(
9402
+ CodeMirror,
9403
+ {
9404
+ value: strValue,
9405
+ onChange: handleChange,
9406
+ theme,
9407
+ extensions: [langJson.jsonLanguage],
9408
+ className: "h-[400px] overflow-y-scroll bg-surface3 rounded-lg overflow-hidden p-3"
9409
+ }
9410
+ )
9411
+ ] });
9412
+ };
9413
+
9219
9414
  function WorkflowInformation({ workflowId, initialRunId }) {
9220
9415
  const { data: workflow, isLoading, error } = useWorkflow(workflowId);
9221
9416
  const {
@@ -9229,6 +9424,7 @@ function WorkflowInformation({ workflowId, initialRunId }) {
9229
9424
  cancelWorkflowRun,
9230
9425
  isCancellingWorkflowRun
9231
9426
  } = React.useContext(WorkflowRunContext);
9427
+ const [tab, setTab] = React.useState("current-run");
9232
9428
  const [runId, setRunId] = React.useState("");
9233
9429
  const { handleCopy } = useCopyToClipboard({ text: workflowId });
9234
9430
  const stepsCount = Object.keys(workflow?.steps ?? {}).length;
@@ -9258,39 +9454,46 @@ function WorkflowInformation({ workflowId, initialRunId }) {
9258
9454
  stepsCount > 1 ? "s" : ""
9259
9455
  ] })
9260
9456
  ] }) }),
9261
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto border-t-sm border-border1", children: workflowId ? initialRunId ? /* @__PURE__ */ jsxRuntime.jsx(
9262
- WorkflowRunDetail,
9263
- {
9264
- workflowId,
9265
- runId: initialRunId,
9266
- setRunId,
9267
- workflow: workflow ?? void 0,
9268
- isLoading,
9269
- createWorkflowRun,
9270
- streamWorkflow,
9271
- resumeWorkflow,
9272
- streamResult,
9273
- isStreamingWorkflow,
9274
- isCancellingWorkflowRun,
9275
- cancelWorkflowRun,
9276
- observeWorkflowStream
9277
- }
9278
- ) : /* @__PURE__ */ jsxRuntime.jsx(
9279
- WorkflowTrigger,
9280
- {
9281
- workflowId,
9282
- setRunId,
9283
- workflow: workflow ?? void 0,
9284
- isLoading,
9285
- createWorkflowRun,
9286
- streamWorkflow,
9287
- resumeWorkflow,
9288
- streamResult,
9289
- isStreamingWorkflow,
9290
- isCancellingWorkflowRun,
9291
- cancelWorkflowRun
9292
- }
9293
- ) : null })
9457
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden border-t-sm border-border1 flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsxs(PlaygroundTabs, { defaultTab: "current-run", value: tab, onValueChange: setTab, children: [
9458
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList$1, { children: [
9459
+ /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "current-run", children: "Current Run" }),
9460
+ /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "run-options", children: "Run options" })
9461
+ ] }),
9462
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "current-run", children: workflowId ? initialRunId ? /* @__PURE__ */ jsxRuntime.jsx(
9463
+ WorkflowRunDetail,
9464
+ {
9465
+ workflowId,
9466
+ runId: initialRunId,
9467
+ setRunId,
9468
+ workflow: workflow ?? void 0,
9469
+ isLoading,
9470
+ createWorkflowRun,
9471
+ streamWorkflow,
9472
+ resumeWorkflow,
9473
+ streamResult,
9474
+ isStreamingWorkflow,
9475
+ isCancellingWorkflowRun,
9476
+ cancelWorkflowRun,
9477
+ observeWorkflowStream
9478
+ }
9479
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
9480
+ WorkflowTrigger,
9481
+ {
9482
+ workflowId,
9483
+ setRunId,
9484
+ workflow: workflow ?? void 0,
9485
+ isLoading,
9486
+ createWorkflowRun,
9487
+ streamWorkflow,
9488
+ resumeWorkflow,
9489
+ streamResult,
9490
+ isStreamingWorkflow,
9491
+ isCancellingWorkflowRun,
9492
+ cancelWorkflowRun
9493
+ }
9494
+ ) : null }),
9495
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "run-options", children: /* @__PURE__ */ jsxRuntime.jsx(TracingRunOptions, {}) })
9496
+ ] }) })
9294
9497
  ] });
9295
9498
  }
9296
9499
 
@@ -9424,7 +9627,7 @@ function Combobox({
9424
9627
  ref: listRef,
9425
9628
  id: "combobox-options",
9426
9629
  role: "listbox",
9427
- className: "max-h-[300px] overflow-y-auto overflow-x-hidden p-1",
9630
+ className: "max-h-dropdown-max-height overflow-y-auto overflow-x-hidden p-1",
9428
9631
  children: filteredOptions.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-6 text-center text-sm", children: emptyText }) : filteredOptions.map((option, index) => {
9429
9632
  const isSelected = value === option.value;
9430
9633
  const isHighlighted = index === highlightedIndex;
@@ -9528,7 +9731,7 @@ const WorkflowBadge = ({
9528
9731
  const { data: runs, isLoading: isRunsLoading } = useWorkflowRuns(workflowId, {
9529
9732
  enabled: Boolean(runId) && !isStreaming
9530
9733
  });
9531
- const run = runs?.runs.find((run2) => run2.runId === runId);
9734
+ const run = runs?.find((run2) => run2.runId === runId);
9532
9735
  const isLoading = isRunsLoading || !run;
9533
9736
  const snapshot = typeof run?.snapshot === "object" ? run?.snapshot : void 0;
9534
9737
  const selectionReason = metadata?.mode === "network" ? metadata.selectionReason : void 0;
@@ -9633,16 +9836,12 @@ const AgentBadge = ({ agentId, messages = [], metadata, toolCallId, toolApproval
9633
9836
  );
9634
9837
  };
9635
9838
 
9636
- const useAgentMessages = ({
9637
- threadId,
9638
- agentId,
9639
- memory
9640
- }) => {
9839
+ const useAgentMessages = ({ threadId, agentId, memory }) => {
9641
9840
  const client = react$1.useMastraClient();
9642
9841
  const { requestContext } = usePlaygroundStore();
9643
9842
  return reactQuery.useQuery({
9644
9843
  queryKey: ["memory", "messages", threadId, agentId, "requestContext"],
9645
- queryFn: () => client.listThreadMessages(threadId, { agentId, requestContext }),
9844
+ queryFn: () => threadId ? client.listThreadMessages(threadId, { agentId, requestContext }) : null,
9646
9845
  enabled: memory && Boolean(threadId),
9647
9846
  staleTime: 0,
9648
9847
  gcTime: 0,
@@ -9659,7 +9858,7 @@ const AgentBadgeWrapper = ({
9659
9858
  toolApprovalMetadata
9660
9859
  }) => {
9661
9860
  const { data } = useAgentMessages({
9662
- threadId: result?.subAgentThreadId ?? "",
9861
+ threadId: result?.subAgentThreadId,
9663
9862
  agentId,
9664
9863
  memory: true
9665
9864
  });
@@ -10368,8 +10567,12 @@ const useSpeechRecognition = ({
10368
10567
  const agent2 = client.getAgent(agentId);
10369
10568
  const check = async () => {
10370
10569
  try {
10371
- await agent2.voice.getSpeakers(requestContext);
10372
- setAgent(agent2);
10570
+ const speakers = await agent2.voice.getSpeakers(requestContext);
10571
+ if (speakers.length > 0) {
10572
+ setAgent(agent2);
10573
+ } else {
10574
+ setAgent(null);
10575
+ }
10373
10576
  } catch (error) {
10374
10577
  setAgent(null);
10375
10578
  }
@@ -11113,8 +11316,12 @@ const useAdapters = (agentId) => {
11113
11316
  const check = async () => {
11114
11317
  const agent = baseClient.getAgent(agentId);
11115
11318
  try {
11116
- await agent.voice.getSpeakers(requestContext);
11117
- setSpeechAdapter(new VoiceAttachmentAdapter(agent));
11319
+ const speakers = await agent.voice.getSpeakers(requestContext);
11320
+ if (speakers.length > 0) {
11321
+ setSpeechAdapter(new VoiceAttachmentAdapter(agent));
11322
+ } else {
11323
+ setSpeechAdapter(new react.WebSpeechSynthesisAdapter());
11324
+ }
11118
11325
  setIsReady(true);
11119
11326
  } catch {
11120
11327
  setSpeechAdapter(new react.WebSpeechSynthesisAdapter());
@@ -11382,6 +11589,7 @@ function MastraRuntimeProvider({
11382
11589
  modelVersion
11383
11590
  }) {
11384
11591
  const { prompt: instructions } = useAgentPromptExperiment();
11592
+ const { settings: tracingSettings } = useTracingSettings();
11385
11593
  const [isLegacyRunning, setIsLegacyRunning] = React.useState(false);
11386
11594
  const [legacyMessages, setLegacyMessages] = React.useState(
11387
11595
  () => memory ? initializeMessageState(initialLegacyMessages || []) : []
@@ -11461,6 +11669,7 @@ function MastraRuntimeProvider({
11461
11669
  threadId,
11462
11670
  modelSettings: modelSettingsArgs,
11463
11671
  signal: controller.signal,
11672
+ tracingOptions: tracingSettings?.tracingOptions,
11464
11673
  onNetworkChunk: async (chunk) => {
11465
11674
  if (chunk.type === "tool-execution-end" && chunk.payload?.toolName === "updateWorkingMemory" && typeof chunk.payload.result === "object" && "success" in chunk.payload.result && chunk.payload.result?.success) {
11466
11675
  refreshWorkingMemory?.();
@@ -11479,7 +11688,8 @@ function MastraRuntimeProvider({
11479
11688
  requestContext: requestContextInstance,
11480
11689
  threadId,
11481
11690
  modelSettings: modelSettingsArgs,
11482
- signal: controller.signal
11691
+ signal: controller.signal,
11692
+ tracingOptions: tracingSettings?.tracingOptions
11483
11693
  });
11484
11694
  await refreshThreadList?.();
11485
11695
  return;
@@ -11491,6 +11701,7 @@ function MastraRuntimeProvider({
11491
11701
  requestContext: requestContextInstance,
11492
11702
  threadId,
11493
11703
  modelSettings: modelSettingsArgs,
11704
+ tracingOptions: tracingSettings?.tracingOptions,
11494
11705
  onChunk: async (chunk) => {
11495
11706
  if (chunk.type === "finish") {
11496
11707
  await refreshThreadList?.();
@@ -11847,13 +12058,15 @@ const AgentChat = ({
11847
12058
  refreshThreadList,
11848
12059
  modelVersion,
11849
12060
  modelList,
11850
- messageId
12061
+ messageId,
12062
+ isNewThread
11851
12063
  }) => {
11852
12064
  const { settings } = useAgentSettings();
11853
12065
  const { requestContext } = usePlaygroundStore();
11854
12066
  const { data, isLoading: isMessagesLoading } = useAgentMessages({
11855
12067
  agentId,
11856
- threadId: threadId ?? "",
12068
+ threadId: isNewThread ? void 0 : threadId,
12069
+ // Prevent fetching when thread is new
11857
12070
  memory: memory ?? false
11858
12071
  });
11859
12072
  React.useEffect(() => {
@@ -12633,7 +12846,7 @@ function InputField({
12633
12846
  className: cn("text-[0.8125rem] text-icon3 flex justify-between items-center"),
12634
12847
  children: [
12635
12848
  label,
12636
- required && /* @__PURE__ */ jsxRuntime.jsx("i", { className: "text-icon2", children: "(required)" })
12849
+ required && /* @__PURE__ */ jsxRuntime.jsx("i", { className: "text-icon2 text-xs", children: "(required)" })
12637
12850
  ]
12638
12851
  }
12639
12852
  ) }),
@@ -15750,7 +15963,7 @@ const AgentToolPanel = ({ toolId, agentId }) => {
15750
15963
  playgroundRequestContext
15751
15964
  });
15752
15965
  };
15753
- const zodInputSchema = tool?.inputSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(tool?.inputSchema))) : z.z.object({});
15966
+ const zodInputSchema = tool?.inputSchema ? resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(superjson.parse(tool?.inputSchema))) : z.z.object({});
15754
15967
  if (isAgentLoading || error) return null;
15755
15968
  if (!tool)
15756
15969
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-12 text-center px-6", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "header-md", className: "text-icon3", children: "Tool not found" }) });
@@ -16484,69 +16697,6 @@ function AgentMemory({ agentId, threadId }) {
16484
16697
  ] });
16485
16698
  }
16486
16699
 
16487
- const Tabs$1 = TabsPrimitive__namespace.Root;
16488
- const TabsList = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
16489
- TabsPrimitive__namespace.List,
16490
- {
16491
- ref,
16492
- className: clsx("bg-muted text-muted-foreground inline-flex items-center bg-transparent", className),
16493
- ...props
16494
- }
16495
- ));
16496
- TabsList.displayName = TabsPrimitive__namespace.List.displayName;
16497
- const TabsTrigger = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
16498
- TabsPrimitive__namespace.Trigger,
16499
- {
16500
- ref,
16501
- className: cn(
16502
- "-outline-offset-2 data-[state=active]:bg-background data-[state=active]:text-foreground whitespace-nowrap text-ui-lg text-icon3 -mb-[0.5px] inline-flex items-center justify-center border-b-2 border-transparent p-3 font-medium disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-b-2 data-[state=active]:border-white data-[state=active]:shadow",
16503
- className
16504
- ),
16505
- ...props
16506
- }
16507
- ));
16508
- TabsTrigger.displayName = TabsPrimitive__namespace.Trigger.displayName;
16509
- const TabsContent = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(TabsPrimitive__namespace.Content, { ref, className: cn("mt-2 -outline-offset-2", className), ...props }));
16510
- TabsContent.displayName = TabsPrimitive__namespace.Content.displayName;
16511
-
16512
- const PlaygroundTabs = ({
16513
- children,
16514
- defaultTab,
16515
- value,
16516
- onValueChange,
16517
- className
16518
- }) => {
16519
- const [internalTab, setInternalTab] = React.useState(defaultTab);
16520
- const isControlled = value !== void 0 && onValueChange !== void 0;
16521
- const currentTab = isControlled ? value : internalTab;
16522
- const handleTabChange = (newValue) => {
16523
- const typedValue = newValue;
16524
- if (isControlled) {
16525
- onValueChange(typedValue);
16526
- } else {
16527
- setInternalTab(typedValue);
16528
- }
16529
- };
16530
- return /* @__PURE__ */ jsxRuntime.jsx(Tabs$1, { value: currentTab, onValueChange: handleTabChange, className: cn("h-full", className), children });
16531
- };
16532
- const TabList$1 = ({ children, className }) => {
16533
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full overflow-x-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx(TabsList, { className: "border-b border-border1 flex min-w-full shrink-0", children }) });
16534
- };
16535
- const Tab$1 = ({ children, value, onClick }) => {
16536
- return /* @__PURE__ */ jsxRuntime.jsx(
16537
- TabsTrigger,
16538
- {
16539
- value,
16540
- className: "text-xs p-3 text-mastra-el-3 data-[state=active]:text-mastra-el-5 data-[state=active]:border-b-2 whitespace-nowrap flex-shrink-0",
16541
- onClick,
16542
- children
16543
- }
16544
- );
16545
- };
16546
- const TabContent$1 = ({ children, value }) => {
16547
- return /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value, className: "h-full overflow-hidden flex flex-col", children });
16548
- };
16549
-
16550
16700
  function AgentInformation({ agentId, threadId }) {
16551
16701
  const { data: memory } = useMemory(agentId);
16552
16702
  const hasMemory = Boolean(memory?.result);
@@ -16556,11 +16706,13 @@ function AgentInformation({ agentId, threadId }) {
16556
16706
  /* @__PURE__ */ jsxRuntime.jsxs(TabList$1, { children: [
16557
16707
  /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "overview", children: "Overview" }),
16558
16708
  /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "model-settings", children: "Model Settings" }),
16559
- hasMemory && /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "memory", children: "Memory" })
16709
+ hasMemory && /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "memory", children: "Memory" }),
16710
+ /* @__PURE__ */ jsxRuntime.jsx(Tab$1, { value: "tracing-options", children: "Tracing Options" })
16560
16711
  ] }),
16561
16712
  /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "overview", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMetadata, { agentId }) }),
16562
16713
  /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "model-settings", children: /* @__PURE__ */ jsxRuntime.jsx(AgentSettings, { agentId }) }),
16563
- hasMemory && /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "memory", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMemory, { agentId, threadId }) })
16714
+ hasMemory && /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "memory", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMemory, { agentId, threadId }) }),
16715
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent$1, { value: "tracing-options", children: /* @__PURE__ */ jsxRuntime.jsx(TracingRunOptions, {}) })
16564
16716
  ] })
16565
16717
  ] });
16566
16718
  }
@@ -16820,7 +16972,7 @@ const ToolPanel = ({ toolId }) => {
16820
16972
  requestContext: playgroundRequestContext
16821
16973
  });
16822
16974
  };
16823
- const zodInputSchema = tool?.inputSchema ? resolveSerializedZodOutput(jsonSchemaToZod(superjson.parse(tool?.inputSchema))) : z.z.object({});
16975
+ const zodInputSchema = tool?.inputSchema ? resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(superjson.parse(tool?.inputSchema))) : z.z.object({});
16824
16976
  if (isLoading || error) return null;
16825
16977
  if (!tool)
16826
16978
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-12 text-center px-6", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "header-md", className: "text-icon3", children: "Tool not found" }) });
@@ -18126,6 +18278,13 @@ function getSpanInfo({ span, withTraceId = true, withSpanId = true }) {
18126
18278
  value: span?.endedAt ? dateFns.format(new Date(span.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18127
18279
  }
18128
18280
  ];
18281
+ if (span?.attributes?.finishReason) {
18282
+ baseInfo.push({
18283
+ key: "finishReason",
18284
+ label: "Finish Reason",
18285
+ value: span.attributes.finishReason
18286
+ });
18287
+ }
18129
18288
  if (withSpanId) {
18130
18289
  baseInfo.unshift({
18131
18290
  key: "spanId",
@@ -18212,11 +18371,38 @@ const Tabs = Object.assign(TabsRoot, {
18212
18371
  Content: TabContent
18213
18372
  });
18214
18373
 
18374
+ function isTokenLimitExceeded(span) {
18375
+ return span?.attributes?.finishReason === "length";
18376
+ }
18377
+ function getTokenLimitMessage(span) {
18378
+ const usage = span?.attributes?.usage;
18379
+ if (!usage) {
18380
+ return `The model stopped generating because it reached the maximum token limit. The response was truncated and may be incomplete.`;
18381
+ }
18382
+ const inputTokens = usage.inputTokens ?? 0;
18383
+ const outputTokens = usage.outputTokens ?? 0;
18384
+ const totalTokens = usage.totalTokens ?? inputTokens + outputTokens;
18385
+ if (inputTokens > 0 || outputTokens > 0) {
18386
+ return `The model stopped generating because it reached the maximum token limit. The response was truncated and may be incomplete.
18387
+
18388
+ Token usage: ${inputTokens} input + ${outputTokens} output = ${totalTokens} total`;
18389
+ }
18390
+ return `The model stopped generating because it reached the maximum token limit (${totalTokens} tokens). The response was truncated and may be incomplete.`;
18391
+ }
18392
+
18215
18393
  function SpanDetails({ span }) {
18216
18394
  if (!span) {
18217
18395
  return null;
18218
18396
  }
18397
+ const tokenLimitExceeded = isTokenLimitExceeded(span);
18219
18398
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
18399
+ tokenLimitExceeded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "bg-yellow-900/20 border border-yellow-200 rounded-md p-2 mb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
18400
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangleIcon, { className: "text-yellow-200 mt-0.5 flex-shrink-0", size: 20 }),
18401
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
18402
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-semibold text-yellow-200 mb-1 text-sm", children: "Token Limit Exceeded" }),
18403
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-mastra-el-3 whitespace-pre-line", children: getTokenLimitMessage(span) })
18404
+ ] })
18405
+ ] }) }),
18220
18406
  /* @__PURE__ */ jsxRuntime.jsx(
18221
18407
  SideDialog.CodeSection,
18222
18408
  {
@@ -19090,23 +19276,27 @@ const parseError = (error) => {
19090
19276
 
19091
19277
  const WorkflowRunList = ({ workflowId, runId }) => {
19092
19278
  const { Link, paths } = useLinkComponent();
19093
- const { isLoading, data: runs } = useWorkflowRuns(workflowId);
19094
- const actualRuns = runs?.runs || [];
19279
+ const { isLoading, data: runs, setEndOfListElement, isFetchingNextPage } = useWorkflowRuns(workflowId);
19280
+ const actualRuns = runs || [];
19095
19281
  if (isLoading) {
19096
19282
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsx(Skeleton, { className: "h-[600px]" }) });
19097
19283
  }
19098
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-y-auto h-full w-full", children: /* @__PURE__ */ jsxRuntime.jsx(Threads, { children: /* @__PURE__ */ jsxRuntime.jsxs(ThreadList, { children: [
19099
- /* @__PURE__ */ jsxRuntime.jsx(ThreadItem, { children: /* @__PURE__ */ jsxRuntime.jsx(ThreadLink, { as: Link, to: paths.workflowLink(workflowId), children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-accent1 flex items-center gap-4", children: [
19100
- /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "bg-surface4 rounded-lg", size: "lg", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}) }),
19101
- "New workflow run"
19102
- ] }) }) }),
19103
- actualRuns.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-md", className: "text-icon3 py-3 px-5", children: "Your run history will appear here once you run the workflow" }),
19104
- actualRuns.map((run) => /* @__PURE__ */ jsxRuntime.jsx(ThreadItem, { isActive: run.runId === runId, className: "h-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ThreadLink, { as: Link, to: paths.workflowRunLink(workflowId, run.runId), children: [
19105
- typeof run?.snapshot === "object" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowRunStatusBadge, { status: run.snapshot.status }) }),
19106
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[14rem] text-muted-foreground", children: run.runId }),
19107
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: typeof run?.snapshot === "string" ? "" : run?.snapshot?.timestamp ? dateFns.formatDate(run?.snapshot?.timestamp, "MMM d, yyyy h:mm a") : "" })
19108
- ] }) }, run.runId))
19109
- ] }) }) });
19284
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "overflow-y-auto h-full w-full", children: [
19285
+ /* @__PURE__ */ jsxRuntime.jsx(Threads, { children: /* @__PURE__ */ jsxRuntime.jsxs(ThreadList, { children: [
19286
+ /* @__PURE__ */ jsxRuntime.jsx(ThreadItem, { children: /* @__PURE__ */ jsxRuntime.jsx(ThreadLink, { as: Link, to: paths.workflowLink(workflowId), children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-accent1 flex items-center gap-4", children: [
19287
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: "bg-surface4 rounded-lg", size: "lg", children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}) }),
19288
+ "New workflow run"
19289
+ ] }) }) }),
19290
+ actualRuns.length === 0 && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-md", className: "text-icon3 py-3 px-5", children: "Your run history will appear here once you run the workflow" }),
19291
+ actualRuns.map((run) => /* @__PURE__ */ jsxRuntime.jsx(ThreadItem, { isActive: run.runId === runId, className: "h-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ThreadLink, { as: Link, to: paths.workflowRunLink(workflowId, run.runId), children: [
19292
+ typeof run?.snapshot === "object" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pb-1", children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowRunStatusBadge, { status: run.snapshot.status }) }),
19293
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[14rem] text-muted-foreground", children: run.runId }),
19294
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: typeof run?.snapshot === "string" ? "" : run?.snapshot?.timestamp ? dateFns.formatDate(run?.snapshot?.timestamp, "MMM d, yyyy h:mm a") : "" })
19295
+ ] }) }, run.runId))
19296
+ ] }) }),
19297
+ isFetchingNextPage && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center items-center", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, {}) }) }),
19298
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: setEndOfListElement })
19299
+ ] });
19110
19300
  };
19111
19301
  const WorkflowRunStatusBadge = ({ status }) => {
19112
19302
  if (status === "running") {
@@ -19310,7 +19500,7 @@ const MCPToolPanel = ({ toolId, serverId }) => {
19310
19500
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-12 text-center px-6", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "header-md", className: "text-icon3", children: "Tool not found" }) });
19311
19501
  let zodInputSchema;
19312
19502
  try {
19313
- zodInputSchema = resolveSerializedZodOutput(jsonSchemaToZod(tool.inputSchema));
19503
+ zodInputSchema = resolveSerializedZodOutput(jsonToZod.jsonSchemaToZod(tool.inputSchema));
19314
19504
  } catch (e) {
19315
19505
  console.error("Error processing input schema:", e);
19316
19506
  toast.error("Failed to process tool input schema.");
@@ -19539,6 +19729,138 @@ function MCPServerCombobox({
19539
19729
  );
19540
19730
  }
19541
19731
 
19732
+ const StudioConfigContext = React.createContext({
19733
+ baseUrl: "",
19734
+ headers: {},
19735
+ isLoading: false,
19736
+ setConfig: () => {
19737
+ }
19738
+ });
19739
+ const useStudioConfig = () => {
19740
+ return React.useContext(StudioConfigContext);
19741
+ };
19742
+ const LOCAL_STORAGE_KEY = "mastra-studio-config";
19743
+ const StudioConfigProvider = ({ children }) => {
19744
+ const [config, setConfig] = React.useState({
19745
+ baseUrl: "",
19746
+ headers: {},
19747
+ isLoading: true
19748
+ });
19749
+ React.useLayoutEffect(() => {
19750
+ const storedConfig = localStorage.getItem(LOCAL_STORAGE_KEY);
19751
+ if (storedConfig) {
19752
+ const parsedConfig = JSON.parse(storedConfig);
19753
+ if (typeof parsedConfig === "object" && parsedConfig !== null) {
19754
+ return setConfig({ ...parsedConfig, isLoading: false });
19755
+ }
19756
+ }
19757
+ return setConfig({ baseUrl: "", headers: {}, isLoading: false });
19758
+ }, []);
19759
+ const doSetConfig = (partialNewConfig) => {
19760
+ setConfig((prev) => {
19761
+ const nextConfig = { ...prev, ...partialNewConfig };
19762
+ localStorage.setItem(LOCAL_STORAGE_KEY, JSON.stringify(nextConfig));
19763
+ return nextConfig;
19764
+ });
19765
+ };
19766
+ return /* @__PURE__ */ jsxRuntime.jsx(StudioConfigContext.Provider, { value: { ...config, setConfig: doSetConfig }, children });
19767
+ };
19768
+
19769
+ const HeaderListForm = ({ headers, onAddHeader, onRemoveHeader }) => {
19770
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4", children: [
19771
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h2", variant: "header-md", className: "text-icon6", children: "Headers" }),
19772
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-surface4 rounded-lg p-4 border-sm border-border2 space-y-4", children: [
19773
+ headers.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-4", children: headers.map((header, index) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(HeaderListFormItem, { index, header, onRemove: () => onRemoveHeader(index) }) }, index)) }),
19774
+ /* @__PURE__ */ jsxRuntime.jsxs(
19775
+ Button$1,
19776
+ {
19777
+ type: "button",
19778
+ variant: "light",
19779
+ className: "w-full border-dashed !bg-surface4 !border-border2 hover:!bg-surface5",
19780
+ size: "lg",
19781
+ onClick: () => onAddHeader({ name: "", value: "" }),
19782
+ children: [
19783
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}) }),
19784
+ "Add Header"
19785
+ ]
19786
+ }
19787
+ )
19788
+ ] })
19789
+ ] });
19790
+ };
19791
+ const HeaderListFormItem = ({ index, header, onRemove }) => {
19792
+ const nameId = React.useId();
19793
+ const valueId = React.useId();
19794
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[1fr_1fr_auto] gap-4 items-end", children: [
19795
+ /* @__PURE__ */ jsxRuntime.jsx(
19796
+ InputField,
19797
+ {
19798
+ id: nameId,
19799
+ name: `headers.${index}.name`,
19800
+ label: "Name",
19801
+ placeholder: "e.g. Authorization",
19802
+ required: true,
19803
+ defaultValue: header.name
19804
+ }
19805
+ ),
19806
+ /* @__PURE__ */ jsxRuntime.jsx(
19807
+ InputField,
19808
+ {
19809
+ id: valueId,
19810
+ name: `headers.${index}.value`,
19811
+ label: "Value",
19812
+ placeholder: "e.g. Bearer <token>",
19813
+ required: true,
19814
+ defaultValue: header.value
19815
+ }
19816
+ ),
19817
+ /* @__PURE__ */ jsxRuntime.jsx(
19818
+ Button$1,
19819
+ {
19820
+ type: "button",
19821
+ variant: "light",
19822
+ className: "w-full !bg-surface4 !border-border2 hover:!bg-surface5",
19823
+ size: "lg",
19824
+ onClick: onRemove,
19825
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, { "aria-label": "Remove header" }) })
19826
+ }
19827
+ )
19828
+ ] });
19829
+ };
19830
+
19831
+ const StudioConfigForm = ({ initialConfig }) => {
19832
+ const { setConfig } = useStudioConfig();
19833
+ const [headers, setHeaders] = React.useState(() => {
19834
+ if (!initialConfig) return [];
19835
+ return Object.entries(initialConfig.headers).map(([name, value]) => ({ name, value }));
19836
+ });
19837
+ const handleSubmit = (e) => {
19838
+ e.preventDefault();
19839
+ const formData = new FormData(e.target);
19840
+ const formHeaders = {};
19841
+ for (let i = 0; i < headers.length; i++) {
19842
+ const headerName = formData.get(`headers.${i}.name`);
19843
+ const headerValue = formData.get(`headers.${i}.value`);
19844
+ formHeaders[headerName] = headerValue;
19845
+ }
19846
+ setConfig({ headers: formHeaders });
19847
+ sonner.toast.success("Configuration saved");
19848
+ };
19849
+ const handleAddHeader = (header) => {
19850
+ setHeaders((prev) => [...prev, header]);
19851
+ };
19852
+ const handleRemoveHeader = (index) => {
19853
+ setHeaders((prev) => prev.filter((_, i) => i !== index));
19854
+ };
19855
+ return /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
19856
+ /* @__PURE__ */ jsxRuntime.jsx(HeaderListForm, { headers, onAddHeader: handleAddHeader, onRemoveHeader: handleRemoveHeader }),
19857
+ /* @__PURE__ */ jsxRuntime.jsxs(Button$1, { type: "submit", variant: "light", className: "w-full", size: "lg", children: [
19858
+ /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Link2, {}) }),
19859
+ "Set Configuration"
19860
+ ] })
19861
+ ] });
19862
+ };
19863
+
19542
19864
  Object.defineProperty(exports, "Toaster", {
19543
19865
  enumerable: true,
19544
19866
  get: () => sonner.Toaster
@@ -19675,6 +19997,9 @@ exports.SlashIcon = SlashIcon;
19675
19997
  exports.SpanScoreList = SpanScoreList;
19676
19998
  exports.SpanScoring = SpanScoring;
19677
19999
  exports.SpanTabs = SpanTabs;
20000
+ exports.StudioConfigContext = StudioConfigContext;
20001
+ exports.StudioConfigForm = StudioConfigForm;
20002
+ exports.StudioConfigProvider = StudioConfigProvider;
19678
20003
  exports.Tab = Tab$1;
19679
20004
  exports.TabContent = TabContent$1;
19680
20005
  exports.TabList = TabList$1;
@@ -19715,6 +20040,8 @@ exports.TraceTimelineLegend = TraceTimelineLegend;
19715
20040
  exports.TraceTimelineSpan = TraceTimelineSpan;
19716
20041
  exports.TracesList = TracesList;
19717
20042
  exports.TracesTools = TracesTools;
20043
+ exports.TracingSettingsContext = TracingSettingsContext;
20044
+ exports.TracingSettingsProvider = TracingSettingsProvider;
19718
20045
  exports.TsIcon = TsIcon;
19719
20046
  exports.Txt = Txt;
19720
20047
  exports.TxtCell = TxtCell;
@@ -19777,11 +20104,13 @@ exports.useScorers = useScorers;
19777
20104
  exports.useScoresByScorerId = useScoresByScorerId;
19778
20105
  exports.useSpeechRecognition = useSpeechRecognition;
19779
20106
  exports.useStreamWorkflow = useStreamWorkflow;
20107
+ exports.useStudioConfig = useStudioConfig;
19780
20108
  exports.useThreadInput = useThreadInput;
19781
20109
  exports.useThreads = useThreads;
19782
20110
  exports.useTool = useTool;
19783
20111
  exports.useTools = useTools;
19784
20112
  exports.useTraceSpanScores = useTraceSpanScores;
20113
+ exports.useTracingSettings = useTracingSettings;
19785
20114
  exports.useUpdateAgentModel = useUpdateAgentModel;
19786
20115
  exports.useUpdateModelInModelList = useUpdateModelInModelList;
19787
20116
  exports.useWorkflow = useWorkflow;