@mastra/playground-ui 19.0.0-alpha.2 → 19.0.0-alpha.4

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 (74) hide show
  1. package/CHANGELOG.md +87 -0
  2. package/dist/index.cjs.js +1259 -19
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +1237 -22
  5. package/dist/index.es.js.map +1 -1
  6. package/dist/src/domains/agents/components/agent-metadata/agent-metadata.d.ts +1 -0
  7. package/dist/src/domains/metrics/components/date-range-selector.d.ts +1 -0
  8. package/dist/src/domains/metrics/components/index.d.ts +28 -0
  9. package/dist/src/domains/metrics/components/latency-card.d.ts +1 -0
  10. package/dist/src/domains/metrics/components/metrics-dashboard.d.ts +1 -0
  11. package/dist/src/domains/metrics/components/metrics-kpi-cards.d.ts +4 -0
  12. package/dist/src/domains/metrics/components/metrics-utils.d.ts +14 -0
  13. package/dist/src/domains/metrics/components/model-usage-cost-card.d.ts +1 -0
  14. package/dist/src/domains/metrics/components/scores-card.d.ts +1 -0
  15. package/dist/src/domains/metrics/components/token-usage-by-agent-card.d.ts +1 -0
  16. package/dist/src/domains/metrics/components/traces-volume-card.d.ts +1 -0
  17. package/dist/src/domains/metrics/hooks/use-agent-runs-kpi-metrics.d.ts +10 -0
  18. package/dist/src/domains/metrics/hooks/use-avg-score-kpi-metrics.d.ts +10 -0
  19. package/dist/src/domains/metrics/hooks/use-latency-metrics.d.ts +11 -0
  20. package/dist/src/domains/metrics/hooks/use-metrics-filters.d.ts +9 -0
  21. package/dist/src/domains/metrics/hooks/use-metrics.d.ts +56 -0
  22. package/dist/src/domains/metrics/hooks/use-model-usage-cost-metrics.d.ts +8 -0
  23. package/dist/src/domains/metrics/hooks/use-scores-metrics.d.ts +22 -0
  24. package/dist/src/domains/metrics/hooks/use-token-usage-by-agent-metrics.d.ts +7 -0
  25. package/dist/src/domains/metrics/hooks/use-total-tokens-kpi-metrics.d.ts +6 -0
  26. package/dist/src/domains/metrics/hooks/use-trace-volume-metrics.d.ts +10 -0
  27. package/dist/src/domains/metrics/index.d.ts +1 -0
  28. package/dist/src/domains/workspace/hooks/use-workspace-skills.d.ts +5 -1
  29. package/dist/src/domains/workspace/types.d.ts +1 -1
  30. package/dist/src/ds/components/DashboardCard/dashboard-card.d.ts +6 -0
  31. package/dist/src/ds/components/DashboardCard/dashboard-card.stories.d.ts +8 -0
  32. package/dist/src/ds/components/DashboardCard/index.d.ts +1 -0
  33. package/dist/src/ds/components/EntityList/entity-list-no-match.d.ts +5 -0
  34. package/dist/src/ds/components/EntityList/entity-list.d.ts +2 -0
  35. package/dist/src/ds/components/HorizontalBars/horizontal-bars.d.ts +15 -0
  36. package/dist/src/ds/components/HorizontalBars/horizontal-bars.stories.d.ts +7 -0
  37. package/dist/src/ds/components/HorizontalBars/index.d.ts +1 -0
  38. package/dist/src/ds/components/MetricsCard/index.d.ts +2 -0
  39. package/dist/src/ds/components/MetricsCard/metrics-card-content.d.ts +5 -0
  40. package/dist/src/ds/components/MetricsCard/metrics-card-description.d.ts +4 -0
  41. package/dist/src/ds/components/MetricsCard/metrics-card-error.d.ts +4 -0
  42. package/dist/src/ds/components/MetricsCard/metrics-card-loading.d.ts +3 -0
  43. package/dist/src/ds/components/MetricsCard/metrics-card-no-data.d.ts +4 -0
  44. package/dist/src/ds/components/MetricsCard/metrics-card-root.d.ts +5 -0
  45. package/dist/src/ds/components/MetricsCard/metrics-card-summary.d.ts +5 -0
  46. package/dist/src/ds/components/MetricsCard/metrics-card-title-and-description.d.ts +15 -0
  47. package/dist/src/ds/components/MetricsCard/metrics-card-title.d.ts +4 -0
  48. package/dist/src/ds/components/MetricsCard/metrics-card-top-bar.d.ts +5 -0
  49. package/dist/src/ds/components/MetricsCard/metrics-card.d.ts +31 -0
  50. package/dist/src/ds/components/MetricsCard/metrics-card.stories.d.ts +11 -0
  51. package/dist/src/ds/components/MetricsDataTable/index.d.ts +1 -0
  52. package/dist/src/ds/components/MetricsDataTable/metrics-data-table.d.ts +13 -0
  53. package/dist/src/ds/components/MetricsDataTable/metrics-data-table.stories.d.ts +16 -0
  54. package/dist/src/ds/components/MetricsFlexGrid/index.d.ts +1 -0
  55. package/dist/src/ds/components/MetricsFlexGrid/metrics-flex-grid.d.ts +5 -0
  56. package/dist/src/ds/components/MetricsFlexGrid/metrics-flex-grid.stories.d.ts +7 -0
  57. package/dist/src/ds/components/MetricsKpiCard/index.d.ts +1 -0
  58. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-change.d.ts +6 -0
  59. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-error.d.ts +4 -0
  60. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-label.d.ts +4 -0
  61. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-loading.d.ts +3 -0
  62. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-no-change.d.ts +4 -0
  63. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-no-data.d.ts +4 -0
  64. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-root.d.ts +5 -0
  65. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-value.d.ts +4 -0
  66. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card.d.ts +17 -0
  67. package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card.stories.d.ts +10 -0
  68. package/dist/src/ds/components/MetricsLineChart/index.d.ts +2 -0
  69. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart-tooltip.d.ts +10 -0
  70. package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +15 -0
  71. package/dist/src/ds/components/Tabs/tabs-list.d.ts +2 -1
  72. package/dist/src/index.d.ts +1 -0
  73. package/dist/src/lib/framework.d.ts +3 -3
  74. package/package.json +11 -10
package/dist/index.cjs.js CHANGED
@@ -70,6 +70,7 @@ const semver = require('semver');
70
70
  const DropdownMenuPrimitive = require('@radix-ui/react-dropdown-menu');
71
71
  const features = require('@mastra/core/features');
72
72
  const observability = require('@mastra/core/observability');
73
+ const recharts = require('recharts');
73
74
  const Papa = require('papaparse');
74
75
  const reactDom = require('react-dom');
75
76
  const isToday = require('date-fns/isToday');
@@ -12612,6 +12613,10 @@ function EntityListDescriptionCell({ children, className }) {
12612
12613
  return /* @__PURE__ */ jsxRuntime.jsx(EntityListCell, { className: cn("text-neutral2", className), children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children }) });
12613
12614
  }
12614
12615
 
12616
+ function EntityListNoMatch({ message = "Nothing matches your search", className }) {
12617
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("col-span-full flex flex-col items-center justify-center gap-2 py-12 text-neutral3", className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-md", children: message }) });
12618
+ }
12619
+
12615
12620
  function EntityListRoot({ children, columns, className }) {
12616
12621
  return /* @__PURE__ */ jsxRuntime.jsx(
12617
12622
  "div",
@@ -12723,7 +12728,8 @@ const EntityList = Object.assign(EntityListRoot, {
12723
12728
  Cell: EntityListCell,
12724
12729
  TextCell: EntityListTextCell,
12725
12730
  NameCell: EntityListNameCell,
12726
- DescriptionCell: EntityListDescriptionCell
12731
+ DescriptionCell: EntityListDescriptionCell,
12732
+ NoMatch: EntityListNoMatch
12727
12733
  });
12728
12734
 
12729
12735
  const widths$2 = ["75%", "50%", "65%", "90%", "60%", "80%"];
@@ -12797,6 +12803,7 @@ function WorkflowsList({ workflows, isLoading, error, search = "" }) {
12797
12803
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { children: "Description" }),
12798
12804
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { children: "Number of steps" })
12799
12805
  ] }),
12806
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Workflows match your search" }) : null,
12800
12807
  filteredData.map((wf) => {
12801
12808
  const name = truncateString(wf.name, 50);
12802
12809
  const description = truncateString(wf.description ?? "", 200);
@@ -13033,7 +13040,7 @@ const Tabs = ({ children, defaultTab, value, onValueChange, className }) => {
13033
13040
  return /* @__PURE__ */ jsxRuntime.jsx(RadixTabs__namespace.Root, { value: currentTab, onValueChange: handleTabChange, className: cn("overflow-y-auto", className), children });
13034
13041
  };
13035
13042
 
13036
- const TabList = ({ children, variant = "default", className }) => {
13043
+ const TabList = ({ children, variant = "default", alignment = "left", className }) => {
13037
13044
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full overflow-x-auto", className), children: /* @__PURE__ */ jsxRuntime.jsx(
13038
13045
  RadixTabs__namespace.List,
13039
13046
  {
@@ -13042,7 +13049,8 @@ const TabList = ({ children, variant = "default", className }) => {
13042
13049
  {
13043
13050
  // variant: default
13044
13051
  "text-ui-lg": variant === "default",
13045
- "[&>button]:py-2 [&>button]:px-6 [&>button]:font-normal [&>button]:text-neutral3 [&>button]:flex-1 [&>button]:border-b [&>button]:border-border1": variant === "default",
13052
+ "[&>button]:py-2 [&>button]:px-6 [&>button]:font-normal [&>button]:text-neutral3 [&>button]:border-b [&>button]:border-border1": variant === "default",
13053
+ "[&>button]:flex-1": variant === "default" && alignment === "full-width",
13046
13054
  [`[&>button]:${transitions.colors} [&>button]:hover:text-neutral4`]: variant === "default",
13047
13055
  "[&>button[data-state=active]]:text-neutral5 [&>button[data-state=active]]:border-white/50": variant === "default",
13048
13056
  // variant: buttons
@@ -19990,6 +19998,7 @@ function ScorersList({ scorers, isLoading, error, search = "" }) {
19990
19998
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Agents" }),
19991
19999
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Workflows" })
19992
20000
  ] }),
20001
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Scorers match your search" }) : null,
19993
20002
  filteredData.map((scorer) => {
19994
20003
  const name = truncateString(scorer.scorer.config?.name ?? scorer.id, 50);
19995
20004
  const description = truncateString(scorer.scorer.config?.description ?? "", 200);
@@ -22026,9 +22035,16 @@ const AgentMetadataSkillList = ({ skills, agentId, workspaceId }) => {
22026
22035
  }
22027
22036
  );
22028
22037
  return /* @__PURE__ */ jsxRuntime.jsx(AgentMetadataListItem, { children: isActivated ? /* @__PURE__ */ jsxRuntime.jsx(TooltipProvider, { children: /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
22029
- /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(Link, { href: paths.agentSkillLink(agentId, skill.name, workspaceId), "data-testid": "skill-badge", children: badge }) }),
22038
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
22039
+ Link,
22040
+ {
22041
+ href: paths.agentSkillLink(agentId, skill.name, skill.path, workspaceId),
22042
+ "data-testid": "skill-badge",
22043
+ children: badge
22044
+ }
22045
+ ) }),
22030
22046
  /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { className: "bg-surface3 text-neutral6 border border-border1", children: "Active" })
22031
- ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(Link, { href: paths.agentSkillLink(agentId, skill.name, workspaceId), "data-testid": "skill-badge", children: badge }) }, skill.name);
22047
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsx(Link, { href: paths.agentSkillLink(agentId, skill.name, skill.path, workspaceId), "data-testid": "skill-badge", children: badge }) }, skill.path);
22032
22048
  }) });
