@mastra/playground-ui 21.0.0 → 21.0.1-alpha.1
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 +40 -0
- package/dist/index.cjs.js +193 -108
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +13 -8
- package/dist/index.es.js +193 -108
- package/dist/index.es.js.map +1 -1
- package/dist/src/domains/agents/components/agent-information/agent-memory.d.ts +2 -1
- package/dist/src/domains/agents/components/agent-traces-panel.d.ts +9 -2
- package/dist/src/domains/agents/components/provider-map-icon.d.ts +1 -0
- package/dist/src/domains/metrics/hooks/use-avg-score-kpi-metrics.d.ts +1 -1
- package/dist/src/ds/icons/MastraIcon.d.ts +2 -0
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,45 @@
|
|
|
1
1
|
# @mastra/playground-ui
|
|
2
2
|
|
|
3
|
+
## 21.0.1-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated scores metrics to use aggregate and time series APIs instead of fetching raw scores. Scores Over Time chart now always shows hourly data points regardless of the selected time range. Avg Score KPI uses weighted averages via the aggregate API. Updated metrics card layout to use flexible row heights and refined chart legend styling. ([#14937](https://github.com/mastra-ai/mastra/pull/14937))
|
|
8
|
+
|
|
9
|
+
- Fixed deep links for scorer, observability, and agent trace dialogs. ([#14970](https://github.com/mastra-ai/mastra/pull/14970))
|
|
10
|
+
|
|
11
|
+
Developers can now share and reload URLs that keep the selected trace, scoring tab, span, and score in Studio.
|
|
12
|
+
|
|
13
|
+
**Before**
|
|
14
|
+
`/observability`
|
|
15
|
+
`/agents/chef-agent/traces`
|
|
16
|
+
`/evaluation/scorers/response-quality`
|
|
17
|
+
|
|
18
|
+
**After**
|
|
19
|
+
`/observability?traceId=...&spanId=...&tab=scores&scoreId=...`
|
|
20
|
+
`/agents/chef-agent/traces?traceId=...&spanId=...&tab=scores&scoreId=...`
|
|
21
|
+
`/evaluation/scorers/response-quality?entity=...&scoreId=...`
|
|
22
|
+
|
|
23
|
+
This makes review links reliable across the scorer page, observability, and the agent traces view.
|
|
24
|
+
|
|
25
|
+
- Fixed light theme visibility for metrics charts: CartesianGrid lines now adapt to the current theme, and HorizontalBars use reduced opacity in light mode so labels remain readable. Updated MetricsCard minimum height. ([#14975](https://github.com/mastra-ai/mastra/pull/14975))
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`81e4259`](https://github.com/mastra-ai/mastra/commit/81e425939b4ceeb4f586e9b6d89c3b1c1f2d2fe7), [`951b8a1`](https://github.com/mastra-ai/mastra/commit/951b8a1b5ef7e1474c59dc4f2b9fc1a8b1e508b6)]:
|
|
28
|
+
- @mastra/core@1.22.0-alpha.1
|
|
29
|
+
- @mastra/client-js@1.12.1-alpha.1
|
|
30
|
+
- @mastra/react@0.2.22-alpha.1
|
|
31
|
+
|
|
32
|
+
## 21.0.1-alpha.0
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- Added gateway memory indicator in Studio agent memory panel. When an agent uses gateway-backed memory, the panel hides local-only sections (search, working memory, config) and shows a "Memory Gateway" badge instead. ([#14952](https://github.com/mastra-ai/mastra/pull/14952))
|
|
37
|
+
|
|
38
|
+
- Updated dependencies [[`2b4ea10`](https://github.com/mastra-ai/mastra/commit/2b4ea10b053e4ea1ab232d536933a4a3c4cba999), [`c8c86aa`](https://github.com/mastra-ai/mastra/commit/c8c86aa1458017fbd1c0776fdc0c520d129df8a6), [`a0544f0`](https://github.com/mastra-ai/mastra/commit/a0544f0a1e6bd52ac12676228967c1938e43648d), [`c8c86aa`](https://github.com/mastra-ai/mastra/commit/c8c86aa1458017fbd1c0776fdc0c520d129df8a6)]:
|
|
39
|
+
- @mastra/core@1.22.0-alpha.0
|
|
40
|
+
- @mastra/client-js@1.12.1-alpha.0
|
|
41
|
+
- @mastra/react@0.2.22-alpha.0
|
|
42
|
+
|
|
3
43
|
## 21.0.0
|
|
4
44
|
|
|
5
45
|
### Patch Changes
|
package/dist/index.cjs.js
CHANGED
|
@@ -14644,6 +14644,14 @@ const GroqIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
|
14644
14644
|
}
|
|
14645
14645
|
);
|
|
14646
14646
|
|
|
14647
|
+
const MastraIcon = (props) => /* @__PURE__ */ jsxRuntime.jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 34 21", fill: "none", ...props, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
14648
|
+
"path",
|
|
14649
|
+
{
|
|
14650
|
+
d: "M4.49805 11.6934C6.98237 11.6934 8.99609 13.7081 8.99609 16.1924C8.9959 18.6765 6.98225 20.6904 4.49805 20.6904C2.01394 20.6903 0.000196352 18.6765 0 16.1924C0 13.7081 2.01382 11.6935 4.49805 11.6934ZM10.3867 0C12.8709 0 14.8846 2.01388 14.8848 4.49805C14.8848 4.8377 14.847 5.16846 14.7755 5.48643C14.4618 6.88139 14.1953 8.4633 14.9928 9.65L16.2575 11.5319C16.3363 11.6491 16.4727 11.7115 16.6137 11.703C16.7369 11.6957 16.8525 11.6343 16.9214 11.5318L18.1876 9.64717C18.9772 8.47198 18.7236 6.90783 18.4205 5.52484C18.3523 5.21392 18.3164 4.89094 18.3164 4.55957C18.3167 2.07546 20.3313 0.0615234 22.8154 0.0615234C25.2994 0.0617476 27.3132 2.0756 27.3135 4.55957C27.3135 4.93883 27.2665 5.30712 27.178 5.65896C26.8547 6.94441 26.5817 8.37932 27.2446 9.52714L28.459 11.6301C28.4819 11.6697 28.5245 11.6934 28.5703 11.6934C31.0545 11.6935 33.0684 13.7081 33.0684 16.1924C33.0682 18.6765 31.0544 20.6903 28.5703 20.6904C26.0861 20.6904 24.0725 18.6765 24.0723 16.1924C24.0723 15.8049 24.1212 15.4288 24.2133 15.0701C24.5458 13.7746 24.8298 12.3251 24.1609 11.1668L23.0044 9.16384C22.9656 9.09659 22.8931 9.05859 22.8154 9.05859C22.7983 9.05859 22.7824 9.06614 22.7728 9.08033L21.4896 10.9895C20.686 12.1851 20.9622 13.781 21.284 15.1851C21.3582 15.5089 21.3975 15.8461 21.3975 16.1924C21.3973 18.6764 19.3834 20.6902 16.8994 20.6904C14.4152 20.6904 12.4006 18.6765 12.4004 16.1924C12.4004 15.932 12.4226 15.6768 12.4651 15.4286C12.6859 14.14 12.8459 12.7122 12.1167 11.6271L11.2419 10.3253C10.6829 9.49347 9.71913 9.05932 8.78286 8.70188C7.0906 8.05584 5.88867 6.41734 5.88867 4.49805C5.88886 2.0139 7.90254 3.29835e-05 10.3867 0Z",
|
|
14651
|
+
fill: props.fill || "currentColor"
|
|
14652
|
+
}
|
|
14653
|
+
) });
|
|
14654
|
+
|
|
14647
14655
|
const MistralIcon = (props) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
14648
14656
|
"svg",
|
|
14649
14657
|
{
|
|
@@ -14878,7 +14886,8 @@ const providerMapToIcon = {
|
|
|
14878
14886
|
GROQ: /* @__PURE__ */ jsxRuntime.jsx(GroqIcon, {}),
|
|
14879
14887
|
X_GROK: /* @__PURE__ */ jsxRuntime.jsx(XGroqIcon, {}),
|
|
14880
14888
|
MISTRAL: /* @__PURE__ */ jsxRuntime.jsx(MistralIcon, {}),
|
|
14881
|
-
netlify: /* @__PURE__ */ jsxRuntime.jsx(NetlifyIcon, {})
|
|
14889
|
+
netlify: /* @__PURE__ */ jsxRuntime.jsx(NetlifyIcon, {}),
|
|
14890
|
+
mastra: /* @__PURE__ */ jsxRuntime.jsx(MastraIcon, {})
|
|
14882
14891
|
};
|
|
14883
14892
|
|
|
14884
14893
|
const cleanProviderId$1 = (providerId) => {
|
|
@@ -14902,12 +14911,13 @@ const ProviderLogo$1 = ({ providerId, className = "", size = 20 }) => {
|
|
|
14902
14911
|
perplexity: "perplexity",
|
|
14903
14912
|
fireworks_ai: "fireworks",
|
|
14904
14913
|
openrouter: "openrouter",
|
|
14905
|
-
netlify: "netlify"
|
|
14914
|
+
netlify: "netlify",
|
|
14915
|
+
mastra: "mastra"
|
|
14906
14916
|
};
|
|
14907
14917
|
return iconMap[id] || "DEFAULT";
|
|
14908
14918
|
};
|
|
14909
14919
|
const fallbackIcon = getFallbackProviderIcon(cleanedProviderId);
|
|
14910
|
-
const isGateway = ["netlify"].includes(cleanProviderId);
|
|
14920
|
+
const isGateway = ["netlify", "mastra"].includes(cleanProviderId);
|
|
14911
14921
|
if (isGateway || imageError || !providerId) {
|
|
14912
14922
|
if (providerMapToIcon[fallbackIcon]) {
|
|
14913
14923
|
return /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: providerMapToIcon[fallbackIcon] });
|
|
@@ -15550,12 +15560,13 @@ const ProviderLogo = ({ providerId, className = "", size = 20 }) => {
|
|
|
15550
15560
|
perplexity: "perplexity",
|
|
15551
15561
|
fireworks_ai: "fireworks",
|
|
15552
15562
|
openrouter: "openrouter",
|
|
15553
|
-
netlify: "netlify"
|
|
15563
|
+
netlify: "netlify",
|
|
15564
|
+
mastra: "mastra"
|
|
15554
15565
|
};
|
|
15555
15566
|
return iconMap[id] || "DEFAULT";
|
|
15556
15567
|
};
|
|
15557
15568
|
const fallbackIcon = getFallbackProviderIcon(cleanedProviderId);
|
|
15558
|
-
const isGateway = ["netlify"].includes(cleanProviderId$1);
|
|
15569
|
+
const isGateway = ["netlify", "mastra"].includes(cleanProviderId$1);
|
|
15559
15570
|
if (isGateway || imageError || !providerId) {
|
|
15560
15571
|
if (providerMapToIcon[fallbackIcon]) {
|
|
15561
15572
|
return /* @__PURE__ */ jsxRuntime.jsx(Icon, { children: providerMapToIcon[fallbackIcon] });
|
|
@@ -19763,8 +19774,9 @@ function ScoreDialog({
|
|
|
19763
19774
|
usageContext = "scorerPage"
|
|
19764
19775
|
}) {
|
|
19765
19776
|
const [datasetDialogOpen, setDatasetDialogOpen] = React.useState(false);
|
|
19766
|
-
const { Link } = useLinkComponent();
|
|
19777
|
+
const { Link, paths } = useLinkComponent();
|
|
19767
19778
|
const isCodeBased = isCodeBasedScorer$1(score);
|
|
19779
|
+
const scorerDetailHref = score?.scorerId && score?.entityId ? `${paths.scorerLink(score.scorerId)}?entity=${encodeURIComponent(score.entityId)}&scoreId=${encodeURIComponent(score.id)}` : void 0;
|
|
19768
19780
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
19769
19781
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
19770
19782
|
SideDialog,
|
|
@@ -19827,7 +19839,7 @@ function ScoreDialog({
|
|
|
19827
19839
|
...usageContext === "SpanDialog" ? [
|
|
19828
19840
|
{
|
|
19829
19841
|
label: "Scorer",
|
|
19830
|
-
value: score?.scorer?.name || "-",
|
|
19842
|
+
value: scorerDetailHref ? /* @__PURE__ */ jsxRuntime.jsx(Link, { href: scorerDetailHref, children: score?.scorer?.name || "-" }) : score?.scorer?.name || "-",
|
|
19831
19843
|
key: "scorer-name"
|
|
19832
19844
|
}
|
|
19833
19845
|
] : [],
|
|
@@ -23265,11 +23277,11 @@ const AgentObservationalMemory = ({ agentId, resourceId, threadId }) => {
|
|
|
23265
23277
|
return threshold.min;
|
|
23266
23278
|
};
|
|
23267
23279
|
const isAdaptiveMode = omAgentConfig?.messageTokens !== void 0 && typeof omAgentConfig.messageTokens !== "number";
|
|
23268
|
-
const totalBudget = isAdaptiveMode ? getThresholdValue(omAgentConfig?.messageTokens,
|
|
23269
|
-
const baseMessageTokens = isAdaptiveMode ? getBaseThresholdValue(omAgentConfig?.messageTokens,
|
|
23270
|
-
const baseObservationTokens = isAdaptiveMode ? getBaseThresholdValue(omAgentConfig?.observationTokens,
|
|
23271
|
-
const messageTokensThreshold = streamProgress?.windows?.active?.messages?.threshold ?? recordConfig?.observation?.messageTokens ?? getThresholdValue(omAgentConfig?.messageTokens,
|
|
23272
|
-
const configObservationTokens = getThresholdValue(omAgentConfig?.observationTokens,
|
|
23280
|
+
const totalBudget = isAdaptiveMode ? getThresholdValue(omAgentConfig?.messageTokens, 3e4) : 0;
|
|
23281
|
+
const baseMessageTokens = isAdaptiveMode ? getBaseThresholdValue(omAgentConfig?.messageTokens, 3e4) : void 0;
|
|
23282
|
+
const baseObservationTokens = isAdaptiveMode ? getBaseThresholdValue(omAgentConfig?.observationTokens, 4e4) : void 0;
|
|
23283
|
+
const messageTokensThreshold = streamProgress?.windows?.active?.messages?.threshold ?? recordConfig?.observation?.messageTokens ?? getThresholdValue(omAgentConfig?.messageTokens, 3e4);
|
|
23284
|
+
const configObservationTokens = getThresholdValue(omAgentConfig?.observationTokens, 4e4);
|
|
23273
23285
|
const observationTokensThreshold = streamProgress?.windows?.active?.observations?.threshold ?? recordConfig?.reflection?.observationTokens ?? configObservationTokens;
|
|
23274
23286
|
const pendingMessageTokens = streamProgress?.windows?.active?.messages?.tokens ?? record?.pendingMessageTokens ?? 0;
|
|
23275
23287
|
const observationTokenCount = streamProgress?.windows?.active?.observations?.tokens ?? record?.observationTokenCount ?? 0;
|
|
@@ -23900,7 +23912,8 @@ const MemorySearch = ({
|
|
|
23900
23912
|
] });
|
|
23901
23913
|
};
|
|
23902
23914
|
|
|
23903
|
-
function AgentMemory({ agentId, threadId }) {
|
|
23915
|
+
function AgentMemory({ agentId, threadId, memoryType }) {
|
|
23916
|
+
const isGatewayMemory = memoryType === "gateway";
|
|
23904
23917
|
const { threadInput: chatInputValue } = useThreadInput();
|
|
23905
23918
|
const { paths, navigate } = useLinkComponent();
|
|
23906
23919
|
const { data: thread } = useThread({ threadId, agentId });
|
|
@@ -23964,7 +23977,7 @@ function AgentMemory({ agentId, threadId }) {
|
|
|
23964
23977
|
] })
|
|
23965
23978
|
] }) }),
|
|
23966
23979
|
isOMEnabled && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-b border-border1 min-w-0 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(AgentObservationalMemory, { agentId, resourceId: effectiveResourceId, threadId }) }),
|
|
23967
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border1", children: [
|
|
23980
|
+
!isGatewayMemory && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "p-4 border-b border-border1", children: [
|
|
23968
23981
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-2", children: [
|
|
23969
23982
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-neutral5", children: "Semantic Recall" }),
|
|
23970
23983
|
searchMemoryData?.searchScope && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -24005,10 +24018,17 @@ function AgentMemory({ agentId, threadId }) {
|
|
|
24005
24018
|
)
|
|
24006
24019
|
] })
|
|
24007
24020
|
] }),
|
|
24008
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
24021
|
+
!isGatewayMemory && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 overflow-y-auto", children: [
|
|
24009
24022
|
/* @__PURE__ */ jsxRuntime.jsx(AgentWorkingMemory, { agentId }),
|
|
24010
24023
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-border1", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMemoryConfig, { agentId }) })
|
|
24011
|
-
] })
|
|
24024
|
+
] }),
|
|
24025
|
+
isGatewayMemory && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4 border-b border-border1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-surface3 border border-border1 rounded-lg p-4", children: [
|
|
24026
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 mb-1", children: [
|
|
24027
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium px-2 py-0.5 rounded bg-green-500/20 text-green-400", children: "Gateway" }),
|
|
24028
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-sm font-medium text-neutral5", children: "Memory Gateway" })
|
|
24029
|
+
] }),
|
|
24030
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-neutral3", children: "Memory is managed by the Memory Gateway. Threads and observations are stored remotely." })
|
|
24031
|
+
] }) })
|
|
24012
24032
|
] });
|
|
24013
24033
|
}
|
|
24014
24034
|
|
|
@@ -24033,7 +24053,7 @@ function AgentInformation({ agentId, threadId }) {
|
|
|
24033
24053
|
/* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "overview", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMetadata, { agentId }) }),
|
|
24034
24054
|
/* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "model-settings", children: /* @__PURE__ */ jsxRuntime.jsx(AgentSettings, { agentId }) }),
|
|
24035
24055
|
agent?.requestContextSchema && /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "request-context", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-5", children: /* @__PURE__ */ jsxRuntime.jsx(RequestContextSchemaForm, { requestContextSchema: agent.requestContextSchema }) }) }),
|
|
24036
|
-
hasMemory && /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "memory", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMemory, { agentId, threadId }) }),
|
|
24056
|
+
hasMemory && /* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "memory", children: /* @__PURE__ */ jsxRuntime.jsx(AgentMemory, { agentId, threadId, memoryType: memory?.memoryType }) }),
|
|
24037
24057
|
/* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "tracing-options", children: /* @__PURE__ */ jsxRuntime.jsx(TracingRunOptions, {}) })
|
|
24038
24058
|
] }) })
|
|
24039
24059
|
] });
|
|
@@ -34467,7 +34487,10 @@ function TraceDialog({
|
|
|
34467
34487
|
if (initialSpanId) {
|
|
34468
34488
|
setSelectedSpanId(initialSpanId);
|
|
34469
34489
|
setDialogIsOpen(true);
|
|
34490
|
+
return;
|
|
34470
34491
|
}
|
|
34492
|
+
setSelectedSpanId(void 0);
|
|
34493
|
+
setDialogIsOpen(false);
|
|
34471
34494
|
}, [initialSpanId]);
|
|
34472
34495
|
React.useEffect(() => {
|
|
34473
34496
|
if (spanScoresPage > 0) {
|
|
@@ -34498,11 +34521,17 @@ function TraceDialog({
|
|
|
34498
34521
|
});
|
|
34499
34522
|
const handleSpanClick = (id) => {
|
|
34500
34523
|
if (selectedSpanId === id) {
|
|
34524
|
+
if (traceId) {
|
|
34525
|
+
navigate(computeTraceLink(traceId));
|
|
34526
|
+
}
|
|
34501
34527
|
setSelectedSpanId(void 0);
|
|
34502
|
-
|
|
34503
|
-
|
|
34504
|
-
|
|
34505
|
-
|
|
34528
|
+
return;
|
|
34529
|
+
}
|
|
34530
|
+
setSelectedSpanId(id);
|
|
34531
|
+
setSpanDialogDefaultTab("details");
|
|
34532
|
+
setDialogIsOpen(true);
|
|
34533
|
+
if (traceId) {
|
|
34534
|
+
navigate(computeTraceLink(traceId, id));
|
|
34506
34535
|
}
|
|
34507
34536
|
};
|
|
34508
34537
|
const handleToScoring = () => {
|
|
@@ -39735,11 +39764,31 @@ function BulkAddToDatasetBar({
|
|
|
39735
39764
|
] })
|
|
39736
39765
|
] });
|
|
39737
39766
|
}
|
|
39738
|
-
function AgentTracesPanel({
|
|
39767
|
+
function AgentTracesPanel({
|
|
39768
|
+
agentId,
|
|
39769
|
+
basePath,
|
|
39770
|
+
initialTraceId,
|
|
39771
|
+
initialSpanId,
|
|
39772
|
+
initialSpanTab,
|
|
39773
|
+
initialScoreId
|
|
39774
|
+
}) {
|
|
39739
39775
|
const client = react.useMastraClient();
|
|
39740
39776
|
const filters = useAgentTracesFilters(agentId);
|
|
39741
|
-
const
|
|
39742
|
-
const
|
|
39777
|
+
const { navigate } = useLinkComponent();
|
|
39778
|
+
const buildTraceUrl = React.useCallback(
|
|
39779
|
+
(traceId, spanId, scoreId, tab) => {
|
|
39780
|
+
const params = new URLSearchParams();
|
|
39781
|
+
if (traceId) params.set("traceId", traceId);
|
|
39782
|
+
if (spanId) params.set("spanId", spanId);
|
|
39783
|
+
if (tab) params.set("tab", tab);
|
|
39784
|
+
if (scoreId) params.set("scoreId", scoreId);
|
|
39785
|
+
const query = params.toString();
|
|
39786
|
+
return query ? `${basePath ?? `/agents/${agentId}/traces`}?${query}` : basePath ?? `/agents/${agentId}/traces`;
|
|
39787
|
+
},
|
|
39788
|
+
[agentId, basePath]
|
|
39789
|
+
);
|
|
39790
|
+
const [selectedTraceId, setSelectedTraceId] = React.useState(initialTraceId);
|
|
39791
|
+
const [dialogIsOpen, setDialogIsOpen] = React.useState(Boolean(initialTraceId));
|
|
39743
39792
|
const [checkedTraceIds, setCheckedTraceIds] = React.useState(/* @__PURE__ */ new Set());
|
|
39744
39793
|
const [sort, setSort] = React.useState(null);
|
|
39745
39794
|
const {
|
|
@@ -39852,20 +39901,31 @@ function AgentTracesPanel({ agentId }) {
|
|
|
39852
39901
|
return next.size === prev.size ? prev : next;
|
|
39853
39902
|
});
|
|
39854
39903
|
}, [displayTraces, checkedTraceIds.size]);
|
|
39904
|
+
React.useEffect(() => {
|
|
39905
|
+
if (initialTraceId) {
|
|
39906
|
+
setSelectedTraceId(initialTraceId);
|
|
39907
|
+
setDialogIsOpen(true);
|
|
39908
|
+
return;
|
|
39909
|
+
}
|
|
39910
|
+
setSelectedTraceId(void 0);
|
|
39911
|
+
setDialogIsOpen(false);
|
|
39912
|
+
}, [initialTraceId]);
|
|
39855
39913
|
const { batchInsertItems } = useDatasetMutations();
|
|
39856
39914
|
const allSelected = displayTraces.length > 0 && displayTraces.every((t) => checkedTraceIds.has(t.traceId));
|
|
39857
39915
|
const someSelected = checkedTraceIds.size > 0;
|
|
39858
39916
|
const handleTraceClick = React.useCallback(
|
|
39859
39917
|
(traceId) => {
|
|
39860
39918
|
if (selectedTraceId === traceId) {
|
|
39919
|
+
navigate(buildTraceUrl());
|
|
39861
39920
|
setSelectedTraceId(void 0);
|
|
39862
39921
|
setDialogIsOpen(false);
|
|
39863
39922
|
} else {
|
|
39923
|
+
navigate(buildTraceUrl(traceId));
|
|
39864
39924
|
setSelectedTraceId(traceId);
|
|
39865
39925
|
setDialogIsOpen(true);
|
|
39866
39926
|
}
|
|
39867
39927
|
},
|
|
39868
|
-
[selectedTraceId]
|
|
39928
|
+
[buildTraceUrl, navigate, selectedTraceId]
|
|
39869
39929
|
);
|
|
39870
39930
|
const handleCheckToggle = React.useCallback((traceId, checked) => {
|
|
39871
39931
|
setCheckedTraceIds((prev) => {
|
|
@@ -39904,14 +39964,16 @@ function AgentTracesPanel({ agentId }) {
|
|
|
39904
39964
|
},
|
|
39905
39965
|
[displayTraces, checkedTraceIds, batchInsertItems]
|
|
39906
39966
|
);
|
|
39907
|
-
const computeTraceLink = React.useCallback(
|
|
39908
|
-
|
|
39909
|
-
|
|
39967
|
+
const computeTraceLink = React.useCallback(
|
|
39968
|
+
(traceId, spanId, tab) => buildTraceUrl(traceId, spanId, void 0, tab),
|
|
39969
|
+
[buildTraceUrl]
|
|
39970
|
+
);
|
|
39910
39971
|
const toNextTrace = React.useMemo(
|
|
39911
39972
|
() => getToNextEntryFn({
|
|
39912
39973
|
entries: displayTraces.map((t) => ({ id: t.traceId })),
|
|
39913
39974
|
id: selectedTraceId,
|
|
39914
39975
|
update: (id) => {
|
|
39976
|
+
navigate(buildTraceUrl(id));
|
|
39915
39977
|
setSelectedTraceId(id);
|
|
39916
39978
|
setDialogIsOpen(true);
|
|
39917
39979
|
}
|
|
@@ -39923,6 +39985,7 @@ function AgentTracesPanel({ agentId }) {
|
|
|
39923
39985
|
entries: displayTraces.map((t) => ({ id: t.traceId })),
|
|
39924
39986
|
id: selectedTraceId,
|
|
39925
39987
|
update: (id) => {
|
|
39988
|
+
navigate(buildTraceUrl(id));
|
|
39926
39989
|
setSelectedTraceId(id);
|
|
39927
39990
|
setDialogIsOpen(true);
|
|
39928
39991
|
}
|
|
@@ -40024,6 +40087,7 @@ function AgentTracesPanel({ agentId }) {
|
|
|
40024
40087
|
traceDetails: selectedTrace?.spans?.find((s) => s.traceId === selectedTraceId && !s.parentSpanId),
|
|
40025
40088
|
isOpen: dialogIsOpen,
|
|
40026
40089
|
onClose: () => {
|
|
40090
|
+
navigate(buildTraceUrl());
|
|
40027
40091
|
setDialogIsOpen(false);
|
|
40028
40092
|
setSelectedTraceId(void 0);
|
|
40029
40093
|
},
|
|
@@ -40031,6 +40095,9 @@ function AgentTracesPanel({ agentId }) {
|
|
|
40031
40095
|
onPrevious: toPreviousTrace,
|
|
40032
40096
|
isLoadingSpans: isSelectedTraceLoading,
|
|
40033
40097
|
computeTraceLink,
|
|
40098
|
+
initialSpanId,
|
|
40099
|
+
initialSpanTab,
|
|
40100
|
+
initialScoreId,
|
|
40034
40101
|
scorers: scorersMap,
|
|
40035
40102
|
isLoadingScorers
|
|
40036
40103
|
}
|
|
@@ -41887,7 +41954,7 @@ function MetricsCardRoot({ children, className }) {
|
|
|
41887
41954
|
DashboardCard,
|
|
41888
41955
|
{
|
|
41889
41956
|
className: cn(
|
|
41890
|
-
"flex-1 grid grid-rows-[
|
|
41957
|
+
"flex-1 grid grid-rows-[4rem_1fr] min-h-72 gap-2 min-w-80 md:min-w-[22rem] lg:min-w-[24rem] xl:min-w-[26rem] 2xl:min-w-[30rem]",
|
|
41891
41958
|
className
|
|
41892
41959
|
),
|
|
41893
41960
|
children
|
|
@@ -42038,12 +42105,12 @@ function MetricsLineChart({
|
|
|
42038
42105
|
yDomain
|
|
42039
42106
|
}) {
|
|
42040
42107
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
42041
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap w-full items-end gap-4 gap-y-1 mb-4", children: series.map((s) => {
|
|
42108
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap w-full items-end gap-4 gap-y-1 mb-4 ", children: series.map((s) => {
|
|
42042
42109
|
const aggregated = s.aggregate?.(data);
|
|
42043
42110
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "inline-flex items-baseline gap-2", children: [
|
|
42044
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 rounded-full translate-y-
|
|
42111
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "size-2 shrink-0 rounded-full -translate-y-px", style: { backgroundColor: s.color } }),
|
|
42045
42112
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-ui-sm text-neutral3 truncate max-w-24", children: s.label }),
|
|
42046
|
-
aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-
|
|
42113
|
+
aggregated && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-sm text-neutral4", children: [
|
|
42047
42114
|
aggregated.value,
|
|
42048
42115
|
aggregated.suffix && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-ui-sm text-neutral2", children: [
|
|
42049
42116
|
" ",
|
|
@@ -42053,7 +42120,15 @@ function MetricsLineChart({
|
|
|
42053
42120
|
] }, s.dataKey);
|
|
42054
42121
|
}) }),
|
|
42055
42122
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx(recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(recharts.LineChart, { data, children: [
|
|
42056
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
42123
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
42124
|
+
recharts.CartesianGrid,
|
|
42125
|
+
{
|
|
42126
|
+
stroke: "currentColor",
|
|
42127
|
+
strokeOpacity: 0.08,
|
|
42128
|
+
vertical: false,
|
|
42129
|
+
className: "text-black dark:text-white"
|
|
42130
|
+
}
|
|
42131
|
+
),
|
|
42057
42132
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
42058
42133
|
recharts.XAxis,
|
|
42059
42134
|
{
|
|
@@ -42164,24 +42239,25 @@ function useAvgScoreKpiMetrics() {
|
|
|
42164
42239
|
if (scorerIds.length === 0) {
|
|
42165
42240
|
return { value: null, previousValue: null, changePercent: null };
|
|
42166
42241
|
}
|
|
42167
|
-
const
|
|
42168
|
-
|
|
42242
|
+
const filters = {
|
|
42243
|
+
timestamp: { start: timestamp.start, end: timestamp.end }
|
|
42244
|
+
};
|
|
42245
|
+
const results = await Promise.all(
|
|
42246
|
+
scorerIds.map(async (scorerId) => {
|
|
42247
|
+
const [avg2, count] = await Promise.all([
|
|
42248
|
+
client.getScoreAggregate({ scorerId, aggregation: "avg", filters }),
|
|
42249
|
+
client.getScoreAggregate({ scorerId, aggregation: "count", filters })
|
|
42250
|
+
]);
|
|
42251
|
+
return { avg: avg2.value ?? 0, count: count.value ?? 0 };
|
|
42252
|
+
})
|
|
42169
42253
|
);
|
|
42170
|
-
const
|
|
42171
|
-
|
|
42172
|
-
const allScoreValues = [];
|
|
42173
|
-
for (const result of allResults) {
|
|
42174
|
-
for (const s of result?.scores ?? []) {
|
|
42175
|
-
const ts = new Date(s.createdAt).getTime();
|
|
42176
|
-
if (ts >= startMs && ts <= endMs) {
|
|
42177
|
-
allScoreValues.push(s.score);
|
|
42178
|
-
}
|
|
42179
|
-
}
|
|
42180
|
-
}
|
|
42181
|
-
if (allScoreValues.length === 0) {
|
|
42254
|
+
const withData = results.filter((r) => r.count > 0);
|
|
42255
|
+
if (withData.length === 0) {
|
|
42182
42256
|
return { value: null, previousValue: null, changePercent: null };
|
|
42183
42257
|
}
|
|
42184
|
-
const
|
|
42258
|
+
const totalCount = withData.reduce((sum, r) => sum + r.count, 0);
|
|
42259
|
+
const weightedSum = withData.reduce((sum, r) => sum + r.avg * r.count, 0);
|
|
42260
|
+
const avg = weightedSum / totalCount;
|
|
42185
42261
|
return { value: Math.round(avg * 100) / 100, previousValue: null, changePercent: null };
|
|
42186
42262
|
}
|
|
42187
42263
|
});
|
|
@@ -42460,78 +42536,84 @@ function useScoresMetrics() {
|
|
|
42460
42536
|
return reactQuery.useQuery({
|
|
42461
42537
|
queryKey: ["metrics", "scores-card", datePreset, customRange],
|
|
42462
42538
|
queryFn: async () => {
|
|
42539
|
+
const filters = {
|
|
42540
|
+
timestamp: { start: timestamp.start, end: timestamp.end }
|
|
42541
|
+
};
|
|
42463
42542
|
const scorersMap = await client.listScorers();
|
|
42464
42543
|
const scorerIds = Object.keys(scorersMap ?? {});
|
|
42465
42544
|
if (scorerIds.length === 0) {
|
|
42466
42545
|
return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
|
|
42467
42546
|
}
|
|
42468
|
-
const
|
|
42469
|
-
|
|
42470
|
-
|
|
42547
|
+
const summaryResults = await Promise.all(
|
|
42548
|
+
scorerIds.map(async (scorerId) => {
|
|
42549
|
+
const [avg, min, max, count] = await Promise.all([
|
|
42550
|
+
client.getScoreAggregate({ scorerId, aggregation: "avg", filters }),
|
|
42551
|
+
client.getScoreAggregate({ scorerId, aggregation: "min", filters }),
|
|
42552
|
+
client.getScoreAggregate({ scorerId, aggregation: "max", filters }),
|
|
42553
|
+
client.getScoreAggregate({ scorerId, aggregation: "count", filters })
|
|
42554
|
+
]);
|
|
42555
|
+
return {
|
|
42556
|
+
scorer: scorerId,
|
|
42557
|
+
avg: avg.value ?? 0,
|
|
42558
|
+
min: min.value ?? 0,
|
|
42559
|
+
max: max.value ?? 0,
|
|
42560
|
+
count: count.value ?? 0
|
|
42561
|
+
};
|
|
42562
|
+
})
|
|
42471
42563
|
);
|
|
42472
|
-
const
|
|
42473
|
-
const endMs = timestamp.end.getTime();
|
|
42474
|
-
const allScores = [];
|
|
42475
|
-
for (let i = 0; i < scorerIds.length; i++) {
|
|
42476
|
-
const scores = allResults[i]?.scores ?? [];
|
|
42477
|
-
for (const s of scores) {
|
|
42478
|
-
const ts = new Date(s.createdAt).getTime();
|
|
42479
|
-
if (ts >= startMs && ts <= endMs) {
|
|
42480
|
-
allScores.push({
|
|
42481
|
-
scorerId: scorerIds[i],
|
|
42482
|
-
score: s.score,
|
|
42483
|
-
createdAt: s.createdAt
|
|
42484
|
-
});
|
|
42485
|
-
}
|
|
42486
|
-
}
|
|
42487
|
-
}
|
|
42488
|
-
if (allScores.length === 0) {
|
|
42489
|
-
return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
|
|
42490
|
-
}
|
|
42491
|
-
const byScorer = /* @__PURE__ */ new Map();
|
|
42492
|
-
for (const s of allScores) {
|
|
42493
|
-
if (!byScorer.has(s.scorerId)) byScorer.set(s.scorerId, []);
|
|
42494
|
-
byScorer.get(s.scorerId).push(s.score);
|
|
42495
|
-
}
|
|
42496
|
-
const summaryData = Array.from(byScorer.entries()).map(([scorer, vals]) => ({
|
|
42497
|
-
scorer,
|
|
42498
|
-
avg: vals.reduce((a, b) => a + b, 0) / vals.length,
|
|
42499
|
-
min: Math.min(...vals),
|
|
42500
|
-
max: Math.max(...vals),
|
|
42501
|
-
count: vals.length
|
|
42502
|
-
}));
|
|
42564
|
+
const summaryData = summaryResults.filter((s) => s.count > 0);
|
|
42503
42565
|
const scorerNames = summaryData.map((s) => s.scorer);
|
|
42504
|
-
|
|
42505
|
-
|
|
42506
|
-
for (const s of allScores) {
|
|
42507
|
-
const ts = new Date(s.createdAt);
|
|
42508
|
-
const bucket = Math.floor(ts.getTime() / 36e5) * 36e5;
|
|
42509
|
-
if (!bucketMap.has(bucket)) bucketMap.set(bucket, /* @__PURE__ */ new Map());
|
|
42510
|
-
const scorerMap = bucketMap.get(bucket);
|
|
42511
|
-
if (!scorerMap.has(s.scorerId)) scorerMap.set(s.scorerId, []);
|
|
42512
|
-
scorerMap.get(s.scorerId).push(s.score);
|
|
42566
|
+
if (summaryData.length === 0) {
|
|
42567
|
+
return { summaryData: [], overTimeData: [], scorerNames: [], avgScore: null };
|
|
42513
42568
|
}
|
|
42514
|
-
const
|
|
42515
|
-
|
|
42516
|
-
|
|
42517
|
-
|
|
42518
|
-
|
|
42519
|
-
|
|
42569
|
+
const totalWeighted = summaryData.reduce((s, d) => s + d.avg * d.count, 0);
|
|
42570
|
+
const totalCount = summaryData.reduce((s, d) => s + d.count, 0);
|
|
42571
|
+
const avgScore = totalCount ? Math.round(totalWeighted / totalCount * 100) / 100 : 0;
|
|
42572
|
+
const interval = "1h";
|
|
42573
|
+
const timeSeriesResults = await Promise.all(
|
|
42574
|
+
scorerNames.map(
|
|
42575
|
+
(scorerId) => client.getScoreTimeSeries({
|
|
42576
|
+
scorerId,
|
|
42577
|
+
interval,
|
|
42578
|
+
aggregation: "avg",
|
|
42579
|
+
filters
|
|
42520
42580
|
})
|
|
42521
|
-
|
|
42522
|
-
|
|
42523
|
-
|
|
42524
|
-
|
|
42525
|
-
|
|
42581
|
+
)
|
|
42582
|
+
);
|
|
42583
|
+
const bucketMap = /* @__PURE__ */ new Map();
|
|
42584
|
+
const rangeSpansDays = timestamp.end.toDateString() !== timestamp.start.toDateString();
|
|
42585
|
+
for (let i = 0; i < scorerNames.length; i++) {
|
|
42586
|
+
const scorerId = scorerNames[i];
|
|
42587
|
+
const series = timeSeriesResults[i]?.series ?? [];
|
|
42588
|
+
for (const s of series) {
|
|
42589
|
+
for (const point of s.points) {
|
|
42590
|
+
const ts = new Date(point.timestamp);
|
|
42591
|
+
const key = ts.toISOString();
|
|
42592
|
+
if (!bucketMap.has(key)) {
|
|
42593
|
+
bucketMap.set(key, {
|
|
42594
|
+
time: rangeSpansDays ? ts.toLocaleString("en-US", {
|
|
42595
|
+
month: "short",
|
|
42596
|
+
day: "numeric",
|
|
42597
|
+
hour: "2-digit",
|
|
42598
|
+
minute: "2-digit",
|
|
42599
|
+
hour12: false
|
|
42600
|
+
}) : ts.toLocaleTimeString("en-US", {
|
|
42601
|
+
hour: "2-digit",
|
|
42602
|
+
minute: "2-digit",
|
|
42603
|
+
hour12: false
|
|
42604
|
+
})
|
|
42605
|
+
});
|
|
42606
|
+
}
|
|
42607
|
+
bucketMap.get(key)[scorerId] = +point.value.toFixed(2);
|
|
42526
42608
|
}
|
|
42527
42609
|
}
|
|
42528
|
-
|
|
42529
|
-
|
|
42610
|
+
}
|
|
42611
|
+
const overTimeData = Array.from(bucketMap.entries()).sort(([a], [b]) => a.localeCompare(b)).map(([, point]) => point);
|
|
42530
42612
|
return {
|
|
42531
42613
|
summaryData,
|
|
42532
42614
|
overTimeData,
|
|
42533
42615
|
scorerNames,
|
|
42534
|
-
avgScore
|
|
42616
|
+
avgScore
|
|
42535
42617
|
};
|
|
42536
42618
|
}
|
|
42537
42619
|
});
|
|
@@ -42576,7 +42658,7 @@ function ScoresCard() {
|
|
|
42576
42658
|
/* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "over-time", children: "Over Time" }),
|
|
42577
42659
|
/* @__PURE__ */ jsxRuntime.jsx(Tab, { value: "summary", children: "Summary" })
|
|
42578
42660
|
] }),
|
|
42579
|
-
/* @__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" }) }),
|
|
42661
|
+
/* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "over-time", className: "pb-0", 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" }) }),
|
|
42580
42662
|
/* @__PURE__ */ jsxRuntime.jsx(TabContent, { value: "summary", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
42581
42663
|
MetricsDataTable,
|
|
42582
42664
|
{
|
|
@@ -42714,7 +42796,7 @@ function HorizontalBars({
|
|
|
42714
42796
|
"div",
|
|
42715
42797
|
{
|
|
42716
42798
|
className: cn(
|
|
42717
|
-
"absolute inset-y-0",
|
|
42799
|
+
"absolute inset-y-0 opacity-40 dark:opacity-100",
|
|
42718
42800
|
si === 0 && "rounded-l",
|
|
42719
42801
|
isLastWithValue && "rounded-r"
|
|
42720
42802
|
),
|
|
@@ -42730,7 +42812,7 @@ function HorizontalBars({
|
|
|
42730
42812
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
42731
42813
|
"div",
|
|
42732
42814
|
{
|
|
42733
|
-
className: "absolute inset-y-0 left-0 rounded",
|
|
42815
|
+
className: "absolute inset-y-0 left-0 rounded opacity-40 dark:opacity-100",
|
|
42734
42816
|
style: { width: `${pct}%`, backgroundColor: seg.color }
|
|
42735
42817
|
},
|
|
42736
42818
|
seg.label
|
|
@@ -43826,6 +43908,9 @@ function SpanScoreList({
|
|
|
43826
43908
|
const score = scoresData?.scores?.find((s) => s?.id === scoreId);
|
|
43827
43909
|
setSelectedScore(score);
|
|
43828
43910
|
setDialogIsOpen(true);
|
|
43911
|
+
if (traceId) {
|
|
43912
|
+
navigate(`${computeTraceLink(traceId, spanId)}&tab=scores&scoreId=${encodeURIComponent(scoreId)}`);
|
|
43913
|
+
}
|
|
43829
43914
|
};
|
|
43830
43915
|
if (isLoadingScoresData) {
|
|
43831
43916
|
return /* @__PURE__ */ jsxRuntime.jsx(EntryListSkeleton, { columns: traceScoresListColumns });
|