@mastra/playground-ui 7.0.0-beta.13 → 7.0.0-beta.15

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 (37) hide show
  1. package/CHANGELOG.md +101 -0
  2. package/dist/index.cjs.js +886 -232
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +882 -235
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/components/ui/containers/MainContent.d.ts +7 -0
  7. package/dist/src/components/ui/searchbar.d.ts +2 -1
  8. package/dist/src/domains/agents/components/agent-layout.d.ts +7 -0
  9. package/dist/src/domains/agents/index.d.ts +1 -0
  10. package/dist/src/domains/configuration/components/mastra-version-footer.d.ts +17 -0
  11. package/dist/src/domains/configuration/hooks/use-mastra-packages.d.ts +1 -0
  12. package/dist/src/domains/configuration/hooks/use-package-updates.d.ts +18 -0
  13. package/dist/src/domains/configuration/index.d.ts +3 -0
  14. package/dist/src/domains/observability/components/helpers.d.ts +11 -3
  15. package/dist/src/domains/observability/components/span-dialog.d.ts +2 -1
  16. package/dist/src/domains/observability/components/span-score-list.d.ts +1 -1
  17. package/dist/src/domains/observability/components/span-tabs.d.ts +2 -1
  18. package/dist/src/domains/observability/components/trace-span-usage.d.ts +1 -1
  19. package/dist/src/domains/observability/components/traces-list.d.ts +1 -1
  20. package/dist/src/domains/observability/context/tracing-settings-context.d.ts +1 -0
  21. package/dist/src/domains/observability/hooks/use-tracing-settings-state.d.ts +1 -0
  22. package/dist/src/domains/scores/components/score-dialog.d.ts +2 -2
  23. package/dist/src/domains/scores/hooks/use-trace-span-scores.d.ts +41 -1
  24. package/dist/src/domains/workflows/components/workflow-layout.d.ts +7 -0
  25. package/dist/src/domains/workflows/context/workflow-run-context.d.ts +3 -1
  26. package/dist/src/domains/workflows/hooks/use-workflows-actions.d.ts +6 -2
  27. package/dist/src/domains/workflows/index.d.ts +1 -0
  28. package/dist/src/domains/workflows/workflow/workflow-default-node.d.ts +2 -1
  29. package/dist/src/domains/workflows/workflow/workflow-nested-node.d.ts +2 -1
  30. package/dist/src/domains/workflows/workflow/workflow-run-options.d.ts +1 -0
  31. package/dist/src/domains/workflows/workflow/workflow-step-action-bar.d.ts +4 -2
  32. package/dist/src/domains/workflows/workflow/workflow-time-travel-form.d.ts +5 -1
  33. package/dist/src/domains/workflows/workflow/workflow-trigger.d.ts +4 -2
  34. package/dist/src/hooks/use-workflow-runs.d.ts +1 -1
  35. package/dist/src/lib/resize/collapsible-panel.d.ts +5 -0
  36. package/dist/src/lib/resize/separator.d.ts +1 -0
  37. package/package.json +11 -9
package/dist/index.cjs.js CHANGED
@@ -73,6 +73,8 @@ const languageData = require('@codemirror/language-data');
73
73
  const codemirrorThemeGithub = require('@uiw/codemirror-theme-github');
74
74
  const AlertDialogPrimitive = require('@radix-ui/react-alert-dialog');
75
75
  const TabsPrimitive = require('@radix-ui/react-tabs');
76
+ const reactResizablePanels = require('react-resizable-panels');
77
+ const semver = require('semver');
76
78
 