22033
22049
  };
22034
22050
  function formatWorkspaceToolName(toolName) {
@@ -22767,6 +22783,8 @@ const AgentMemoryConfig = ({ agentId }) => {
22767
22783
  };
22768
22784
 
22769
22785
  const formatTokens = (n) => {
22786
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
22787
+ if (n >= 1e5) return `${(n / 1e3).toFixed(0)}k`;
22770
22788
  if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
22771
22789
  return Math.round(n).toString();
22772
22790
  };
@@ -22774,6 +22792,11 @@ const getBarColor = (percentage) => {
22774
22792
  if (percentage >= 60) return "bg-blue-500";
22775
22793
  return "bg-green-500";
22776
22794
  };
22795
+ const getModelLabel = (model, modelRouting) => {
22796
+ if (typeof model === "string") return model;
22797
+ if (modelRouting?.length) return "Auto (tiered)";
22798
+ return void 0;
22799
+ };
22777
22800
  const useElapsedTime = (isActive) => {
22778
22801
  const [elapsed, setElapsed] = React.useState(0);
22779
22802
  const startTimeRef = React.useRef(null);
@@ -22800,6 +22823,7 @@ const ProgressBar = ({
22800
22823
  label,
22801
22824
  isActive = false,
22802
22825
  model,
22826
+ modelRouting,
22803
22827
  baseThreshold,
22804
22828
  totalBudget
22805
22829
  }) => {
@@ -22832,7 +22856,15 @@ const ProgressBar = ({
22832
22856
  " ",
22833
22857
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-neutral5", children: model || "not configured" })
22834
22858
  ] }),
22835
- /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
22859
+ modelRouting?.length ? /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
22860
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-neutral4", children: "Routing:" }),
22861
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 pl-2 space-y-0.5", children: modelRouting.map((route) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-neutral5", children: [
22862
+ "≤",
22863
+ formatTokens(route.upTo),
22864
+ " → ",
22865
+ route.model
22866
+ ] }, `${route.upTo}-${route.model}`)) })
22867
+ ] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
22836
22868
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-neutral4", children: "Threshold:" }),
22837
22869
  " ",
22838
22870
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-neutral5", children: [
@@ -22953,8 +22985,16 @@ const AgentObservationalMemory = ({ agentId, resourceId, threadId }) => {
22953
22985
  const history = omData?.history ?? [];
22954
22986
  const omAgentConfig = configData?.config?.observationalMemory;
22955
22987
  const recordConfig = record?.config;
22956
- const observationModel = recordConfig?.observationModel ?? omAgentConfig?.observationModel;
22957
- const reflectionModel = recordConfig?.reflectionModel ?? omAgentConfig?.reflectionModel;
22988
+ const observationModelRouting = recordConfig?.observationModelRouting ?? recordConfig?.observation?.routing ?? omAgentConfig?.observationModelRouting ?? omAgentConfig?.observation?.routing;
22989
+ const reflectionModelRouting = recordConfig?.reflectionModelRouting ?? recordConfig?.reflection?.routing ?? omAgentConfig?.reflectionModelRouting ?? omAgentConfig?.reflection?.routing;
22990
+ const observationModel = getModelLabel(
22991
+ recordConfig?.observationModel ?? recordConfig?.observation?.model ?? omAgentConfig?.observationModel ?? omAgentConfig?.model ?? omAgentConfig?.observation?.model,
22992
+ observationModelRouting
22993
+ );
22994
+ const reflectionModel = getModelLabel(
22995
+ recordConfig?.reflectionModel ?? recordConfig?.reflection?.model ?? omAgentConfig?.reflectionModel ?? omAgentConfig?.model ?? omAgentConfig?.reflection?.model,
22996
+ reflectionModelRouting
22997
+ );
22958
22998
  const getThresholdValue = (threshold, defaultValue) => {
22959
22999
  if (!threshold) return defaultValue;
22960
23000
  if (typeof threshold === "number") return threshold;
@@ -23063,6 +23103,7 @@ const AgentObservationalMemory = ({ agentId, resourceId, threadId }) => {
23063
23103
  label: "Messages",
23064
23104
  isActive: isObserving,
23065
23105
  model: observationModel,
23106
+ modelRouting: observationModelRouting,
23066
23107
  baseThreshold: baseMessageTokens,
23067
23108
  totalBudget
23068
23109
  }
@@ -23076,6 +23117,7 @@ const AgentObservationalMemory = ({ agentId, resourceId, threadId }) => {
23076
23117
  isActive: isReflecting,
23077
23118
  baseThreshold: baseObservationTokens,
23078
23119
  model: reflectionModel,
23120
+ modelRouting: reflectionModelRouting,
23079
23121
  totalBudget
23080
23122
  }
23081
23123
  )
@@ -25119,6 +25161,7 @@ function PromptsList({ promptBlocks, isLoading, error, search = "" }) {
25119
25161
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Has Draft" }),
25120
25162
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Is Published" })
25121
25163
  ] }),
