@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.
- package/CHANGELOG.md +49 -0
- package/dist/index.cjs.js +1230 -16
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.es.js +1208 -19
- package/dist/index.es.js.map +1 -1
- package/dist/src/domains/agents/components/agent-metadata/agent-metadata.d.ts +1 -0
- package/dist/src/domains/metrics/components/date-range-selector.d.ts +1 -0
- package/dist/src/domains/metrics/components/index.d.ts +28 -0
- package/dist/src/domains/metrics/components/latency-card.d.ts +1 -0
- package/dist/src/domains/metrics/components/metrics-dashboard.d.ts +1 -0
- package/dist/src/domains/metrics/components/metrics-kpi-cards.d.ts +4 -0
- package/dist/src/domains/metrics/components/metrics-utils.d.ts +14 -0
- package/dist/src/domains/metrics/components/model-usage-cost-card.d.ts +1 -0
- package/dist/src/domains/metrics/components/scores-card.d.ts +1 -0
- package/dist/src/domains/metrics/components/token-usage-by-agent-card.d.ts +1 -0
- package/dist/src/domains/metrics/components/traces-volume-card.d.ts +1 -0
- package/dist/src/domains/metrics/hooks/use-agent-runs-kpi-metrics.d.ts +10 -0
- package/dist/src/domains/metrics/hooks/use-avg-score-kpi-metrics.d.ts +10 -0
- package/dist/src/domains/metrics/hooks/use-latency-metrics.d.ts +11 -0
- package/dist/src/domains/metrics/hooks/use-metrics-filters.d.ts +9 -0
- package/dist/src/domains/metrics/hooks/use-metrics.d.ts +56 -0
- package/dist/src/domains/metrics/hooks/use-model-usage-cost-metrics.d.ts +8 -0
- package/dist/src/domains/metrics/hooks/use-scores-metrics.d.ts +22 -0
- package/dist/src/domains/metrics/hooks/use-token-usage-by-agent-metrics.d.ts +7 -0
- package/dist/src/domains/metrics/hooks/use-total-tokens-kpi-metrics.d.ts +6 -0
- package/dist/src/domains/metrics/hooks/use-trace-volume-metrics.d.ts +10 -0
- package/dist/src/domains/metrics/index.d.ts +1 -0
- package/dist/src/domains/workspace/hooks/use-workspace-skills.d.ts +5 -1
- package/dist/src/domains/workspace/types.d.ts +1 -1
- package/dist/src/ds/components/DashboardCard/dashboard-card.d.ts +6 -0
- package/dist/src/ds/components/DashboardCard/dashboard-card.stories.d.ts +8 -0
- package/dist/src/ds/components/DashboardCard/index.d.ts +1 -0
- package/dist/src/ds/components/EntityList/entity-list-no-match.d.ts +5 -0
- package/dist/src/ds/components/EntityList/entity-list.d.ts +2 -0
- package/dist/src/ds/components/HorizontalBars/horizontal-bars.d.ts +15 -0
- package/dist/src/ds/components/HorizontalBars/horizontal-bars.stories.d.ts +7 -0
- package/dist/src/ds/components/HorizontalBars/index.d.ts +1 -0
- package/dist/src/ds/components/MetricsCard/index.d.ts +2 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-content.d.ts +5 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-description.d.ts +4 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-error.d.ts +4 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-loading.d.ts +3 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-no-data.d.ts +4 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-root.d.ts +5 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-summary.d.ts +5 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-title-and-description.d.ts +15 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-title.d.ts +4 -0
- package/dist/src/ds/components/MetricsCard/metrics-card-top-bar.d.ts +5 -0
- package/dist/src/ds/components/MetricsCard/metrics-card.d.ts +31 -0
- package/dist/src/ds/components/MetricsCard/metrics-card.stories.d.ts +11 -0
- package/dist/src/ds/components/MetricsDataTable/index.d.ts +1 -0
- package/dist/src/ds/components/MetricsDataTable/metrics-data-table.d.ts +13 -0
- package/dist/src/ds/components/MetricsDataTable/metrics-data-table.stories.d.ts +16 -0
- package/dist/src/ds/components/MetricsFlexGrid/index.d.ts +1 -0
- package/dist/src/ds/components/MetricsFlexGrid/metrics-flex-grid.d.ts +5 -0
- package/dist/src/ds/components/MetricsFlexGrid/metrics-flex-grid.stories.d.ts +7 -0
- package/dist/src/ds/components/MetricsKpiCard/index.d.ts +1 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-change.d.ts +6 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-error.d.ts +4 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-label.d.ts +4 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-loading.d.ts +3 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-no-change.d.ts +4 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-no-data.d.ts +4 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-root.d.ts +5 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card-value.d.ts +4 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card.d.ts +17 -0
- package/dist/src/ds/components/MetricsKpiCard/metrics-kpi-card.stories.d.ts +10 -0
- package/dist/src/ds/components/MetricsLineChart/index.d.ts +2 -0
- package/dist/src/ds/components/MetricsLineChart/metrics-line-chart-tooltip.d.ts +10 -0
- package/dist/src/ds/components/MetricsLineChart/metrics-line-chart.d.ts +15 -0
- package/dist/src/ds/components/Tabs/tabs-list.d.ts +2 -1
- package/dist/src/index.d.ts +1 -0
- package/dist/src/lib/framework.d.ts +3 -3
- 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]:
|
|
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(
|
|
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.
|
|
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.
|
|
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.
|
|
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;
|