77
79
  function _interopNamespaceDefault(e) {
78
80
  const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
@@ -4491,6 +4493,7 @@ const BadgeWrapper = ({
4491
4493
  };
4492
4494
 
4493
4495
  const Dialog = DialogPrimitive__namespace.Root;
4496
+ const DialogTrigger = DialogPrimitive__namespace.Trigger;
4494
4497
  const DialogPortal = DialogPrimitive__namespace.Portal;
4495
4498
  const DialogOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
4496
4499
  DialogPrimitive__namespace.Overlay,
@@ -4988,7 +4991,8 @@ function useTracingSettingsState({ entityId, entityType }) {
4988
4991
  return {
4989
4992
  settings,
4990
4993
  setSettings,
4991
- resetAll
4994
+ resetAll,
4995
+ entityType
4992
4996
  };
4993
4997
  }
4994
4998
 
@@ -4997,7 +5001,8 @@ const TracingSettingsContext = React.createContext({
4997
5001
  },
4998
5002
  resetAll: () => {
4999
5003
  },
5000
- settings: void 0
5004
+ settings: void 0,
5005
+ entityType: void 0
5001
5006
  });
5002
5007
  const TracingSettingsProvider = ({ children, entityId, entityType }) => {
5003
5008
  const state = useTracingSettingsState({ entityId, entityType });
@@ -5070,7 +5075,7 @@ const useExecuteWorkflow = () => {
5070
5075
  startAsyncWorkflowRun
5071
5076
  };
5072
5077
  };
5073
- const useStreamWorkflow = () => {
5078
+ const useStreamWorkflow = ({ debugMode }) => {
5074
5079
  const client = react$1.useMastraClient();
5075
5080
  const { settings } = useTracingSettings();
5076
5081
  const [streamResult, setStreamResult] = React.useState({});
@@ -5126,6 +5131,10 @@ const useStreamWorkflow = () => {
5126
5131
  if (value.type === "workflow-finish") {
5127
5132
  const streamStatus = value.payload?.workflowStatus;
5128
5133
  const metadata = value.payload?.metadata;
5134
+ setStreamResult((prev) => ({
5135
+ ...prev,
5136
+ status: streamStatus
5137
+ }));
5129
5138
  if (streamStatus === "failed") {
5130
5139
  throw new Error(metadata?.errorMessage || "Workflow execution failed");
5131
5140
  }
@@ -5136,7 +5145,8 @@ const useStreamWorkflow = () => {
5136
5145
  workflowId,
5137
5146
  runId,
5138
5147
  inputData,
5139
- requestContext: playgroundRequestContext
5148
+ requestContext: playgroundRequestContext,
5149
+ perStep
5140
5150
  }) => {
5141
5151
  if (readerRef.current) {
5142
5152
  readerRef.current.releaseLock();
@@ -5154,7 +5164,8 @@ const useStreamWorkflow = () => {
5154
5164
  inputData,
5155
5165
  requestContext: requestContext$1,
5156
5166
  closeOnSuspend: true,
5157
- tracingOptions: settings?.tracingOptions
5167
+ tracingOptions: settings?.tracingOptions,
5168
+ perStep: perStep ?? debugMode
5158
5169
  });
5159
5170
  if (!stream) {
5160
5171
  return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
@@ -5259,7 +5270,8 @@ const useStreamWorkflow = () => {
5259
5270
  runId,
5260
5271
  step,
5261
5272
  resumeData,
5262
- requestContext: playgroundRequestContext
5273
+ requestContext: playgroundRequestContext,
5274
+ perStep
5263
5275
  }) => {
5264
5276
  if (resumeStreamRef.current) {
5265
5277
  resumeStreamRef.current.releaseLock();
@@ -5276,7 +5288,8 @@ const useStreamWorkflow = () => {
5276
5288
  step,
5277
5289
  resumeData,
5278
5290
  requestContext: requestContext$1,
5279
- tracingOptions: settings?.tracingOptions
5291
+ tracingOptions: settings?.tracingOptions,
5292
+ perStep: perStep ?? debugMode
5280
5293
  });
5281
5294
  if (!stream) {
5282
5295
  return handleStreamError(new Error("No stream returned"), "No stream returned", setIsStreaming);
@@ -5322,6 +5335,7 @@ const useStreamWorkflow = () => {
5322
5335
  workflowId,
5323
5336
  requestContext: playgroundRequestContext,
5324
5337
  runId,
5338
+ perStep,
5325
5339
  ...params
5326
5340
  }) => {
5327
5341
  if (timeTravelStreamRef.current) {
@@ -5337,6 +5351,7 @@ const useStreamWorkflow = () => {
5337
5351
  const run = await workflow.createRun({ runId });
5338
5352
  const stream = await run.timeTravelStream({
5339
5353
  ...params,
5354
+ perStep: perStep ?? debugMode,
5340
5355
  requestContext: requestContext$1,
5341
5356
  tracingOptions: settings?.tracingOptions
5342
5357
  });
@@ -5588,6 +5603,7 @@ function WorkflowRunProvider({
5588
5603
  const [payload, setPayload] = React.useState(() => snapshot?.context?.input ?? null);
5589
5604
  const [runId, setRunId] = React.useState(() => initialRunId ?? "");
5590
5605
  const [isRunning, setIsRunning] = React.useState(false);
5606
+ const [debugMode, setDebugMode] = React.useState(false);
5591
5607
  const refetchExecResultInterval = isRunning ? void 0 : ["success", "failed", "canceled", "bailed"].includes(result?.status ?? "") ? void 0 : 5e3;
5592
5608
  const { isLoading: isLoadingRunExecutionResult, data: runExecutionResult } = useWorkflowRunExecutionResult(
5593
5609
  workflowId,
@@ -5617,7 +5633,7 @@ function WorkflowRunProvider({
5617
5633
  closeStreamsAndReset,
5618
5634
  resumeWorkflowStream,
5619
5635
  timeTravelWorkflowStream
5620
- } = useStreamWorkflow();
5636
+ } = useStreamWorkflow({ debugMode });
5621
5637
  const { mutateAsync: cancelWorkflowRun, isPending: isCancellingWorkflowRun } = useCancelWorkflowRun();
5622
5638
  const clearData = () => {
5623
5639
  setResult(null);
@@ -5673,7 +5689,9 @@ function WorkflowRunProvider({
5673
5689
  },
5674
5690
  runSnapshot,
5675
5691
  isLoadingRunExecutionResult,
5676
- withoutTimeTravel
5692
+ withoutTimeTravel,
5693
+ debugMode,
5694
+ setDebugMode
5677
5695
  },
5678
5696
  children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowStepDetailProvider, { children })
5679
5697
  }
@@ -7851,17 +7869,24 @@ const JsonField = ({
7851
7869
  ] })
7852
7870
  ] });
7853
7871
  };
7854
- const WorkflowTimeTravelForm = ({ stepKey, closeModal }) => {
7872
+ const WorkflowTimeTravelForm = ({
7873
+ stepKey,
7874
+ closeModal,
7875
+ isPerStepRun,
7876
+ isContinueRun,
7877
+ buttonText = "Start time travel",
7878
+ inputData
7879
+ }) => {
7855
7880
  const {
7856
7881
  result,
7857
7882
  workflow,
7858
7883
  timeTravelWorkflowStream,
7859
- createWorkflowRun,
7860
7884
  runId: prevRunId,
7861
- workflowId
7885
+ workflowId,
7886
+ setDebugMode
7862
7887
  } = React.useContext(WorkflowRunContext);
7863
7888
  const { requestContext } = usePlaygroundStore();
7864
- const stepResult = result?.steps?.[stepKey];
7889
+ const stepResult = inputData ? { payload: inputData } : result?.steps?.[stepKey];
7865
7890
  const [resumeData, setResumeData] = React.useState(() => "{}");
7866
7891
  const [contextValue, setContextValue] = React.useState(() => "{}");
7867
7892
  const [nestedContextValue, setNestedContextValue] = React.useState(() => "{}");
@@ -7887,17 +7912,20 @@ const WorkflowTimeTravelForm = ({ stepKey, closeModal }) => {
7887
7912
  const parsedResume = resumeData.trim() ? JSON.parse(resumeData) : {};
7888
7913
  const parsedContext = contextValue.trim() ? JSON.parse(contextValue) : {};
7889
7914
  const parsedNestedContext = nestedContextValue.trim() ? JSON.parse(nestedContextValue) : {};
7890
- const run = await createWorkflowRun({ workflowId, prevRunId });
7891
7915
  const payload = {
7892
- runId: run.runId,
7916
+ runId: prevRunId,
7893
7917
  workflowId,
7894
7918
  step: stepKey,
7895
7919
  inputData: data,
7896
7920
  resumeData: Object.keys(parsedResume)?.length > 0 ? parsedResume : void 0,
7897
7921
  context: Object.keys(parsedContext)?.length > 0 ? parsedContext : void 0,
7898
7922
  nestedStepsContext: Object.keys(parsedNestedContext)?.length > 0 ? parsedNestedContext : void 0,
7899
- requestContext
7923
+ requestContext,
7924
+ ...isContinueRun ? { perStep: false } : {}
7900
7925
  };
7926
+ if (isContinueRun) {
7927
+ setDebugMode(false);
7928
+ }
7901
7929
  timeTravelWorkflowStream(payload);
7902
7930
  closeModal();
7903
7931
  } catch (error) {
@@ -7921,47 +7949,27 @@ const WorkflowTimeTravelForm = ({ stepKey, closeModal }) => {
7921
7949
  schema: stepSchema,
7922
7950
  defaultValues: stepResult?.payload,
7923
7951
  isSubmitLoading: isSubmitting,
7924
- submitButtonLabel: "Start time travel",
7952
+ submitButtonLabel: buttonText,
7925
7953
  onSubmit: handleSubmit,
7926
7954
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-4 pb-4", children: [
7927
- /* @__PURE__ */ jsxRuntime.jsx(
7928
- JsonField,
7929
- {
7930
- label: "Resume Data (JSON)",
7931
- value: resumeData,
7932
- onChange: setResumeData,
7933
- helperText: "Provide any resume payloads that should be passed to the step."
7934
- }
7935
- ),
7936
- /* @__PURE__ */ jsxRuntime.jsx(
7937
- JsonField,
7938
- {
7939
- label: "Context (JSON)",
7940
- value: contextValue,
7941
- onChange: setContextValue,
7942
- helperText: "Only include top level steps (no nested workflow steps) that are required in the time travel execution.",
7943
- exampleCode: prettyJson({
7944
- stepId: {
7945
- status: "success",
7946
- payload: {
7947
- value: "test value"
7948
- },
7949
- output: {
7950
- value: "test output"
7951
- }
7952
- }
7953
- })
7954
- }
7955
- ),
7956
- /* @__PURE__ */ jsxRuntime.jsx(
7957
- JsonField,
7958
- {
7959
- label: "Nested Step Context (JSON)",
7960
- value: nestedContextValue,
7961
- onChange: setNestedContextValue,
7962
- helperText: "Includes nested workflow steps that are required in the time travel execution.",
7963
- exampleCode: prettyJson({
7964
- nestedWorkflowId: {
7955
+ isPerStepRun || isContinueRun ? null : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
7956
+ /* @__PURE__ */ jsxRuntime.jsx(
7957
+ JsonField,
7958
+ {
7959
+ label: "Resume Data (JSON)",
7960
+ value: resumeData,
7961
+ onChange: setResumeData,
7962
+ helperText: "Provide any resume payloads that should be passed to the step."
7963
+ }
7964
+ ),
7965
+ /* @__PURE__ */ jsxRuntime.jsx(
7966
+ JsonField,
7967
+ {
7968
+ label: "Context (JSON)",
7969
+ value: contextValue,
7970
+ onChange: setContextValue,
7971
+ helperText: "Only include top level steps (no nested workflow steps) that are required in the time travel execution.",
7972
+ exampleCode: prettyJson({
7965
7973
  stepId: {
7966
7974
  status: "success",
7967
7975
  payload: {
@@ -7971,10 +7979,32 @@ const WorkflowTimeTravelForm = ({ stepKey, closeModal }) => {
7971
7979
  value: "test output"
7972
7980
  }
7973
7981
  }
7974
- }
7975
- })
7976
- }
7977
- ),
7982
+ })
7983
+ }
7984
+ ),
7985
+ /* @__PURE__ */ jsxRuntime.jsx(
7986
+ JsonField,
7987
+ {
7988
+ label: "Nested Step Context (JSON)",
7989
+ value: nestedContextValue,
7990
+ onChange: setNestedContextValue,
7991
+ helperText: "Includes nested workflow steps that are required in the time travel execution.",
7992
+ exampleCode: prettyJson({
7993
+ nestedWorkflowId: {
7994
+ stepId: {
7995
+ status: "success",
7996
+ payload: {
7997
+ value: "test value"
7998
+ },
7999
+ output: {
8000
+ value: "test output"
8001
+ }
8002
+ }
8003
+ }
8004
+ })
8005
+ }
8006
+ )
8007
+ ] }),
7978
8008
  formError && /* @__PURE__ */ jsxRuntime.jsx(Txt, { variant: "ui-sm", className: "text-accent2", children: formError })
7979
8009
  ] })
7980
8010
  }
@@ -7994,7 +8024,8 @@ const WorkflowStepActionBar = ({
7994
8024
  stepId,
7995
8025
  onShowNestedGraph,
7996
8026
  status,
7997
- stepKey
8027
+ stepKey,
8028
+ stepsFlow
7998
8029
  }) => {
7999
8030
  const [isInputOpen, setIsInputOpen] = React.useState(false);
8000
8031
  const [isOutputOpen, setIsOutputOpen] = React.useState(false);
@@ -8002,11 +8033,53 @@ const WorkflowStepActionBar = ({
8002
8033
  const [isErrorOpen, setIsErrorOpen] = React.useState(false);
8003
8034
  const [isTripwireOpen, setIsTripwireOpen] = React.useState(false);
8004
8035
  const [isTimeTravelOpen, setIsTimeTravelOpen] = React.useState(false);
8005
- const { withoutTimeTravel } = React.useContext(WorkflowRunContext);
8036
+ const [isContinueRunOpen, setIsContinueRunOpen] = React.useState(false);
8037
+ const [isPerStepRunOpen, setIsPerStepRunOpen] = React.useState(false);
8038
+ const {
8039
+ withoutTimeTravel,
8040
+ debugMode,
8041
+ result,
8042
+ runSnapshot,
8043
+ timeTravelWorkflowStream,
8044
+ runId: prevRunId,
8045
+ workflowId,
8046
+ setDebugMode
8047
+ } = React.useContext(WorkflowRunContext);
8006
8048
  const { showMapConfig, stepDetail, closeStepDetail } = useWorkflowStepDetail();
8049
+ const { requestContext } = usePlaygroundStore();
8050
+ const workflowStatus = result?.status ?? runSnapshot?.status;
8007
8051
  const dialogContentClass = "bg-surface2 rounded-lg border-sm border-border1 max-w-4xl w-full px-0";
8008
8052
  const dialogTitleClass = "border-b-sm border-border1 pb-4 px-6";
8009
- const showTimeTravel = !withoutTimeTravel && stepKey && !mapConfig;
8053
+ const showTimeTravel = !withoutTimeTravel && stepKey && !mapConfig && workflowStatus !== "running" && workflowStatus !== "paused";
8054
+ const inDebugMode = stepKey && debugMode && workflowStatus === "paused";
8055
+ const stepPayload = React.useMemo(() => {
8056
+ if (!stepKey || !inDebugMode) return void 0;
8057
+ const previousSteps = stepsFlow?.[stepKey] ?? [];
8058
+ if (previousSteps.length === 0) return void 0;
8059
+ if (previousSteps.length > 1) {
8060
+ return {
8061
+ hasMultiSteps: true,
8062
+ input: previousSteps.reduce(
8063
+ (acc, stepId2) => {
8064
+ if (result?.steps?.[stepId2]?.status === "success") {
8065
+ acc[stepId2] = result?.steps?.[stepId2].output;
8066
+ }
8067
+ return acc;
8068
+ },
8069
+ {}
8070
+ )
8071
+ };
8072
+ }
8073
+ const prevStepId = previousSteps[0];
8074
+ if (result?.steps?.[prevStepId]?.status === "success") {
8075
+ return {
8076
+ hasMultiSteps: false,
8077
+ input: result?.steps?.[prevStepId].output
8078
+ };
8079
+ }
8080
+ return void 0;
8081
+ }, [stepKey, stepsFlow, inDebugMode, result]);
8082
+ const showDebugMode = inDebugMode && stepPayload && !result?.steps[stepKey];
8010
8083
  const isMapConfigOpen = stepDetail?.type === "map-config" && stepDetail?.stepName === stepName;
8011
8084
  const isNestedGraphOpen = stepDetail?.type === "nested-graph" && stepDetail?.stepName === stepName;
8012
8085
  const activeButtonClass = "ring-2 ring-accent1 ring-offset-1 ring-offset-transparent";
@@ -8024,7 +8097,32 @@ const WorkflowStepActionBar = ({
8024
8097
  onShowNestedGraph?.();
8025
8098
  }
8026
8099
  };
8027
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (input || output || error || tripwire || mapConfig || resumeData || onShowNestedGraph || showTimeTravel) && /* @__PURE__ */ jsxRuntime.jsxs(
8100
+ const handleRunMapStep = (isContinueRun) => {
8101
+ const payload = {
8102
+ runId: prevRunId,
8103
+ workflowId,
8104
+ step: stepKey,
8105
+ inputData: stepPayload?.hasMultiSteps ? void 0 : stepPayload?.input,
8106
+ requestContext,
8107
+ ...isContinueRun ? { perStep: false } : {},
8108
+ ...stepPayload?.hasMultiSteps ? {
8109
+ context: Object.keys(stepPayload.input)?.reduce(
8110
+ (acc, stepId2) => {
8111
+ acc[stepId2] = {
8112
+ output: stepPayload.input[stepId2]
8113
+ };
8114
+ return acc;
8115
+ },
8116
+ {}
8117
+ )
8118
+ } : {}
8119
+ };
8120
+ if (isContinueRun) {
8121
+ setDebugMode(false);
8122
+ }
8123
+ timeTravelWorkflowStream(payload);
8124
+ };
8125
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: (input || output || error || tripwire || mapConfig || resumeData || onShowNestedGraph || showTimeTravel || showDebugMode) && /* @__PURE__ */ jsxRuntime.jsxs(
8028
8126
  "div",
8029
8127
  {
8030
8128
  className: cn(
@@ -8048,6 +8146,66 @@ const WorkflowStepActionBar = ({
8048
8146
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-scroll max-h-[600px]", children: /* @__PURE__ */ jsxRuntime.jsx(WorkflowTimeTravelForm, { stepKey, closeModal: () => setIsTimeTravelOpen(false) }) })
8049
8147
  ] }) })
8050
8148
  ] }),
8149
+ showDebugMode && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8150
+ /* @__PURE__ */ jsxRuntime.jsx(
8151
+ Button$1,
8152
+ {
8153
+ onClick: () => {
8154
+ if (mapConfig) {
8155
+ handleRunMapStep();
8156
+ } else {
8157
+ setIsPerStepRunOpen(true);
8158
+ }
8159
+ },
8160
+ children: "Run step"
8161
+ }
8162
+ ),
8163
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isPerStepRunOpen, onOpenChange: setIsPerStepRunOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
8164
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
8165
+ "Run step ",
8166
+ stepKey
8167
+ ] }),
8168
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-scroll max-h-[600px]", children: /* @__PURE__ */ jsxRuntime.jsx(
8169
+ WorkflowTimeTravelForm,
8170
+ {
8171
+ stepKey,
8172
+ closeModal: () => setIsPerStepRunOpen(false),
8173
+ isPerStepRun: true,
8174
+ buttonText: "Run step",
8175
+ inputData: stepPayload?.input
8176
+ }
8177
+ ) })
8178
+ ] }) }),
8179
+ /* @__PURE__ */ jsxRuntime.jsx(
8180
+ Button$1,
8181
+ {
8182
+ onClick: () => {
8183
+ if (mapConfig) {
8184
+ handleRunMapStep(true);
8185
+ } else {
8186
+ setIsContinueRunOpen(true);
8187
+ }
8188
+ },
8189
+ children: "Continue run"
8190
+ }
8191
+ ),
8192
+ /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open: isContinueRunOpen, onOpenChange: setIsContinueRunOpen, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: dialogContentClass, children: [
8193
+ /* @__PURE__ */ jsxRuntime.jsxs(DialogTitle, { className: dialogTitleClass, children: [
8194
+ "Continue run ",
8195
+ stepKey
8196
+ ] }),
8197
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 overflow-scroll max-h-[600px]", children: /* @__PURE__ */ jsxRuntime.jsx(
8198
+ WorkflowTimeTravelForm,
8199
+ {
8200
+ stepKey,
8201
+ closeModal: () => setIsContinueRunOpen(false),
8202
+ isContinueRun: true,
8203
+ buttonText: "Continue run",
8204
+ inputData: stepPayload?.input
8205
+ }
8206
+ ) })
8207
+ ] }) })
8208
+ ] }),
8051
8209
  mapConfig && /* @__PURE__ */ jsxRuntime.jsx(Button$1, { onClick: handleMapConfigClick, className: cn(isMapConfigOpen && activeButtonClass), children: "Map config" }),