25164
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Prompts match your search" }) : null,
25122
25165
  filteredData.map((block) => {
25123
25166
  const name = truncateString(block.name, 50);
25124
25167
  const description = truncateString(block.description ?? "", 200);
@@ -30627,7 +30670,7 @@ const useWorkspaceSkills = (options) => {
30627
30670
  const useWorkspaceSkill = (skillName, options) => {
30628
30671
  const client = react.useMastraClient();
30629
30672
  return reactQuery.useQuery({
30630
- queryKey: ["workspace", "skills", skillName, options?.workspaceId],
30673
+ queryKey: ["workspace", "skills", skillName, options?.path, options?.workspaceId],
30631
30674
  queryFn: async () => {
30632
30675
  if (!compatibility.isWorkspaceV1Supported(client)) {
30633
30676
  throw new Error("Workspace v1 not supported by core or client");
@@ -30636,7 +30679,7 @@ const useWorkspaceSkill = (skillName, options) => {
30636
30679
  throw new Error("workspaceId is required");
30637
30680
  }
30638
30681
  const workspace = client.getWorkspace(options.workspaceId);
30639
- const skill = workspace.getSkill(skillName);
30682
+ const skill = workspace.getSkill(skillName, options?.path);
30640
30683
  return skill.details();
30641
30684
  },
30642
30685
  enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30646,7 +30689,7 @@ const useWorkspaceSkill = (skillName, options) => {
30646
30689
  const useWorkspaceSkillReferences = (skillName, options) => {
30647
30690
  const client = react.useMastraClient();
30648
30691
  return reactQuery.useQuery({
30649
- queryKey: ["workspace", "skills", skillName, "references", options?.workspaceId],
30692
+ queryKey: ["workspace", "skills", skillName, options?.path, "references", options?.workspaceId],
30650
30693
  queryFn: async () => {
30651
30694
  if (!compatibility.isWorkspaceV1Supported(client)) {
30652
30695
  throw new Error("Workspace v1 not supported by core or client");
@@ -30655,7 +30698,7 @@ const useWorkspaceSkillReferences = (skillName, options) => {
30655
30698
  throw new Error("workspaceId is required");
30656
30699
  }
30657
30700
  const workspace = client.getWorkspace(options.workspaceId);
30658
- const skill = workspace.getSkill(skillName);
30701
+ const skill = workspace.getSkill(skillName, options?.path);
30659
30702
  return skill.listReferences();
30660
30703
  },
30661
30704
  enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30665,7 +30708,7 @@ const useWorkspaceSkillReferences = (skillName, options) => {
30665
30708
  const useWorkspaceSkillReference = (skillName, referencePath, options) => {
30666
30709
  const client = react.useMastraClient();
30667
30710
  return reactQuery.useQuery({
30668
- queryKey: ["workspace", "skills", skillName, "references", referencePath, options?.workspaceId],
30711
+ queryKey: ["workspace", "skills", skillName, options?.path, "references", referencePath, options?.workspaceId],
30669
30712
  queryFn: async () => {
30670
30713
  if (!compatibility.isWorkspaceV1Supported(client)) {
30671
30714
  throw new Error("Workspace v1 not supported by core or client");
@@ -30674,7 +30717,7 @@ const useWorkspaceSkillReference = (skillName, referencePath, options) => {
30674
30717
  throw new Error("workspaceId is required");
30675
30718
  }
30676
30719
  const workspace = client.getWorkspace(options.workspaceId);
30677
- const skill = workspace.getSkill(skillName);
30720
+ const skill = workspace.getSkill(skillName, options?.path);
30678
30721
  return skill.getReference(referencePath);
30679
30722
  },
30680
30723
  enabled: options?.enabled !== false && !!skillName && !!referencePath && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30696,7 +30739,7 @@ const useSearchWorkspaceSkills = () => {
30696
30739
  const useAgentSkill = (agentId, skillName, options) => {
30697
30740
  const client = react.useMastraClient();
30698
30741
  return reactQuery.useQuery({
30699
- queryKey: ["agents", agentId, "skills", skillName, options?.workspaceId],
30742
+ queryKey: ["agents", agentId, "skills", skillName, options?.path, options?.workspaceId],
30700
30743
  queryFn: async () => {
30701
30744
  if (!compatibility.isWorkspaceV1Supported(client)) {
30702
30745
  throw new Error("Workspace v1 not supported by core or client");
@@ -30705,7 +30748,7 @@ const useAgentSkill = (agentId, skillName, options) => {
30705
30748
  throw new Error("workspaceId is required");
30706
30749
  }
30707
30750
  const workspace = client.getWorkspace(options.workspaceId);
30708
- const skill = workspace.getSkill(skillName);
30751
+ const skill = workspace.getSkill(skillName, options?.path);
30709
30752
  return skill.details();
30710
30753
  },
30711
30754
  enabled: options?.enabled !== false && !!agentId && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -39313,6 +39356,7 @@ function AgentsList({ agents, isLoading, error, search = "" }) {
39313
39356
  }
39314
39357
  )
39315
39358
  ] }),
39359
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Agents match your search" }) : null,
39316
39360
  filteredData.map((agent) => {
39317
39361
  const name = truncateString(agent.name, 50);
39318
39362
  const instructions = truncateString(extractPrompt(agent.instructions), 200);
@@ -39584,6 +39628,7 @@ function ProcessorsList({ processors, isLoading, error, search = "" }) {
39584
39628
  ),
39585
39629
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCellSmart, { short: "Used by", long: "Used by Agents", className: "text-center" })
39586
39630
  ] }),
39631
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Processors match your search" }) : null,
39587
39632
  filteredData.map((processor) => {
39588
39633
  const name = truncateString(processor.name || processor.id, 50);
39589
39634
  const description = truncateString(processor.description ?? "", 200);
@@ -40038,6 +40083,7 @@ function ToolsList({ tools, agents, isLoading, error, search = "" }) {
40038
40083
  }
40039
40084
  )
40040
40085
  ] }),
40086
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Tools match your search" }) : null,
40041
40087
  filteredData.map((tool) => {
40042
40088
  const name = truncateString(tool.id, 50);
40043
40089
  const description = truncateString(tool.description ?? "", 200);
@@ -40860,6 +40906,1173 @@ function TemplateFailure({ errorMsg, validationErrors }) {
40860
40906
  ] });
40861
40907
  }
40862
40908
 
40909
+ const DATE_PRESETS$1 = [
40910
+ { label: "Last 24 hours", value: "24h" },
40911
+ { label: "Last 3 days", value: "3d" },
40912
+ { label: "Last 7 days", value: "7d" },
40913
+ { label: "Last 14 days", value: "14d" },
40914
+ { label: "Last 30 days", value: "30d" }
40915
+ ];
40916
+ const VALID_PRESETS = new Set(DATE_PRESETS$1.map((p) => p.value));
40917
+ function isValidPreset(value) {
40918
+ return typeof value === "string" && (VALID_PRESETS.has(value) || value === "custom");
40919
+ }
40920
+ const PRESET_DAYS = {
40921
+ "24h": 1,
40922
+ "3d": 3,
40923
+ "7d": 7,
40924
+ "14d": 14,
40925
+ "30d": 30
40926
+ };
40927
+ const ENV_PCTS = {
40928
+ "Studio Cloud": 42,
40929
+ Production: 31,
40930
+ Staging: 18,
40931
+ Dev: 7,
40932
+ "CI / Preview": 2
40933
+ };
40934
+ function getMultiplier(preset, customRange, filterGroups) {
40935
+ let dateMul = 1;
40936
+ if (preset !== "custom") {
40937
+ dateMul = PRESET_DAYS[preset] ?? 1;
40938
+ } else if (customRange?.from && customRange?.to) {
40939
+ dateMul = Math.max(1, dateFns.differenceInDays(customRange.to, customRange.from) + 1);
40940
+ }
40941
+ const envGroups = filterGroups.filter((g) => g.field === "Environment" && g.comparator === "is");
40942
+ const envPct = envGroups.length === 0 ? 100 : envGroups.flatMap((g) => g.values).reduce((s, v) => s + (ENV_PCTS[v] ?? 0), 0);
40943
+ return dateMul * (envPct / 100);
40944
+ }
40945
+ const MetricsContext = React.createContext({
40946
+ datePreset: "24h",
40947
+ setDatePreset: () => {
40948
+ },
40949
+ customRange: void 0,
40950
+ setCustomRange: () => {
40951
+ },
40952
+ dateRangeLabel: "Last 24 hours",
40953
+ filterGroups: [],
40954
+ setFilterGroups: () => {
40955
+ },
40956
+ multiplier: 1
40957
+ });
40958
+ function useMetrics() {
40959
+ return React.useContext(MetricsContext);
40960
+ }
40961
+ function getDateRangeLabel(preset, customRange) {
40962
+ if (preset !== "custom") {
40963
+ return DATE_PRESETS$1.find((p) => p.value === preset).label;
40964
+ }
40965
+ if (customRange?.from) {
40966
+ if (customRange.to) {
40967
+ return `${dateFns.format(customRange.from, "MMM d, yyyy")} – ${dateFns.format(customRange.to, "MMM d, yyyy")}`;
40968
+ }
40969
+ return dateFns.format(customRange.from, "MMM d, yyyy");
40970
+ }
40971
+ return "Custom range";
40972
+ }
40973
+ function MetricsProvider({
40974
+ children,
40975
+ initialPreset,
40976
+ onPresetChange
40977
+ }) {
40978
+ const [datePreset, setDatePresetState] = React.useState(initialPreset ?? "24h");
40979
+ const [customRange, setCustomRange] = React.useState(void 0);
40980
+ const [filterGroups, setFilterGroups] = React.useState([]);
40981
+ const dateRangeLabel = getDateRangeLabel(datePreset, customRange);
40982
+ const multiplier = getMultiplier(datePreset, customRange, filterGroups);
40983
+ React.useEffect(() => {
40984
+ if (initialPreset && initialPreset !== datePreset) {
40985
+ setDatePresetState(initialPreset);
40986
+ }
40987
+ }, [initialPreset]);
40988
+ const setDatePreset = React.useCallback(
40989
+ (v) => {
40990
+ setDatePresetState(v);
40991
+ onPresetChange?.(v);
40992
+ },
40993
+ [onPresetChange]
40994
+ );
40995
+ return /* @__PURE__ */ jsxRuntime.jsx(
40996
+ MetricsContext.Provider,
40997
+ {
40998
+ value: {
40999
+ datePreset,
41000
+ setDatePreset,
41001
+ customRange,
41002
+ setCustomRange,
41003
+ dateRangeLabel,
41004
+ filterGroups,
41005
+ setFilterGroups,
41006
+ multiplier
41007
+ },
41008
+ children
41009
+ }
41010
+ );
41011
+ }
41012
+
41013
+ const PRESET_MS = {
41014
+ "24h": 24 * 60 * 60 * 1e3,
41015
+ "3d": 3 * 24 * 60 * 60 * 1e3,
41016
+ "7d": 7 * 24 * 60 * 60 * 1e3,
41017
+ "14d": 14 * 24 * 60 * 60 * 1e3,
41018
+ "30d": 30 * 24 * 60 * 60 * 1e3
41019
+ };
41020
+ function buildTimestamp(preset, customRange) {
41021
+ const now = /* @__PURE__ */ new Date();
41022
+ if (preset !== "custom") {
41023
+ const ms = PRESET_MS[preset] ?? PRESET_MS["24h"];
41024
+ return { start: new Date(now.getTime() - ms), end: now };
41025
+ }
41026
+ return {
41027
+ start: customRange?.from ?? new Date(now.getTime() - PRESET_MS["24h"]),
41028
+ end: customRange?.to ?? now
41029
+ };
41030
+ }
41031
+ function useMetricsFilters() {
41032
+ const { datePreset, customRange } = useMetrics();
41033
+ const timestamp = buildTimestamp(datePreset, customRange);
41034
+ return { datePreset, customRange, timestamp };
41035
+ }
41036
+
41037
+ async function fetchPercentiles(client, metricName, timestamp) {
41038
+ const res = await client.getMetricPercentiles({
41039
+ name: metricName,
41040
+ percentiles: [0.5, 0.95],
41041
+ interval: "1h",
41042
+ filters: { timestamp }
41043
+ });
41044
+ const p50Series = res.series.find((s) => s.percentile === 0.5);
41045
+ const p95Series = res.series.find((s) => s.percentile === 0.95);
41046
+ if (!p50Series || !p95Series) return [];
41047
+ const p95Map = new Map(p95Series.points.map((p) => [new Date(p.timestamp).getTime(), p.value]));
41048
+ return p50Series.points.map((p) => {
41049
+ const ts = new Date(p.timestamp);
41050
+ return {
41051
+ time: ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
41052
+ p50: Math.round(p.value),
41053
+ p95: Math.round(p95Map.get(ts.getTime()) ?? 0)
41054
+ };
41055
+ });
41056
+ }
41057
+ function useLatencyMetrics() {
41058
+ const client = react.useMastraClient();
41059
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41060
+ return reactQuery.useQuery({
41061
+ queryKey: ["metrics", "latency", datePreset, customRange],
41062
+ queryFn: async () => {
41063
+ const [agentData, workflowData, toolData] = await Promise.all([
41064
+ fetchPercentiles(client, "mastra_agent_duration_ms", timestamp),
41065
+ fetchPercentiles(client, "mastra_workflow_duration_ms", timestamp),
41066
+ fetchPercentiles(client, "mastra_tool_duration_ms", timestamp)
41067
+ ]);
41068
+ return { agentData, workflowData, toolData };
41069
+ }
41070
+ });
41071
+ }
41072
+
41073
+ function formatCompact(n) {
41074
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
41075
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
41076
+ return n.toLocaleString();
41077
+ }
41078
+ const CHART_COLORS = {
41079
+ green: "#22c55e",
41080
+ orange: "#fb923c",
41081
+ pink: "#f472b6",
41082
+ purple: "#8b5cf6",
41083
+ blue: "#4f83f1",
41084
+ blueDark: "#2b5cd9",
41085
+ blueLight: "#6b8fe5",
41086
+ red: "#f87171",
41087
+ greenDark: "#15613a",
41088
+ redDark: "#991b1b",
41089
+ yellow: "#facc15"
41090
+ };
41091
+
41092
+ function MetricsCardContent({ children, className }) {
41093
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-x-auto ", className), children });
41094
+ }
41095
+
41096
+ function MetricsCardDescription({ children, className }) {
41097
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-ui-md text-neutral2 leading-tight mt-0.5", className), children });
41098
+ }
41099
+
41100
+ function MetricsCardError({
41101
+ message = "Failed to load data",
41102
+ className
41103
+ }) {
41104
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-3 items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-sm text-accent2", children: message }) });
41105
+ }
41106
+
41107
+ function MetricsCardLoading({ className }) {
41108
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: spacings.Colors.neutral1 }) });
41109
+ }
41110
+
41111
+ function MetricsCardNoData({ message = "No data yet", className }) {
41112
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center justify-center h-full", className), children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-neutral1 text-sm", children: message }) });
41113
+ }
41114
+
41115
+ function DashboardCard({ children, className }) {
41116
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border1 rounded-lg p-6 bg-surface2", className), children });
41117
+ }
41118
+
41119
+ function MetricsCardRoot({ children, className }) {
41120
+ return /* @__PURE__ */ jsxRuntime.jsx(
41121
+ DashboardCard,
41122
+ {
41123
+ className: cn(
41124
+ "flex-1 grid grid-rows-[4rem_20rem] gap-2 min-w-[20rem] md:min-w-[22rem] lg:min-w-[24rem] xl:min-w-[26rem] 2xl:min-w-[30rem] 3xl:min-w-[32rem]",
41125
+ className
41126
+ ),
41127
+ children
41128
+ }
41129
+ );
41130
+ }
41131
+
41132
+ function MetricsCardSummary({ value, label, className }) {
41133
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid justify-end content-start text-right gap-1", className), children: [
41134
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-lg font-semibold text-neutral4 leading-none", children: value }),
41135
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-md text-neutral2", children: label })
41136
+ ] });
41137
+ }
41138
+
41139
+ function MetricsCardTitle({ children, className }) {
41140
+ return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("text-ui-md font-normal text-neutral4", className), children });
41141
+ }
41142
+
41143
+ function MetricsCardTitleAndDescription(props) {
41144
+ if ("children" in props) {
41145
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: props.className, children: props.children });
41146
+ }
41147
+ const { title, description } = props;
41148
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: props.className, children: [
41149
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCardTitle, { children: title }),
41150
+ description && /* @__PURE__ */ jsxRuntime.jsx(MetricsCardDescription, { children: description })
41151
+ ] });
41152
+ }
41153
+
41154
+ function MetricsCardTopBar({ children, className }) {
41155
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-[1fr_auto] gap-4", className), children });
41156
+ }
41157
+
41158
+ function MetricsKpiCardChange({
41159
+ changePct,
41160
+ prevValue,
41161
+ lowerIsBetter,
41162
+ className
41163
+ }) {
41164
+ const isGood = lowerIsBetter ? changePct < 0 : changePct >= 0;
41165
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-1 text-sm text-neutral1 flex-wrap", className), children: [
41166
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
41167
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("[&>svg]:w-4 [&>svg]:h-4", isGood ? "text-green-600" : "text-red-600"), children: changePct >= 0 ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUpIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingDownIcon, {}) }),
41168
+ /* @__PURE__ */ jsxRuntime.jsx(
41169
+ "span",
41170
+ {
41171
+ className: cn(isGood ? "text-green-600" : "text-red-600"),
41172
+ children: `${changePct >= 0 ? "+" : "-"}${Math.abs(changePct).toFixed(1)}%`
41173
+ }
41174
+ )
41175
+ ] }),
41176
+ prevValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
41177
+ "vs previous ",
41178
+ /* @__PURE__ */ jsxRuntime.jsx("b", { className: "text-neutral2 font-semibold", children: prevValue })
41179
+ ] })
41180
+ ] });
41181
+ }
41182
+
41183
+ function MetricsKpiCardError({
41184
+ message = "Failed to load data",
41185
+ className
41186
+ }) {
41187
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-ui-sm text-accent2", className), children: message });
41188
+ }
41189
+
41190
+ function MetricsKpiCardLabel({ children, className }) {
41191
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-ui-md text-neutral3 leading-relaxed", className), children });
41192
+ }
41193
+
41194
+ function MetricsKpiCardLoading({ className }) {
41195
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: spacings.Colors.neutral1 }) });
41196
+ }
41197
+
41198
+ function MetricsKpiCardNoChange({
41199
+ message = "No previous value to compare",
41200
+ className
41201
+ }) {
41202
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm text-neutral1", className), children: message });
41203
+ }
41204
+
41205
+ function MetricsKpiCardNoData({ message = "No data yet", className }) {
41206
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm text-neutral1", className), children: message });
41207
+ }
41208
+
41209
+ function MetricsKpiCardRoot({ children, className }) {
41210
+ return /* @__PURE__ */ jsxRuntime.jsx(DashboardCard, { className: cn("flex-1 min-w-[15rem]", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-1", children }) });
41211
+ }
41212
+
41213
+ function MetricsKpiCardValue({ children, className }) {
41214
+ return /* @__PURE__ */ jsxRuntime.jsx("strong", { className: cn("text-header-lg text-neutral4 font-semibold", className), children });
41215
+ }
41216
+
41217
+ const MetricsKpiCard = Object.assign(MetricsKpiCardRoot, {
41218
+ Label: MetricsKpiCardLabel,
41219
+ Value: MetricsKpiCardValue,
41220
+ Change: MetricsKpiCardChange,
41221
+ NoChange: MetricsKpiCardNoChange,
41222
+ NoData: MetricsKpiCardNoData,
41223
+ Error: MetricsKpiCardError,
41224
+ Loading: MetricsKpiCardLoading
41225
+ });
41226
+
41227
+ const MetricsCard = Object.assign(MetricsCardRoot, {
41228
+ Root: MetricsCardRoot,
41229
+ Kpi: MetricsKpiCard,
41230
+ TopBar: MetricsCardTopBar,
41231
+ TitleAndDescription: MetricsCardTitleAndDescription,
41232
+ Title: MetricsCardTitle,
41233
+ Description: MetricsCardDescription,
41234
+ Summary: MetricsCardSummary,
41235
+ Loading: MetricsCardLoading,
41236
+ Error: MetricsCardError,
41237
+ Content: MetricsCardContent,
41238
+ NoData: MetricsCardNoData
41239
+ });
41240
+
41241
+ function MetricsLineChartTooltip({
41242
+ active,
41243
+ payload,
41244
+ label,
41245
+ suffix
41246
+ }) {
41247
+ if (!active || !payload?.length) return null;
41248
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-border1 bg-surface2 px-3 py-2 text-xs shadow-lg", children: [
41249
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1 font-medium text-icon6", children: label }),
41250
+ payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-icon2", children: [
41251
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-2 inline-block size-2 rounded-full", style: { backgroundColor: entry.color } }),
41252
+ entry.name,
41253
+ ":",
41254
+ " ",
41255
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
41256
+ entry.value,
41257
+ suffix
41258
+ ] })
41259
+ ] }, entry.name))
41260
+ ] });
41261
+ }
41262
+
41263
+ const LABEL_COLOR = "#a1a1aa";
41264
+ function MetricsLineChart({
41265
+ data,
41266
+ series,
41267
+ height = 210,
41268
+ yDomain
41269
+ }) {
41270
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
41271
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap w-full items-end gap-4 gap-y-1 mb-4", children: series.map((s) => {
41272
+ const aggregated = s.aggregate?.(data);
41273
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-baseline gap-2", children: [
41274
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 rounded-full translate-y-[-1px]", style: { backgroundColor: s.color } }),
41275
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm text-neutral3 truncate max-w-24", children: s.label }),
41276
+ aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-lg text-neutral4", children: [
41277
+ aggregated.value,
41278
+ aggregated.suffix && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-sm text-neutral2", children: [
41279
+ " ",
41280
+ aggregated.suffix
41281
+ ] })
41282
+ ] })
41283
+ ] }, s.dataKey);
41284
+ }) }),
41285
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, children: [
41286
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { stroke: "rgba(255,255,255,0.08)", vertical: false }),
41287
+ /* @__PURE__ */ jsxRuntime.jsx(
41288
+ recharts.XAxis,
41289
+ {
41290
+ dataKey: "time",
41291
+ tick: { fontSize: 10, fill: LABEL_COLOR, fontFamily: "var(--font-mono)" },
41292
+ tickLine: false,
41293
+ axisLine: false,
41294
+ interval: 5
41295
+ }
41296
+ ),
41297
+ /* @__PURE__ */ jsxRuntime.jsx(
41298
+ recharts.YAxis,
41299
+ {
41300
+ tick: { fontSize: 10, fill: LABEL_COLOR, fontFamily: "var(--font-mono)" },
41301
+ tickLine: false,
41302
+ axisLine: false,
41303
+ width: 30,
41304
+ domain: yDomain
41305
+ }
41306
+ ),
41307
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChartTooltip, {}) }),
41308
+ series.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
41309
+ recharts.Line,
41310
+ {
41311
+ type: "linear",
41312
+ dataKey: s.dataKey,
41313
+ stroke: s.color,
41314
+ strokeWidth: 2,
41315
+ dot: false,
41316
+ name: s.label
41317
+ },
41318
+ s.dataKey
41319
+ ))
41320
+ ] }) }) })
41321
+ ] });
41322
+ }
41323
+
41324
+ const latencySeries = [
41325
+ {
41326
+ dataKey: "p50",
41327
+ label: "p50",
41328
+ color: CHART_COLORS.blue,
41329
+ aggregate: (data) => ({
41330
+ value: data.length > 0 ? `${Math.round(data.reduce((s, d) => s + d.p50, 0) / data.length)}` : "0",
41331
+ suffix: "avg ms"
41332
+ })
41333
+ },
41334
+ {
41335
+ dataKey: "p95",
41336
+ label: "p95",
41337
+ color: CHART_COLORS.yellow,
41338
+ aggregate: (data) => ({
41339
+ value: data.length > 0 ? `${Math.round(data.reduce((s, d) => s + d.p95, 0) / data.length)}` : "0",
41340
+ suffix: "avg ms"
41341
+ })
41342
+ }
41343
+ ];
41344
+ function LatencyChart({ data }) {
41345
+ if (data.length === 0) {
41346
+ return /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No latency data yet" });
41347
+ }
41348
+ return /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChart, { data, series: latencySeries });
41349
+ }
41350
+ function LatencyCard() {
41351
+ const { data, isLoading, isError } = useLatencyMetrics();
41352
+ const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);
41353
+ const avgP50 = data && data.agentData.length > 0 ? `${Math.round(data.agentData.reduce((s, d) => s + d.p50, 0) / data.agentData.length)}ms` : "—";
41354
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41355
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41356
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Latency", description: "Hourly p50 and p95 latency." }),
41357
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: avgP50, label: "Avg p50" })
41358
+ ] }),
41359
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Loading, {}) : isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Error, { message: "Failed to load latency data" }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Content, { children: !hasData ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No latency data yet" }) : /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { defaultTab: "agents", className: "overflow-visible", children: [
41360
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41361
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "agents", children: "Agents" }),
41362
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "workflows", children: "Workflows" }),
41363
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tools", children: "Tools" })
41364
+ ] }),
41365
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "agents", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.agentData }) }),
41366
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "workflows", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.workflowData }) }),
41367
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tools", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.toolData }) })
41368
+ ] }) })
41369
+ ] });
41370
+ }
41371
+
41372
+ function useAgentRunsKpiMetrics() {
41373
+ const client = react.useMastraClient();
41374
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41375
+ return reactQuery.useQuery({
41376
+ queryKey: ["metrics", "agent-runs-kpi", datePreset, customRange],
41377
+ queryFn: () => client.getMetricAggregate({
41378
+ name: ["mastra_agent_duration_ms"],
41379
+ aggregation: "count",
41380
+ filters: { timestamp },
41381
+ comparePeriod: "previous_period"
41382
+ })
41383
+ });
41384
+ }
41385
+
41386
+ function useAvgScoreKpiMetrics() {
41387
+ const client = react.useMastraClient();
41388
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41389
+ return reactQuery.useQuery({
41390
+ queryKey: ["metrics", "avg-score-kpi", datePreset, customRange],
41391
+ queryFn: async () => {
41392
+ const scorersMap = await client.listScorers();
41393
+ const scorerIds = Object.keys(scorersMap ?? {});
41394
+ if (scorerIds.length === 0) {
41395
+ return { value: null, previousValue: null, changePercent: null };
41396
+ }
41397
+ const allResults = await Promise.all(
41398
+ scorerIds.map((scorerId) => client.listScoresByScorerId({ scorerId, perPage: 100 }))
41399
+ );
41400
+ const startMs = timestamp.start.getTime();
41401
+ const endMs = timestamp.end.getTime();
41402
+ const allScoreValues = [];
41403
+ for (const result of allResults) {
41404
+ for (const s of result?.scores ?? []) {
41405
+ const ts = new Date(s.createdAt).getTime();
41406
+ if (ts >= startMs && ts <= endMs) {
41407
+ allScoreValues.push(s.score);
41408
+ }
41409
+ }
41410
+ }
41411
+ if (allScoreValues.length === 0) {
41412
+ return { value: null, previousValue: null, changePercent: null };
41413
+ }
41414
+ const avg = allScoreValues.reduce((sum, v) => sum + v, 0) / allScoreValues.length;
41415
+ return { value: Math.round(avg * 100) / 100, previousValue: null, changePercent: null };
41416
+ }
41417
+ });
41418
+ }
41419
+
41420
+ function useTotalTokensKpiMetrics() {
41421
+ const client = react.useMastraClient();
41422
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41423
+ return reactQuery.useQuery({
41424
+ queryKey: ["metrics", "total-tokens-kpi", datePreset, customRange],
41425
+ queryFn: async () => {
41426
+ const [input, output] = await Promise.all([
41427
+ client.getMetricAggregate({
41428
+ name: ["mastra_model_total_input_tokens"],
41429
+ aggregation: "sum",
41430
+ filters: { timestamp },
41431
+ comparePeriod: "previous_period"
41432
+ }),
41433
+ client.getMetricAggregate({
41434
+ name: ["mastra_model_total_output_tokens"],
41435
+ aggregation: "sum",
41436
+ filters: { timestamp },
41437
+ comparePeriod: "previous_period"
41438
+ })
41439
+ ]);
41440
+ const hasCurrent = input.value != null || output.value != null;
41441
+ const hasPrevious = input.previousValue != null || output.previousValue != null;
41442
+ const value = (input.value ?? 0) + (output.value ?? 0);
41443
+ const previousValue = (input.previousValue ?? 0) + (output.previousValue ?? 0);
41444
+ const changePercent = hasPrevious && previousValue > 0 ? (value - previousValue) / previousValue * 100 : null;
41445
+ return {
41446
+ value: hasCurrent ? value : null,
41447
+ previousValue: hasPrevious ? previousValue : null,
41448
+ changePercent
41449
+ };
41450
+ }
41451
+ });
41452
+ }
41453
+
41454
+ function AgentRunsKpiCard() {
41455
+ const { data: agentRunsKpi, isLoading, isError } = useAgentRunsKpiMetrics();
41456
+ const hasData = agentRunsKpi?.value != null;
41457
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41458
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Total Agent Runs" }),
41459
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? agentRunsKpi.value.toLocaleString() : "—" }),
41460
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? agentRunsKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41461
+ MetricsKpiCard.Change,
41462
+ {
41463
+ changePct: agentRunsKpi.changePercent,
41464
+ prevValue: agentRunsKpi.previousValue?.toLocaleString()
41465
+ }
41466
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41467
+ ] });
41468
+ }
41469
+ function TotalTokensKpiCard() {
41470
+ const { data: totalTokensKpi, isLoading, isError } = useTotalTokensKpiMetrics();
41471
+ const hasData = totalTokensKpi?.value != null;
41472
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41473
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Total Tokens" }),
41474
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? formatCompact(totalTokensKpi.value) : "—" }),
41475
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? totalTokensKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41476
+ MetricsKpiCard.Change,
41477
+ {
41478
+ changePct: totalTokensKpi.changePercent,
41479
+ prevValue: totalTokensKpi.previousValue != null ? formatCompact(totalTokensKpi.previousValue) : void 0
41480
+ }
41481
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41482
+ ] });
41483
+ }
41484
+ function AvgScoreKpiCard() {
41485
+ const { data: avgScoreKpi, isLoading, isError } = useAvgScoreKpiMetrics();
41486
+ const hasData = avgScoreKpi?.value != null;
41487
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41488
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Avg Score" }),
41489
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? String(avgScoreKpi.value) : "—" }),
41490
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? avgScoreKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41491
+ MetricsKpiCard.Change,
41492
+ {
41493
+ changePct: avgScoreKpi.changePercent,
41494
+ prevValue: avgScoreKpi.previousValue != null ? String(avgScoreKpi.previousValue) : void 0
41495
+ }
41496
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41497
+ ] });
41498
+ }
41499
+
41500
+ function useModelUsageCostMetrics() {
41501
+ const client = react.useMastraClient();
41502
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41503
+ return reactQuery.useQuery({
41504
+ queryKey: ["metrics", "model-usage-cost", datePreset, customRange],
41505
+ queryFn: async () => {
41506
+ const metrics = [
41507
+ "mastra_model_total_input_tokens",
41508
+ "mastra_model_total_output_tokens",
41509
+ "mastra_model_input_cache_read_tokens",
41510
+ "mastra_model_input_cache_write_tokens"
41511
+ ];
41512
+ const [inputRes, outputRes, cacheReadRes, cacheWriteRes] = await Promise.all(
41513
+ metrics.map(
41514
+ (name) => client.getMetricBreakdown({
41515
+ name: [name],
41516
+ groupBy: ["model"],
41517
+ aggregation: "sum",
41518
+ filters: { timestamp }
41519
+ })
41520
+ )
41521
+ );
41522
+ const modelMap = /* @__PURE__ */ new Map();
41523
+ const ensureModel = (model) => {
41524
+ if (!modelMap.has(model)) {
41525
+ modelMap.set(model, { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
41526
+ }
41527
+ return modelMap.get(model);
41528
+ };
41529
+ for (const group of inputRes.groups) {
41530
+ const m = group.dimensions.model ?? "unknown";
41531
+ ensureModel(m).input = group.value;
41532
+ }
41533
+ for (const group of outputRes.groups) {
41534
+ const m = group.dimensions.model ?? "unknown";
41535
+ ensureModel(m).output = group.value;
41536
+ }
41537
+ for (const group of cacheReadRes.groups) {
41538
+ const m = group.dimensions.model ?? "unknown";
41539
+ ensureModel(m).cacheRead = group.value;
41540
+ }
41541
+ for (const group of cacheWriteRes.groups) {
41542
+ const m = group.dimensions.model ?? "unknown";
41543
+ ensureModel(m).cacheWrite = group.value;
41544
+ }
41545
+ return Array.from(modelMap.entries()).map(([model, vals]) => ({
41546
+ model,
41547
+ input: formatCompact(vals.input),
41548
+ output: formatCompact(vals.output),
41549
+ cacheRead: formatCompact(vals.cacheRead),
41550
+ cacheWrite: formatCompact(vals.cacheWrite)
41551
+ })).sort((a, b) => a.model.localeCompare(b.model));
41552
+ }
41553
+ });
41554
+ }
41555
+
41556
+ function MetricsDataTable({
41557
+ columns,
41558
+ data,
41559
+ className
41560
+ }) {
41561
+ if (columns.length === 0) return null;
41562
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: cn("w-full h-full", className), maxHeight: "20rem", children: /* @__PURE__ */ jsxRuntime.jsxs(
41563
+ "div",
41564
+ {
41565
+ className: "grid items-center",
41566
+ style: {
41567
+ gridTemplateColumns: `auto ${columns.slice(1).map(() => "1fr").join(" ")}`
41568
+ },
41569
+ children: [
41570
+ columns.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx(
41571
+ "span",
41572
+ {
41573
+ className: cn(
41574
+ "h-9 py-1 flex items-center border-b border-surface5 uppercase whitespace-nowrap text-neutral2 tracking-widest text-ui-xs sticky top-0 z-10 bg-surface2",
41575
+ i === 0 ? "text-left sticky left-0 z-20 bg-surface2 pr-4 after:absolute after:right-1 after:top-1/2 after:-translate-y-1/2 after:h-3/5 after:w-px after:bg-surface5" : "px-4 text-right"
41576
+ ),
41577
+ children: col.label
41578
+ },
41579
+ `${i}-${col.label}`
41580
+ )),
41581
+ data.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: columns.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx(
41582
+ "span",
41583
+ {
41584
+ className: cn(
41585
+ "h-10 flex items-center text-ui-sm whitespace-nowrap border-t border-surface5",
41586
+ rowIndex === 0 && "border-t-transparent",
41587
+ i === 0 ? "text-left text-neutral3 sticky left-0 z-10 bg-surface2 pr-4 after:absolute after:right-1 after:top-1/2 after:-translate-y-1/2 after:h-3/5 after:w-px after:bg-surface5" : cn(
41588
+ "px-4 text-right tabular-nums",
41589
+ col.highlight ? "text-neutral4 font-semibold" : "text-neutral3"
41590
+ )
41591
+ ),
41592
+ children: col.value(row)
41593
+ },
41594
+ `${row.key}-${i}`
41595
+ )) }, row.key))
41596
+ ]
41597
+ }
41598
+ ) });
41599
+ }
41600
+
41601
+ function ModelUsageCostCard() {
41602
+ const { data: rows, isLoading, isError } = useModelUsageCostMetrics();
41603
+ const hasData = !!rows && rows.length > 0;
41604
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41605
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TopBar, { children: /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Model Usage", description: "Token consumption by model." }) }),
41606
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Loading, {}) : isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Error, { message: "Failed to load model usage data" }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Content, { children: !hasData ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No model usage data yet" }) : /* @__PURE__ */ jsxRuntime.jsx(
41607
+ MetricsDataTable,
41608
+ {
41609
+ columns: [
41610
+ { label: "Model", value: (row) => row.model },
41611
+ { label: "Input", value: (row) => row.input },
41612
+ { label: "Output", value: (row) => row.output },
41613
+ { label: "Cache Read", value: (row) => row.cacheRead },
41614
+ { label: "Cache Write", value: (row) => row.cacheWrite }
41615
+ // { label: 'Cost', value: () => '—', highlight: true },
41616
+ ],
41617
+ data: rows.map((row) => ({ ...row, key: row.model }))
41618
+ }
41619
+ ) })
41620
+ ] });
41621
+ }
41622
+
41623
+ function useScoresMetrics() {
41624
+ const client = react.useMastraClient();
41625
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41626
+ return reactQuery.useQuery({
41627
+ queryKey: ["metrics", "scores-card", datePreset, customRange],
41628
+ queryFn: async () => {
41629
+ const scorersMap = await client.listScorers();
41630
+ const scorerIds = Object.keys(scorersMap ?? {});
41631
+ if (scorerIds.length === 0) {
41632
+ return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
41633
+ }
41634
+ const allResults = await Promise.all(
41635
+ // Limited to 100 most recent scores per scorer; pagination not yet implemented
41636
+ scorerIds.map((scorerId) => client.listScoresByScorerId({ scorerId, perPage: 100 }))
41637
+ );
41638
+ const startMs = timestamp.start.getTime();
41639
+ const endMs = timestamp.end.getTime();
41640
+ const allScores = [];
41641
+ for (let i = 0; i < scorerIds.length; i++) {
41642
+ const scores = allResults[i]?.scores ?? [];
41643
+ for (const s of scores) {
41644
+ const ts = new Date(s.createdAt).getTime();
41645
+ if (ts >= startMs && ts <= endMs) {
41646
+ allScores.push({
41647
+ scorerId: scorerIds[i],
41648
+ score: s.score,
41649
+ createdAt: s.createdAt
41650
+ });
41651
+ }
41652
+ }
41653
+ }
41654
+ if (allScores.length === 0) {
41655
+ return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
41656
+ }
41657
+ const byScorer = /* @__PURE__ */ new Map();
41658
+ for (const s of allScores) {
41659
+ if (!byScorer.has(s.scorerId)) byScorer.set(s.scorerId, []);
41660
+ byScorer.get(s.scorerId).push(s.score);
41661
+ }
41662
+ const summaryData = Array.from(byScorer.entries()).map(([scorer, vals]) => ({
41663
+ scorer,
41664
+ avg: vals.reduce((a, b) => a + b, 0) / vals.length,
41665
+ min: Math.min(...vals),
41666
+ max: Math.max(...vals),
41667
+ count: vals.length
41668
+ }));
41669
+ const scorerNames = summaryData.map((s) => s.scorer);
41670
+ const avgScore = summaryData.reduce((s, d) => s + d.avg, 0) / summaryData.length;
41671
+ const bucketMap = /* @__PURE__ */ new Map();
41672
+ for (const s of allScores) {
41673
+ const ts = new Date(s.createdAt);
41674
+ const bucket = Math.floor(ts.getTime() / 36e5) * 36e5;
41675
+ if (!bucketMap.has(bucket)) bucketMap.set(bucket, /* @__PURE__ */ new Map());
41676
+ const scorerMap = bucketMap.get(bucket);
41677
+ if (!scorerMap.has(s.scorerId)) scorerMap.set(s.scorerId, []);
41678
+ scorerMap.get(s.scorerId).push(s.score);
41679
+ }
41680
+ const overTimeData = Array.from(bucketMap.entries()).sort(([a], [b]) => a - b).map(([bucket, scorerMap]) => {
41681
+ const point = {
41682
+ time: new Date(bucket).toLocaleTimeString("en-US", {
41683
+ hour: "2-digit",
41684
+ minute: "2-digit",
41685
+ hour12: false
41686
+ })
41687
+ };
41688
+ for (const name of scorerNames) {
41689
+ const vals = scorerMap.get(name);
41690
+ if (vals && vals.length > 0) {
41691
+ point[name] = +(vals.reduce((a, b) => a + b, 0) / vals.length).toFixed(2);
41692
+ }
41693
+ }
41694
+ return point;
41695
+ });
41696
+ return {
41697
+ summaryData,
41698
+ overTimeData,
41699
+ scorerNames,
41700
+ avgScore: Math.round(avgScore * 100) / 100
41701
+ };
41702
+ }
41703
+ });
41704
+ }
41705
+
41706
+ const SERIES_COLORS = [
41707
+ CHART_COLORS.green,
41708
+ CHART_COLORS.blue,
41709
+ CHART_COLORS.purple,
41710
+ CHART_COLORS.orange,
41711
+ CHART_COLORS.pink,
41712
+ CHART_COLORS.yellow
41713
+ ];
41714
+ function ScoresCard() {
41715
+ const { data, isLoading, isError } = useScoresMetrics();
41716
+ const hasData = !!data && data.summaryData.length > 0;
41717
+ const series = React.useMemo(() => {
41718
+ if (!data?.scorerNames) return [];
41719
+ return data.scorerNames.map((name, i) => ({
41720
+ dataKey: name,
41721
+ label: name,
41722
+ color: SERIES_COLORS[i % SERIES_COLORS.length],
41723
+ aggregate: (points) => ({
41724
+ value: points.length > 0 ? (points.reduce((s, d) => s + (d[name] ?? 0), 0) / points.length).toFixed(2) : "0",
41725
+ suffix: "avg"
41726
+ })
41727
+ }));
41728
+ }, [data?.scorerNames]);
41729
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41730
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41731
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Scores", description: "Evaluation scorer performance." }),
41732
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(
41733
+ MetricsCard.Summary,
41734
+ {
41735
+ value: data?.avgScore != null ? `avg ${data.avgScore}` : "—",
41736
+ label: "Across all scorers"
41737
+ }
41738
+ )
41739
+ ] }),
41740
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Loading, {}) : isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Error, { message: "Failed to load scores data" }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Content, { children: !hasData ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No scores data yet" }) : /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { defaultTab: "over-time", className: "overflow-visible", children: [
41741
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41742
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "over-time", children: "Over Time" }),
41743
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "summary", children: "Summary" })
41744
+ ] }),
41745
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "over-time", children: data.overTimeData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChart, { data: data.overTimeData, series, yDomain: [0, 1] }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No time series data yet" }) }),
41746
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "summary", children: /* @__PURE__ */ jsxRuntime.jsx(
41747
+ MetricsDataTable,
41748
+ {
41749
+ columns: [
41750
+ { label: "Scorer", value: (row) => row.scorer },
41751
+ { label: "Avg", value: (row) => row.avg.toFixed(2), highlight: true },
41752
+ { label: "Min", value: (row) => row.min.toFixed(2) },
41753
+ { label: "Max", value: (row) => row.max.toFixed(2) },
41754
+ { label: "Count", value: (row) => row.count.toLocaleString() }
41755
+ ],
41756
+ data: data.summaryData.map((row) => ({ ...row, key: row.scorer }))
41757
+ }
41758
+ ) })
41759
+ ] }) })
41760
+ ] });
41761
+ }
41762
+
41763
+ function useTokenUsageByAgentMetrics() {
41764
+ const client = react.useMastraClient();
41765
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41766
+ return reactQuery.useQuery({
41767
+ queryKey: ["metrics", "token-usage-by-agent", datePreset, customRange],
41768
+ queryFn: async () => {
41769
+ const [inputRes, outputRes] = await Promise.all([
41770
+ client.getMetricBreakdown({
41771
+ name: ["mastra_model_total_input_tokens"],
41772
+ groupBy: ["entityName"],
41773
+ aggregation: "sum",
41774
+ filters: { timestamp }
41775
+ }),
41776
+ client.getMetricBreakdown({
41777
+ name: ["mastra_model_total_output_tokens"],
41778
+ groupBy: ["entityName"],
41779
+ aggregation: "sum",
41780
+ filters: { timestamp }
41781
+ })
41782
+ ]);
41783
+ const agentMap = /* @__PURE__ */ new Map();
41784
+ const ensure = (name) => {
41785
+ if (!agentMap.has(name)) {
41786
+ agentMap.set(name, { input: 0, output: 0 });
41787
+ }
41788
+ return agentMap.get(name);
41789
+ };
41790
+ for (const group of inputRes.groups) {
41791
+ const name = group.dimensions.entityName ?? "unknown";
41792
+ ensure(name).input = group.value;
41793
+ }
41794
+ for (const group of outputRes.groups) {
41795
+ const name = group.dimensions.entityName ?? "unknown";
41796
+ ensure(name).output = group.value;
41797
+ }
41798
+ return Array.from(agentMap.entries()).map(([name, vals]) => ({
41799
+ name,
41800
+ input: vals.input,
41801
+ output: vals.output,
41802
+ total: vals.input + vals.output
41803
+ })).sort((a, b) => b.total - a.total);
41804
+ }
41805
+ });
41806
+ }
41807
+
41808
+ function HorizontalBars({
41809
+ data,
41810
+ segments,
41811
+ maxVal,
41812
+ fmt,
41813
+ className
41814
+ }) {
41815
+ const sorted = [...data].sort((a, b) => {
41816
+ const totalB = b.values.reduce((s, v) => s + v, 0);
41817
+ const totalA = a.values.reduce((s, v) => s + v, 0);
41818
+ return totalB - totalA;
41819
+ });
41820
+ const isStacked = segments.length > 1;
41821
+ return /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: cn("w-full h-full", className), children: [
41822
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4 mt-2", children: [
41823
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 flex items-center gap-4", children: segments.map((seg) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
41824
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 rounded-full", style: { backgroundColor: seg.color } }),
41825
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm text-neutral3", children: seg.label })
41826
+ ] }, seg.label)) }),
41827
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-ui-sm text-neutral2 pr-2", children: "Total" })
41828
+ ] }),
41829
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3.5", children: sorted.map((d) => {
41830
+ const total = d.values.reduce((s, v) => s + v, 0);
41831
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-14 h-6 ", children: [
41832
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full flex-1 min-w-0", children: [
41833
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
41834
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
41835
+ "div",
41836
+ {
41837
+ className: "absolute inset-y-0 left-0 cursor-default",
41838
+ style: { width: `${maxVal > 0 ? total / maxVal * 100 : 0}%` },
41839
+ children: segments.map((seg, si) => {
41840
+ const val = d.values[si] ?? 0;
41841
+ const pct = total > 0 ? val / total * 100 : 0;
41842
+ const left = d.values.slice(0, si).reduce((s, v) => s + (total > 0 ? v / total * 100 : 0), 0);
41843
+ const isLastWithValue = d.values.slice(si + 1).every((v) => !v);
41844
+ if (isStacked) {
41845
+ return /* @__PURE__ */ jsxRuntime.jsx(
41846
+ "div",
41847
+ {
41848
+ className: cn(
41849
+ "absolute inset-y-0",
41850
+ si === 0 && "rounded-l",
41851
+ isLastWithValue && "rounded-r"
41852
+ ),
41853
+ style: {
41854
+ left: `${left}%`,
41855
+ width: `${pct}%`,
41856
+ backgroundColor: seg.color
41857
+ }
41858
+ },
41859
+ seg.label
41860
+ );
41861
+ }
41862
+ return /* @__PURE__ */ jsxRuntime.jsx(
41863
+ "div",
41864
+ {
41865
+ className: "absolute inset-y-0 left-0 rounded",
41866
+ style: { width: `${pct}%`, backgroundColor: seg.color }
41867
+ },
41868
+ seg.label
41869
+ );
41870
+ })
41871
+ }
41872
+ ) }),
41873
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipContent, { side: "top", className: "font-mono", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-1", children: segments.map((seg, si) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
41874
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: seg.label }),
41875
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto pl-3", children: fmt(d.values[si] ?? 0) })
41876
+ ] }, seg.label)) }) })
41877
+ ] }),
41878
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "absolute inset-y-0 left-2.5 flex items-center text-ui-sm text-neutral4 truncate z-10 pointer-events-none", children: d.name })
41879
+ ] }),
41880
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-md text-neutral4 tabular-nums shrink-0 pr-3", children: fmt(total) })
41881
+ ] }, d.name);
41882
+ }) })
41883
+ ] });
41884
+ }
41885
+
41886
+ function TokenUsageByAgentCard() {
41887
+ const { data, isLoading, isError } = useTokenUsageByAgentMetrics();
41888
+ const hasData = !!data && data.length > 0;
41889
+ const totalTokens = data?.reduce((s, d) => s + d.total, 0) ?? 0;
41890
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41891
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41892
+ /* @__PURE__ */ jsxRuntime.jsx(
41893
+ MetricsCard.TitleAndDescription,
41894
+ {
41895
+ title: "Token Usage by Agent",
41896
+ description: "Token consumption grouped by agent."
41897
+ }
41898
+ ),
41899
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: formatCompact(totalTokens), label: "Total tokens" })
41900
+ ] }),
41901
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Loading, {}) : isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Error, { message: "Failed to load token usage data" }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Content, { children: !hasData ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No token usage data yet" }) : /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { defaultTab: "tokens", className: "grid grid-rows-[auto_1fr] overflow-y-auto h-full", children: [
41902
+ /* @__PURE__ */ jsxRuntime.jsx(TabList, { children: /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tokens", children: "Tokens" }) }),
41903
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tokens", children: /* @__PURE__ */ jsxRuntime.jsx(
41904
+ HorizontalBars,
41905
+ {
41906
+ data: data.map((d) => ({ name: d.name, values: [d.input, d.output] })),
41907
+ segments: [
41908
+ { label: "Input", color: CHART_COLORS.blueDark },
41909
+ { label: "Output", color: CHART_COLORS.blue }
41910
+ ],
41911
+ maxVal: Math.max(...data.map((d) => d.input + d.output)),
41912
+ fmt: formatCompact
41913
+ }
41914
+ ) })
41915
+ ] }) })
41916
+ ] });
41917
+ }
41918
+
41919
+ async function fetchVolume(client, metricName, timestamp) {
41920
+ const res = await client.getMetricBreakdown({
41921
+ name: [metricName],
41922
+ groupBy: ["entityName", "status"],
41923
+ aggregation: "count",
41924
+ filters: { timestamp }
41925
+ });
41926
+ const map = /* @__PURE__ */ new Map();
41927
+ for (const group of res.groups) {
41928
+ const name = group.dimensions.entityName ?? "unknown";
41929
+ const status = group.dimensions.status ?? "ok";
41930
+ if (!map.has(name)) {
41931
+ map.set(name, { completed: 0, errors: 0 });
41932
+ }
41933
+ const entry = map.get(name);
41934
+ if (status === "error") {
41935
+ entry.errors += group.value;
41936
+ } else {
41937
+ entry.completed += group.value;
41938
+ }
41939
+ }
41940
+ return Array.from(map.entries()).map(([name, vals]) => ({ name, ...vals })).sort((a, b) => b.completed + b.errors - (a.completed + a.errors));
41941
+ }
41942
+ function useTraceVolumeMetrics() {
41943
+ const client = react.useMastraClient();
41944
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41945
+ return reactQuery.useQuery({
41946
+ queryKey: ["metrics", "trace-volume", datePreset, customRange],
41947
+ queryFn: async () => {
41948
+ const [agentData, workflowData, toolData] = await Promise.all([
41949
+ fetchVolume(client, "mastra_agent_duration_ms", timestamp),
41950
+ fetchVolume(client, "mastra_workflow_duration_ms", timestamp),
41951
+ fetchVolume(client, "mastra_tool_duration_ms", timestamp)
41952
+ ]);
41953
+ return { agentData, workflowData, toolData };
41954
+ }
41955
+ });
41956
+ }
41957
+
41958
+ function VolumeBars({ data }) {
41959
+ return /* @__PURE__ */ jsxRuntime.jsx(
41960
+ HorizontalBars,
41961
+ {
41962
+ data: data.map((d) => ({ name: d.name, values: [d.completed, d.errors] })),
41963
+ segments: [
41964
+ { label: "Completed", color: CHART_COLORS.blueDark },
41965
+ { label: "Errors", color: CHART_COLORS.pink }
41966
+ ],
41967
+ maxVal: Math.max(...data.map((d) => d.completed + d.errors)),
41968
+ fmt: formatCompact
41969
+ }
41970
+ );
41971
+ }
41972
+ function TracesVolumeCard() {
41973
+ const { data, isLoading, isError } = useTraceVolumeMetrics();
41974
+ const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);
41975
+ const total = data ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0) : 0;
41976
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41977
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41978
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Trace Volume", description: "Runs and call counts." }),
41979
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: formatCompact(total), label: "Total runs" })
41980
+ ] }),
41981
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Loading, {}) : isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Error, { message: "Failed to load trace volume data" }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Content, { children: !hasData ? /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No trace volume data yet" }) : /* @__PURE__ */ jsxRuntime.jsxs(Tabs, { defaultTab: "agents", className: "grid grid-rows-[auto_1fr] overflow-y-auto h-full", children: [
41982
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41983
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "agents", children: "Agents" }),
41984
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "workflows", children: "Workflows" }),
41985
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tools", children: "Tools" })
41986
+ ] }),
41987
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "agents", children: data.agentData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(VolumeBars, { data: data.agentData }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No agent data yet" }) }),
41988
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "workflows", children: data.workflowData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(VolumeBars, { data: data.workflowData }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No workflow data yet" }) }),
41989
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tools", children: data.toolData.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(VolumeBars, { data: data.toolData }) : /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No tool data yet" }) })
41990
+ ] }) })
41991
+ ] });
41992
+ }
41993
+
41994
+ function MetricsFlexGrid({ children, className }) {
41995
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap gap-8", className), children });
41996
+ }
41997
+
41998
+ const ANALYTICS_OBSERVABILITY_TYPES = /* @__PURE__ */ new Set([
41999
+ // 'ObservabilityStorageClickhouse',
42000
+ // 'ObservabilityStorageDuckDB',
42001
+ "ObservabilityInMemory"
42002
+ ]);
42003
+ function MetricsDashboard() {
42004
+ const { data, isLoading } = useMastraPackages();
42005
+ const observabilityType = data?.observabilityStorageType;
42006
+ const supportsMetrics = observabilityType ? ANALYTICS_OBSERVABILITY_TYPES.has(observabilityType) : false;
42007
+ const isInMemory = observabilityType === "ObservabilityInMemory";
42008
+ if (isLoading) {
42009
+ return null;
42010
+ }
42011
+ if (!supportsMetrics) {
42012
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
42013
+ EmptyState$1,
42014
+ {
42015
+ iconSlot: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlashIcon, {}),
42016
+ titleSlot: "Metrics are not available with your current storage",
42017
+ descriptionSlot: "Metrics currently require in-memory storage for observability. ClickHouse and DuckDB support is coming soon. Relational databases (PostgreSQL, LibSQL) do not support metrics collection. To enable metrics on an existing project, switch the observability storage in the Mastra configuration.",
42018
+ actionSlot: /* @__PURE__ */ jsxRuntime.jsxs(
42019
+ Button,
42020
+ {
42021
+ variant: "ghost",
42022
+ as: "a",
42023
+ href: "https://mastra.ai/en/docs/observability/metrics",
42024
+ target: "_blank",
42025
+ rel: "noopener noreferrer",
42026
+ children: [
42027
+ "Metrics Documentation ",
42028
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLinkIcon, {})
42029
+ ]
42030
+ }
42031
+ )
42032
+ }
42033
+ ) });
42034
+ }
42035
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 content-start pb-10", children: [
42036
+ isInMemory && /* @__PURE__ */ jsxRuntime.jsxs(Alert, { variant: "info", children: [
42037
+ /* @__PURE__ */ jsxRuntime.jsx(AlertTitle, { children: "Metrics are not persisted" }),
42038
+ /* @__PURE__ */ jsxRuntime.jsx(AlertDescription, { as: "p", children: "This project uses in-memory storage for observability. Metrics will be lost on every server restart. For persistent metrics, switch the observability storage to ClickHouse or DuckDB." })
42039
+ ] }),
42040
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsFlexGrid, { children: [
42041
+ /* @__PURE__ */ jsxRuntime.jsx(AgentRunsKpiCard, {}),
42042
+ /* @__PURE__ */ jsxRuntime.jsx(TotalTokensKpiCard, {}),
42043
+ /* @__PURE__ */ jsxRuntime.jsx(AvgScoreKpiCard, {})
42044
+ ] }),
42045
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsFlexGrid, { children: [
42046
+ /* @__PURE__ */ jsxRuntime.jsx(ModelUsageCostCard, {}),
42047
+ /* @__PURE__ */ jsxRuntime.jsx(TokenUsageByAgentCard, {}),
42048
+ /* @__PURE__ */ jsxRuntime.jsx(ScoresCard, {}),
42049
+ /* @__PURE__ */ jsxRuntime.jsx(TracesVolumeCard, {}),
42050
+ /* @__PURE__ */ jsxRuntime.jsx(LatencyCard, {})
42051
+ ] })
42052
+ ] });
42053
+ }
42054
+
42055
+ const DATE_PRESETS = [
42056
+ { label: "Last 24 hours", value: "24h" },
42057
+ { label: "Last 3 days", value: "3d" },
42058
+ { label: "Last 7 days", value: "7d" },
42059
+ { label: "Last 14 days", value: "14d" },
42060
+ { label: "Last 30 days", value: "30d" }
42061
+ ];
42062
+ function DateRangeSelector() {
42063
+ const { datePreset, setDatePreset } = useMetrics();
42064
+ return /* @__PURE__ */ jsxRuntime.jsx(
42065
+ SelectFieldBlock,
42066
+ {
42067
+ name: "date-range",
42068
+ labelIsHidden: true,
42069
+ value: datePreset,
42070
+ options: DATE_PRESETS,
42071
+ onValueChange: (value) => setDatePreset(value)
42072
+ }
42073
+ );
42074
+ }
42075
+
40863
42076
  function groupTracesByThread(traces) {
40864
42077
  const threadMap = /* @__PURE__ */ new Map();
40865
42078
  const ungrouped = [];
@@ -42061,6 +43274,7 @@ function DatasetsList({ datasets, isLoading, error, search = "" }) {
42061
43274
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Version" }),
42062
43275
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Created" })
42063
43276
  ] }),
