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

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 +49 -0
  2. package/dist/index.cjs.js +1230 -16
  3. package/dist/index.cjs.js.map +1 -1
  4. package/dist/index.es.js +1208 -19
  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) {
@@ -25119,6 +25135,7 @@ function PromptsList({ promptBlocks, isLoading, error, search = "" }) {
25119
25135
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Has Draft" }),
25120
25136
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Is Published" })
25121
25137
  ] }),
25138
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Prompts match your search" }) : null,
25122
25139
  filteredData.map((block) => {
25123
25140
  const name = truncateString(block.name, 50);
25124
25141
  const description = truncateString(block.description ?? "", 200);
@@ -30627,7 +30644,7 @@ const useWorkspaceSkills = (options) => {
30627
30644
  const useWorkspaceSkill = (skillName, options) => {
30628
30645
  const client = react.useMastraClient();
30629
30646
  return reactQuery.useQuery({
30630
- queryKey: ["workspace", "skills", skillName, options?.workspaceId],
30647
+ queryKey: ["workspace", "skills", skillName, options?.path, options?.workspaceId],
30631
30648
  queryFn: async () => {
30632
30649
  if (!compatibility.isWorkspaceV1Supported(client)) {
30633
30650
  throw new Error("Workspace v1 not supported by core or client");
@@ -30636,7 +30653,7 @@ const useWorkspaceSkill = (skillName, options) => {
30636
30653
  throw new Error("workspaceId is required");
30637
30654
  }
30638
30655
  const workspace = client.getWorkspace(options.workspaceId);
30639
- const skill = workspace.getSkill(skillName);
30656
+ const skill = workspace.getSkill(skillName, options?.path);
30640
30657
  return skill.details();
30641
30658
  },
30642
30659
  enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30646,7 +30663,7 @@ const useWorkspaceSkill = (skillName, options) => {
30646
30663
  const useWorkspaceSkillReferences = (skillName, options) => {
30647
30664
  const client = react.useMastraClient();
30648
30665
  return reactQuery.useQuery({
30649
- queryKey: ["workspace", "skills", skillName, "references", options?.workspaceId],
30666
+ queryKey: ["workspace", "skills", skillName, options?.path, "references", options?.workspaceId],
30650
30667
  queryFn: async () => {
30651
30668
  if (!compatibility.isWorkspaceV1Supported(client)) {
30652
30669
  throw new Error("Workspace v1 not supported by core or client");
@@ -30655,7 +30672,7 @@ const useWorkspaceSkillReferences = (skillName, options) => {
30655
30672
  throw new Error("workspaceId is required");
30656
30673
  }
30657
30674
  const workspace = client.getWorkspace(options.workspaceId);
30658
- const skill = workspace.getSkill(skillName);
30675
+ const skill = workspace.getSkill(skillName, options?.path);
30659
30676
  return skill.listReferences();
30660
30677
  },
30661
30678
  enabled: options?.enabled !== false && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30665,7 +30682,7 @@ const useWorkspaceSkillReferences = (skillName, options) => {
30665
30682
  const useWorkspaceSkillReference = (skillName, referencePath, options) => {
30666
30683
  const client = react.useMastraClient();
30667
30684
  return reactQuery.useQuery({
30668
- queryKey: ["workspace", "skills", skillName, "references", referencePath, options?.workspaceId],
30685
+ queryKey: ["workspace", "skills", skillName, options?.path, "references", referencePath, options?.workspaceId],
30669
30686
  queryFn: async () => {
30670
30687
  if (!compatibility.isWorkspaceV1Supported(client)) {
30671
30688
  throw new Error("Workspace v1 not supported by core or client");
@@ -30674,7 +30691,7 @@ const useWorkspaceSkillReference = (skillName, referencePath, options) => {
30674
30691
  throw new Error("workspaceId is required");
30675
30692
  }
30676
30693
  const workspace = client.getWorkspace(options.workspaceId);
30677
- const skill = workspace.getSkill(skillName);
30694
+ const skill = workspace.getSkill(skillName, options?.path);
30678
30695
  return skill.getReference(referencePath);
30679
30696
  },
30680
30697
  enabled: options?.enabled !== false && !!skillName && !!referencePath && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -30696,7 +30713,7 @@ const useSearchWorkspaceSkills = () => {
30696
30713
  const useAgentSkill = (agentId, skillName, options) => {
30697
30714
  const client = react.useMastraClient();
30698
30715
  return reactQuery.useQuery({
30699
- queryKey: ["agents", agentId, "skills", skillName, options?.workspaceId],
30716
+ queryKey: ["agents", agentId, "skills", skillName, options?.path, options?.workspaceId],
30700
30717
  queryFn: async () => {
30701
30718
  if (!compatibility.isWorkspaceV1Supported(client)) {
30702
30719
  throw new Error("Workspace v1 not supported by core or client");
@@ -30705,7 +30722,7 @@ const useAgentSkill = (agentId, skillName, options) => {
30705
30722
  throw new Error("workspaceId is required");
30706
30723
  }
30707
30724
  const workspace = client.getWorkspace(options.workspaceId);
30708
- const skill = workspace.getSkill(skillName);
30725
+ const skill = workspace.getSkill(skillName, options?.path);
30709
30726
  return skill.details();
30710
30727
  },
30711
30728
  enabled: options?.enabled !== false && !!agentId && !!skillName && !!options?.workspaceId && compatibility.isWorkspaceV1Supported(client),
@@ -39313,6 +39330,7 @@ function AgentsList({ agents, isLoading, error, search = "" }) {
39313
39330
  }
39314
39331
  )
39315
39332
  ] }),
39333
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Agents match your search" }) : null,
39316
39334
  filteredData.map((agent) => {
39317
39335
  const name = truncateString(agent.name, 50);
39318
39336
  const instructions = truncateString(extractPrompt(agent.instructions), 200);
@@ -39584,6 +39602,7 @@ function ProcessorsList({ processors, isLoading, error, search = "" }) {
39584
39602
  ),
39585
39603
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCellSmart, { short: "Used by", long: "Used by Agents", className: "text-center" })
39586
39604
  ] }),
39605
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Processors match your search" }) : null,
39587
39606
  filteredData.map((processor) => {
39588
39607
  const name = truncateString(processor.name || processor.id, 50);
39589
39608
  const description = truncateString(processor.description ?? "", 200);
@@ -40038,6 +40057,7 @@ function ToolsList({ tools, agents, isLoading, error, search = "" }) {
40038
40057
  }
40039
40058
  )
40040
40059
  ] }),
40060
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Tools match your search" }) : null,
40041
40061
  filteredData.map((tool) => {
40042
40062
  const name = truncateString(tool.id, 50);
40043
40063
  const description = truncateString(tool.description ?? "", 200);
@@ -40860,6 +40880,1173 @@ function TemplateFailure({ errorMsg, validationErrors }) {
40860
40880
  ] });
40861
40881
  }
40862
40882
 
40883
+ const DATE_PRESETS$1 = [
40884
+ { label: "Last 24 hours", value: "24h" },
40885
+ { label: "Last 3 days", value: "3d" },
40886
+ { label: "Last 7 days", value: "7d" },
40887
+ { label: "Last 14 days", value: "14d" },
40888
+ { label: "Last 30 days", value: "30d" }
40889
+ ];
40890
+ const VALID_PRESETS = new Set(DATE_PRESETS$1.map((p) => p.value));
40891
+ function isValidPreset(value) {
40892
+ return typeof value === "string" && (VALID_PRESETS.has(value) || value === "custom");
40893
+ }
40894
+ const PRESET_DAYS = {
40895
+ "24h": 1,
40896
+ "3d": 3,
40897
+ "7d": 7,
40898
+ "14d": 14,
40899
+ "30d": 30
40900
+ };
40901
+ const ENV_PCTS = {
40902
+ "Studio Cloud": 42,
40903
+ Production: 31,
40904
+ Staging: 18,
40905
+ Dev: 7,
40906
+ "CI / Preview": 2
40907
+ };
40908
+ function getMultiplier(preset, customRange, filterGroups) {
40909
+ let dateMul = 1;
40910
+ if (preset !== "custom") {
40911
+ dateMul = PRESET_DAYS[preset] ?? 1;
40912
+ } else if (customRange?.from && customRange?.to) {
40913
+ dateMul = Math.max(1, dateFns.differenceInDays(customRange.to, customRange.from) + 1);
40914
+ }
40915
+ const envGroups = filterGroups.filter((g) => g.field === "Environment" && g.comparator === "is");
40916
+ const envPct = envGroups.length === 0 ? 100 : envGroups.flatMap((g) => g.values).reduce((s, v) => s + (ENV_PCTS[v] ?? 0), 0);
40917
+ return dateMul * (envPct / 100);
40918
+ }
40919
+ const MetricsContext = React.createContext({
40920
+ datePreset: "24h",
40921
+ setDatePreset: () => {
40922
+ },
40923
+ customRange: void 0,
40924
+ setCustomRange: () => {
40925
+ },
40926
+ dateRangeLabel: "Last 24 hours",
40927
+ filterGroups: [],
40928
+ setFilterGroups: () => {
40929
+ },
40930
+ multiplier: 1
40931
+ });
40932
+ function useMetrics() {
40933
+ return React.useContext(MetricsContext);
40934
+ }
40935
+ function getDateRangeLabel(preset, customRange) {
40936
+ if (preset !== "custom") {
40937
+ return DATE_PRESETS$1.find((p) => p.value === preset).label;
40938
+ }
40939
+ if (customRange?.from) {
40940
+ if (customRange.to) {
40941
+ return `${dateFns.format(customRange.from, "MMM d, yyyy")} – ${dateFns.format(customRange.to, "MMM d, yyyy")}`;
40942
+ }
40943
+ return dateFns.format(customRange.from, "MMM d, yyyy");
40944
+ }
40945
+ return "Custom range";
40946
+ }
40947
+ function MetricsProvider({
40948
+ children,
40949
+ initialPreset,
40950
+ onPresetChange
40951
+ }) {
40952
+ const [datePreset, setDatePresetState] = React.useState(initialPreset ?? "24h");
40953
+ const [customRange, setCustomRange] = React.useState(void 0);
40954
+ const [filterGroups, setFilterGroups] = React.useState([]);
40955
+ const dateRangeLabel = getDateRangeLabel(datePreset, customRange);
40956
+ const multiplier = getMultiplier(datePreset, customRange, filterGroups);
40957
+ React.useEffect(() => {
40958
+ if (initialPreset && initialPreset !== datePreset) {
40959
+ setDatePresetState(initialPreset);
40960
+ }
40961
+ }, [initialPreset]);
40962
+ const setDatePreset = React.useCallback(
40963
+ (v) => {
40964
+ setDatePresetState(v);
40965
+ onPresetChange?.(v);
40966
+ },
40967
+ [onPresetChange]
40968
+ );
40969
+ return /* @__PURE__ */ jsxRuntime.jsx(
40970
+ MetricsContext.Provider,
40971
+ {
40972
+ value: {
40973
+ datePreset,
40974
+ setDatePreset,
40975
+ customRange,
40976
+ setCustomRange,
40977
+ dateRangeLabel,
40978
+ filterGroups,
40979
+ setFilterGroups,
40980
+ multiplier
40981
+ },
40982
+ children
40983
+ }
40984
+ );
40985
+ }
40986
+
40987
+ const PRESET_MS = {
40988
+ "24h": 24 * 60 * 60 * 1e3,
40989
+ "3d": 3 * 24 * 60 * 60 * 1e3,
40990
+ "7d": 7 * 24 * 60 * 60 * 1e3,
40991
+ "14d": 14 * 24 * 60 * 60 * 1e3,
40992
+ "30d": 30 * 24 * 60 * 60 * 1e3
40993
+ };
40994
+ function buildTimestamp(preset, customRange) {
40995
+ const now = /* @__PURE__ */ new Date();
40996
+ if (preset !== "custom") {
40997
+ const ms = PRESET_MS[preset] ?? PRESET_MS["24h"];
40998
+ return { start: new Date(now.getTime() - ms), end: now };
40999
+ }
41000
+ return {
41001
+ start: customRange?.from ?? new Date(now.getTime() - PRESET_MS["24h"]),
41002
+ end: customRange?.to ?? now
41003
+ };
41004
+ }
41005
+ function useMetricsFilters() {
41006
+ const { datePreset, customRange } = useMetrics();
41007
+ const timestamp = buildTimestamp(datePreset, customRange);
41008
+ return { datePreset, customRange, timestamp };
41009
+ }
41010
+
41011
+ async function fetchPercentiles(client, metricName, timestamp) {
41012
+ const res = await client.getMetricPercentiles({
41013
+ name: metricName,
41014
+ percentiles: [0.5, 0.95],
41015
+ interval: "1h",
41016
+ filters: { timestamp }
41017
+ });
41018
+ const p50Series = res.series.find((s) => s.percentile === 0.5);
41019
+ const p95Series = res.series.find((s) => s.percentile === 0.95);
41020
+ if (!p50Series || !p95Series) return [];
41021
+ const p95Map = new Map(p95Series.points.map((p) => [new Date(p.timestamp).getTime(), p.value]));
41022
+ return p50Series.points.map((p) => {
41023
+ const ts = new Date(p.timestamp);
41024
+ return {
41025
+ time: ts.toLocaleTimeString("en-US", { hour: "2-digit", minute: "2-digit", hour12: false }),
41026
+ p50: Math.round(p.value),
41027
+ p95: Math.round(p95Map.get(ts.getTime()) ?? 0)
41028
+ };
41029
+ });
41030
+ }
41031
+ function useLatencyMetrics() {
41032
+ const client = react.useMastraClient();
41033
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41034
+ return reactQuery.useQuery({
41035
+ queryKey: ["metrics", "latency", datePreset, customRange],
41036
+ queryFn: async () => {
41037
+ const [agentData, workflowData, toolData] = await Promise.all([
41038
+ fetchPercentiles(client, "mastra_agent_duration_ms", timestamp),
41039
+ fetchPercentiles(client, "mastra_workflow_duration_ms", timestamp),
41040
+ fetchPercentiles(client, "mastra_tool_duration_ms", timestamp)
41041
+ ]);
41042
+ return { agentData, workflowData, toolData };
41043
+ }
41044
+ });
41045
+ }
41046
+
41047
+ function formatCompact(n) {
41048
+ if (n >= 1e6) return `${(n / 1e6).toFixed(1)}M`;
41049
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}K`;
41050
+ return n.toLocaleString();
41051
+ }
41052
+ const CHART_COLORS = {
41053
+ green: "#22c55e",
41054
+ orange: "#fb923c",
41055
+ pink: "#f472b6",
41056
+ purple: "#8b5cf6",
41057
+ blue: "#4f83f1",
41058
+ blueDark: "#2b5cd9",
41059
+ blueLight: "#6b8fe5",
41060
+ red: "#f87171",
41061
+ greenDark: "#15613a",
41062
+ redDark: "#991b1b",
41063
+ yellow: "#facc15"
41064
+ };
41065
+
41066
+ function MetricsCardContent({ children, className }) {
41067
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("overflow-x-auto ", className), children });
41068
+ }
41069
+
41070
+ function MetricsCardDescription({ children, className }) {
41071
+ return /* @__PURE__ */ jsxRuntime.jsx("p", { className: cn("text-ui-md text-neutral2 leading-tight mt-0.5", className), children });
41072
+ }
41073
+
41074
+ function MetricsCardError({
41075
+ message = "Failed to load data",
41076
+ className
41077
+ }) {
41078
+ 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 }) });
41079
+ }
41080
+
41081
+ function MetricsCardLoading({ className }) {
41082
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center justify-center", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: spacings.Colors.neutral1 }) });
41083
+ }
41084
+
41085
+ function MetricsCardNoData({ message = "No data yet", className }) {
41086
+ 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 }) });
41087
+ }
41088
+
41089
+ function DashboardCard({ children, className }) {
41090
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("border border-border1 rounded-lg p-6 bg-surface2", className), children });
41091
+ }
41092
+
41093
+ function MetricsCardRoot({ children, className }) {
41094
+ return /* @__PURE__ */ jsxRuntime.jsx(
41095
+ DashboardCard,
41096
+ {
41097
+ className: cn(
41098
+ "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]",
41099
+ className
41100
+ ),
41101
+ children
41102
+ }
41103
+ );
41104
+ }
41105
+
41106
+ function MetricsCardSummary({ value, label, className }) {
41107
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("grid justify-end content-start text-right gap-1", className), children: [
41108
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-lg font-semibold text-neutral4 leading-none", children: value }),
41109
+ label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-md text-neutral2", children: label })
41110
+ ] });
41111
+ }
41112
+
41113
+ function MetricsCardTitle({ children, className }) {
41114
+ return /* @__PURE__ */ jsxRuntime.jsx("h3", { className: cn("text-ui-md font-normal text-neutral4", className), children });
41115
+ }
41116
+
41117
+ function MetricsCardTitleAndDescription(props) {
41118
+ if ("children" in props) {
41119
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: props.className, children: props.children });
41120
+ }
41121
+ const { title, description } = props;
41122
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: props.className, children: [
41123
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCardTitle, { children: title }),
41124
+ description && /* @__PURE__ */ jsxRuntime.jsx(MetricsCardDescription, { children: description })
41125
+ ] });
41126
+ }
41127
+
41128
+ function MetricsCardTopBar({ children, className }) {
41129
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("grid grid-cols-[1fr_auto] gap-4", className), children });
41130
+ }
41131
+
41132
+ function MetricsKpiCardChange({
41133
+ changePct,
41134
+ prevValue,
41135
+ lowerIsBetter,
41136
+ className
41137
+ }) {
41138
+ const isGood = lowerIsBetter ? changePct < 0 : changePct >= 0;
41139
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex items-center gap-1 text-sm text-neutral1 flex-wrap", className), children: [
41140
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1", children: [
41141
+ /* @__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, {}) }),
41142
+ /* @__PURE__ */ jsxRuntime.jsx(
41143
+ "span",
41144
+ {
41145
+ className: cn(isGood ? "text-green-600" : "text-red-600"),
41146
+ children: `${changePct >= 0 ? "+" : "-"}${Math.abs(changePct).toFixed(1)}%`
41147
+ }
41148
+ )
41149
+ ] }),
41150
+ prevValue && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
41151
+ "vs previous ",
41152
+ /* @__PURE__ */ jsxRuntime.jsx("b", { className: "text-neutral2 font-semibold", children: prevValue })
41153
+ ] })
41154
+ ] });
41155
+ }
41156
+
41157
+ function MetricsKpiCardError({
41158
+ message = "Failed to load data",
41159
+ className
41160
+ }) {
41161
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-ui-sm text-accent2", className), children: message });
41162
+ }
41163
+
41164
+ function MetricsKpiCardLabel({ children, className }) {
41165
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-ui-md text-neutral3 leading-relaxed", className), children });
41166
+ }
41167
+
41168
+ function MetricsKpiCardLoading({ className }) {
41169
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm", className), children: /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: "md", color: spacings.Colors.neutral1 }) });
41170
+ }
41171
+
41172
+ function MetricsKpiCardNoChange({
41173
+ message = "No previous value to compare",
41174
+ className
41175
+ }) {
41176
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm text-neutral1", className), children: message });
41177
+ }
41178
+
41179
+ function MetricsKpiCardNoData({ message = "No data yet", className }) {
41180
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("text-sm text-neutral1", className), children: message });
41181
+ }
41182
+
41183
+ function MetricsKpiCardRoot({ children, className }) {
41184
+ return /* @__PURE__ */ jsxRuntime.jsx(DashboardCard, { className: cn("flex-1 min-w-[15rem]", className), children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-1", children }) });
41185
+ }
41186
+
41187
+ function MetricsKpiCardValue({ children, className }) {
41188
+ return /* @__PURE__ */ jsxRuntime.jsx("strong", { className: cn("text-header-lg text-neutral4 font-semibold", className), children });
41189
+ }
41190
+
41191
+ const MetricsKpiCard = Object.assign(MetricsKpiCardRoot, {
41192
+ Label: MetricsKpiCardLabel,
41193
+ Value: MetricsKpiCardValue,
41194
+ Change: MetricsKpiCardChange,
41195
+ NoChange: MetricsKpiCardNoChange,
41196
+ NoData: MetricsKpiCardNoData,
41197
+ Error: MetricsKpiCardError,
41198
+ Loading: MetricsKpiCardLoading
41199
+ });
41200
+
41201
+ const MetricsCard = Object.assign(MetricsCardRoot, {
41202
+ Root: MetricsCardRoot,
41203
+ Kpi: MetricsKpiCard,
41204
+ TopBar: MetricsCardTopBar,
41205
+ TitleAndDescription: MetricsCardTitleAndDescription,
41206
+ Title: MetricsCardTitle,
41207
+ Description: MetricsCardDescription,
41208
+ Summary: MetricsCardSummary,
41209
+ Loading: MetricsCardLoading,
41210
+ Error: MetricsCardError,
41211
+ Content: MetricsCardContent,
41212
+ NoData: MetricsCardNoData
41213
+ });
41214
+
41215
+ function MetricsLineChartTooltip({
41216
+ active,
41217
+ payload,
41218
+ label,
41219
+ suffix
41220
+ }) {
41221
+ if (!active || !payload?.length) return null;
41222
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md border border-border1 bg-surface2 px-3 py-2 text-xs shadow-lg", children: [
41223
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-1 font-medium text-icon6", children: label }),
41224
+ payload.map((entry) => /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-icon2", children: [
41225
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-2 inline-block size-2 rounded-full", style: { backgroundColor: entry.color } }),
41226
+ entry.name,
41227
+ ":",
41228
+ " ",
41229
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-mono", children: [
41230
+ entry.value,
41231
+ suffix
41232
+ ] })
41233
+ ] }, entry.name))
41234
+ ] });
41235
+ }
41236
+
41237
+ const LABEL_COLOR = "#a1a1aa";
41238
+ function MetricsLineChart({
41239
+ data,
41240
+ series,
41241
+ height = 210,
41242
+ yDomain
41243
+ }) {
41244
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
41245
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap w-full items-end gap-4 gap-y-1 mb-4", children: series.map((s) => {
41246
+ const aggregated = s.aggregate?.(data);
41247
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-baseline gap-2", children: [
41248
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 rounded-full translate-y-[-1px]", style: { backgroundColor: s.color } }),
41249
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm text-neutral3 truncate max-w-24", children: s.label }),
41250
+ aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-lg text-neutral4", children: [
41251
+ aggregated.value,
41252
+ aggregated.suffix && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-sm text-neutral2", children: [
41253
+ " ",
41254
+ aggregated.suffix
41255
+ ] })
41256
+ ] })
41257
+ ] }, s.dataKey);
41258
+ }) }),
41259
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, children: [
41260
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.CartesianGrid, { stroke: "rgba(255,255,255,0.08)", vertical: false }),
41261
+ /* @__PURE__ */ jsxRuntime.jsx(
41262
+ recharts.XAxis,
41263
+ {
41264
+ dataKey: "time",
41265
+ tick: { fontSize: 10, fill: LABEL_COLOR, fontFamily: "var(--font-mono)" },
41266
+ tickLine: false,
41267
+ axisLine: false,
41268
+ interval: 5
41269
+ }
41270
+ ),
41271
+ /* @__PURE__ */ jsxRuntime.jsx(
41272
+ recharts.YAxis,
41273
+ {
41274
+ tick: { fontSize: 10, fill: LABEL_COLOR, fontFamily: "var(--font-mono)" },
41275
+ tickLine: false,
41276
+ axisLine: false,
41277
+ width: 30,
41278
+ domain: yDomain
41279
+ }
41280
+ ),
41281
+ /* @__PURE__ */ jsxRuntime.jsx(recharts.Tooltip, { content: /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChartTooltip, {}) }),
41282
+ series.map((s) => /* @__PURE__ */ jsxRuntime.jsx(
41283
+ recharts.Line,
41284
+ {
41285
+ type: "linear",
41286
+ dataKey: s.dataKey,
41287
+ stroke: s.color,
41288
+ strokeWidth: 2,
41289
+ dot: false,
41290
+ name: s.label
41291
+ },
41292
+ s.dataKey
41293
+ ))
41294
+ ] }) }) })
41295
+ ] });
41296
+ }
41297
+
41298
+ const latencySeries = [
41299
+ {
41300
+ dataKey: "p50",
41301
+ label: "p50",
41302
+ color: CHART_COLORS.blue,
41303
+ aggregate: (data) => ({
41304
+ value: data.length > 0 ? `${Math.round(data.reduce((s, d) => s + d.p50, 0) / data.length)}` : "0",
41305
+ suffix: "avg ms"
41306
+ })
41307
+ },
41308
+ {
41309
+ dataKey: "p95",
41310
+ label: "p95",
41311
+ color: CHART_COLORS.yellow,
41312
+ aggregate: (data) => ({
41313
+ value: data.length > 0 ? `${Math.round(data.reduce((s, d) => s + d.p95, 0) / data.length)}` : "0",
41314
+ suffix: "avg ms"
41315
+ })
41316
+ }
41317
+ ];
41318
+ function LatencyChart({ data }) {
41319
+ if (data.length === 0) {
41320
+ return /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.NoData, { message: "No latency data yet" });
41321
+ }
41322
+ return /* @__PURE__ */ jsxRuntime.jsx(MetricsLineChart, { data, series: latencySeries });
41323
+ }
41324
+ function LatencyCard() {
41325
+ const { data, isLoading, isError } = useLatencyMetrics();
41326
+ const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);
41327
+ const avgP50 = data && data.agentData.length > 0 ? `${Math.round(data.agentData.reduce((s, d) => s + d.p50, 0) / data.agentData.length)}ms` : "—";
41328
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41329
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41330
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Latency", description: "Hourly p50 and p95 latency." }),
41331
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: avgP50, label: "Avg p50" })
41332
+ ] }),
41333
+ 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: [
41334
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41335
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "agents", children: "Agents" }),
41336
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "workflows", children: "Workflows" }),
41337
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tools", children: "Tools" })
41338
+ ] }),
41339
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "agents", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.agentData }) }),
41340
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "workflows", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.workflowData }) }),
41341
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tools", children: /* @__PURE__ */ jsxRuntime.jsx(LatencyChart, { data: data.toolData }) })
41342
+ ] }) })
41343
+ ] });
41344
+ }
41345
+
41346
+ function useAgentRunsKpiMetrics() {
41347
+ const client = react.useMastraClient();
41348
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41349
+ return reactQuery.useQuery({
41350
+ queryKey: ["metrics", "agent-runs-kpi", datePreset, customRange],
41351
+ queryFn: () => client.getMetricAggregate({
41352
+ name: ["mastra_agent_duration_ms"],
41353
+ aggregation: "count",
41354
+ filters: { timestamp },
41355
+ comparePeriod: "previous_period"
41356
+ })
41357
+ });
41358
+ }
41359
+
41360
+ function useAvgScoreKpiMetrics() {
41361
+ const client = react.useMastraClient();
41362
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41363
+ return reactQuery.useQuery({
41364
+ queryKey: ["metrics", "avg-score-kpi", datePreset, customRange],
41365
+ queryFn: async () => {
41366
+ const scorersMap = await client.listScorers();
41367
+ const scorerIds = Object.keys(scorersMap ?? {});
41368
+ if (scorerIds.length === 0) {
41369
+ return { value: null, previousValue: null, changePercent: null };
41370
+ }
41371
+ const allResults = await Promise.all(
41372
+ scorerIds.map((scorerId) => client.listScoresByScorerId({ scorerId, perPage: 100 }))
41373
+ );
41374
+ const startMs = timestamp.start.getTime();
41375
+ const endMs = timestamp.end.getTime();
41376
+ const allScoreValues = [];
41377
+ for (const result of allResults) {
41378
+ for (const s of result?.scores ?? []) {
41379
+ const ts = new Date(s.createdAt).getTime();
41380
+ if (ts >= startMs && ts <= endMs) {
41381
+ allScoreValues.push(s.score);
41382
+ }
41383
+ }
41384
+ }
41385
+ if (allScoreValues.length === 0) {
41386
+ return { value: null, previousValue: null, changePercent: null };
41387
+ }
41388
+ const avg = allScoreValues.reduce((sum, v) => sum + v, 0) / allScoreValues.length;
41389
+ return { value: Math.round(avg * 100) / 100, previousValue: null, changePercent: null };
41390
+ }
41391
+ });
41392
+ }
41393
+
41394
+ function useTotalTokensKpiMetrics() {
41395
+ const client = react.useMastraClient();
41396
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41397
+ return reactQuery.useQuery({
41398
+ queryKey: ["metrics", "total-tokens-kpi", datePreset, customRange],
41399
+ queryFn: async () => {
41400
+ const [input, output] = await Promise.all([
41401
+ client.getMetricAggregate({
41402
+ name: ["mastra_model_total_input_tokens"],
41403
+ aggregation: "sum",
41404
+ filters: { timestamp },
41405
+ comparePeriod: "previous_period"
41406
+ }),
41407
+ client.getMetricAggregate({
41408
+ name: ["mastra_model_total_output_tokens"],
41409
+ aggregation: "sum",
41410
+ filters: { timestamp },
41411
+ comparePeriod: "previous_period"
41412
+ })
41413
+ ]);
41414
+ const hasCurrent = input.value != null || output.value != null;
41415
+ const hasPrevious = input.previousValue != null || output.previousValue != null;
41416
+ const value = (input.value ?? 0) + (output.value ?? 0);
41417
+ const previousValue = (input.previousValue ?? 0) + (output.previousValue ?? 0);
41418
+ const changePercent = hasPrevious && previousValue > 0 ? (value - previousValue) / previousValue * 100 : null;
41419
+ return {
41420
+ value: hasCurrent ? value : null,
41421
+ previousValue: hasPrevious ? previousValue : null,
41422
+ changePercent
41423
+ };
41424
+ }
41425
+ });
41426
+ }
41427
+
41428
+ function AgentRunsKpiCard() {
41429
+ const { data: agentRunsKpi, isLoading, isError } = useAgentRunsKpiMetrics();
41430
+ const hasData = agentRunsKpi?.value != null;
41431
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41432
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Total Agent Runs" }),
41433
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? agentRunsKpi.value.toLocaleString() : "—" }),
41434
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? agentRunsKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41435
+ MetricsKpiCard.Change,
41436
+ {
41437
+ changePct: agentRunsKpi.changePercent,
41438
+ prevValue: agentRunsKpi.previousValue?.toLocaleString()
41439
+ }
41440
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41441
+ ] });
41442
+ }
41443
+ function TotalTokensKpiCard() {
41444
+ const { data: totalTokensKpi, isLoading, isError } = useTotalTokensKpiMetrics();
41445
+ const hasData = totalTokensKpi?.value != null;
41446
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41447
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Total Tokens" }),
41448
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? formatCompact(totalTokensKpi.value) : "—" }),
41449
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? totalTokensKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41450
+ MetricsKpiCard.Change,
41451
+ {
41452
+ changePct: totalTokensKpi.changePercent,
41453
+ prevValue: totalTokensKpi.previousValue != null ? formatCompact(totalTokensKpi.previousValue) : void 0
41454
+ }
41455
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41456
+ ] });
41457
+ }
41458
+ function AvgScoreKpiCard() {
41459
+ const { data: avgScoreKpi, isLoading, isError } = useAvgScoreKpiMetrics();
41460
+ const hasData = avgScoreKpi?.value != null;
41461
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsKpiCard, { children: [
41462
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Label, { children: "Avg Score" }),
41463
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Value, { className: hasData ? void 0 : "invisible", children: hasData ? String(avgScoreKpi.value) : "—" }),
41464
+ isError ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Error, {}) : isLoading ? /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.Loading, {}) : hasData ? avgScoreKpi.changePercent != null ? /* @__PURE__ */ jsxRuntime.jsx(
41465
+ MetricsKpiCard.Change,
41466
+ {
41467
+ changePct: avgScoreKpi.changePercent,
41468
+ prevValue: avgScoreKpi.previousValue != null ? String(avgScoreKpi.previousValue) : void 0
41469
+ }
41470
+ ) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoChange, {}) : /* @__PURE__ */ jsxRuntime.jsx(MetricsKpiCard.NoData, {})
41471
+ ] });
41472
+ }
41473
+
41474
+ function useModelUsageCostMetrics() {
41475
+ const client = react.useMastraClient();
41476
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41477
+ return reactQuery.useQuery({
41478
+ queryKey: ["metrics", "model-usage-cost", datePreset, customRange],
41479
+ queryFn: async () => {
41480
+ const metrics = [
41481
+ "mastra_model_total_input_tokens",
41482
+ "mastra_model_total_output_tokens",
41483
+ "mastra_model_input_cache_read_tokens",
41484
+ "mastra_model_input_cache_write_tokens"
41485
+ ];
41486
+ const [inputRes, outputRes, cacheReadRes, cacheWriteRes] = await Promise.all(
41487
+ metrics.map(
41488
+ (name) => client.getMetricBreakdown({
41489
+ name: [name],
41490
+ groupBy: ["model"],
41491
+ aggregation: "sum",
41492
+ filters: { timestamp }
41493
+ })
41494
+ )
41495
+ );
41496
+ const modelMap = /* @__PURE__ */ new Map();
41497
+ const ensureModel = (model) => {
41498
+ if (!modelMap.has(model)) {
41499
+ modelMap.set(model, { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 });
41500
+ }
41501
+ return modelMap.get(model);
41502
+ };
41503
+ for (const group of inputRes.groups) {
41504
+ const m = group.dimensions.model ?? "unknown";
41505
+ ensureModel(m).input = group.value;
41506
+ }
41507
+ for (const group of outputRes.groups) {
41508
+ const m = group.dimensions.model ?? "unknown";
41509
+ ensureModel(m).output = group.value;
41510
+ }
41511
+ for (const group of cacheReadRes.groups) {
41512
+ const m = group.dimensions.model ?? "unknown";
41513
+ ensureModel(m).cacheRead = group.value;
41514
+ }
41515
+ for (const group of cacheWriteRes.groups) {
41516
+ const m = group.dimensions.model ?? "unknown";
41517
+ ensureModel(m).cacheWrite = group.value;
41518
+ }
41519
+ return Array.from(modelMap.entries()).map(([model, vals]) => ({
41520
+ model,
41521
+ input: formatCompact(vals.input),
41522
+ output: formatCompact(vals.output),
41523
+ cacheRead: formatCompact(vals.cacheRead),
41524
+ cacheWrite: formatCompact(vals.cacheWrite)
41525
+ })).sort((a, b) => a.model.localeCompare(b.model));
41526
+ }
41527
+ });
41528
+ }
41529
+
41530
+ function MetricsDataTable({
41531
+ columns,
41532
+ data,
41533
+ className
41534
+ }) {
41535
+ if (columns.length === 0) return null;
41536
+ return /* @__PURE__ */ jsxRuntime.jsx(ScrollArea, { className: cn("w-full h-full", className), maxHeight: "20rem", children: /* @__PURE__ */ jsxRuntime.jsxs(
41537
+ "div",
41538
+ {
41539
+ className: "grid items-center",
41540
+ style: {
41541
+ gridTemplateColumns: `auto ${columns.slice(1).map(() => "1fr").join(" ")}`
41542
+ },
41543
+ children: [
41544
+ columns.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx(
41545
+ "span",
41546
+ {
41547
+ className: cn(
41548
+ "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",
41549
+ 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"
41550
+ ),
41551
+ children: col.label
41552
+ },
41553
+ `${i}-${col.label}`
41554
+ )),
41555
+ data.map((row, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: columns.map((col, i) => /* @__PURE__ */ jsxRuntime.jsx(
41556
+ "span",
41557
+ {
41558
+ className: cn(
41559
+ "h-10 flex items-center text-ui-sm whitespace-nowrap border-t border-surface5",
41560
+ rowIndex === 0 && "border-t-transparent",
41561
+ 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(
41562
+ "px-4 text-right tabular-nums",
41563
+ col.highlight ? "text-neutral4 font-semibold" : "text-neutral3"
41564
+ )
41565
+ ),
41566
+ children: col.value(row)
41567
+ },
41568
+ `${row.key}-${i}`
41569
+ )) }, row.key))
41570
+ ]
41571
+ }
41572
+ ) });
41573
+ }
41574
+
41575
+ function ModelUsageCostCard() {
41576
+ const { data: rows, isLoading, isError } = useModelUsageCostMetrics();
41577
+ const hasData = !!rows && rows.length > 0;
41578
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41579
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TopBar, { children: /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Model Usage", description: "Token consumption by model." }) }),
41580
+ 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(
41581
+ MetricsDataTable,
41582
+ {
41583
+ columns: [
41584
+ { label: "Model", value: (row) => row.model },
41585
+ { label: "Input", value: (row) => row.input },
41586
+ { label: "Output", value: (row) => row.output },
41587
+ { label: "Cache Read", value: (row) => row.cacheRead },
41588
+ { label: "Cache Write", value: (row) => row.cacheWrite }
41589
+ // { label: 'Cost', value: () => '—', highlight: true },
41590
+ ],
41591
+ data: rows.map((row) => ({ ...row, key: row.model }))
41592
+ }
41593
+ ) })
41594
+ ] });
41595
+ }
41596
+
41597
+ function useScoresMetrics() {
41598
+ const client = react.useMastraClient();
41599
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41600
+ return reactQuery.useQuery({
41601
+ queryKey: ["metrics", "scores-card", datePreset, customRange],
41602
+ queryFn: async () => {
41603
+ const scorersMap = await client.listScorers();
41604
+ const scorerIds = Object.keys(scorersMap ?? {});
41605
+ if (scorerIds.length === 0) {
41606
+ return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
41607
+ }
41608
+ const allResults = await Promise.all(
41609
+ // Limited to 100 most recent scores per scorer; pagination not yet implemented
41610
+ scorerIds.map((scorerId) => client.listScoresByScorerId({ scorerId, perPage: 100 }))
41611
+ );
41612
+ const startMs = timestamp.start.getTime();
41613
+ const endMs = timestamp.end.getTime();
41614
+ const allScores = [];
41615
+ for (let i = 0; i < scorerIds.length; i++) {
41616
+ const scores = allResults[i]?.scores ?? [];
41617
+ for (const s of scores) {
41618
+ const ts = new Date(s.createdAt).getTime();
41619
+ if (ts >= startMs && ts <= endMs) {
41620
+ allScores.push({
41621
+ scorerId: scorerIds[i],
41622
+ score: s.score,
41623
+ createdAt: s.createdAt
41624
+ });
41625
+ }
41626
+ }
41627
+ }
41628
+ if (allScores.length === 0) {
41629
+ return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
41630
+ }
41631
+ const byScorer = /* @__PURE__ */ new Map();
41632
+ for (const s of allScores) {
41633
+ if (!byScorer.has(s.scorerId)) byScorer.set(s.scorerId, []);
41634
+ byScorer.get(s.scorerId).push(s.score);
41635
+ }
41636
+ const summaryData = Array.from(byScorer.entries()).map(([scorer, vals]) => ({
41637
+ scorer,
41638
+ avg: vals.reduce((a, b) => a + b, 0) / vals.length,
41639
+ min: Math.min(...vals),
41640
+ max: Math.max(...vals),
41641
+ count: vals.length
41642
+ }));
41643
+ const scorerNames = summaryData.map((s) => s.scorer);
41644
+ const avgScore = summaryData.reduce((s, d) => s + d.avg, 0) / summaryData.length;
41645
+ const bucketMap = /* @__PURE__ */ new Map();
41646
+ for (const s of allScores) {
41647
+ const ts = new Date(s.createdAt);
41648
+ const bucket = Math.floor(ts.getTime() / 36e5) * 36e5;
41649
+ if (!bucketMap.has(bucket)) bucketMap.set(bucket, /* @__PURE__ */ new Map());
41650
+ const scorerMap = bucketMap.get(bucket);
41651
+ if (!scorerMap.has(s.scorerId)) scorerMap.set(s.scorerId, []);
41652
+ scorerMap.get(s.scorerId).push(s.score);
41653
+ }
41654
+ const overTimeData = Array.from(bucketMap.entries()).sort(([a], [b]) => a - b).map(([bucket, scorerMap]) => {
41655
+ const point = {
41656
+ time: new Date(bucket).toLocaleTimeString("en-US", {
41657
+ hour: "2-digit",
41658
+ minute: "2-digit",
41659
+ hour12: false
41660
+ })
41661
+ };
41662
+ for (const name of scorerNames) {
41663
+ const vals = scorerMap.get(name);
41664
+ if (vals && vals.length > 0) {
41665
+ point[name] = +(vals.reduce((a, b) => a + b, 0) / vals.length).toFixed(2);
41666
+ }
41667
+ }
41668
+ return point;
41669
+ });
41670
+ return {
41671
+ summaryData,
41672
+ overTimeData,
41673
+ scorerNames,
41674
+ avgScore: Math.round(avgScore * 100) / 100
41675
+ };
41676
+ }
41677
+ });
41678
+ }
41679
+
41680
+ const SERIES_COLORS = [
41681
+ CHART_COLORS.green,
41682
+ CHART_COLORS.blue,
41683
+ CHART_COLORS.purple,
41684
+ CHART_COLORS.orange,
41685
+ CHART_COLORS.pink,
41686
+ CHART_COLORS.yellow
41687
+ ];
41688
+ function ScoresCard() {
41689
+ const { data, isLoading, isError } = useScoresMetrics();
41690
+ const hasData = !!data && data.summaryData.length > 0;
41691
+ const series = React.useMemo(() => {
41692
+ if (!data?.scorerNames) return [];
41693
+ return data.scorerNames.map((name, i) => ({
41694
+ dataKey: name,
41695
+ label: name,
41696
+ color: SERIES_COLORS[i % SERIES_COLORS.length],
41697
+ aggregate: (points) => ({
41698
+ value: points.length > 0 ? (points.reduce((s, d) => s + (d[name] ?? 0), 0) / points.length).toFixed(2) : "0",
41699
+ suffix: "avg"
41700
+ })
41701
+ }));
41702
+ }, [data?.scorerNames]);
41703
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41704
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41705
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Scores", description: "Evaluation scorer performance." }),
41706
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(
41707
+ MetricsCard.Summary,
41708
+ {
41709
+ value: data?.avgScore != null ? `avg ${data.avgScore}` : "—",
41710
+ label: "Across all scorers"
41711
+ }
41712
+ )
41713
+ ] }),
41714
+ 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: [
41715
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41716
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "over-time", children: "Over Time" }),
41717
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "summary", children: "Summary" })
41718
+ ] }),
41719
+ /* @__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" }) }),
41720
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "summary", children: /* @__PURE__ */ jsxRuntime.jsx(
41721
+ MetricsDataTable,
41722
+ {
41723
+ columns: [
41724
+ { label: "Scorer", value: (row) => row.scorer },
41725
+ { label: "Avg", value: (row) => row.avg.toFixed(2), highlight: true },
41726
+ { label: "Min", value: (row) => row.min.toFixed(2) },
41727
+ { label: "Max", value: (row) => row.max.toFixed(2) },
41728
+ { label: "Count", value: (row) => row.count.toLocaleString() }
41729
+ ],
41730
+ data: data.summaryData.map((row) => ({ ...row, key: row.scorer }))
41731
+ }
41732
+ ) })
41733
+ ] }) })
41734
+ ] });
41735
+ }
41736
+
41737
+ function useTokenUsageByAgentMetrics() {
41738
+ const client = react.useMastraClient();
41739
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41740
+ return reactQuery.useQuery({
41741
+ queryKey: ["metrics", "token-usage-by-agent", datePreset, customRange],
41742
+ queryFn: async () => {
41743
+ const [inputRes, outputRes] = await Promise.all([
41744
+ client.getMetricBreakdown({
41745
+ name: ["mastra_model_total_input_tokens"],
41746
+ groupBy: ["entityName"],
41747
+ aggregation: "sum",
41748
+ filters: { timestamp }
41749
+ }),
41750
+ client.getMetricBreakdown({
41751
+ name: ["mastra_model_total_output_tokens"],
41752
+ groupBy: ["entityName"],
41753
+ aggregation: "sum",
41754
+ filters: { timestamp }
41755
+ })
41756
+ ]);
41757
+ const agentMap = /* @__PURE__ */ new Map();
41758
+ const ensure = (name) => {
41759
+ if (!agentMap.has(name)) {
41760
+ agentMap.set(name, { input: 0, output: 0 });
41761
+ }
41762
+ return agentMap.get(name);
41763
+ };
41764
+ for (const group of inputRes.groups) {
41765
+ const name = group.dimensions.entityName ?? "unknown";
41766
+ ensure(name).input = group.value;
41767
+ }
41768
+ for (const group of outputRes.groups) {
41769
+ const name = group.dimensions.entityName ?? "unknown";
41770
+ ensure(name).output = group.value;
41771
+ }
41772
+ return Array.from(agentMap.entries()).map(([name, vals]) => ({
41773
+ name,
41774
+ input: vals.input,
41775
+ output: vals.output,
41776
+ total: vals.input + vals.output
41777
+ })).sort((a, b) => b.total - a.total);
41778
+ }
41779
+ });
41780
+ }
41781
+
41782
+ function HorizontalBars({
41783
+ data,
41784
+ segments,
41785
+ maxVal,
41786
+ fmt,
41787
+ className
41788
+ }) {
41789
+ const sorted = [...data].sort((a, b) => {
41790
+ const totalB = b.values.reduce((s, v) => s + v, 0);
41791
+ const totalA = a.values.reduce((s, v) => s + v, 0);
41792
+ return totalB - totalA;
41793
+ });
41794
+ const isStacked = segments.length > 1;
41795
+ return /* @__PURE__ */ jsxRuntime.jsxs(ScrollArea, { className: cn("w-full h-full", className), children: [
41796
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4 mt-2", children: [
41797
+ /* @__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: [
41798
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 rounded-full", style: { backgroundColor: seg.color } }),
41799
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm text-neutral3", children: seg.label })
41800
+ ] }, seg.label)) }),
41801
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 text-ui-sm text-neutral2 pr-2", children: "Total" })
41802
+ ] }),
41803
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-3.5", children: sorted.map((d) => {
41804
+ const total = d.values.reduce((s, v) => s + v, 0);
41805
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-14 h-6 ", children: [
41806
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative h-full flex-1 min-w-0", children: [
41807
+ /* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
41808
+ /* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
41809
+ "div",
41810
+ {
41811
+ className: "absolute inset-y-0 left-0 cursor-default",
41812
+ style: { width: `${maxVal > 0 ? total / maxVal * 100 : 0}%` },
41813
+ children: segments.map((seg, si) => {
41814
+ const val = d.values[si] ?? 0;
41815
+ const pct = total > 0 ? val / total * 100 : 0;
41816
+ const left = d.values.slice(0, si).reduce((s, v) => s + (total > 0 ? v / total * 100 : 0), 0);
41817
+ const isLastWithValue = d.values.slice(si + 1).every((v) => !v);
41818
+ if (isStacked) {
41819
+ return /* @__PURE__ */ jsxRuntime.jsx(
41820
+ "div",
41821
+ {
41822
+ className: cn(
41823
+ "absolute inset-y-0",
41824
+ si === 0 && "rounded-l",
41825
+ isLastWithValue && "rounded-r"
41826
+ ),
41827
+ style: {
41828
+ left: `${left}%`,
41829
+ width: `${pct}%`,
41830
+ backgroundColor: seg.color
41831
+ }
41832
+ },
41833
+ seg.label
41834
+ );
41835
+ }
41836
+ return /* @__PURE__ */ jsxRuntime.jsx(
41837
+ "div",
41838
+ {
41839
+ className: "absolute inset-y-0 left-0 rounded",
41840
+ style: { width: `${pct}%`, backgroundColor: seg.color }
41841
+ },
41842
+ seg.label
41843
+ );
41844
+ })
41845
+ }
41846
+ ) }),
41847
+ /* @__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: [
41848
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: seg.label }),
41849
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto pl-3", children: fmt(d.values[si] ?? 0) })
41850
+ ] }, seg.label)) }) })
41851
+ ] }),
41852
+ /* @__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 })
41853
+ ] }),
41854
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-md text-neutral4 tabular-nums shrink-0 pr-3", children: fmt(total) })
41855
+ ] }, d.name);
41856
+ }) })
41857
+ ] });
41858
+ }
41859
+
41860
+ function TokenUsageByAgentCard() {
41861
+ const { data, isLoading, isError } = useTokenUsageByAgentMetrics();
41862
+ const hasData = !!data && data.length > 0;
41863
+ const totalTokens = data?.reduce((s, d) => s + d.total, 0) ?? 0;
41864
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41865
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41866
+ /* @__PURE__ */ jsxRuntime.jsx(
41867
+ MetricsCard.TitleAndDescription,
41868
+ {
41869
+ title: "Token Usage by Agent",
41870
+ description: "Token consumption grouped by agent."
41871
+ }
41872
+ ),
41873
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: formatCompact(totalTokens), label: "Total tokens" })
41874
+ ] }),
41875
+ 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: [
41876
+ /* @__PURE__ */ jsxRuntime.jsx(TabList, { children: /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tokens", children: "Tokens" }) }),
41877
+ /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tokens", children: /* @__PURE__ */ jsxRuntime.jsx(
41878
+ HorizontalBars,
41879
+ {
41880
+ data: data.map((d) => ({ name: d.name, values: [d.input, d.output] })),
41881
+ segments: [
41882
+ { label: "Input", color: CHART_COLORS.blueDark },
41883
+ { label: "Output", color: CHART_COLORS.blue }
41884
+ ],
41885
+ maxVal: Math.max(...data.map((d) => d.input + d.output)),
41886
+ fmt: formatCompact
41887
+ }
41888
+ ) })
41889
+ ] }) })
41890
+ ] });
41891
+ }
41892
+
41893
+ async function fetchVolume(client, metricName, timestamp) {
41894
+ const res = await client.getMetricBreakdown({
41895
+ name: [metricName],
41896
+ groupBy: ["entityName", "status"],
41897
+ aggregation: "count",
41898
+ filters: { timestamp }
41899
+ });
41900
+ const map = /* @__PURE__ */ new Map();
41901
+ for (const group of res.groups) {
41902
+ const name = group.dimensions.entityName ?? "unknown";
41903
+ const status = group.dimensions.status ?? "ok";
41904
+ if (!map.has(name)) {
41905
+ map.set(name, { completed: 0, errors: 0 });
41906
+ }
41907
+ const entry = map.get(name);
41908
+ if (status === "error") {
41909
+ entry.errors += group.value;
41910
+ } else {
41911
+ entry.completed += group.value;
41912
+ }
41913
+ }
41914
+ return Array.from(map.entries()).map(([name, vals]) => ({ name, ...vals })).sort((a, b) => b.completed + b.errors - (a.completed + a.errors));
41915
+ }
41916
+ function useTraceVolumeMetrics() {
41917
+ const client = react.useMastraClient();
41918
+ const { datePreset, customRange, timestamp } = useMetricsFilters();
41919
+ return reactQuery.useQuery({
41920
+ queryKey: ["metrics", "trace-volume", datePreset, customRange],
41921
+ queryFn: async () => {
41922
+ const [agentData, workflowData, toolData] = await Promise.all([
41923
+ fetchVolume(client, "mastra_agent_duration_ms", timestamp),
41924
+ fetchVolume(client, "mastra_workflow_duration_ms", timestamp),
41925
+ fetchVolume(client, "mastra_tool_duration_ms", timestamp)
41926
+ ]);
41927
+ return { agentData, workflowData, toolData };
41928
+ }
41929
+ });
41930
+ }
41931
+
41932
+ function VolumeBars({ data }) {
41933
+ return /* @__PURE__ */ jsxRuntime.jsx(
41934
+ HorizontalBars,
41935
+ {
41936
+ data: data.map((d) => ({ name: d.name, values: [d.completed, d.errors] })),
41937
+ segments: [
41938
+ { label: "Completed", color: CHART_COLORS.blueDark },
41939
+ { label: "Errors", color: CHART_COLORS.pink }
41940
+ ],
41941
+ maxVal: Math.max(...data.map((d) => d.completed + d.errors)),
41942
+ fmt: formatCompact
41943
+ }
41944
+ );
41945
+ }
41946
+ function TracesVolumeCard() {
41947
+ const { data, isLoading, isError } = useTraceVolumeMetrics();
41948
+ const hasData = !!data && (data.agentData.length > 0 || data.workflowData.length > 0 || data.toolData.length > 0);
41949
+ const total = data ? [...data.agentData, ...data.workflowData, ...data.toolData].reduce((s, d) => s + d.completed + d.errors, 0) : 0;
41950
+ return /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard, { children: [
41951
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsCard.TopBar, { children: [
41952
+ /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.TitleAndDescription, { title: "Trace Volume", description: "Runs and call counts." }),
41953
+ hasData && /* @__PURE__ */ jsxRuntime.jsx(MetricsCard.Summary, { value: formatCompact(total), label: "Total runs" })
41954
+ ] }),
41955
+ 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: [
41956
+ /* @__PURE__ */ jsxRuntime.jsxs(TabList, { children: [
41957
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "agents", children: "Agents" }),
41958
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "workflows", children: "Workflows" }),
41959
+ /* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "tools", children: "Tools" })
41960
+ ] }),
41961
+ /* @__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" }) }),
41962
+ /* @__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" }) }),
41963
+ /* @__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" }) })
41964
+ ] }) })
41965
+ ] });
41966
+ }
41967
+
41968
+ function MetricsFlexGrid({ children, className }) {
41969
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-wrap gap-8", className), children });
41970
+ }
41971
+
41972
+ const ANALYTICS_OBSERVABILITY_TYPES = /* @__PURE__ */ new Set([
41973
+ // 'ObservabilityStorageClickhouse',
41974
+ // 'ObservabilityStorageDuckDB',
41975
+ "ObservabilityInMemory"
41976
+ ]);
41977
+ function MetricsDashboard() {
41978
+ const { data, isLoading } = useMastraPackages();
41979
+ const observabilityType = data?.observabilityStorageType;
41980
+ const supportsMetrics = observabilityType ? ANALYTICS_OBSERVABILITY_TYPES.has(observabilityType) : false;
41981
+ const isInMemory = observabilityType === "ObservabilityInMemory";
41982
+ if (isLoading) {
41983
+ return null;
41984
+ }
41985
+ if (!supportsMetrics) {
41986
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(
41987
+ EmptyState$1,
41988
+ {
41989
+ iconSlot: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlashIcon, {}),
41990
+ titleSlot: "Metrics are not available with your current storage",
41991
+ 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.",
41992
+ actionSlot: /* @__PURE__ */ jsxRuntime.jsxs(
41993
+ Button,
41994
+ {
41995
+ variant: "ghost",
41996
+ as: "a",
41997
+ href: "https://mastra.ai/en/docs/observability/metrics",
41998
+ target: "_blank",
41999
+ rel: "noopener noreferrer",
42000
+ children: [
42001
+ "Metrics Documentation ",
42002
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLinkIcon, {})
42003
+ ]
42004
+ }
42005
+ )
42006
+ }
42007
+ ) });
42008
+ }
42009
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid gap-8 content-start pb-10", children: [
42010
+ isInMemory && /* @__PURE__ */ jsxRuntime.jsxs(Alert, { variant: "info", children: [
42011
+ /* @__PURE__ */ jsxRuntime.jsx(AlertTitle, { children: "Metrics are not persisted" }),
42012
+ /* @__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." })
42013
+ ] }),
42014
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsFlexGrid, { children: [
42015
+ /* @__PURE__ */ jsxRuntime.jsx(AgentRunsKpiCard, {}),
42016
+ /* @__PURE__ */ jsxRuntime.jsx(TotalTokensKpiCard, {}),
42017
+ /* @__PURE__ */ jsxRuntime.jsx(AvgScoreKpiCard, {})
42018
+ ] }),
42019
+ /* @__PURE__ */ jsxRuntime.jsxs(MetricsFlexGrid, { children: [
42020
+ /* @__PURE__ */ jsxRuntime.jsx(ModelUsageCostCard, {}),
42021
+ /* @__PURE__ */ jsxRuntime.jsx(TokenUsageByAgentCard, {}),
42022
+ /* @__PURE__ */ jsxRuntime.jsx(ScoresCard, {}),
42023
+ /* @__PURE__ */ jsxRuntime.jsx(TracesVolumeCard, {}),
42024
+ /* @__PURE__ */ jsxRuntime.jsx(LatencyCard, {})
42025
+ ] })
42026
+ ] });
42027
+ }
42028
+
42029
+ const DATE_PRESETS = [
42030
+ { label: "Last 24 hours", value: "24h" },
42031
+ { label: "Last 3 days", value: "3d" },
42032
+ { label: "Last 7 days", value: "7d" },
42033
+ { label: "Last 14 days", value: "14d" },
42034
+ { label: "Last 30 days", value: "30d" }
42035
+ ];
42036
+ function DateRangeSelector() {
42037
+ const { datePreset, setDatePreset } = useMetrics();
42038
+ return /* @__PURE__ */ jsxRuntime.jsx(
42039
+ SelectFieldBlock,
42040
+ {
42041
+ name: "date-range",
42042
+ labelIsHidden: true,
42043
+ value: datePreset,
42044
+ options: DATE_PRESETS,
42045
+ onValueChange: (value) => setDatePreset(value)
42046
+ }
42047
+ );
42048
+ }
42049
+
40863
42050
  function groupTracesByThread(traces) {
40864
42051
  const threadMap = /* @__PURE__ */ new Map();
40865
42052
  const ungrouped = [];
@@ -42061,6 +43248,7 @@ function DatasetsList({ datasets, isLoading, error, search = "" }) {
42061
43248
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Version" }),
42062
43249
  /* @__PURE__ */ jsxRuntime.jsx(EntityList.TopCell, { className: "text-center", children: "Created" })
42063
43250
  ] }),
43251
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No Datasets match your search" }) : null,
42064
43252
  filteredData.map((ds) => {
42065
43253
  const name = truncateString(ds.name, 50);
42066
43254
  const description = truncateString(ds.description ?? "", 200);
@@ -49058,6 +50246,7 @@ function McpServersList({ mcpServers, isLoading, error, search = "" }) {
49058
50246
  }
49059
50247
  )
49060
50248
  ] }),
50249
+ filteredData.length === 0 && search ? /* @__PURE__ */ jsxRuntime.jsx(EntityList.NoMatch, { message: "No MCP Servers match your search" }) : null,
49061
50250
  filteredData.map((server) => /* @__PURE__ */ jsxRuntime.jsx(McpServerRow, { server }, server.id))
49062
50251
  ] });
49063
50252
  }
@@ -49971,7 +51160,7 @@ function SkillsTable({
49971
51160
  /* @__PURE__ */ jsxRuntime.jsx(EntryList.Header, { columns: effectiveColumns }),
49972
51161
  skills.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(EntryList.Entries, { children: skills.map((skill) => {
49973
51162
  const entry = {
49974
- id: skill.name,
51163
+ id: skill.path,
49975
51164
  name: skill.name,
49976
51165
  description: skill.description || "—"
49977
51166
  };
@@ -49982,7 +51171,7 @@ function SkillsTable({
49982
51171
  entry,
49983
51172
  columns: effectiveColumns,
49984
51173
  onClick: () => {
49985
- const url = `${basePath}/${encodeURIComponent(skill.name)}`;
51174
+ const url = `${basePath}/${encodeURIComponent(skill.name)}?path=${encodeURIComponent(skill.path)}`;
49986
51175
  navigate(url);
49987
51176
  },
49988
51177
  children: [
@@ -50017,7 +51206,7 @@ function SkillsTable({
50017
51206
  ] }) })
50018
51207
  ]
50019
51208
  },
50020
- skill.name
51209
+ skill.path
50021
51210
  );
50022
51211
  }) }) : /* @__PURE__ */ jsxRuntime.jsx(
50023
51212
  EntryList.Message,
@@ -51284,6 +52473,7 @@ exports.Breadcrumb = Breadcrumb$1;
51284
52473
  exports.Button = Button;
51285
52474
  exports.ButtonWithTooltip = ButtonWithTooltip;
51286
52475
  exports.ButtonsGroup = ButtonsGroup;
52476
+ exports.CHART_COLORS = CHART_COLORS;
51287
52477
  exports.CODE_AGENT_OVERRIDE_SECTIONS = CODE_AGENT_OVERRIDE_SECTIONS;
51288
52478
  exports.CSVImportDialog = CSVImportDialog;
51289
52479
  exports.Cell = Cell;
@@ -51334,6 +52524,7 @@ exports.DatasetVersionsPanel = DatasetVersionsPanel;
51334
52524
  exports.DatasetsList = DatasetsList;
51335
52525
  exports.DatasetsTable = DatasetsTable;
51336
52526
  exports.DatePicker = DatePicker;
52527
+ exports.DateRangeSelector = DateRangeSelector;
51337
52528
  exports.DateTimeCell = DateTimeCell;
51338
52529
  exports.DateTimePicker = DateTimePicker;
51339
52530
  exports.DateTimePickerContent = DateTimePickerContent;
@@ -51407,6 +52598,7 @@ exports.HeaderAction = HeaderAction;
51407
52598
  exports.HeaderGroup = HeaderGroup;
51408
52599
  exports.HeaderTitle = HeaderTitle;
51409
52600
  exports.HomeIcon = HomeIcon;
52601
+ exports.HorizontalBars = HorizontalBars;
51410
52602
  exports.HoverPopover = HoverPopover;
51411
52603
  exports.Icon = Icon;
51412
52604
  exports.InfoIcon = InfoIcon;
@@ -51425,6 +52617,7 @@ exports.KeyValueList = KeyValueList;
51425
52617
  exports.LLMModels = LLMModels;
51426
52618
  exports.LLMProviders = LLMProviders;
51427
52619
  exports.Label = Label;
52620
+ exports.LatencyCard = LatencyCard;
51428
52621
  exports.LatencyIcon = LatencyIcon;
51429
52622
  exports.LinkComponentProvider = LinkComponentProvider;
51430
52623
  exports.ListSearch = ListSearch;
@@ -51456,6 +52649,12 @@ exports.MemoryIcon = MemoryIcon;
51456
52649
  exports.MemoryPage = MemoryPage;
51457
52650
  exports.MemorySearch = MemorySearch;
51458
52651
  exports.MemorySection = MemorySection;
52652
+ exports.MetricsCard = MetricsCard;
52653
+ exports.MetricsDashboard = MetricsDashboard;
52654
+ exports.MetricsDataTable = MetricsDataTable;
52655
+ exports.MetricsKpiCard = MetricsKpiCard;
52656
+ exports.MetricsProvider = MetricsProvider;
52657
+ exports.ModelUsageCostCard = ModelUsageCostCard;
51459
52658
  exports.MultiColumn = MultiColumn;
51460
52659
  exports.MultiCombobox = MultiCombobox;
51461
52660
  exports.NavigationCommand = NavigationCommand;
@@ -51523,6 +52722,7 @@ exports.ScorersList = ScorersList;
51523
52722
  exports.ScorersPage = ScorersPage;
51524
52723
  exports.ScorersSection = ScorersSection;
51525
52724
  exports.ScorersTable = ScorersTable;
52725
+ exports.ScoresCard = ScoresCard;
51526
52726
  exports.ScoresList = ScoresList;
51527
52727
  exports.ScoresTools = ScoresTools;
51528
52728
  exports.ScrollArea = ScrollArea;
@@ -51587,6 +52787,7 @@ exports.ThreadLink = ThreadLink;
51587
52787
  exports.ThreadList = ThreadList;
51588
52788
  exports.Threads = Threads;
51589
52789
  exports.TimePicker = TimePicker;
52790
+ exports.TokenUsageByAgentCard = TokenUsageByAgentCard;
51590
52791
  exports.ToolCoinIcon = ToolCoinIcon;
51591
52792
  exports.ToolCombobox = ToolCombobox;
51592
52793
  exports.ToolFallback = ToolFallback;
@@ -51613,6 +52814,7 @@ exports.TraceTimelineSpan = TraceTimelineSpan;
51613
52814
  exports.TraceTimelineTools = TraceTimelineTools;
51614
52815
  exports.TracesList = TracesList;
51615
52816
  exports.TracesTools = TracesTools;
52817
+ exports.TracesVolumeCard = TracesVolumeCard;
51616
52818
  exports.TracingSettingsContext = TracingSettingsContext;
51617
52819
  exports.TracingSettingsProvider = TracingSettingsProvider;
51618
52820
  exports.Tree = Tree;
@@ -51670,6 +52872,7 @@ exports.fieldConfig = fieldConfig;
51670
52872
  exports.fieldsToJSONSchema = fieldsToJSONSchema;
51671
52873
  exports.findProviderById = findProviderById;
51672
52874
  exports.flattenSchemaToVariables = flattenSchemaToVariables;
52875
+ exports.formatCompact = formatCompact;
51673
52876
  exports.formatHierarchicalSpans = formatHierarchicalSpans;
51674
52877
  exports.getChildFieldOptions = getChildFieldOptions;
51675
52878
  exports.getColumnTemplate = getColumnTemplate;
@@ -51692,6 +52895,7 @@ exports.isActive = isActive;
51692
52895
  exports.isAuthenticated = isAuthenticated;
51693
52896
  exports.isRule = isRule;
51694
52897
  exports.isRuleGroup = isRuleGroup;
52898
+ exports.isValidPreset = isValidPreset;
51695
52899
  exports.joinModelId = joinModelId;
51696
52900
  exports.jsonSchemaToFields = jsonSchemaToFields;
51697
52901
  exports.makeAuthCapabilitiesRequest = makeAuthCapabilitiesRequest;
@@ -51736,6 +52940,7 @@ exports.useAgentEditForm = useAgentEditForm;
51736
52940
  exports.useAgentEditFormContext = useAgentEditFormContext;
51737
52941
  exports.useAgentExperiments = useAgentExperiments;
51738
52942
  exports.useAgentInformationTab = useAgentInformationTab;
52943
+ exports.useAgentRunsKpiMetrics = useAgentRunsKpiMetrics;
51739
52944
  exports.useAgentSettings = useAgentSettings;
51740
52945
  exports.useAgentSkill = useAgentSkill;
51741
52946
  exports.useAgentVersion = useAgentVersion;
@@ -51744,6 +52949,7 @@ exports.useAgents = useAgents;
51744
52949
  exports.useAllIntegrationTools = useAllIntegrationTools;
51745
52950
  exports.useAllModels = useAllModels;
51746
52951
  exports.useAuthCapabilities = useAuthCapabilities;
52952
+ exports.useAvgScoreKpiMetrics = useAvgScoreKpiMetrics;
51747
52953
  exports.useCSVParser = useCSVParser;
51748
52954
  exports.useCloneThread = useCloneThread;
51749
52955
  exports.useCodemirrorTheme = useCodemirrorTheme$1;
@@ -51795,6 +53001,7 @@ exports.useJSONSchemaForm = useJSONSchemaForm;
51795
53001
  exports.useJSONSchemaFormField = useJSONSchemaFormField;
51796
53002
  exports.useJSONSchemaFormNestedContext = useJSONSchemaFormNestedContext;
51797
53003
  exports.useLLMProviders = useLLMProviders;
53004
+ exports.useLatencyMetrics = useLatencyMetrics;
51798
53005
  exports.useLinkComponent = useLinkComponent;
51799
53006
  exports.useLogout = useLogout;
51800
53007
  exports.useMCPServerTool = useMCPServerTool;
@@ -51810,6 +53017,9 @@ exports.useMemoryConfig = useMemoryConfig;
51810
53017
  exports.useMemorySearch = useMemorySearch;
51811
53018
  exports.useMemoryWithOMStatus = useMemoryWithOMStatus;
51812
53019
  exports.useMergedRequestContext = useMergedRequestContext;
53020
+ exports.useMetrics = useMetrics;
53021
+ exports.useMetricsFilters = useMetricsFilters;
53022
+ exports.useModelUsageCostMetrics = useModelUsageCostMetrics;
51813
53023
  exports.useNavigationCommand = useNavigationCommand;
51814
53024
  exports.useObservationalMemory = useObservationalMemory;
51815
53025
  exports.useObservationalMemoryContext = useObservationalMemoryContext;
@@ -51842,6 +53052,7 @@ exports.useScorerVersions = useScorerVersions;
51842
53052
  exports.useScorers = useScorers;
51843
53053
  exports.useScoresByExperimentId = useScoresByExperimentId;
51844
53054
  exports.useScoresByScorerId = useScoresByScorerId;
53055
+ exports.useScoresMetrics = useScoresMetrics;
51845
53056
  exports.useSearchSkillsSh = useSearchSkillsSh;
51846
53057
  exports.useSearchWorkspace = useSearchWorkspace;
51847
53058
  exports.useSearchWorkspaceSkills = useSearchWorkspaceSkills;
@@ -51861,11 +53072,14 @@ exports.useTableKeyboardNavigation = useTableKeyboardNavigation;
51861
53072
  exports.useThread = useThread;
51862
53073
  exports.useThreadInput = useThreadInput;
51863
53074
  exports.useThreads = useThreads;
53075
+ exports.useTokenUsageByAgentMetrics = useTokenUsageByAgentMetrics;
51864
53076
  exports.useTool = useTool;
51865
53077
  exports.useToolProviders = useToolProviders;
51866
53078
  exports.useToolkits = useToolkits;
51867
53079
  exports.useTools = useTools;
53080
+ exports.useTotalTokensKpiMetrics = useTotalTokensKpiMetrics;
51868
53081
  exports.useTraceSpanScores = useTraceSpanScores;
53082
+ exports.useTraceVolumeMetrics = useTraceVolumeMetrics;
51869
53083
  exports.useTracingSettings = useTracingSettings;
51870
53084
  exports.useTryConnectMcp = useTryConnectMcp;
51871
53085
  exports.useUpdateAgentModel = useUpdateAgentModel;