8052
8210
  input && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
8053
8211
  /* @__PURE__ */ jsxRuntime.jsx(Button$1, { onClick: () => setIsInputOpen(true), children: "Input" }),
@@ -8280,7 +8438,11 @@ const Clock = ({ startedAt, endedAt }) => {
8280
8438
  ] });
8281
8439
  };
8282
8440
 
8283
- function WorkflowDefaultNode({ data, parentWorkflowName }) {
8441
+ function WorkflowDefaultNode({
8442
+ data,
8443
+ parentWorkflowName,
8444
+ stepsFlow
8445
+ }) {
8284
8446
  const { steps } = useCurrentRun();
8285
8447
  const {
8286
8448
  label,
@@ -8380,7 +8542,8 @@ function WorkflowDefaultNode({ data, parentWorkflowName }) {
8380
8542
  tripwire: isTripwire ? step?.tripwire : void 0,
8381
8543
  mapConfig,
8382
8544
  status: displayStatus,
8383
- stepKey
8545
+ stepKey,
8546
+ stepsFlow
8384
8547
  }
8385
8548
  )
8386
8549
  ]
@@ -8443,36 +8606,13 @@ function WorkflowLoopResultNode({ data }) {
8443
8606
  );
8444
8607
  }
8445
8608
 
8446
- const WorkflowNestedGraphContext = React.createContext(
8447
- {}
8448
- );
8449
- function WorkflowNestedGraphProvider({ children }) {
8450
- const { showNestedGraph: showNestedGraphInPanel, closeStepDetail } = useWorkflowStepDetail();
8451
- const showNestedGraph = ({
8452
- label,
8453
- stepGraph,
8454
- fullStep
8455
- }) => {
8456
- showNestedGraphInPanel({ label, stepGraph, fullStep });
8457
- };
8458
- const closeNestedGraph = () => {
8459
- closeStepDetail();
8460
- };
8461
- return /* @__PURE__ */ jsxRuntime.jsx(
8462
- WorkflowNestedGraphContext.Provider,
8463
- {
8464
- value: {
8465
- showNestedGraph,
8466
- closeNestedGraph
8467
- },
8468
- children
8469
- }
8470
- );
8471
- }
8472
-
8473
- function WorkflowNestedNode({ data, parentWorkflowName }) {
8609
+ function WorkflowNestedNode({
8610
+ data,
8611
+ parentWorkflowName,
8612
+ stepsFlow
8613
+ }) {
8474
8614
  const { steps } = useCurrentRun();
8475
- const { showNestedGraph } = React.useContext(WorkflowNestedGraphContext);
8615
+ const { showNestedGraph } = useWorkflowStepDetail();
8476
8616
  const {
8477
8617
  label,
8478
8618
  stepId,
@@ -8554,7 +8694,8 @@ function WorkflowNestedNode({ data, parentWorkflowName }) {
8554
8694
  mapConfig,
8555
8695
  onShowNestedGraph: () => showNestedGraph({ label, fullStep: fullLabel, stepGraph }),
8556
8696
  status: displayStatus,
8557
- stepKey
8697
+ stepKey,
8698
+ stepsFlow
8558
8699
  }
8559
8700
  )
8560
8701
  ]
@@ -8611,12 +8752,28 @@ function WorkflowGraphInner({ workflow }) {
8611
8752
  const [nodes, _, onNodesChange] = react$2.useNodesState(initialNodes);
8612
8753
  const [edges] = react$2.useEdgesState(initialEdges);
8613
8754
  const { steps } = useCurrentRun();
8755
+ const stepsFlow = React.useMemo(() => {
8756
+ return initialEdges.reduce(
8757
+ (acc, edge) => {
8758
+ if (edge.data) {
8759
+ const stepId = edge.data.nextStepId;
8760
+ const prevStepId = edge.data.previousStepId;
8761
+ return {
8762
+ ...acc,
8763
+ [stepId]: [.../* @__PURE__ */ new Set([...acc[stepId] || [], prevStepId])]
8764
+ };
8765
+ }
8766
+ return acc;
8767
+ },
8768
+ {}
8769
+ );
8770
+ }, [initialEdges]);
8614
8771
  const nodeTypes = {
8615
- "default-node": WorkflowDefaultNode,
8772
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { ...props, stepsFlow }),
8616
8773
  "condition-node": WorkflowConditionNode,
8617
8774
  "after-node": WorkflowAfterNode,
8618
8775
  "loop-result-node": WorkflowLoopResultNode,
8619
- "nested-node": WorkflowNestedNode
8776
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { ...props, stepsFlow })
8620
8777
  };
8621
8778
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-full bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs(
8622
8779
  react$2.ReactFlow,
@@ -8645,6 +8802,33 @@ function WorkflowGraphInner({ workflow }) {
8645
8802
  ) });
8646
8803
  }
8647
8804
 