43277
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Datasets match your search" }) : null,
42064
43278
  filteredData.map((ds) => {
42065
43279
  const name = truncateString(ds.name, 50);
42066
43280
  const description = truncateString(ds.description ?? "", 200);
@@ -49058,6 +50272,7 @@ function McpServersList({ mcpServers, isLoading, error, search = "" }) {
49058
50272
  }
49059
50273
  )
49060
50274
  ] }),
50275
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No MCP Servers match your search" }) : null,
49061
50276
  filteredData.map((server) => /* @__PURE__ */ jsxRuntime.jsx(McpServerRow, { server }, server.id))
49062
50277
  ] });
49063
50278
  }
@@ -49971,7 +51186,7 @@ function SkillsTable({
49971
51186
  /* @__PURE__ */ jsxRuntime.jsx(EntryList.Header, { columns: effectiveColumns }),
49972
51187
  skills.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(EntryList.Entries, { children: skills.map((skill) => {
49973
51188
  const entry = {
49974
- id: skill.name,
51189
+ id: skill.path,
49975
51190
  name: skill.name,
49976
51191
  description: skill.description || "—"
49977
51192
  };
@@ -49982,7 +51197,7 @@ function SkillsTable({
49982
51197
  entry,
49983
51198
  columns: effectiveColumns,
49984
51199
  onClick: () => {
49985
- const url = `${basePath}/${encodeURIComponent(skill.name)}`;
51200
+ const url = `${basePath}/${encodeURIComponent(skill.name)}?path=${encodeURIComponent(skill.path)}`;
49986
51201
  navigate(url);
49987
51202
  },
49988
51203
  children: [
@@ -50017,7 +51232,7 @@ function SkillsTable({
50017
51232
  ] }) })
50018
51233
  ]
50019
51234
  },
50020
- skill.name
51235
+ skill.path
50021
51236
  );
50022
51237
  }) }) : /* @__PURE__ */ jsxRuntime.jsx(
50023
51238
  EntryList.Message,
@@ -51284,6 +52499,7 @@ exports.Breadcrumb = Breadcrumb$1;
51284
52499
  exports.Button = Button;
51285
52500
  exports.ButtonWithTooltip = ButtonWithTooltip;
51286
52501
  exports.ButtonsGroup = ButtonsGroup;
52502
+ exports.CHART_COLORS = CHART_COLORS;
51287
52503
  exports.CODE_AGENT_OVERRIDE_SECTIONS = CODE_AGENT_OVERRIDE_SECTIONS;
51288
52504
  exports.CSVImportDialog = CSVImportDialog;
51289
52505
  exports.Cell = Cell;
@@ -51334,6 +52550,7 @@ exports.DatasetVersionsPanel = DatasetVersionsPanel;
51334
52550
  exports.DatasetsList = DatasetsList;
51335
52551
  exports.DatasetsTable = DatasetsTable;
51336
52552
  exports.DatePicker = DatePicker;
52553
+ exports.DateRangeSelector = DateRangeSelector;
51337
52554
  exports.DateTimeCell = DateTimeCell;
51338
52555
  exports.DateTimePicker = DateTimePicker;
51339
52556
  exports.DateTimePickerContent = DateTimePickerContent;
@@ -51407,6 +52624,7 @@ exports.HeaderAction = HeaderAction;
51407
52624
  exports.HeaderGroup = HeaderGroup;
51408
52625
  exports.HeaderTitle = HeaderTitle;
51409
52626
  exports.HomeIcon = HomeIcon;
52627
+ exports.HorizontalBars = HorizontalBars;
51410
52628
  exports.HoverPopover = HoverPopover;
51411
52629
  exports.Icon = Icon;
51412
52630
  exports.InfoIcon = InfoIcon;
@@ -51425,6 +52643,7 @@ exports.KeyValueList = KeyValueList;
51425
52643
  exports.LLMModels = LLMModels;
51426
52644
  exports.LLMProviders = LLMProviders;
51427
52645
  exports.Label = Label;
52646
+ exports.LatencyCard = LatencyCard;
51428
52647
  exports.LatencyIcon = LatencyIcon;
51429
52648
  exports.LinkComponentProvider = LinkComponentProvider;
51430
52649
  exports.ListSearch = ListSearch;
@@ -51456,6 +52675,12 @@ exports.MemoryIcon = MemoryIcon;
51456
52675
  exports.MemoryPage = MemoryPage;
51457
52676
  exports.MemorySearch = MemorySearch;
51458
52677
  exports.MemorySection = MemorySection;
52678
+ exports.MetricsCard = MetricsCard;
52679
+ exports.MetricsDashboard = MetricsDashboard;
52680
+ exports.MetricsDataTable = MetricsDataTable;
52681
+ exports.MetricsKpiCard = MetricsKpiCard;
52682
+ exports.MetricsProvider = MetricsProvider;
52683
+ exports.ModelUsageCostCard = ModelUsageCostCard;
51459
52684
  exports.MultiColumn = MultiColumn;
51460
52685
  exports.MultiCombobox = MultiCombobox;
51461
52686
  exports.NavigationCommand = NavigationCommand;
@@ -51523,6 +52748,7 @@ exports.ScorersList = ScorersList;
51523
52748
  exports.ScorersPage = ScorersPage;
51524
52749
  exports.ScorersSection = ScorersSection;
51525
52750
  exports.ScorersTable = ScorersTable;
52751
+ exports.ScoresCard = ScoresCard;
51526
52752
  exports.ScoresList = ScoresList;
51527
52753
  exports.ScoresTools = ScoresTools;
51528
52754
  exports.ScrollArea = ScrollArea;
@@ -51587,6 +52813,7 @@ exports.ThreadLink = ThreadLink;
51587
52813
  exports.ThreadList = ThreadList;
51588
52814
  exports.Threads = Threads;
51589
52815
  exports.TimePicker = TimePicker;
52816
+ exports.TokenUsageByAgentCard = TokenUsageByAgentCard;
51590
52817
  exports.ToolCoinIcon = ToolCoinIcon;
51591
52818
  exports.ToolCombobox = ToolCombobox;
51592
52819
  exports.ToolFallback = ToolFallback;
@@ -51613,6 +52840,7 @@ exports.TraceTimelineSpan = TraceTimelineSpan;
51613
52840
  exports.TraceTimelineTools = TraceTimelineTools;
51614
52841
  exports.TracesList = TracesList;
51615
52842
  exports.TracesTools = TracesTools;
52843
+ exports.TracesVolumeCard = TracesVolumeCard;
51616
52844
  exports.TracingSettingsContext = TracingSettingsContext;
51617
52845
  exports.TracingSettingsProvider = TracingSettingsProvider;
51618
52846
  exports.Tree = Tree;
@@ -51670,6 +52898,7 @@ exports.fieldConfig = fieldConfig;
51670
52898
  exports.fieldsToJSONSchema = fieldsToJSONSchema;
51671
52899
  exports.findProviderById = findProviderById;
51672
52900
  exports.flattenSchemaToVariables = flattenSchemaToVariables;
52901
+ exports.formatCompact = formatCompact;
51673
52902
  exports.formatHierarchicalSpans = formatHierarchicalSpans;
51674
52903
  exports.getChildFieldOptions = getChildFieldOptions;
51675
52904
  exports.getColumnTemplate = getColumnTemplate;
@@ -51692,6 +52921,7 @@ exports.isActive = isActive;
51692
52921
  exports.isAuthenticated = isAuthenticated;
51693
52922
  exports.isRule = isRule;
51694
52923
  exports.isRuleGroup = isRuleGroup;
52924
+ exports.isValidPreset = isValidPreset;
51695
52925
  exports.joinModelId = joinModelId;
51696
52926
  exports.jsonSchemaToFields = jsonSchemaToFields;
51697
52927
  exports.makeAuthCapabilitiesRequest = makeAuthCapabilitiesRequest;
@@ -51736,6 +52966,7 @@ exports.useAgentEditForm = useAgentEditForm;
51736
52966
  exports.useAgentEditFormContext = useAgentEditFormContext;
51737
52967
  exports.useAgentExperiments = useAgentExperiments;
51738
52968
  exports.useAgentInformationTab = useAgentInformationTab;
52969
+ exports.useAgentRunsKpiMetrics = useAgentRunsKpiMetrics;
51739
52970
  exports.useAgentSettings = useAgentSettings;
51740
52971
  exports.useAgentSkill = useAgentSkill;
51741
52972
  exports.useAgentVersion = useAgentVersion;
@@ -51744,6 +52975,7 @@ exports.useAgents = useAgents;
51744
52975
  exports.useAllIntegrationTools = useAllIntegrationTools;
51745
52976
  exports.useAllModels = useAllModels;
51746
52977
  exports.useAuthCapabilities = useAuthCapabilities;
52978
+ exports.useAvgScoreKpiMetrics = useAvgScoreKpiMetrics;
51747
52979
  exports.useCSVParser = useCSVParser;
51748
52980
  exports.useCloneThread = useCloneThread;
51749
52981
  exports.useCodemirrorTheme = useCodemirrorTheme$1;
@@ -51795,6 +53027,7 @@ exports.useJSONSchemaForm = useJSONSchemaForm;
51795
53027
  exports.useJSONSchemaFormField = useJSONSchemaFormField;
51796
53028
  exports.useJSONSchemaFormNestedContext = useJSONSchemaFormNestedContext;
51797
53029
  exports.useLLMProviders = useLLMProviders;
53030
+ exports.useLatencyMetrics = useLatencyMetrics;
51798
53031
  exports.useLinkComponent = useLinkComponent;
51799
53032
  exports.useLogout = useLogout;
51800
53033
  exports.useMCPServerTool = useMCPServerTool;
@@ -51810,6 +53043,9 @@ exports.useMemoryConfig = useMemoryConfig;
51810
53043
  exports.useMemorySearch = useMemorySearch;
51811
53044
  exports.useMemoryWithOMStatus = useMemoryWithOMStatus;
51812
53045
  exports.useMergedRequestContext = useMergedRequestContext;
53046
+ exports.useMetrics = useMetrics;
53047
+ exports.useMetricsFilters = useMetricsFilters;
53048
+ exports.useModelUsageCostMetrics = useModelUsageCostMetrics;
51813
53049
  exports.useNavigationCommand = useNavigationCommand;
51814
53050
  exports.useObservationalMemory = useObservationalMemory;
51815
53051
  exports.useObservationalMemoryContext = useObservationalMemoryContext;
@@ -51842,6 +53078,7 @@ exports.useScorerVersions = useScorerVersions;
51842
53078
  exports.useScorers = useScorers;
51843
53079
  exports.useScoresByExperimentId = useScoresByExperimentId;
51844
53080
  exports.useScoresByScorerId = useScoresByScorerId;
53081
+ exports.useScoresMetrics = useScoresMetrics;
51845
53082
  exports.useSearchSkillsSh = useSearchSkillsSh;
51846
53083
  exports.useSearchWorkspace = useSearchWorkspace;
51847
53084
  exports.useSearchWorkspaceSkills = useSearchWorkspaceSkills;
@@ -51861,11 +53098,14 @@ exports.useTableKeyboardNavigation = useTableKeyboardNavigation;
51861
53098
  exports.useThread = useThread;
51862
53099
  exports.useThreadInput = useThreadInput;
51863
53100
  exports.useThreads = useThreads;
53101
+ exports.useTokenUsageByAgentMetrics = useTokenUsageByAgentMetrics;
51864
53102
  exports.useTool = useTool;
51865
53103
  exports.useToolProviders = useToolProviders;
51866
53104
  exports.useToolkits = useToolkits;
51867
53105
  exports.useTools = useTools;
53106
+ exports.useTotalTokensKpiMetrics = useTotalTokensKpiMetrics;
51868
53107
  exports.useTraceSpanScores = useTraceSpanScores;
53108
+ exports.useTraceVolumeMetrics = useTraceVolumeMetrics;
51869
53109
  exports.useTracingSettings = useTracingSettings;
51870
53110
  exports.useTryConnectMcp = useTryConnectMcp;
51871
53111
  exports.useUpdateAgentModel = useUpdateAgentModel;