8805
+ const WorkflowNestedGraphContext = React.createContext(
8806
+ {}
8807
+ );
8808
+ function WorkflowNestedGraphProvider({ children }) {
8809
+ const { showNestedGraph: showNestedGraphInPanel, closeStepDetail } = useWorkflowStepDetail();
8810
+ const showNestedGraph = ({
8811
+ label,
8812
+ stepGraph,
8813
+ fullStep
8814
+ }) => {
8815
+ showNestedGraphInPanel({ label, stepGraph, fullStep });
8816
+ };
8817
+ const closeNestedGraph = () => {
8818
+ closeStepDetail();
8819
+ };
8820
+ return /* @__PURE__ */ jsxRuntime.jsx(
8821
+ WorkflowNestedGraphContext.Provider,
8822
+ {
8823
+ value: {
8824
+ showNestedGraph,
8825
+ closeNestedGraph
8826
+ },
8827
+ children
8828
+ }
8829
+ );
8830
+ }
8831
+
8648
8832
  function WorkflowGraph({ workflowId, workflow, isLoading }) {
8649
8833
  const { snapshot } = React.useContext(WorkflowRunContext);
8650
8834
  if (isLoading) {
@@ -9363,18 +9547,17 @@ const columns$4 = [
9363
9547
  }
9364
9548
  ];
9365
9549
 
9366
- const themeClasses = {
9367
- light: "bg-gray-100 border-gray-300 text-gray-700",
9368
- dark: "bg-surface4 border-border1 text-icon6"
9369
- };
9370
- const Kbd = ({ children, theme = "dark" }) => {
9371
- const themeClass = themeClasses[theme];
9372
- return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: clsx("border-sm rounded-md px-1 py-0.5 font-mono", themeClass), children });
9373
- };
9374
-
9375
- const Searchbar = ({ onSearch, label, placeholder }) => {
9550
+ const Searchbar = ({ onSearch, label, placeholder, debounceMs = 300 }) => {
9376
9551
  const id = React.useId();
9377
9552
  const inputRef = React.useRef(null);
9553
+ const debouncedSearch = useDebounce.useDebouncedCallback((value) => {
9554
+ onSearch(value);
9555
+ }, debounceMs);
9556
+ React.useEffect(() => {
9557
+ return () => {
9558
+ debouncedSearch.cancel();
9559
+ };
9560
+ }, [debouncedSearch]);
9378
9561
  React.useEffect(() => {
9379
9562
  const input = inputRef.current;
9380
9563
  if (!input) return;
@@ -9389,37 +9572,27 @@ const Searchbar = ({ onSearch, label, placeholder }) => {
9389
9572
  window.removeEventListener("keydown", handleKeyDown);
9390
9573
  };
9391
9574
  }, []);
9392
- const handleSubmit = (e) => {
9393
- e.preventDefault();
9394
- const formData = new FormData(e.target);
9395
- const search = formData.get(id);
9396
- onSearch(search);
9575
+ const handleChange = (e) => {
9576
+ debouncedSearch(e.target.value);
9397
9577
  };
9398
- return /* @__PURE__ */ jsxRuntime.jsxs(
9399
- "form",
9400
- {
9401
- onSubmit: handleSubmit,
9402
- className: "focus-within:outline focus-within:outline-accent1 -outline-offset-2 border-sm border-icon-3 flex h-8 w-full items-center gap-2 overflow-hidden rounded-lg pl-2 pr-1",
9403
- children: [
9404
- /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "text-icon3 h-4 w-4" }),
9405
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
9406
- /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "sr-only", children: label }),
9407
- /* @__PURE__ */ jsxRuntime.jsx(
9408
- "input",
9409
- {
9410
- id,
9411
- type: "text",
9412
- placeholder,
9413
- className: "bg-surface2 text-ui-md placeholder:text-icon-3 block h-8 w-full px-2 outline-none",
9414
- name: id,
9415
- ref: inputRef
9416
- }
9417
- )
9418
- ] }),
9419
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "submit", className: "text-ui-sm text-icon3 flex flex-row items-center gap-1", children: /* @__PURE__ */ jsxRuntime.jsx(Kbd, { children: "↵ Enter" }) })
9420
- ]
9421
- }
9422
- );
9578
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "focus-within:outline focus-within:outline-accent1 -outline-offset-2 border-sm border-icon-3 flex h-8 w-full items-center gap-2 overflow-hidden rounded-lg pl-2 pr-1", children: [
9579
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SearchIcon, { className: "text-icon3 h-4 w-4" }),
9580
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1", children: [
9581
+ /* @__PURE__ */ jsxRuntime.jsx("label", { htmlFor: id, className: "sr-only", children: label }),
9582
+ /* @__PURE__ */ jsxRuntime.jsx(
9583
+ "input",
9584
+ {
9585
+ id,
9586
+ type: "text",
9587
+ placeholder,
9588
+ className: "bg-surface2 text-ui-md placeholder:text-icon-3 block h-8 w-full px-2 outline-none",
9589
+ name: id,
9590
+ ref: inputRef,
9591
+ onChange: handleChange
9592
+ }
9593
+ )
9594
+ ] })
9595
+ ] });
9423
9596
  };
9424
9597
  const SearchbarWrapper = ({ children }) => {
9425
9598
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-2 border-b-sm border-border1", children });
@@ -9544,7 +9717,7 @@ const PlaygroundTabs = ({
9544
9717
  setInternalTab(typedValue);
9545
9718
  }
9546
9719
  };
9547
- return /* @__PURE__ */ jsxRuntime.jsx(Tabs$1, { value: currentTab, onValueChange: handleTabChange, className: cn("h-full", className), children });
9720
+ return /* @__PURE__ */ jsxRuntime.jsx(Tabs$1, { value: currentTab, onValueChange: handleTabChange, className: cn("h-full overflow-x-auto", className), children });
9548
9721
  };
9549
9722
  const TabList$1 = ({ children, className }) => {
9550
9723
  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 }) });
@@ -9578,9 +9751,17 @@ const TabContent$1 = ({ children, value }) => {
9578
9751
  return /* @__PURE__ */ jsxRuntime.jsx(TabsContent, { value, className: "h-full overflow-auto flex flex-col", children });
9579
9752
  };
9580
9753
 
9754
+ const WorkflowRunOptions = () => {
9755
+ const { debugMode, setDebugMode } = React.useContext(WorkflowRunContext);
9756
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
9757
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "h3", variant: "ui-md", className: "text-icon3", children: "Debug Mode" }),
9758
+ /* @__PURE__ */ jsxRuntime.jsx(Checkbox, { checked: debugMode, onCheckedChange: (value) => setDebugMode(value) })
9759
+ ] });
9760
+ };
9761
+
9581
9762
  const TracingRunOptions = () => {
9582
9763
  const theme = useCodemirrorTheme$1();
9583
- const { settings, setSettings } = useTracingSettings();
9764
+ const { settings, setSettings, entityType } = useTracingSettings();
9584
9765
  const handleChange = (value) => {
9585
9766
  if (!value) {
9586
9767
  return setSettings({ ...settings, tracingOptions: void 0 });
@@ -9609,7 +9790,8 @@ const TracingRunOptions = () => {
9609
9790
  extensions: [langJson.jsonLanguage],
9610
9791
  className: "h-[400px] overflow-y-scroll bg-surface3 rounded-lg overflow-hidden p-3"
9611
9792
  }
9612
- )
9793
+ ),
9794
+ entityType === "workflow" && /* @__PURE__ */ jsxRuntime.jsx(WorkflowRunOptions, {})
9613
9795
  ] });
9614
9796
  };
9615
9797
 
@@ -9640,12 +9822,28 @@ function WorkflowNestedGraph({ stepGraph, open, workflowName }) {
9640
9822
  const [nodes, _, onNodesChange] = react$2.useNodesState(initialNodes);
9641
9823
  const [edges] = react$2.useEdgesState(initialEdges);
9642
9824
  const { steps } = useCurrentRun();
9825
+ const stepsFlow = React.useMemo(() => {
9826
+ return initialEdges.reduce(
9827
+ (acc, edge) => {
9828
+ if (edge.data) {
9829
+ const stepId = edge.data.nextStepId;
9830
+ const prevStepId = edge.data.previousStepId;
9831
+ return {
9832
+ ...acc,
9833
+ [stepId]: [.../* @__PURE__ */ new Set([...acc[stepId] || [], prevStepId])]
9834
+ };
9835
+ }
9836
+ return acc;
9837
+ },
9838
+ {}
9839
+ );
9840
+ }, [initialEdges]);
9643
9841
  const nodeTypes = {
9644
- "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { parentWorkflowName: workflowName, ...props }),
9842
+ "default-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowDefaultNode, { parentWorkflowName: workflowName, ...props, stepsFlow }),
9645
9843
  "condition-node": WorkflowConditionNode,
9646
9844
  "after-node": WorkflowAfterNode,
9647
9845
  "loop-result-node": WorkflowLoopResultNode,
9648
- "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { parentWorkflowName: workflowName, ...props })
9846
+ "nested-node": (props) => /* @__PURE__ */ jsxRuntime.jsx(WorkflowNestedNode, { parentWorkflowName: workflowName, ...props, stepsFlow })
9649
9847
  };
9650
9848
  React.useEffect(() => {
9651
9849
  if (open) {
@@ -9715,7 +9913,7 @@ function WorkflowStepDetailContent() {
9715
9913
  open: true,
9716
9914
  workflowName: stepDetail.nestedGraph.fullStep
9717
9915
  }
9718
- ) }) })
9916
+ ) }, stepDetail.nestedGraph.fullStep) })
9719
9917
  ] })
9720
9918
  ] });
9721
9919
  }
@@ -10056,6 +10254,162 @@ function WorkflowCombobox({
10056
10254
  );
10057
10255
  }
10058
10256
 
10257
+ function MainContentLayout({
10258
+ children,
10259
+ className,
10260
+ style
10261
+ }) {
10262
+ const devStyleRequested = devUIStyleRequested("MainContentLayout");
10263
+ return /* @__PURE__ */ jsxRuntime.jsx(
10264
+ "main",
10265
+ {
10266
+ className: cn(`grid grid-rows-[auto_1fr] h-full items-start content-start`, className),
10267
+ style: { ...style, ...devStyleRequested ? { border: "3px dotted red" } : {} },
10268
+ children
10269
+ }
10270
+ );
10271
+ }
10272
+ function MainContentContent({
10273
+ children,
10274
+ className,
10275
+ isCentered = false,
10276
+ isDivided = false,
10277
+ hasLeftServiceColumn = false,
10278
+ style
10279
+ }) {
10280
+ const devStyleRequested = devUIStyleRequested("MainContentContent");
10281
+ const contentClassName = getMainContentContentClassName({ isCentered, isDivided, hasLeftServiceColumn, className });
10282
+ return /* @__PURE__ */ jsxRuntime.jsx(
10283
+ "div",
10284
+ {
10285
+ className: contentClassName,
10286
+ style: { ...style, ...devStyleRequested ? { border: "3px dotted orange" } : {} },
10287
+ children
10288
+ }
10289
+ );
10290
+ }
10291
+ const getMainContentContentClassName = ({
10292
+ isCentered,
10293
+ isDivided,
10294
+ hasLeftServiceColumn,
10295
+ className
10296
+ }) => {
10297
+ return cn(
10298
+ `grid overflow-y-auto h-full `,
10299
+ `overflow-x-auto min-w-[min-content]`,
10300
+ {
10301
+ "items-start content-start": !isCentered && !isDivided && !hasLeftServiceColumn,
10302
+ "grid place-items-center": isCentered,
10303
+ "grid-cols-[1fr_1fr]": isDivided && !hasLeftServiceColumn,
10304
+ "grid-cols-[12rem_1fr_1fr]": isDivided && hasLeftServiceColumn,
10305
+ "grid-cols-[auto_1fr]": !isDivided && hasLeftServiceColumn
10306
+ },
10307
+ className
10308
+ );
10309
+ };
10310
+ function devUIStyleRequested(name) {
10311
+ try {
10312
+ const raw = localStorage.getItem("add-dev-style-to-components");
10313
+ if (!raw) return false;
10314
+ const components = raw.split(",").map((c) => c.trim()).filter(Boolean);
10315
+ return components.includes(name);
10316
+ } catch (error) {
10317
+ console.error("Error reading or parsing localStorage:", error);
10318
+ return false;
10319
+ }
10320
+ }
10321
+
10322
+ const PanelSeparator = () => {
10323
+ return /* @__PURE__ */ jsxRuntime.jsx(
10324
+ reactResizablePanels.Separator,
10325
+ {
10326
+ className: clsx(
10327
+ "w-1.5 bg-surface3",
10328
+ "[&[data-separator='hover']]:!bg-surface4",
10329
+ "[&[data-separator='active']]:!bg-surface5",
10330
+ "focus:outline-none"
10331
+ )
10332
+ }
10333
+ );
10334
+ };
10335
+
10336
+ const CollapsiblePanel = ({ collapsedSize, children, direction, ...props }) => {
10337
+ const [collapsed, setCollapsed] = React.useState(false);
10338
+ const panelRef = reactResizablePanels.usePanelRef();
10339
+ const expand = () => {
10340
+ if (!panelRef.current) return;
10341
+ panelRef.current.expand();
10342
+ };
10343
+ return /* @__PURE__ */ jsxRuntime.jsx(
10344
+ reactResizablePanels.Panel,
10345
+ {
10346
+ panelRef,
10347
+ collapsedSize,
10348
+ ...props,
10349
+ onResize: (size) => {
10350
+ if (!collapsedSize) return;
10351
+ if (typeof collapsedSize !== "number") return;
10352
+ if (size.inPixels <= collapsedSize) {
10353
+ setCollapsed(true);
10354
+ } else if (collapsed) {
10355
+ setCollapsed(false);
10356
+ }
10357
+ },
10358
+ children: collapsed ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
10359
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Button$1, { onClick: expand, className: "!h-48 border-none", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: direction === "left" ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowLeft, {}) }) }) }) }),
10360
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: "Expand" })
10361
+ ] }) : children
10362
+ }
10363
+ );
10364
+ };
10365
+
10366
+ const WorkflowLayout = ({ workflowId, children, leftSlot, rightSlot }) => {
10367
+ const { defaultLayout, onLayoutChange } = reactResizablePanels.useDefaultLayout({
10368
+ id: `workflow-layout-${workflowId}`,
10369
+ storage: localStorage
10370
+ });
10371
+ const computedClassName = getMainContentContentClassName({
10372
+ isCentered: false,
10373
+ isDivided: true,
10374
+ hasLeftServiceColumn: Boolean(leftSlot)
10375
+ });
10376
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactResizablePanels.Group, { className: computedClassName, defaultLayout, onLayoutChange, children: [
10377
+ leftSlot && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10378
+ /* @__PURE__ */ jsxRuntime.jsx(
10379
+ CollapsiblePanel,
10380
+ {
10381
+ direction: "left",
10382
+ id: "left-slot",
10383
+ minSize: 200,
10384
+ maxSize: "30%",
10385
+ defaultSize: 200,
10386
+ collapsedSize: 60,
10387
+ collapsible: true,
10388
+ children: leftSlot
10389
+ }
10390
+ ),
10391
+ /* @__PURE__ */ jsxRuntime.jsx(PanelSeparator, {})
10392
+ ] }),
10393
+ /* @__PURE__ */ jsxRuntime.jsx(reactResizablePanels.Panel, { id: "main-slot", children }),
10394
+ rightSlot && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10395
+ /* @__PURE__ */ jsxRuntime.jsx(PanelSeparator, {}),
10396
+ /* @__PURE__ */ jsxRuntime.jsx(
10397
+ CollapsiblePanel,
10398
+ {
10399
+ direction: "right",
10400
+ id: "right-slot",
10401
+ minSize: 300,
10402
+ maxSize: "50%",
10403
+ defaultSize: 300,
10404
+ collapsedSize: 60,
10405
+ collapsible: true,
10406
+ children: rightSlot
10407
+ }
10408
+ )
10409
+ ] })
10410
+ ] });
10411
+ };
10412
+
10059
10413
  const LoadingBadge = () => {
10060
10414
  return /* @__PURE__ */ jsxRuntime.jsx(
10061
10415
  BadgeWrapper,
@@ -12018,12 +12372,12 @@ function MastraRuntimeProvider({
12018
12372
  requireToolApproval
12019
12373
  };
12020
12374
  const baseClient = react$1.useMastraClient();
12021
- const isVNext = modelVersion === "v2";
12375
+ const isSupportedModel = modelVersion === "v2" || modelVersion === "v3";
12022
12376
  const onNew = async (message) => {
12023
12377
  if (message.content[0]?.type !== "text") throw new Error("Only text messages are supported");
12024
12378
  const attachments = await convertToAIAttachments(message.attachments);
12025
12379
  const input = message.content[0].text;
12026
- if (!isVNext) {
12380
+ if (!isSupportedModel) {
12027
12381
  setLegacyMessages((s) => [...s, { role: "user", content: input, attachments: message.attachments }]);
12028
12382
  }
12029
12383
  const controller = new AbortController();
@@ -12034,7 +12388,7 @@ function MastraRuntimeProvider({
12034
12388
  });
12035
12389
  const agent = clientWithAbort.getAgent(agentId);
12036
12390
  try {
12037
- if (isVNext) {
12391
+ if (isSupportedModel) {
12038
12392
  if (chatWithNetwork) {
12039
12393
  await sendMessage({
12040
12394
  message: input,
@@ -12377,7 +12731,7 @@ function MastraRuntimeProvider({
12377
12731
  if (error.name === "AbortError") {
12378
12732
  return;
12379
12733
  }
12380
- if (isVNext) {
12734
+ if (isSupportedModel) {
12381
12735
  setMessages((currentConversation) => [
12382
12736
  ...currentConversation,
12383
12737
  { role: "assistant", parts: [{ type: "text", text: `${error}` }] }
@@ -12404,7 +12758,7 @@ function MastraRuntimeProvider({
12404
12758
  const vnextmessages = messages.map(react$1.toAssistantUIMessage);
12405
12759
  const runtime = react.useExternalStoreRuntime({
12406
12760
  isRunning: isLegacyRunning || isRunningStream,
12407
- messages: isVNext ? vnextmessages : legacyMessages,
12761
+ messages: isSupportedModel ? vnextmessages : legacyMessages,
12408
12762
  convertMessage: (x) => x,
12409
12763
  onNew,
12410
12764
  onCancel,
@@ -12854,8 +13208,9 @@ const AgentSettings = ({ agentId }) => {
12854
13208
  const hasMemory = Boolean(memory?.result);
12855
13209
  const hasSubAgents = Boolean(Object.keys(agent.agents || {}).length > 0);
12856
13210
  const modelVersion = agent.modelVersion;
13211
+ const isSupportedModel = modelVersion === "v2" || modelVersion === "v3";
12857
13212
  let radioValue;
12858
- if (modelVersion === "v2") {
13213
+ if (isSupportedModel) {
12859
13214
  if (settings?.modelSettings?.chatWithNetwork) {
12860
13215
  radioValue = "network";
12861
13216
  } else {
@@ -12882,23 +13237,23 @@ const AgentSettings = ({ agentId }) => {
12882
13237
  }),
12883
13238
  className: "flex flex-row gap-4",
12884
13239
  children: [
12885
- modelVersion !== "v2" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
13240
+ !isSupportedModel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
12886
13241
  /* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "generateLegacy", id: "generateLegacy", className: "text-icon6" }),
12887
13242
  /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-icon6 text-ui-md", htmlFor: "generateLegacy", children: "Generate (Legacy)" })
12888
13243
  ] }),
12889
- modelVersion === "v2" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
13244
+ isSupportedModel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
12890
13245
  /* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "generate", id: "generate", className: "text-icon6" }),
12891
13246
  /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-icon6 text-ui-md", htmlFor: "generate", children: "Generate" })
12892
13247
  ] }),
12893
- modelVersion !== "v2" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
13248
+ !isSupportedModel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
12894
13249
  /* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "streamLegacy", id: "streamLegacy", className: "text-icon6" }),
12895
13250
  /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-icon6 text-ui-md", htmlFor: "streamLegacy", children: "Stream (Legacy)" })
12896
13251
  ] }),
12897
- modelVersion === "v2" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
13252
+ isSupportedModel && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
12898
13253
  /* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: "stream", id: "stream", className: "text-icon6" }),
12899
13254
  /* @__PURE__ */ jsxRuntime.jsx(Label, { className: "text-icon6 text-ui-md", htmlFor: "stream", children: "Stream" })
12900
13255
  ] }),
12901
- modelVersion === "v2" && /* @__PURE__ */ jsxRuntime.jsx(NetworkCheckbox, { hasMemory, hasSubAgents })
13256
+ isSupportedModel && /* @__PURE__ */ jsxRuntime.jsx(NetworkCheckbox, { hasMemory, hasSubAgents })
12902
13257
  ]
12903
13258
  }
12904
13259
  ) }),
@@ -13752,62 +14107,6 @@ const CombinedButtons = ({ className, children }) => {
13752
14107
  );
13753
14108
  };
13754
14109
 
13755
- function MainContentLayout({
13756
- children,
13757
- className,
13758
- style
13759
- }) {
13760
- const devStyleRequested = devUIStyleRequested("MainContentLayout");
13761
- return /* @__PURE__ */ jsxRuntime.jsx(
13762
- "main",
13763
- {
13764
- className: cn(`grid grid-rows-[auto_1fr] h-full items-start content-start`, className),
13765
- style: { ...style, ...devStyleRequested ? { border: "3px dotted red" } : {} },
13766
- children
13767
- }
13768
- );
13769
- }
13770
- function MainContentContent({
13771
- children,
13772
- className,
13773
- isCentered = false,
13774
- isDivided = false,
13775
- hasLeftServiceColumn = false,
13776
- style
13777
- }) {
13778
- const devStyleRequested = devUIStyleRequested("MainContentContent");
13779
- return /* @__PURE__ */ jsxRuntime.jsx(
13780
- "div",
13781
- {
13782
- className: cn(
13783
- `grid overflow-y-auto h-full `,
13784
- `overflow-x-auto min-w-[min-content]`,
13785
- {
13786
- "items-start content-start": !isCentered && !isDivided && !hasLeftServiceColumn,
13787
- "grid place-items-center": isCentered,
13788
- "grid-cols-[1fr_1fr]": isDivided && !hasLeftServiceColumn,
13789
- "grid-cols-[12rem_1fr_1fr]": isDivided && hasLeftServiceColumn,
13790
- "grid-cols-[auto_1fr]": !isDivided && hasLeftServiceColumn
13791
- },
13792
- className
13793
- ),
13794
- style: { ...style, ...devStyleRequested ? { border: "3px dotted orange" } : {} },
13795
- children
13796
- }
13797
- );
13798
- }
13799
- function devUIStyleRequested(name) {
13800
- try {
13801
- const raw = localStorage.getItem("add-dev-style-to-components");
13802
- if (!raw) return false;
13803
- const components = raw.split(",").map((c) => c.trim()).filter(Boolean);
13804
- return components.includes(name);
13805
- } catch (error) {
13806
- console.error("Error reading or parsing localStorage:", error);
13807
- return false;
13808
- }
13809
- }
13810
-
13811
14110
  function ButtonsGroup({ children, className }) {
13812
14111
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(`flex gap-2 items-center`, "[&>button]:flex-grow", className), children });
13813
14112
  }
@@ -15973,7 +16272,7 @@ const AgentMetadata = ({ agentId }) => {
15973
16272
  AgentMetadataSection,
15974
16273
  {
15975
16274
  title: "Model",
15976
- hint: agent.modelVersion === "v2" ? void 0 : {
16275
+ hint: agent.modelVersion === "v2" || agent.modelVersion === "v3" ? void 0 : {
15977
16276
  link: "https://mastra.ai/guides/migrations/vnext-to-standard-apis",
15978
16277
  title: "You are using a legacy v1 model",
15979
16278
  icon: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangleIcon, { fontSize: 14, className: "mb-0.5" })
@@ -16101,7 +16400,7 @@ const AgentEntityHeader = ({ agentId }) => {
16101
16400
  };
16102
16401
 
16103
16402
  const Threads = ({ children }) => {
16104
- return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "bg-surface2 border-r-sm border-border1 min-h-full overflow-hidden", children });
16403
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "bg-surface2 min-h-full overflow-hidden", children });
16105
16404
  };
16106
16405
  const ThreadLink = ({ children, as: Component = "a", href, className, prefetch, to }) => {
16107
16406
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -17215,7 +17514,7 @@ const useAgentInformationSettings = ({ modelId }) => {
17215
17514
  const AgentInformationLayout = ({ children, agentId }) => {
17216
17515
  const { data: agent } = useAgent(agentId);
17217
17516
  useAgentInformationSettings({ modelId: agent?.modelId || "" });
17218
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-rows-[auto_1fr] h-full items-start overflow-y-auto border-l-sm border-border1", children });
17517
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-rows-[auto_1fr] h-full items-start overflow-y-auto", children });
17219
17518
  };
17220
17519
  const AgentInformationTabLayout = ({ children, agentId }) => {
17221
17520
  const { data: memory, isLoading: isMemoryLoading } = useMemory(agentId);
@@ -17227,6 +17526,53 @@ const AgentInformationTabLayout = ({ children, agentId }) => {
17227
17526
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 overflow-hidden border-t-sm border-border1 flex flex-col", children: /* @__PURE__ */ jsxRuntime.jsx(PlaygroundTabs, { defaultTab: "overview", value: selectedTab, onValueChange: handleTabChange, children }) });
17228
17527
  };
17229
17528
 
17529
+ const AgentLayout = ({ agentId, children, leftSlot, rightSlot }) => {
17530
+ const { defaultLayout, onLayoutChange } = reactResizablePanels.useDefaultLayout({
17531
+ id: `agent-layout-${agentId}`,
17532
+ storage: localStorage
17533
+ });
17534
+ const computedClassName = getMainContentContentClassName({
17535
+ isCentered: false,
17536
+ isDivided: true,
17537
+ hasLeftServiceColumn: Boolean(leftSlot)
17538
+ });
17539
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactResizablePanels.Group, { className: computedClassName, defaultLayout, onLayoutChange, children: [
17540
+ leftSlot && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17541
+ /* @__PURE__ */ jsxRuntime.jsx(
17542
+ CollapsiblePanel,
17543
+ {
17544
+ direction: "left",
17545
+ id: "left-slot",
17546
+ minSize: 200,
17547
+ maxSize: "30%",
17548
+ defaultSize: 200,
17549
+ collapsedSize: 60,
17550
+ collapsible: true,
17551
+ children: leftSlot
17552
+ }
17553
+ ),
17554
+ /* @__PURE__ */ jsxRuntime.jsx(PanelSeparator, {})
17555
+ ] }),
17556
+ /* @__PURE__ */ jsxRuntime.jsx(reactResizablePanels.Panel, { id: "main-slot", className: "grid overflow-y-auto relative bg-surface1 py-4", children }),
17557
+ rightSlot && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17558
+ /* @__PURE__ */ jsxRuntime.jsx(PanelSeparator, {}),
17559
+ /* @__PURE__ */ jsxRuntime.jsx(
17560
+ CollapsiblePanel,
17561
+ {
17562
+ direction: "right",
17563
+ id: "right-slot",
17564
+ minSize: 300,
17565
+ maxSize: "50%",
17566
+ defaultSize: 300,
17567
+ collapsedSize: 60,
17568
+ collapsible: true,
17569
+ children: rightSlot
17570
+ }
17571
+ )
17572
+ ] })
17573
+ ] });
17574
+ };
17575
+
17230
17576
  const NameCell$1 = ({ row }) => {
17231
17577
  const { Link, paths } = useLinkComponent();
17232
17578
  const tool = row.original;
@@ -18194,7 +18540,7 @@ const formatHierarchicalSpans = (spans) => {
18194
18540
  });
18195
18541
  spans.forEach((spanRecord) => {
18196
18542
  const uiSpan = spanMap.get(spanRecord.spanId);
18197
- if (spanRecord?.parentSpanId === null) {
18543
+ if (spanRecord?.parentSpanId == null) {
18198
18544
  if (overallEndDate && uiSpan.endTime && overallEndDate > new Date(uiSpan.endTime)) {
18199
18545
  uiSpan.endTime = overallEndDate.toISOString();
18200
18546
  const overallEndTime = new Date(overallEndDate).getTime();
@@ -18789,17 +19135,21 @@ function useTraceInfo(trace) {
18789
19135
  }
18790
19136
  const agentsLink = paths.agentsLink();
18791
19137
  const workflowsLink = paths.workflowsLink();
18792
- const agentLink = paths.agentLink(trace?.metadata?.resourceId);
18793
- const workflowLink = paths.workflowLink(trace?.attributes?.workflowId);
19138
+ const entityId = trace.entityId;
19139
+ const entityType = trace.entityType;
19140
+ const entityName = trace.entityName;
19141
+ const isAgent = entityType === "agent";
19142
+ const isWorkflow = entityType === "workflow_run";
19143
+ const entityLink = isAgent && entityId ? paths.agentLink(entityId) : isWorkflow && entityId ? paths.workflowLink(entityId) : void 0;
18794
19144
  return [
18795
19145
  {
18796
19146
  key: "entityId",
18797
19147
  label: "Entity Id",
18798
19148
  value: [
18799
19149
  {
18800
- id: trace?.metadata?.resourceId,
18801
- name: trace?.attributes?.agentId || trace?.attributes?.workflowId || "-",
18802
- path: trace?.attributes?.agentId ? agentLink : trace?.attributes?.workflowId ? workflowLink : void 0
19150
+ id: entityId ?? "unknown",
19151
+ name: entityName || entityId || "-",
19152
+ path: entityLink
18803
19153
  }
18804
19154
  ]
18805
19155
  },
@@ -18808,9 +19158,9 @@ function useTraceInfo(trace) {
18808
19158
  label: "Entity Type",
18809
19159
  value: [
18810
19160
  {
18811
- id: trace?.attributes?.agentId || trace?.attributes?.workflowId,
18812
- name: trace?.attributes?.agentId ? "Agent" : trace?.attributes?.workflowId ? "Workflow" : "-",
18813
- path: trace?.attributes?.agentId ? agentsLink : trace?.attributes?.workflowId ? workflowsLink : void 0
19161
+ id: entityType ?? "unknown",
19162
+ name: entityType ?? "-",
19163
+ path: isAgent ? agentsLink : isWorkflow ? workflowsLink : void 0
18814
19164
  }
18815
19165
  ]
18816
19166
  },
@@ -18852,11 +19202,12 @@ function getSpanInfo({ span }) {
18852
19202
  value: span?.endedAt ? dateFns.format(new Date(span.endedAt), "MMM dd, h:mm:ss.SSS aaa") : "-"
18853
19203
  }
18854
19204
  ];
18855
- if (span?.attributes?.finishReason) {
19205
+ const finishReason = span?.attributes?.finishReason;
19206
+ if (finishReason) {
18856
19207
  baseInfo.push({
18857
19208
  key: "finishReason",
18858
19209
  label: "Finish Reason",
18859
- value: span.attributes.finishReason
19210
+ value: finishReason
18860
19211
  });
18861
19212
  }
18862
19213
  return baseInfo;
@@ -18959,9 +19310,10 @@ function TraceSpanUsage({ traceUsage, traceSpans = [], spanUsage, className }) {
18959
19310
  return null;
18960
19311
  }
18961
19312
  const generationSpans = traceSpans.filter((span) => span.spanType === "model_generation");
18962
- const hasV5Format = generationSpans.some(
18963
- (span) => span.attributes?.usage?.inputTokens !== void 0 || span.attributes?.usage?.outputTokens !== void 0
18964
- );
19313
+ const hasV5Format = generationSpans.some((span) => {
19314
+ const usage = span.attributes?.usage;
19315
+ return usage && "inputTokens" in usage;
19316
+ });
18965
19317
  const tokensByProvider = generationSpans.reduce(
18966
19318
  (acc, span) => {
18967
19319
  const spanUsage2 = span.attributes?.usage || {};
@@ -18989,8 +19341,8 @@ function TraceSpanUsage({ traceUsage, traceSpans = [], spanUsage, className }) {
18989
19341
  const v5Acc = acc[spanModelProvider];
18990
19342
  v5Acc.inputTokens += inputTokens;
18991
19343
  v5Acc.outputTokens += outputTokens;
18992
- v5Acc.reasoningTokens += reasoningTokens;
18993
- v5Acc.cachedInputTokens += cachedInputTokens;
19344
+ v5Acc.reasoningTokens = (v5Acc.reasoningTokens ?? 0) + reasoningTokens;
19345
+ v5Acc.cachedInputTokens = (v5Acc.cachedInputTokens ?? 0) + cachedInputTokens;
18994
19346
  v5Acc.totalTokens += spanUsage2.totalTokens || inputTokens + outputTokens;
18995
19347
  } else if ("promptTokens" in acc[spanModelProvider] && !hasV5Format) {
18996
19348
  const promptTokens = spanUsage2.promptTokens ?? 0;
@@ -19247,7 +19599,7 @@ function SpanTabs({
19247
19599
  ] })
19248
19600
  ] }),
19249
19601
  /* @__PURE__ */ jsxRuntime.jsx(Tabs.Content, { value: "details", children: /* @__PURE__ */ jsxRuntime.jsxs(Sections, { children: [
19250
- span?.attributes?.usage && /* @__PURE__ */ jsxRuntime.jsx(TraceSpanUsage, { spanUsage: span.attributes.usage }),
19602
+ span?.attributes?.usage ? /* @__PURE__ */ jsxRuntime.jsx(TraceSpanUsage, { spanUsage: span.attributes.usage }) : null,
19251
19603
  /* @__PURE__ */ jsxRuntime.jsx(KeyValueList, { data: spanInfo, LinkComponent: Link }),
19252
19604
  /* @__PURE__ */ jsxRuntime.jsx(SpanDetails, { span })
19253
19605
  ] }) }),
@@ -19781,7 +20133,7 @@ function TracesList({
19781
20133
  date: isTodayDate ? "Today" : dateFns.format(createdAtDate, "MMM dd"),
19782
20134
  time: dateFns.format(createdAtDate, "h:mm:ss aaa"),
19783
20135
  name: trace?.name,
19784
- entityId: trace?.attributes?.agentId || trace?.attributes?.workflowId,
20136
+ entityId: trace?.entityName || trace?.entityId || trace?.attributes?.agentId || trace?.attributes?.workflowId,
19785
20137
  status: trace?.attributes?.status
19786
20138
  };
19787
20139
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -19887,7 +20239,7 @@ function SpanScoreList({
19887
20239
  entry,
19888
20240
  children: traceScoresListColumns.map((col) => {
19889
20241
  const key = `col-${col.name}`;
19890
- return /* @__PURE__ */ jsxRuntime.jsx(EntryList.EntryText, { children: entry?.[col.name] }, key);
20242
+ return /* @__PURE__ */ jsxRuntime.jsx(EntryList.EntryText, { children: String(entry?.[col.name] ?? "") }, key);
19891
20243
  })
19892
20244
  },
19893
20245
  score.id
@@ -20120,6 +20472,15 @@ const PlaygroundQueryClient = ({ children, options }) => {
20120
20472
  return /* @__PURE__ */ jsxRuntime.jsx(reactQuery.QueryClientProvider, { client: queryClient, children });
20121
20473
  };
20122
20474
 
20475
+ const themeClasses = {
20476
+ light: "bg-gray-100 border-gray-300 text-gray-700",
20477
+ dark: "bg-surface4 border-border1 text-icon6"
20478
+ };
20479
+ const Kbd = ({ children, theme = "dark" }) => {
20480
+ const themeClass = themeClasses[theme];
20481
+ return /* @__PURE__ */ jsxRuntime.jsx("kbd", { className: clsx("border-sm rounded-md px-1 py-0.5 font-mono", themeClass), children });
20482
+ };
20483
+
20123
20484
  const errorFallback = "Something went wrong while fetching the data.";
20124
20485
  const parseError = (error) => {
20125
20486
  try {
@@ -20720,6 +21081,292 @@ const StudioConfigForm = ({ initialConfig }) => {
20720
21081
  ] });
20721
21082
  };
20722
21083
 
21084
+ const useMastraPackages = () => {
21085
+ const client = react$1.useMastraClient();
21086
+ return reactQuery.useQuery({
21087
+ queryKey: ["mastra-packages"],
21088
+ queryFn: () => {
21089
+ return client.getSystemPackages();
21090
+ }
21091
+ });
21092
+ };
21093
+
21094
+ async function fetchPackageInfo(packageName, installedVersion) {
21095
+ const prereleaseComponents = semver.prerelease(installedVersion);
21096
+ const prereleaseTag = prereleaseComponents ? String(prereleaseComponents[0]) : null;
21097
+ try {
21098
+ const response = await fetch(`https://registry.npmjs.org/${encodeURIComponent(packageName)}`);
21099
+ if (!response.ok) {
21100
+ return {
21101
+ name: packageName,
21102
+ version: installedVersion,
21103
+ latestVersion: null,
21104
+ isOutdated: false,
21105
+ isDeprecated: false,
21106
+ prereleaseTag,
21107
+ targetPrereleaseTag: null
21108
+ };
21109
+ }
21110
+ const data = await response.json();
21111
+ const latestVersion = data["dist-tags"]?.latest ?? null;
21112
+ const versionInfo = data.versions?.[installedVersion];
21113
+ const deprecationMessage = versionInfo?.deprecated;
21114
+ const targetPrereleaseComponents = latestVersion ? semver.prerelease(latestVersion) : null;
21115
+ const targetPrereleaseTag = targetPrereleaseComponents ? String(targetPrereleaseComponents[0]) : null;
21116
+ let isOutdated = false;
21117
+ if (latestVersion !== null && semver.valid(installedVersion) && semver.valid(latestVersion)) {
21118
+ isOutdated = semver.gt(latestVersion, installedVersion);
21119
+ }
21120
+ return {
21121
+ name: packageName,
21122
+ version: installedVersion,
21123
+ latestVersion,
21124
+ isOutdated,
21125
+ isDeprecated: !!deprecationMessage,
21126
+ prereleaseTag,
21127
+ targetPrereleaseTag,
21128
+ deprecationMessage
21129
+ };
21130
+ } catch {
21131
+ return {
21132
+ name: packageName,
21133
+ version: installedVersion,
21134
+ latestVersion: null,
21135
+ isOutdated: false,
21136
+ isDeprecated: false,
21137
+ prereleaseTag,
21138
+ targetPrereleaseTag: null
21139
+ };
21140
+ }
21141
+ }
21142
+ function usePackageUpdates(packages) {
21143
+ const queries = reactQuery.useQueries({
21144
+ queries: packages.map((pkg) => ({
21145
+ queryKey: ["package-update", pkg.name, pkg.version],
21146
+ queryFn: () => fetchPackageInfo(pkg.name, pkg.version),
21147
+ staleTime: 1e3 * 60 * 60,
21148
+ // 1 hour - latest versions don't change often
21149
+ gcTime: 1e3 * 60 * 60 * 24
21150
+ // 24 hours
21151
+ }))
21152
+ });
21153
+ const isLoading = queries.some((q) => q.isLoading);
21154
+ const packageUpdates = queries.map((q) => q.data).filter((p) => p !== void 0);
21155
+ const allComplete = !isLoading && packageUpdates.length === packages.length;
21156
+ const outdatedCount = allComplete ? packageUpdates.filter((p) => p.isOutdated && !p.isDeprecated).length : 0;
21157
+ const deprecatedCount = allComplete ? packageUpdates.filter((p) => p.isDeprecated).length : 0;
21158
+ return {
21159
+ packages: packageUpdates,
21160
+ isLoading,
21161
+ outdatedCount,
21162
+ deprecatedCount
21163
+ };
21164
+ }
21165
+
21166
+ const packageManagerCommands = {
21167
+ pnpm: "pnpm add",
21168
+ npm: "npm install",
21169
+ yarn: "yarn add",
21170
+ bun: "bun add"
21171
+ };
21172
+ const MastraVersionFooter = ({ collapsed }) => {
21173
+ const { data, isLoading: isLoadingPackages } = useMastraPackages();
21174
+ const installedPackages = data?.packages ?? [];
21175
+ const {
21176
+ packages: packageUpdates,
21177
+ isLoading: isLoadingUpdates,
21178
+ outdatedCount,
21179
+ deprecatedCount
21180
+ } = usePackageUpdates(installedPackages);
21181
+ const [packageManager, setPackageManager] = React.useState("pnpm");
21182
+ if (collapsed) {
21183
+ return null;
21184
+ }
21185
+ if (isLoadingPackages) {
21186
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-3 py-2", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-pulse h-4 bg-surface2 rounded w-16" }) });
21187
+ }
21188
+ const mastraCorePackage = installedPackages.find((pkg) => pkg.name === "@mastra/core");
21189
+ if (!mastraCorePackage && installedPackages.length === 0) {
21190
+ return null;
21191
+ }
21192
+ const mainVersion = mastraCorePackage?.version ?? installedPackages[0]?.version ?? "";
21193
+ const updateCommand = generateUpdateCommand(packageUpdates, packageManager);
21194
+ return /* @__PURE__ */ jsxRuntime.jsxs(Dialog, { children: [
21195
+ /* @__PURE__ */ jsxRuntime.jsx(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("button", { className: "px-3 py-2 hover:bg-surface2 transition-colors rounded w-full text-left", children: [
21196
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1.5", children: /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-sm", className: "text-accent1 font-mono", children: "mastra version:" }) }),
21197
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
21198
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-sm", className: "text-icon3 font-mono", children: mainVersion }),
21199
+ isLoadingUpdates && /* @__PURE__ */ jsxRuntime.jsx(Spinner, { className: "w-3 h-3", color: "currentColor" }),
21200
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center -space-x-1.5", children: [
21201
+ outdatedCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(CountBadge, { count: outdatedCount, variant: "warning" }),
21202
+ deprecatedCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(CountBadge, { count: deprecatedCount, variant: "error" })
21203
+ ] })
21204
+ ] })
21205
+ ] }) }),
21206
+ /* @__PURE__ */ jsxRuntime.jsx(
21207
+ PackagesModalContent,
21208
+ {
21209
+ packages: packageUpdates,
21210
+ isLoadingUpdates,
21211
+ outdatedCount,
21212
+ deprecatedCount,
21213
+ updateCommand,
21214
+ packageManager,
21215
+ onPackageManagerChange: setPackageManager
21216
+ }
21217
+ )
21218
+ ] });
21219
+ };
21220
+ function generateUpdateCommand(packages, packageManager) {
21221
+ const outdatedPackages = packages.filter((p) => p.isOutdated || p.isDeprecated);
21222
+ if (outdatedPackages.length === 0) return null;
21223
+ const command = packageManagerCommands[packageManager];
21224
+ const packageArgs = outdatedPackages.map((p) => `${p.name}@${p.targetPrereleaseTag ?? "latest"}`).join(" ");
21225
+ return `${command} ${packageArgs}`;
21226
+ }
21227
+ function CountBadge({ count, variant }) {
21228
+ return /* @__PURE__ */ jsxRuntime.jsx(
21229
+ "span",
21230
+ {
21231
+ className: cn(
21232
+ "inline-flex items-center justify-center min-w-[1.125rem] h-[1.125rem] px-1 rounded-full text-[0.625rem] font-bold text-black",
21233
+ variant === "error" ? "bg-red-700" : "bg-yellow-700"
21234
+ ),
21235
+ children: count
21236
+ }
21237
+ );
21238
+ }
21239
+ function StatusBadge({ value, variant }) {
21240
+ return /* @__PURE__ */ jsxRuntime.jsx(
21241
+ "span",
21242
+ {
21243
+ className: cn(
21244
+ "inline-flex font-bold rounded-md px-1.5 py-0.5 items-center justify-center text-black text-xs min-w-[1.25rem]",
21245
+ variant === "error" ? "bg-red-700" : "bg-yellow-700"
21246
+ ),
21247
+ children: value
21248
+ }
21249
+ );
21250
+ }
21251
+ const PackagesModalContent = ({
21252
+ packages,
21253
+ isLoadingUpdates,
21254
+ outdatedCount,
21255
+ deprecatedCount,
21256
+ updateCommand,
21257
+ packageManager,
21258
+ onPackageManagerChange
21259
+ }) => {
21260
+ const hasUpdates = outdatedCount > 0 || deprecatedCount > 0;
21261
+ const packagesText = packages.map((pkg) => `${pkg.name}@${pkg.version}`).join("\n");
21262
+ const { isCopied: isCopiedAll, handleCopy: handleCopyAll } = useCopyToClipboard({
21263
+ text: packagesText,
21264
+ copyMessage: "Copied package versions!"
21265
+ });
21266
+ const { isCopied: isCopiedCommand, handleCopy: handleCopyCommand } = useCopyToClipboard({
21267
+ text: updateCommand ?? "",
21268
+ copyMessage: "Copied update command!"
21269
+ });
21270
+ return /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "bg-surface1 border-border1 max-w-2xl", children: [
21271
+ /* @__PURE__ */ jsxRuntime.jsx(DialogHeader, { children: /* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { className: "text-text1", children: "Installed Mastra Packages" }) }),
21272
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-icon3 py-2", children: isLoadingUpdates ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-icon3", children: "Checking for updates..." }) : !hasUpdates ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-accent1", children: "✓ All packages are up to date" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
21273
+ outdatedCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
21274
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { value: outdatedCount, variant: "warning" }),
21275
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
21276
+ "package",
21277
+ outdatedCount !== 1 ? "s" : "",
21278
+ " outdated"
21279
+ ] })
21280
+ ] }),
21281
+ deprecatedCount > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-center gap-1.5", children: [
21282
+ /* @__PURE__ */ jsxRuntime.jsx(StatusBadge, { value: deprecatedCount, variant: "error" }),
21283
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
21284
+ "package",
21285
+ deprecatedCount !== 1 ? "s" : "",
21286
+ " deprecated"
21287
+ ] })
21288
+ ] })
21289
+ ] }) }),
21290
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "max-h-64 overflow-y-auto border border-border1 rounded-md", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-[1fr_auto_auto] text-sm", children: packages.map((pkg, index) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("contents", index > 0 && "[&>div]:border-t [&>div]:border-border1"), children: [
21291
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 px-3 font-mono text-text1 truncate min-w-0", children: /* @__PURE__ */ jsxRuntime.jsxs(
21292
+ "a",
21293
+ {
21294
+ href: `https://www.npmjs.com/package/${pkg.name}`,
21295
+ target: "_blank",
21296
+ rel: "noopener noreferrer",
21297
+ className: "hover:text-accent1 hover:underline inline-flex items-center gap-1 group",
21298
+ children: [
21299
+ pkg.name,
21300
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "w-3 h-3 opacity-0 group-hover:opacity-100 transition-opacity" })
21301
+ ]
21302
+ }
21303
+ ) }),
21304
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 px-3 font-mono text-icon3 flex items-center gap-1.5", children: pkg.isOutdated || pkg.isDeprecated ? /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
21305
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
21306
+ "span",
21307
+ {
21308
+ className: cn(
21309
+ "cursor-help",
21310
+ pkg.isDeprecated ? "text-red-500" : pkg.isOutdated ? "text-yellow-500" : ""
21311
+ ),
21312
+ children: pkg.version
21313
+ }
21314
+ ) }),
21315
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { children: pkg.isDeprecated ? pkg.deprecationMessage || "This version is deprecated" : "Newer version available" })
21316
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("span", { children: pkg.version }) }),
21317
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "py-2 px-3 font-mono text-icon3 flex items-center", children: (pkg.isOutdated || pkg.isDeprecated) && pkg.latestVersion && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
21318
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MoveRight, { className: "w-4 h-4 mx-2 text-icon3" }),
21319
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-accent1", children: pkg.latestVersion })
21320
+ ] }) })
21321
+ ] }, pkg.name)) }) }),
21322
+ /* @__PURE__ */ jsxRuntime.jsxs(
21323
+ "button",
21324
+ {
21325
+ onClick: handleCopyAll,
21326
+ className: "flex items-center justify-center gap-2 w-full py-2 px-3 rounded bg-surface2 hover:bg-surface3 text-icon3 hover:text-icon1 transition-colors",
21327
+ children: [
21328
+ isCopiedAll ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-accent1" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
21329
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-sm", children: isCopiedAll ? "Copied!" : "Copy current versions" })
21330
+ ]
21331
+ }
21332
+ ),
21333
+ hasUpdates && updateCommand && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-3 pt-2 border-t border-border1", children: [
21334
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-icon3 pt-3", children: [
21335
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "w-4 h-4" }),
21336
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "Use the command below to update your packages" })
21337
+ ] }),
21338
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2 items-center", children: [
21339
+ /* @__PURE__ */ jsxRuntime.jsx(
21340
+ SelectField,
21341
+ {
21342
+ value: packageManager,
21343
+ onValueChange: (value) => onPackageManagerChange(value),
21344
+ options: [
21345
+ { label: "pnpm", value: "pnpm" },
21346
+ { label: "npm", value: "npm" },
21347
+ { label: "yarn", value: "yarn" },
21348
+ { label: "bun", value: "bun" }
21349
+ ]
21350
+ }
21351
+ ),
21352
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "flex-1 text-sm text-icon3 bg-surface2 rounded-md px-3 py-1.5 overflow-x-auto whitespace-pre-wrap break-all", children: updateCommand })
21353
+ ] }),
21354
+ /* @__PURE__ */ jsxRuntime.jsxs(
21355
+ "button",
21356
+ {
21357
+ onClick: handleCopyCommand,
21358
+ className: "flex items-center justify-center gap-2 w-full py-2 px-3 rounded bg-surface2 hover:bg-surface3 text-icon3 hover:text-icon1 transition-colors",
21359
+ children: [
21360
+ isCopiedCommand ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-4 h-4 text-accent1" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-4 h-4" }),
21361
+ /* @__PURE__ */ jsxRuntime.jsx(Txt, { as: "span", variant: "ui-sm", children: isCopiedCommand ? "Copied!" : "Copy command" })
21362
+ ]
21363
+ }
21364
+ )
21365
+ ] })
21366
+ ] });
21367
+ };
21368
+ const MastraPackagesInfo = MastraVersionFooter;
21369
+
20723
21370
  const PlaygroundConfigGuard = () => {
20724
21371
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col h-screen w-full items-center justify-center bg-surface1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-md w-full mx-auto px-4 pt-4", children: [
20725
21372
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center pb-4", children: /* @__PURE__ */ jsxRuntime.jsx(LogoWithoutText, { className: "size-32" }) }),
@@ -20739,6 +21386,7 @@ exports.AgentIcon = AgentIcon;
20739
21386
  exports.AgentInformation = AgentInformation;
20740
21387
  exports.AgentInformationLayout = AgentInformationLayout;
20741
21388
  exports.AgentInformationTabLayout = AgentInformationTabLayout;
21389
+ exports.AgentLayout = AgentLayout;
20742
21390
  exports.AgentMemory = AgentMemory;
20743
21391
  exports.AgentMetadata = AgentMetadata;
20744
21392
  exports.AgentMetadataList = AgentMetadataList;
@@ -20829,6 +21477,8 @@ exports.MainContentContent = MainContentContent;
20829
21477
  exports.MainContentLayout = MainContentLayout;
20830
21478
  exports.MainSidebar = MainSidebar;
20831
21479
  exports.MainSidebarProvider = MainSidebarProvider;
21480
+ exports.MastraPackagesInfo = MastraPackagesInfo;
21481
+ exports.MastraVersionFooter = MastraVersionFooter;
20832
21482
  exports.McpCoinIcon = McpCoinIcon;
20833
21483
  exports.McpServerIcon = McpServerIcon;
20834
21484
  exports.MemoryIcon = MemoryIcon;
@@ -20918,6 +21568,7 @@ exports.WorkflowCombobox = WorkflowCombobox;
20918
21568
  exports.WorkflowGraph = WorkflowGraph;
20919
21569
  exports.WorkflowIcon = WorkflowIcon;
20920
21570
  exports.WorkflowInformation = WorkflowInformation;
21571
+ exports.WorkflowLayout = WorkflowLayout;
20921
21572
  exports.WorkflowRunContext = WorkflowRunContext;
20922
21573
  exports.WorkflowRunDetail = WorkflowRunDetail;
20923
21574
  exports.WorkflowRunList = WorkflowRunList;
@@ -20932,6 +21583,7 @@ exports.convertWorkflowRunStateToStreamResult = convertWorkflowRunStateToStreamR
20932
21583
  exports.extractPrompt = extractPrompt;
20933
21584
  exports.formatHierarchicalSpans = formatHierarchicalSpans;
20934
21585
  exports.getColumnTemplate = getColumnTemplate;
21586
+ exports.getMainContentContentClassName = getMainContentContentClassName;
20935
21587
  exports.getShortId = getShortId;
20936
21588
  exports.getSpanTypeUi = getSpanTypeUi;
20937
21589
  exports.getToNextEntryFn = getToNextEntryFn;
@@ -20963,9 +21615,11 @@ exports.useMCPServerTool = useMCPServerTool;
20963
21615
  exports.useMCPServerTools = useMCPServerTools;
20964
21616
  exports.useMCPServers = useMCPServers;
20965
21617
  exports.useMainSidebar = useMainSidebar;
21618
+ exports.useMastraPackages = useMastraPackages;
20966
21619
  exports.useMemory = useMemory;
20967
21620
  exports.useMemoryConfig = useMemoryConfig;
20968
21621
  exports.useMemorySearch = useMemorySearch;
21622
+ exports.usePackageUpdates = usePackageUpdates;
20969
21623
  exports.usePlaygroundStore = usePlaygroundStore;
20970
21624
  exports.useReorderModelList = useReorderModelList;
20971
21625
  exports.useResetAgentModel = useResetAgentModel;