@mastra/playground-ui 36.0.0 → 36.1.0-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 +24 -0
- package/dist/components/ScatterPlotChart.cjs.js +13 -0
- package/dist/components/ScatterPlotChart.cjs.js.map +1 -0
- package/dist/components/ScatterPlotChart.d.ts +2 -0
- package/dist/components/ScatterPlotChart.es.js +2 -0
- package/dist/components/ScatterPlotChart.es.js.map +1 -0
- package/dist/components/ThreadList.cjs.js +15 -0
- package/dist/components/ThreadList.cjs.js.map +1 -0
- package/dist/components/ThreadList.d.ts +2 -0
- package/dist/components/ThreadList.es.js +2 -0
- package/dist/components/ThreadList.es.js.map +1 -0
- package/dist/index.cjs.js +789 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +80 -1
- package/dist/index.es.js +764 -8
- package/dist/index.es.js.map +1 -1
- package/dist/scatter-plot-chart-BDRQ77OX.js +162 -0
- package/dist/scatter-plot-chart-BDRQ77OX.js.map +1 -0
- package/dist/scatter-plot-chart-MLvMlaxH.cjs +167 -0
- package/dist/scatter-plot-chart-MLvMlaxH.cjs.map +1 -0
- package/dist/src/domains/logs/hooks/use-logs.d.ts +5 -0
- package/dist/src/ds/components/ScatterPlotChart/index.d.ts +2 -0
- package/dist/src/ds/components/ScatterPlotChart/scatter-plot-chart-tooltip.d.ts +16 -0
- package/dist/src/ds/components/ScatterPlotChart/scatter-plot-chart.d.ts +24 -0
- package/dist/src/ds/components/ScatterPlotChart/scatter-plot-chart.stories.d.ts +11 -0
- package/dist/src/ds/components/ThreadList/index.d.ts +1 -0
- package/dist/src/ds/components/ThreadList/thread-list.d.ts +39 -0
- package/dist/src/ee/index.d.ts +2 -0
- package/dist/src/ee/signals/components/index.d.ts +2 -0
- package/dist/src/ee/signals/components/signal-details-page.d.ts +45 -0
- package/dist/src/ee/signals/components/signals-overview-page.d.ts +16 -0
- package/dist/src/ee/signals/index.d.ts +4 -0
- package/dist/src/ee/signals/signals-chart-data.d.ts +10 -0
- package/dist/src/ee/signals/signals-data.d.ts +2 -0
- package/dist/src/ee/signals/types.d.ts +13 -0
- package/dist/src/ee/topics/components/index.d.ts +6 -0
- package/dist/src/ee/topics/components/topic-trace-details-panel.d.ts +7 -0
- package/dist/src/ee/topics/components/topic-trace-summary-list.d.ts +8 -0
- package/dist/src/ee/topics/components/topics-layout.d.ts +7 -0
- package/dist/src/ee/topics/index.d.ts +3 -0
- package/dist/src/ee/topics/types.d.ts +40 -0
- package/dist/src/ee/topics/utils.d.ts +18 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/lib/query-utils.d.ts +10 -0
- package/dist/thread-list-CX4UNk2L.cjs +79 -0
- package/dist/thread-list-CX4UNk2L.cjs.map +1 -0
- package/dist/thread-list-CkgV4nYA.js +72 -0
- package/dist/thread-list-CkgV4nYA.js.map +1 -0
- package/package.json +6 -6
package/dist/index.cjs.js
CHANGED
|
@@ -63,6 +63,7 @@ const themeProvider = require('./theme-provider-aO5-jZVp.cjs');
|
|
|
63
63
|
const themeToggle = require('./theme-toggle-DWtjTo-a.cjs');
|
|
64
64
|
const tooltip = require('./tooltip-j8gUR1Qk.cjs');
|
|
65
65
|
const truncate = require('./truncate-Csk5KmAy.cjs');
|
|
66
|
+
const threadList = require('./thread-list-CX4UNk2L.cjs');
|
|
66
67
|
const buttonsGroup = require('./buttons-group-BvLg2kpv.cjs');
|
|
67
68
|
const mainContent = require('./main-content-CnmMWNin.cjs');
|
|
68
69
|
const mainHeader = require('./main-header-DJLRceP9.cjs');
|
|
@@ -105,6 +106,7 @@ const dateTimeRangePicker = require('./date-time-range-picker-DjcVeD-Z.cjs');
|
|
|
105
106
|
const horizontalBars = require('./horizontal-bars-uPFpgihX.cjs');
|
|
106
107
|
const metricsDataTable = require('./metrics-data-table-AjAA-dqH.cjs');
|
|
107
108
|
const metricsLineChart = require('./metrics-line-chart-D1ZGVepo.cjs');
|
|
109
|
+
const scatterPlotChart = require('./scatter-plot-chart-MLvMlaxH.cjs');
|
|
108
110
|
const StatusBadge = require('./StatusBadge-DKtfODhH.cjs');
|
|
109
111
|
const tokens = require('./tokens.cjs.js');
|
|
110
112
|
const spacings = require('./spacings-BP8L49kn.cjs');
|
|
@@ -1553,6 +1555,12 @@ function isBranchesNotSupportedError(error) {
|
|
|
1553
1555
|
if (typeof message !== "string") return false;
|
|
1554
1556
|
return message.includes("does not support listing trace branches");
|
|
1555
1557
|
}
|
|
1558
|
+
function isUnsupportedObservabilityOperationError(error, operation) {
|
|
1559
|
+
if (!error || typeof error !== "object" || !("message" in error)) return false;
|
|
1560
|
+
const message = error.message;
|
|
1561
|
+
if (typeof message !== "string") return false;
|
|
1562
|
+
return message.includes(`does not support listing ${operation}`);
|
|
1563
|
+
}
|
|
1556
1564
|
function isNonRetryableError(error) {
|
|
1557
1565
|
if (!error || typeof error !== "object") return false;
|
|
1558
1566
|
if ("status" in error) {
|
|
@@ -7865,6 +7873,16 @@ function LogDetailsView({
|
|
|
7865
7873
|
function LogsErrorContent({ error, resource, errorTitle }) {
|
|
7866
7874
|
if (is401UnauthorizedError(error)) return /* @__PURE__ */ jsxRuntime.jsx(SessionExpired.SessionExpired, {});
|
|
7867
7875
|
if (is403ForbiddenError(error)) return /* @__PURE__ */ jsxRuntime.jsx(PermissionDenied.PermissionDenied, { resource });
|
|
7876
|
+
if (isUnsupportedObservabilityOperationError(error, "logs")) {
|
|
7877
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7878
|
+
EmptyState.EmptyState,
|
|
7879
|
+
{
|
|
7880
|
+
iconSlot: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CircleSlashIcon, {}),
|
|
7881
|
+
titleSlot: "Logs are not available with your current storage",
|
|
7882
|
+
descriptionSlot: "The configured observability storage provider does not support listing logs. Switch to a storage provider with logs support to view runtime logs in Studio."
|
|
7883
|
+
}
|
|
7884
|
+
);
|
|
7885
|
+
}
|
|
7868
7886
|
const message = error instanceof Error ? error.message : void 0;
|
|
7869
7887
|
return /* @__PURE__ */ jsxRuntime.jsx(ErrorState.ErrorState, { title: errorTitle, message: message ?? "Unknown error" });
|
|
7870
7888
|
}
|
|
@@ -8092,6 +8110,7 @@ const NoLogsInfo = ({ datePreset, dateFrom, dateTo } = {}) => {
|
|
|
8092
8110
|
};
|
|
8093
8111
|
|
|
8094
8112
|
const LOGS_PER_PAGE = 20;
|
|
8113
|
+
const LOGS_REFETCH_INTERVAL_MS = 1e4;
|
|
8095
8114
|
function getNextPageParam(lastPage, _allPages, lastPageParam) {
|
|
8096
8115
|
if (lastPage?.pagination?.hasMore) {
|
|
8097
8116
|
return lastPageParam + 1;
|
|
@@ -8111,6 +8130,12 @@ function selectLogs(data) {
|
|
|
8111
8130
|
}
|
|
8112
8131
|
return result;
|
|
8113
8132
|
}
|
|
8133
|
+
function getLogsRefetchInterval(query) {
|
|
8134
|
+
if (isUnsupportedObservabilityOperationError(query.state.error, "logs")) {
|
|
8135
|
+
return false;
|
|
8136
|
+
}
|
|
8137
|
+
return LOGS_REFETCH_INTERVAL_MS;
|
|
8138
|
+
}
|
|
8114
8139
|
const useLogs = ({ filters } = {}) => {
|
|
8115
8140
|
const client = react.useMastraClient();
|
|
8116
8141
|
const { inView: isEndOfListInView, setRef: setEndOfListElement } = hooks_useInView.useInView();
|
|
@@ -8125,7 +8150,7 @@ const useLogs = ({ filters } = {}) => {
|
|
|
8125
8150
|
getNextPageParam,
|
|
8126
8151
|
select: selectLogs,
|
|
8127
8152
|
retry: false,
|
|
8128
|
-
refetchInterval:
|
|
8153
|
+
refetchInterval: getLogsRefetchInterval
|
|
8129
8154
|
});
|
|
8130
8155
|
const { hasNextPage, isFetchingNextPage, fetchNextPage, data, isLoading, isError, error } = query;
|
|
8131
8156
|
React.useEffect(() => {
|
|
@@ -8441,6 +8466,735 @@ function useLogsListNavigation(logs, featuredLogId, onFeaturedChange, featuredTr
|
|
|
8441
8466
|
};
|
|
8442
8467
|
}
|
|
8443
8468
|
|
|
8469
|
+
function TopicsLayout({ sidebar, children, tracePanel, contentPadding = true }) {
|
|
8470
|
+
const hasContent = Boolean(children || tracePanel);
|
|
8471
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-0 bg-surface2 text-neutral4", children: [
|
|
8472
|
+
sidebar ? /* @__PURE__ */ jsxRuntime.jsx("aside", { className: "min-h-0 w-[22rem] shrink-0 border-r border-border1", children: sidebar }) : null,
|
|
8473
|
+
hasContent ? /* @__PURE__ */ jsxRuntime.jsx("main", { className: contentPadding ? "min-w-0 flex-1 p-4" : "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsxs(reactResizablePanels.Group, { className: "h-full min-h-0 w-full min-w-0", direction: "horizontal", children: [
|
|
8474
|
+
children ? /* @__PURE__ */ jsxRuntime.jsx(reactResizablePanels.Panel, { id: "topic-main", className: "min-w-0 pr-2", minSize: 35, children }) : null,
|
|
8475
|
+
tracePanel ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8476
|
+
children ? /* @__PURE__ */ jsxRuntime.jsx(PanelSeparator, {}) : null,
|
|
8477
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8478
|
+
CollapsiblePanel,
|
|
8479
|
+
{
|
|
8480
|
+
direction: "right",
|
|
8481
|
+
id: "topic-trace-details",
|
|
8482
|
+
minSize: 300,
|
|
8483
|
+
maxSize: "70%",
|
|
8484
|
+
defaultSize: children ? "40%" : "100%",
|
|
8485
|
+
collapsedSize: 60,
|
|
8486
|
+
collapsible: true,
|
|
8487
|
+
className: "min-w-0 pl-2",
|
|
8488
|
+
children: tracePanel
|
|
8489
|
+
}
|
|
8490
|
+
)
|
|
8491
|
+
] }) : null
|
|
8492
|
+
] }) }) : null
|
|
8493
|
+
] });
|
|
8494
|
+
}
|
|
8495
|
+
|
|
8496
|
+
const TOPIC_COLORS = ["#7C3AED", "#2563EB", "#0891B2", "#059669", "#CA8A04", "#EA580C", "#DC2626", "#DB2777"];
|
|
8497
|
+
function hashString(value) {
|
|
8498
|
+
let hash = 0;
|
|
8499
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
8500
|
+
hash = (hash << 5) - hash + value.charCodeAt(index);
|
|
8501
|
+
hash |= 0;
|
|
8502
|
+
}
|
|
8503
|
+
return Math.abs(hash);
|
|
8504
|
+
}
|
|
8505
|
+
function getTopicColor(id) {
|
|
8506
|
+
return TOPIC_COLORS[hashString(id) % TOPIC_COLORS.length];
|
|
8507
|
+
}
|
|
8508
|
+
function getTraceCount(subtopic) {
|
|
8509
|
+
return subtopic.traceSummaries.length;
|
|
8510
|
+
}
|
|
8511
|
+
function getTopicTraceCount(topic) {
|
|
8512
|
+
return topic.subtopics.reduce((total, subtopic) => total + getTraceCount(subtopic), 0);
|
|
8513
|
+
}
|
|
8514
|
+
function getTraceShare$1(count, total) {
|
|
8515
|
+
return {
|
|
8516
|
+
count,
|
|
8517
|
+
total,
|
|
8518
|
+
percentage: total > 0 ? Math.round(count / total * 100) : 0
|
|
8519
|
+
};
|
|
8520
|
+
}
|
|
8521
|
+
function aggregateTopics(topics) {
|
|
8522
|
+
const totalTraceCount = topics.reduce((total, topic) => total + getTopicTraceCount(topic), 0);
|
|
8523
|
+
return topics.map((topic) => ({
|
|
8524
|
+
...topic,
|
|
8525
|
+
color: topic.color ?? getTopicColor(topic.id),
|
|
8526
|
+
traceCount: getTopicTraceCount(topic),
|
|
8527
|
+
subtopics: topic.subtopics.map((subtopic) => {
|
|
8528
|
+
const traceCount = getTraceCount(subtopic);
|
|
8529
|
+
return {
|
|
8530
|
+
...subtopic,
|
|
8531
|
+
color: subtopic.color ?? topic.color ?? getTopicColor(subtopic.id),
|
|
8532
|
+
traceCount,
|
|
8533
|
+
traceShare: getTraceShare$1(traceCount, totalTraceCount)
|
|
8534
|
+
};
|
|
8535
|
+
})
|
|
8536
|
+
}));
|
|
8537
|
+
}
|
|
8538
|
+
function toTime(value) {
|
|
8539
|
+
if (!value) return 0;
|
|
8540
|
+
const time = value instanceof Date ? value.getTime() : new Date(value).getTime();
|
|
8541
|
+
return Number.isNaN(time) ? 0 : time;
|
|
8542
|
+
}
|
|
8543
|
+
function filterTraceSummaries(traces, search) {
|
|
8544
|
+
const normalizedSearch = search.trim().toLowerCase();
|
|
8545
|
+
if (!normalizedSearch) return traces;
|
|
8546
|
+
return traces.filter(
|
|
8547
|
+
(trace) => [trace.id, trace.name, trace.entityName, trace.status].some(
|
|
8548
|
+
(value) => value?.toLowerCase().includes(normalizedSearch)
|
|
8549
|
+
)
|
|
8550
|
+
);
|
|
8551
|
+
}
|
|
8552
|
+
function sortTraceSummaries(traces, sort) {
|
|
8553
|
+
return traces.toSorted((left, right) => {
|
|
8554
|
+
switch (sort) {
|
|
8555
|
+
case "oldest":
|
|
8556
|
+
return toTime(left.startedAt) - toTime(right.startedAt);
|
|
8557
|
+
case "duration-desc":
|
|
8558
|
+
return (right.durationMs ?? 0) - (left.durationMs ?? 0);
|
|
8559
|
+
case "duration-asc":
|
|
8560
|
+
return (left.durationMs ?? 0) - (right.durationMs ?? 0);
|
|
8561
|
+
case "newest":
|
|
8562
|
+
default:
|
|
8563
|
+
return toTime(right.startedAt) - toTime(left.startedAt);
|
|
8564
|
+
}
|
|
8565
|
+
});
|
|
8566
|
+
}
|
|
8567
|
+
function getVisibleTraceSummaries(traces, options) {
|
|
8568
|
+
const filtered = filterTraceSummaries(traces, options.search);
|
|
8569
|
+
const sorted = sortTraceSummaries(filtered, options.sort);
|
|
8570
|
+
const end = options.page * options.pageSize;
|
|
8571
|
+
return {
|
|
8572
|
+
traces: sorted.slice(0, end),
|
|
8573
|
+
total: sorted.length,
|
|
8574
|
+
hasMore: end < sorted.length
|
|
8575
|
+
};
|
|
8576
|
+
}
|
|
8577
|
+
|
|
8578
|
+
function TopicTraceSummaryList({
|
|
8579
|
+
traces,
|
|
8580
|
+
selectedTraceId,
|
|
8581
|
+
onTraceSelect,
|
|
8582
|
+
pageSize = 25
|
|
8583
|
+
}) {
|
|
8584
|
+
const [search, setSearch] = React.useState("");
|
|
8585
|
+
const [page, setPage] = React.useState(1);
|
|
8586
|
+
const visible = React.useMemo(
|
|
8587
|
+
() => getVisibleTraceSummaries(traces, { search, sort: "newest", page, pageSize }),
|
|
8588
|
+
[page, pageSize, search, traces]
|
|
8589
|
+
);
|
|
8590
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex min-h-0 flex-1 flex-col gap-4", "aria-label": "Topic trace summaries", children: [
|
|
8591
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8592
|
+
searchbar.Searchbar,
|
|
8593
|
+
{
|
|
8594
|
+
label: "Search traces",
|
|
8595
|
+
placeholder: "Search traces",
|
|
8596
|
+
onSearch: (value) => {
|
|
8597
|
+
setSearch(value);
|
|
8598
|
+
setPage(1);
|
|
8599
|
+
}
|
|
8600
|
+
}
|
|
8601
|
+
),
|
|
8602
|
+
/* @__PURE__ */ jsxRuntime.jsxs(tracesDataList.DataList, { columns: "minmax(12rem,1fr)", className: "min-h-0 flex-1", children: [
|
|
8603
|
+
/* @__PURE__ */ jsxRuntime.jsx(tracesDataList.DataList.Top, { children: /* @__PURE__ */ jsxRuntime.jsx(tracesDataList.DataList.TopCells, { children: /* @__PURE__ */ jsxRuntime.jsx(tracesDataList.DataList.TopCell, { children: "Trace summary" }) }) }),
|
|
8604
|
+
visible.traces.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(tracesDataList.DataList.NoMatch, { message: "No traces match this subtopic." }) : visible.traces.map((trace) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
8605
|
+
tracesDataList.DataList.RowButton,
|
|
8606
|
+
{
|
|
8607
|
+
featured: selectedTraceId === trace.id,
|
|
8608
|
+
onClick: () => onTraceSelect(trace),
|
|
8609
|
+
"aria-pressed": selectedTraceId === trace.id,
|
|
8610
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(tracesDataList.DataList.TextCell, { children: trace.name ?? trace.id })
|
|
8611
|
+
},
|
|
8612
|
+
trace.id
|
|
8613
|
+
))
|
|
8614
|
+
] }),
|
|
8615
|
+
visible.hasMore ? /* @__PURE__ */ jsxRuntime.jsxs(Button.Button, { variant: "outline", size: "sm", onClick: () => setPage((currentPage) => currentPage + 1), children: [
|
|
8616
|
+
"Load more traces (",
|
|
8617
|
+
visible.traces.length,
|
|
8618
|
+
" of ",
|
|
8619
|
+
visible.total,
|
|
8620
|
+
")"
|
|
8621
|
+
] }) : null
|
|
8622
|
+
] });
|
|
8623
|
+
}
|
|
8624
|
+
|
|
8625
|
+
function TopicTraceDetailsPanel({
|
|
8626
|
+
traceId,
|
|
8627
|
+
selectedSpanId,
|
|
8628
|
+
onSpanSelect,
|
|
8629
|
+
onClose
|
|
8630
|
+
}) {
|
|
8631
|
+
const traceSpans = useTraceLightSpans(traceId);
|
|
8632
|
+
const spanDetail = useSpanDetail(traceId, selectedSpanId);
|
|
8633
|
+
const { handlePreviousSpan, handleNextSpan } = useTraceSpanNavigation(
|
|
8634
|
+
traceSpans.data?.spans,
|
|
8635
|
+
selectedSpanId,
|
|
8636
|
+
(spanId) => onSpanSelect?.(spanId)
|
|
8637
|
+
);
|
|
8638
|
+
if (!traceId) return null;
|
|
8639
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8640
|
+
"div",
|
|
8641
|
+
{
|
|
8642
|
+
className: utils.cn(
|
|
8643
|
+
"grid h-full min-h-0 overflow-auto",
|
|
8644
|
+
selectedSpanId ? "grid-rows-[minmax(0,1fr)_minmax(0,1fr)] gap-4" : "grid-rows-[minmax(0,1fr)]"
|
|
8645
|
+
),
|
|
8646
|
+
children: [
|
|
8647
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8648
|
+
TraceDetailsView,
|
|
8649
|
+
{
|
|
8650
|
+
traceId,
|
|
8651
|
+
spans: traceSpans.data?.spans,
|
|
8652
|
+
isLoading: traceSpans.isLoading,
|
|
8653
|
+
selectedSpanId,
|
|
8654
|
+
onSpanSelect,
|
|
8655
|
+
onClose
|
|
8656
|
+
}
|
|
8657
|
+
),
|
|
8658
|
+
selectedSpanId ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
8659
|
+
SpanDataPanelView,
|
|
8660
|
+
{
|
|
8661
|
+
traceId,
|
|
8662
|
+
spanId: selectedSpanId,
|
|
8663
|
+
span: spanDetail.data?.span,
|
|
8664
|
+
isLoading: spanDetail.isLoading,
|
|
8665
|
+
onClose: () => onSpanSelect?.(void 0),
|
|
8666
|
+
onPrevious: handlePreviousSpan,
|
|
8667
|
+
onNext: handleNextSpan
|
|
8668
|
+
}
|
|
8669
|
+
) : null
|
|
8670
|
+
]
|
|
8671
|
+
}
|
|
8672
|
+
);
|
|
8673
|
+
}
|
|
8674
|
+
|
|
8675
|
+
const SIGNAL_CHART_CLUSTERS = [
|
|
8676
|
+
{ label: "Fast paths", count: 27, duration: 120, spans: 5 },
|
|
8677
|
+
{ label: "Standard paths", count: 27, duration: 620, spans: 14 },
|
|
8678
|
+
{ label: "Complex paths", count: 26, duration: 1280, spans: 28 }
|
|
8679
|
+
];
|
|
8680
|
+
function getSignalChartData(clusters) {
|
|
8681
|
+
return clusters.flatMap(
|
|
8682
|
+
(cluster, clusterIndex) => SIGNAL_CHART_CLUSTERS.flatMap(
|
|
8683
|
+
(path) => Array.from({ length: path.count }, (_, index) => {
|
|
8684
|
+
const offset = index - (path.count - 1) / 2;
|
|
8685
|
+
const durationJitter = (index * 37 + clusterIndex * 19) % 90 - 45;
|
|
8686
|
+
const durationScatter = Math.sin((index + 1 + clusterIndex) * 1.7) * 34 + Math.cos((index + 3) * 0.9) * 21;
|
|
8687
|
+
const spanJitter = (index * 11 + clusterIndex * 3) % 7 - 3;
|
|
8688
|
+
return {
|
|
8689
|
+
id: `${cluster.id}-${path.label.toLowerCase().replaceAll(" ", "-")}-${index + 1}`,
|
|
8690
|
+
name: `${cluster.name} · ${path.label} ${index + 1}`,
|
|
8691
|
+
cluster: path.label,
|
|
8692
|
+
duration: Math.max(0, Math.round(path.duration + offset * 8 + durationJitter + durationScatter)),
|
|
8693
|
+
spans: Math.max(1, path.spans + spanJitter),
|
|
8694
|
+
color: stringToColor(`${cluster.name}-${path.label}`)
|
|
8695
|
+
};
|
|
8696
|
+
})
|
|
8697
|
+
)
|
|
8698
|
+
);
|
|
8699
|
+
}
|
|
8700
|
+
|
|
8701
|
+
const signals = [
|
|
8702
|
+
{
|
|
8703
|
+
id: "tasks",
|
|
8704
|
+
name: "Tasks",
|
|
8705
|
+
description: "Operational work patterns inferred from agent traces and user requests.",
|
|
8706
|
+
clusters: [
|
|
8707
|
+
{
|
|
8708
|
+
id: "refunds",
|
|
8709
|
+
name: "Refunds",
|
|
8710
|
+
description: "Refund requests, policy checks, and payment reversals.",
|
|
8711
|
+
traceSummaries: [
|
|
8712
|
+
{
|
|
8713
|
+
id: "trace-refund-1",
|
|
8714
|
+
name: "Refund eligibility check",
|
|
8715
|
+
status: "success",
|
|
8716
|
+
startedAt: "2026-06-15T10:00:00.000Z",
|
|
8717
|
+
durationMs: 1240,
|
|
8718
|
+
entityName: "support-agent",
|
|
8719
|
+
spanCount: 8
|
|
8720
|
+
},
|
|
8721
|
+
{
|
|
8722
|
+
id: "trace-refund-2",
|
|
8723
|
+
name: "Refund escalation",
|
|
8724
|
+
status: "error",
|
|
8725
|
+
startedAt: "2026-06-15T09:40:00.000Z",
|
|
8726
|
+
durationMs: 3180,
|
|
8727
|
+
entityName: "support-agent",
|
|
8728
|
+
spanCount: 12
|
|
8729
|
+
}
|
|
8730
|
+
]
|
|
8731
|
+
},
|
|
8732
|
+
{
|
|
8733
|
+
id: "shipping",
|
|
8734
|
+
name: "Shipping",
|
|
8735
|
+
description: "Shipment lookup, carrier updates, and delivery exceptions.",
|
|
8736
|
+
traceSummaries: [
|
|
8737
|
+
{
|
|
8738
|
+
id: "trace-shipping-1",
|
|
8739
|
+
name: "Track delayed package",
|
|
8740
|
+
status: "success",
|
|
8741
|
+
startedAt: "2026-06-15T08:30:00.000Z",
|
|
8742
|
+
durationMs: 980,
|
|
8743
|
+
entityName: "support-agent",
|
|
8744
|
+
spanCount: 6
|
|
8745
|
+
}
|
|
8746
|
+
]
|
|
8747
|
+
},
|
|
8748
|
+
{
|
|
8749
|
+
id: "account-updates",
|
|
8750
|
+
name: "Account updates",
|
|
8751
|
+
description: "Profile edits, plan changes, and account recovery requests.",
|
|
8752
|
+
traceSummaries: [
|
|
8753
|
+
{
|
|
8754
|
+
id: "trace-account-1",
|
|
8755
|
+
name: "Update billing contact",
|
|
8756
|
+
status: "success",
|
|
8757
|
+
startedAt: "2026-06-15T07:45:00.000Z",
|
|
8758
|
+
durationMs: 1420,
|
|
8759
|
+
entityName: "support-agent",
|
|
8760
|
+
spanCount: 7
|
|
8761
|
+
},
|
|
8762
|
+
{
|
|
8763
|
+
id: "trace-account-2",
|
|
8764
|
+
name: "Recover locked account",
|
|
8765
|
+
status: "success",
|
|
8766
|
+
startedAt: "2026-06-15T07:10:00.000Z",
|
|
8767
|
+
durationMs: 2640,
|
|
8768
|
+
entityName: "support-agent",
|
|
8769
|
+
spanCount: 11
|
|
8770
|
+
}
|
|
8771
|
+
]
|
|
8772
|
+
},
|
|
8773
|
+
{
|
|
8774
|
+
id: "subscription-changes",
|
|
8775
|
+
name: "Subscription changes",
|
|
8776
|
+
description: "Upgrade, downgrade, pause, and renewal intent across plans.",
|
|
8777
|
+
traceSummaries: [
|
|
8778
|
+
{
|
|
8779
|
+
id: "trace-subscription-1",
|
|
8780
|
+
name: "Downgrade plan request",
|
|
8781
|
+
status: "success",
|
|
8782
|
+
startedAt: "2026-06-15T06:50:00.000Z",
|
|
8783
|
+
durationMs: 1880,
|
|
8784
|
+
entityName: "support-agent",
|
|
8785
|
+
spanCount: 9
|
|
8786
|
+
}
|
|
8787
|
+
]
|
|
8788
|
+
}
|
|
8789
|
+
]
|
|
8790
|
+
},
|
|
8791
|
+
{
|
|
8792
|
+
id: "sentiment",
|
|
8793
|
+
name: "Sentiment",
|
|
8794
|
+
description: "Conversation tone and confidence shifts that affect user outcomes.",
|
|
8795
|
+
clusters: [
|
|
8796
|
+
{
|
|
8797
|
+
id: "negative-feedback",
|
|
8798
|
+
name: "Negative feedback",
|
|
8799
|
+
description: "Escalations, frustration signals, and unresolved customer intent.",
|
|
8800
|
+
traceSummaries: [
|
|
8801
|
+
{
|
|
8802
|
+
id: "trace-sentiment-1",
|
|
8803
|
+
name: "De-escalate frustrated customer",
|
|
8804
|
+
status: "success",
|
|
8805
|
+
startedAt: "2026-06-15T12:30:00.000Z",
|
|
8806
|
+
durationMs: 2150,
|
|
8807
|
+
entityName: "support-agent",
|
|
8808
|
+
spanCount: 10
|
|
8809
|
+
}
|
|
8810
|
+
]
|
|
8811
|
+
},
|
|
8812
|
+
{
|
|
8813
|
+
id: "positive-feedback",
|
|
8814
|
+
name: "Positive feedback",
|
|
8815
|
+
description: "Gratitude, satisfaction, and confirmation that the user outcome was met.",
|
|
8816
|
+
traceSummaries: [
|
|
8817
|
+
{
|
|
8818
|
+
id: "trace-sentiment-2",
|
|
8819
|
+
name: "Capture satisfied customer outcome",
|
|
8820
|
+
status: "success",
|
|
8821
|
+
startedAt: "2026-06-15T12:05:00.000Z",
|
|
8822
|
+
durationMs: 1320,
|
|
8823
|
+
entityName: "support-agent",
|
|
8824
|
+
spanCount: 5
|
|
8825
|
+
}
|
|
8826
|
+
]
|
|
8827
|
+
},
|
|
8828
|
+
{
|
|
8829
|
+
id: "uncertain-feedback",
|
|
8830
|
+
name: "Uncertain feedback",
|
|
8831
|
+
description: "Ambiguous responses where sentiment or next best action needs clarification.",
|
|
8832
|
+
traceSummaries: [
|
|
8833
|
+
{
|
|
8834
|
+
id: "trace-sentiment-3",
|
|
8835
|
+
name: "Clarify ambiguous response",
|
|
8836
|
+
status: "running",
|
|
8837
|
+
startedAt: "2026-06-15T11:35:00.000Z",
|
|
8838
|
+
durationMs: 1760,
|
|
8839
|
+
entityName: "support-agent",
|
|
8840
|
+
spanCount: 8
|
|
8841
|
+
}
|
|
8842
|
+
]
|
|
8843
|
+
}
|
|
8844
|
+
]
|
|
8845
|
+
},
|
|
8846
|
+
{
|
|
8847
|
+
id: "issue",
|
|
8848
|
+
name: "Issue",
|
|
8849
|
+
description: "Recurring issue families found across support, research, and workflow traces.",
|
|
8850
|
+
clusters: [
|
|
8851
|
+
{
|
|
8852
|
+
id: "revenue-analysis",
|
|
8853
|
+
name: "Revenue analysis",
|
|
8854
|
+
description: "Revenue-impacting requests, market scans, and financial summaries.",
|
|
8855
|
+
traceSummaries: [
|
|
8856
|
+
{
|
|
8857
|
+
id: "trace-revenue-1",
|
|
8858
|
+
name: "Summarize revenue movement",
|
|
8859
|
+
status: "running",
|
|
8860
|
+
startedAt: "2026-06-15T11:05:00.000Z",
|
|
8861
|
+
durationMs: 4520,
|
|
8862
|
+
entityName: "research-agent",
|
|
8863
|
+
spanCount: 15
|
|
8864
|
+
}
|
|
8865
|
+
]
|
|
8866
|
+
}
|
|
8867
|
+
]
|
|
8868
|
+
},
|
|
8869
|
+
{
|
|
8870
|
+
id: "severity",
|
|
8871
|
+
name: "Severity",
|
|
8872
|
+
description: "Risk and urgency bands inferred from trace paths and intervention needs.",
|
|
8873
|
+
clusters: [
|
|
8874
|
+
{
|
|
8875
|
+
id: "urgent-escalations",
|
|
8876
|
+
name: "Urgent escalations",
|
|
8877
|
+
description: "High-priority paths that require faster handoff or deeper inspection.",
|
|
8878
|
+
traceSummaries: [
|
|
8879
|
+
{
|
|
8880
|
+
id: "trace-severity-1",
|
|
8881
|
+
name: "Escalate urgent account issue",
|
|
8882
|
+
status: "error",
|
|
8883
|
+
startedAt: "2026-06-15T13:10:00.000Z",
|
|
8884
|
+
durationMs: 3880,
|
|
8885
|
+
entityName: "support-agent",
|
|
8886
|
+
spanCount: 18
|
|
8887
|
+
}
|
|
8888
|
+
]
|
|
8889
|
+
}
|
|
8890
|
+
]
|
|
8891
|
+
}
|
|
8892
|
+
];
|
|
8893
|
+
|
|
8894
|
+
const SignalTraceSummaryList = TopicTraceSummaryList;
|
|
8895
|
+
const SignalTraceDetailsPanel = TopicTraceDetailsPanel;
|
|
8896
|
+
const SignalsLayout = TopicsLayout;
|
|
8897
|
+
function findClusterByTraceId(signal, traceId) {
|
|
8898
|
+
if (!signal || !traceId) return void 0;
|
|
8899
|
+
return signal.clusters.find((cluster) => cluster.traceSummaries.some((trace) => trace.id === traceId));
|
|
8900
|
+
}
|
|
8901
|
+
function getSignalName(signalId) {
|
|
8902
|
+
return signals.find((signal) => signal.id === signalId)?.name ?? signalId;
|
|
8903
|
+
}
|
|
8904
|
+
function SignalClusterSidebar({
|
|
8905
|
+
signal,
|
|
8906
|
+
selectedClusterIds,
|
|
8907
|
+
onClusterSelect,
|
|
8908
|
+
multiple = false,
|
|
8909
|
+
ariaLabel = "Signal clusters"
|
|
8910
|
+
}) {
|
|
8911
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8912
|
+
"aside",
|
|
8913
|
+
{
|
|
8914
|
+
className: "min-h-0 w-72 shrink-0 overflow-y-auto border-r border-border1/60 pr-4 py-4",
|
|
8915
|
+
"aria-label": ariaLabel,
|
|
8916
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "space-y-1", role: multiple ? "group" : void 0, children: signal.clusters.map((cluster) => {
|
|
8917
|
+
const selected = selectedClusterIds.includes(cluster.id);
|
|
8918
|
+
return /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8919
|
+
"button",
|
|
8920
|
+
{
|
|
8921
|
+
type: "button",
|
|
8922
|
+
role: multiple ? "checkbox" : void 0,
|
|
8923
|
+
"aria-checked": multiple ? selected : void 0,
|
|
8924
|
+
"aria-pressed": multiple ? void 0 : selected,
|
|
8925
|
+
className: "group cursor-pointer w-full rounded-xl px-3 py-2 text-left transition-colors hover:bg-surface3 aria-pressed:bg-surface3 aria-checked:bg-surface3 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent1",
|
|
8926
|
+
onClick: () => onClusterSelect(cluster.id),
|
|
8927
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-start gap-2", children: [
|
|
8928
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8929
|
+
"span",
|
|
8930
|
+
{
|
|
8931
|
+
className: utils.cn("mt-1.5 h-2 w-2 shrink-0 rounded-full", multiple && !selected && "invisible"),
|
|
8932
|
+
style: { backgroundColor: stringToColor(cluster.name) }
|
|
8933
|
+
}
|
|
8934
|
+
),
|
|
8935
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 space-y-1", children: [
|
|
8936
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8937
|
+
"span",
|
|
8938
|
+
{
|
|
8939
|
+
className: utils.cn(
|
|
8940
|
+
"block text-sm font-medium",
|
|
8941
|
+
multiple && !selected ? "text-neutral3" : "text-neutral5"
|
|
8942
|
+
),
|
|
8943
|
+
children: cluster.name
|
|
8944
|
+
}
|
|
8945
|
+
),
|
|
8946
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8947
|
+
"span",
|
|
8948
|
+
{
|
|
8949
|
+
className: utils.cn(
|
|
8950
|
+
"line-clamp-2 block text-sm",
|
|
8951
|
+
multiple && !selected ? "text-neutral1" : "text-neutral2"
|
|
8952
|
+
),
|
|
8953
|
+
children: cluster.description
|
|
8954
|
+
}
|
|
8955
|
+
)
|
|
8956
|
+
] })
|
|
8957
|
+
] })
|
|
8958
|
+
}
|
|
8959
|
+
) }, cluster.id);
|
|
8960
|
+
}) })
|
|
8961
|
+
}
|
|
8962
|
+
);
|
|
8963
|
+
}
|
|
8964
|
+
function SignalTraceListTab({
|
|
8965
|
+
cluster,
|
|
8966
|
+
selectedTraceId,
|
|
8967
|
+
onTraceSelect
|
|
8968
|
+
}) {
|
|
8969
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8970
|
+
SignalTraceSummaryList,
|
|
8971
|
+
{
|
|
8972
|
+
traces: cluster.traceSummaries,
|
|
8973
|
+
selectedTraceId,
|
|
8974
|
+
onTraceSelect
|
|
8975
|
+
}
|
|
8976
|
+
);
|
|
8977
|
+
}
|
|
8978
|
+
function SignalChartTab({ signal, selectedClusterIds, onClusterToggle }) {
|
|
8979
|
+
const selectedClusters = React.useMemo(
|
|
8980
|
+
() => signal.clusters.filter((cluster) => selectedClusterIds.includes(cluster.id)),
|
|
8981
|
+
[signal.clusters, selectedClusterIds]
|
|
8982
|
+
);
|
|
8983
|
+
const chartData = React.useMemo(() => getSignalChartData(selectedClusters), [selectedClusters]);
|
|
8984
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-w-0 gap-6", children: [
|
|
8985
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8986
|
+
SignalClusterSidebar,
|
|
8987
|
+
{
|
|
8988
|
+
signal,
|
|
8989
|
+
selectedClusterIds,
|
|
8990
|
+
onClusterSelect: onClusterToggle,
|
|
8991
|
+
multiple: true,
|
|
8992
|
+
ariaLabel: "Chart cluster filters"
|
|
8993
|
+
}
|
|
8994
|
+
),
|
|
8995
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 min-w-0 flex-1 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8996
|
+
scatterPlotChart.ScatterPlotChart,
|
|
8997
|
+
{
|
|
8998
|
+
data: chartData,
|
|
8999
|
+
xKey: "duration",
|
|
9000
|
+
yKey: "spans",
|
|
9001
|
+
nameKey: "name",
|
|
9002
|
+
colorKey: "color",
|
|
9003
|
+
height: "100%",
|
|
9004
|
+
className: "h-full",
|
|
9005
|
+
xLabel: "Duration",
|
|
9006
|
+
yLabel: "Spans",
|
|
9007
|
+
formatX: (value) => `${value}ms`,
|
|
9008
|
+
formatY: (value) => `${value} spans`
|
|
9009
|
+
}
|
|
9010
|
+
) })
|
|
9011
|
+
] });
|
|
9012
|
+
}
|
|
9013
|
+
function SignalClusterTabs({
|
|
9014
|
+
signal,
|
|
9015
|
+
selectedCluster,
|
|
9016
|
+
selectedTraceId,
|
|
9017
|
+
selectedChartClusterIds,
|
|
9018
|
+
activeTab,
|
|
9019
|
+
onActiveTabChange,
|
|
9020
|
+
onClusterSelect,
|
|
9021
|
+
onChartClusterToggle,
|
|
9022
|
+
onTraceSelect
|
|
9023
|
+
}) {
|
|
9024
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9025
|
+
tabsTab.Tabs,
|
|
9026
|
+
{
|
|
9027
|
+
defaultTab: "trace-list",
|
|
9028
|
+
value: activeTab,
|
|
9029
|
+
onValueChange: onActiveTabChange,
|
|
9030
|
+
className: "flex h-full min-h-0 flex-col overflow-hidden",
|
|
9031
|
+
children: [
|
|
9032
|
+
/* @__PURE__ */ jsxRuntime.jsxs(tabsTab.TabList, { variant: "line", children: [
|
|
9033
|
+
/* @__PURE__ */ jsxRuntime.jsx(tabsTab.Tab, { value: "trace-list", children: "Trace list" }),
|
|
9034
|
+
/* @__PURE__ */ jsxRuntime.jsx(tabsTab.Tab, { value: "chart", children: "Chart" })
|
|
9035
|
+
] }),
|
|
9036
|
+
/* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "trace-list", className: "min-h-0 flex-1 overflow-hidden py-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-w-0 gap-6", children: [
|
|
9037
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9038
|
+
SignalClusterSidebar,
|
|
9039
|
+
{
|
|
9040
|
+
signal,
|
|
9041
|
+
selectedClusterIds: [selectedCluster.id],
|
|
9042
|
+
onClusterSelect
|
|
9043
|
+
}
|
|
9044
|
+
),
|
|
9045
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1 overflow-hidden py-4", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9046
|
+
SignalTraceListTab,
|
|
9047
|
+
{
|
|
9048
|
+
cluster: selectedCluster,
|
|
9049
|
+
selectedTraceId,
|
|
9050
|
+
onTraceSelect
|
|
9051
|
+
}
|
|
9052
|
+
) })
|
|
9053
|
+
] }) }),
|
|
9054
|
+
/* @__PURE__ */ jsxRuntime.jsx(tabsContent.TabContent, { value: "chart", className: "min-h-0 flex-1 overflow-hidden py-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9055
|
+
SignalChartTab,
|
|
9056
|
+
{
|
|
9057
|
+
signal,
|
|
9058
|
+
selectedClusterIds: selectedChartClusterIds,
|
|
9059
|
+
onClusterToggle: onChartClusterToggle
|
|
9060
|
+
}
|
|
9061
|
+
) })
|
|
9062
|
+
]
|
|
9063
|
+
}
|
|
9064
|
+
);
|
|
9065
|
+
}
|
|
9066
|
+
function SignalDetailsPage({ signalId, selectedTraceId, tracePanel, onTraceSelect }) {
|
|
9067
|
+
const selectedSignal = React.useMemo(() => signals.find((signal) => signal.id === signalId), [signalId]);
|
|
9068
|
+
const initialCluster = findClusterByTraceId(selectedSignal, selectedTraceId ?? void 0) ?? selectedSignal?.clusters[0];
|
|
9069
|
+
const [selectedClusterId, setSelectedClusterId] = React.useState(() => initialCluster?.id ?? null);
|
|
9070
|
+
const [selectedChartClusterIds, setSelectedChartClusterIds] = React.useState(
|
|
9071
|
+
() => selectedSignal?.clusters.map((cluster) => cluster.id) ?? []
|
|
9072
|
+
);
|
|
9073
|
+
const [activeTab, setActiveTab] = React.useState("trace-list");
|
|
9074
|
+
const selectedCluster = selectedSignal?.clusters.find((cluster) => cluster.id === selectedClusterId) ?? initialCluster;
|
|
9075
|
+
const { data: tracesData } = useTraces({});
|
|
9076
|
+
const resolvedTraceId = tracesData?.spans[0]?.traceId ?? null;
|
|
9077
|
+
const handleTraceSelect = () => {
|
|
9078
|
+
if (!selectedSignal || !resolvedTraceId) return;
|
|
9079
|
+
onTraceSelect(selectedSignal.id, resolvedTraceId);
|
|
9080
|
+
};
|
|
9081
|
+
const handleChartClusterToggle = (clusterId) => {
|
|
9082
|
+
setSelectedChartClusterIds(
|
|
9083
|
+
(current) => current.includes(clusterId) ? current.filter((id) => id !== clusterId) : [...current, clusterId]
|
|
9084
|
+
);
|
|
9085
|
+
};
|
|
9086
|
+
if (!selectedSignal || !selectedCluster) {
|
|
9087
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SignalsLayout, { sidebar: null, children: "Signal not found" });
|
|
9088
|
+
}
|
|
9089
|
+
return /* @__PURE__ */ jsxRuntime.jsx(SignalsLayout, { sidebar: null, tracePanel: activeTab === "trace-list" ? tracePanel : void 0, children: /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "flex h-full min-w-0 flex-col gap-4", children: [
|
|
9090
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "space-y-1", children: [
|
|
9091
|
+
/* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-icon-xl font-semibold text-neutral6", children: selectedSignal.name }),
|
|
9092
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-sm text-neutral3", children: "Explore trace patterns by cluster." })
|
|
9093
|
+
] }),
|
|
9094
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9095
|
+
SignalClusterTabs,
|
|
9096
|
+
{
|
|
9097
|
+
signal: selectedSignal,
|
|
9098
|
+
selectedCluster,
|
|
9099
|
+
selectedTraceId,
|
|
9100
|
+
selectedChartClusterIds,
|
|
9101
|
+
activeTab,
|
|
9102
|
+
onActiveTabChange: setActiveTab,
|
|
9103
|
+
onClusterSelect: setSelectedClusterId,
|
|
9104
|
+
onChartClusterToggle: handleChartClusterToggle,
|
|
9105
|
+
onTraceSelect: handleTraceSelect
|
|
9106
|
+
}
|
|
9107
|
+
) })
|
|
9108
|
+
] }) });
|
|
9109
|
+
}
|
|
9110
|
+
|
|
9111
|
+
const getTraceShare = (traceCount, totalTraceCount) => {
|
|
9112
|
+
if (totalTraceCount === 0) return 0;
|
|
9113
|
+
return Math.round(traceCount / totalTraceCount * 100);
|
|
9114
|
+
};
|
|
9115
|
+
function SignalClusterCard({ cluster, totalTraceCount }) {
|
|
9116
|
+
const traceCount = cluster.traceSummaries.length;
|
|
9117
|
+
const traceShare = getTraceShare(traceCount, totalTraceCount);
|
|
9118
|
+
const traceLabel = traceCount === 1 ? "trace" : "traces";
|
|
9119
|
+
const clusterColor = stringToColor(cluster.name);
|
|
9120
|
+
return /* @__PURE__ */ jsxRuntime.jsx("article", { className: "rounded-2xl border border-border1/70 bg-surface2 p-5 shadow-sm", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-w-0 flex-col", children: [
|
|
9121
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
|
|
9122
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mt-2 h-2.5 w-2.5 shrink-0 rounded-full", style: { backgroundColor: clusterColor } }),
|
|
9123
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
9124
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-md font-semibold text-neutral6", children: cluster.name }),
|
|
9125
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "line-clamp-2 text-sm text-neutral3", children: cluster.description })
|
|
9126
|
+
] })
|
|
9127
|
+
] }),
|
|
9128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 pt-4 pl-4", children: [
|
|
9129
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
9130
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-mono text-xs uppercase text-neutral3", children: "Trace share" }),
|
|
9131
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "font-mono text-xs text-neutral3", children: [
|
|
9132
|
+
traceCount,
|
|
9133
|
+
" ",
|
|
9134
|
+
traceLabel
|
|
9135
|
+
] })
|
|
9136
|
+
] }),
|
|
9137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-[minmax(0,1fr)_4rem] items-center gap-4", children: [
|
|
9138
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9139
|
+
"div",
|
|
9140
|
+
{
|
|
9141
|
+
className: "h-3 overflow-hidden rounded-full bg-surface4",
|
|
9142
|
+
role: "progressbar",
|
|
9143
|
+
"aria-label": `${cluster.name} trace share`,
|
|
9144
|
+
"aria-valuemin": 0,
|
|
9145
|
+
"aria-valuemax": 100,
|
|
9146
|
+
"aria-valuenow": traceShare,
|
|
9147
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-full rounded-full", style: { width: `${traceShare}%`, backgroundColor: clusterColor } })
|
|
9148
|
+
}
|
|
9149
|
+
),
|
|
9150
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-right text-ui-md font-semibold text-neutral6", children: [
|
|
9151
|
+
traceShare,
|
|
9152
|
+
"%"
|
|
9153
|
+
] })
|
|
9154
|
+
] })
|
|
9155
|
+
] })
|
|
9156
|
+
] }) });
|
|
9157
|
+
}
|
|
9158
|
+
function SignalSection({ signal, onSeeDetails }) {
|
|
9159
|
+
const totalTraceCount = React.useMemo(
|
|
9160
|
+
() => signal.clusters.reduce((total, cluster) => total + cluster.traceSummaries.length, 0),
|
|
9161
|
+
[signal.clusters]
|
|
9162
|
+
);
|
|
9163
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "space-y-4", children: [
|
|
9164
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-start justify-between gap-6 px-1", children: [
|
|
9165
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "min-w-0", children: [
|
|
9166
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
|
|
9167
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-ui-2xl font-semibold text-neutral6", children: signal.name }),
|
|
9168
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Badge.Badge, { variant: "default", children: [
|
|
9169
|
+
signal.clusters.length,
|
|
9170
|
+
" ",
|
|
9171
|
+
signal.clusters.length === 1 ? "cluster" : "clusters"
|
|
9172
|
+
] })
|
|
9173
|
+
] }),
|
|
9174
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-lg text-neutral3", children: signal.description })
|
|
9175
|
+
] }),
|
|
9176
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9177
|
+
Button.Button,
|
|
9178
|
+
{
|
|
9179
|
+
type: "button",
|
|
9180
|
+
variant: "outline",
|
|
9181
|
+
size: "lg",
|
|
9182
|
+
className: "shrink-0 gap-2 rounded-xl px-5",
|
|
9183
|
+
onClick: () => onSeeDetails(signal),
|
|
9184
|
+
children: [
|
|
9185
|
+
"See details",
|
|
9186
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowUpRight, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
9187
|
+
]
|
|
9188
|
+
}
|
|
9189
|
+
)
|
|
9190
|
+
] }),
|
|
9191
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid gap-6 md:grid-cols-2", children: signal.clusters.map((cluster) => /* @__PURE__ */ jsxRuntime.jsx(SignalClusterCard, { cluster, totalTraceCount }, cluster.id)) })
|
|
9192
|
+
] });
|
|
9193
|
+
}
|
|
9194
|
+
function SignalsOverviewPage({ onSignalSelect }) {
|
|
9195
|
+
return /* @__PURE__ */ jsxRuntime.jsx(TopicsLayout, { sidebar: null, contentPadding: false, children: /* @__PURE__ */ jsxRuntime.jsx("nav", { className: "h-full min-w-0 overflow-y-auto p-6", "aria-label": "Signals", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto flex max-w-6xl flex-col gap-12", children: signals.map((signal) => /* @__PURE__ */ jsxRuntime.jsx(SignalSection, { signal, onSeeDetails: onSignalSelect }, signal.id)) }) }) });
|
|
9196
|
+
}
|
|
9197
|
+
|
|
8444
9198
|
exports.Avatar = Avatar.Avatar;
|
|
8445
9199
|
exports.Badge = Badge.Badge;
|
|
8446
9200
|
exports.Breadcrumb = Breadcrumb.Breadcrumb;
|
|
@@ -8595,6 +9349,12 @@ exports.TooltipContent = tooltip.TooltipContent;
|
|
|
8595
9349
|
exports.TooltipProvider = tooltip.TooltipProvider;
|
|
8596
9350
|
exports.TooltipTrigger = tooltip.TooltipTrigger;
|
|
8597
9351
|
exports.Truncate = truncate.Truncate;
|
|
9352
|
+
exports.ThreadList = threadList.ThreadList;
|
|
9353
|
+
exports.ThreadListEmpty = threadList.ThreadListEmpty;
|
|
9354
|
+
exports.ThreadListItem = threadList.ThreadListItem;
|
|
9355
|
+
exports.ThreadListItems = threadList.ThreadListItems;
|
|
9356
|
+
exports.ThreadListNewItem = threadList.ThreadListNewItem;
|
|
9357
|
+
exports.ThreadListSeparator = threadList.ThreadListSeparator;
|
|
8598
9358
|
exports.ButtonsGroup = buttonsGroup.ButtonsGroup;
|
|
8599
9359
|
exports.ButtonsGroupSeparator = buttonsGroup.ButtonsGroupSeparator;
|
|
8600
9360
|
exports.ButtonsGroupText = buttonsGroup.ButtonsGroupText;
|
|
@@ -8699,6 +9459,10 @@ exports.HorizontalBars = horizontalBars.HorizontalBars;
|
|
|
8699
9459
|
exports.MetricsDataTable = metricsDataTable.MetricsDataTable;
|
|
8700
9460
|
exports.MetricsLineChart = metricsLineChart.MetricsLineChart;
|
|
8701
9461
|
exports.MetricsLineChartTooltip = metricsLineChart.MetricsLineChartTooltip;
|
|
9462
|
+
exports.ScatterPlotChart = scatterPlotChart.ScatterPlotChart;
|
|
9463
|
+
exports.ScatterPlotChartTooltip = scatterPlotChart.ScatterPlotChartTooltip;
|
|
9464
|
+
exports.getScatterPlotClickedPoint = scatterPlotChart.getScatterPlotClickedPoint;
|
|
9465
|
+
exports.getScatterPlotPointColor = scatterPlotChart.getScatterPlotPointColor;
|
|
8702
9466
|
exports.StatusBadge = StatusBadge.StatusBadge;
|
|
8703
9467
|
exports.Animations = tokens.Animations;
|
|
8704
9468
|
exports.BorderColors = spacings.BorderColors;
|
|
@@ -8832,6 +9596,15 @@ exports.RuleValueInput = RuleValueInput;
|
|
|
8832
9596
|
exports.ScorersIcon = ScorersIcon;
|
|
8833
9597
|
exports.ScoresCardView = ScoresCardView;
|
|
8834
9598
|
exports.SettingsIcon = SettingsIcon;
|
|
9599
|
+
exports.SignalChartTab = SignalChartTab;
|
|
9600
|
+
exports.SignalClusterCard = SignalClusterCard;
|
|
9601
|
+
exports.SignalClusterSidebar = SignalClusterSidebar;
|
|
9602
|
+
exports.SignalClusterTabs = SignalClusterTabs;
|
|
9603
|
+
exports.SignalDetailsPage = SignalDetailsPage;
|
|
9604
|
+
exports.SignalSection = SignalSection;
|
|
9605
|
+
exports.SignalTraceDetailsPanel = SignalTraceDetailsPanel;
|
|
9606
|
+
exports.SignalTraceListTab = SignalTraceListTab;
|
|
9607
|
+
exports.SignalsOverviewPage = SignalsOverviewPage;
|
|
8835
9608
|
exports.SkillIcon = SkillIcon;
|
|
8836
9609
|
exports.SpanDataPanelView = SpanDataPanelView;
|
|
8837
9610
|
exports.SpanDetailsView = SpanDetailsView;
|
|
@@ -8859,6 +9632,9 @@ exports.TimelineTimingCol = TimelineTimingCol;
|
|
|
8859
9632
|
exports.TokenUsageByAgentCardView = TokenUsageByAgentCardView;
|
|
8860
9633
|
exports.TokenUsageTimelineCardView = TokenUsageTimelineCardView;
|
|
8861
9634
|
exports.ToolCoinIcon = ToolCoinIcon;
|
|
9635
|
+
exports.TopicTraceDetailsPanel = TopicTraceDetailsPanel;
|
|
9636
|
+
exports.TopicTraceSummaryList = TopicTraceSummaryList;
|
|
9637
|
+
exports.TopicsLayout = TopicsLayout;
|
|
8862
9638
|
exports.TraceDataPanelView = TraceDataPanelView;
|
|
8863
9639
|
exports.TraceDetailsView = TraceDetailsView;
|
|
8864
9640
|
exports.TraceIcon = TraceIcon;
|
|
@@ -8876,6 +9652,7 @@ exports.VariablesIcon = VariablesIcon;
|
|
|
8876
9652
|
exports.WorkflowCoinIcon = WorkflowCoinIcon;
|
|
8877
9653
|
exports.WorkspacesIcon = WorkspacesIcon;
|
|
8878
9654
|
exports.XGroqIcon = XGroqIcon;
|
|
9655
|
+
exports.aggregateTopics = aggregateTopics;
|
|
8879
9656
|
exports.applyLogsPropertyFilterTokens = applyLogsPropertyFilterTokens;
|
|
8880
9657
|
exports.applyMetricsPropertyFilterTokens = applyMetricsPropertyFilterTokens;
|
|
8881
9658
|
exports.applyTracePropertyFilterTokens = applyTracePropertyFilterTokens;
|
|
@@ -8895,6 +9672,7 @@ exports.createMetricsPropertyFilterFields = createMetricsPropertyFilterFields;
|
|
|
8895
9672
|
exports.createTracePropertyFilterFields = createTracePropertyFilterFields;
|
|
8896
9673
|
exports.downloadJson = downloadJson;
|
|
8897
9674
|
exports.fileToBase64 = fileToBase64;
|
|
9675
|
+
exports.filterTraceSummaries = filterTraceSummaries;
|
|
8898
9676
|
exports.formatCompact = formatCompact;
|
|
8899
9677
|
exports.formatCost = formatCost;
|
|
8900
9678
|
exports.formatHierarchicalSpans = formatHierarchicalSpans;
|
|
@@ -8911,10 +9689,17 @@ exports.getLogsPropertyFilterTokens = getLogsPropertyFilterTokens;
|
|
|
8911
9689
|
exports.getMetricsPropertyFilterTokens = getMetricsPropertyFilterTokens;
|
|
8912
9690
|
exports.getPreservedLogsFilterParams = getPreservedLogsFilterParams;
|
|
8913
9691
|
exports.getPreservedTraceFilterParams = getPreservedTraceFilterParams;
|
|
9692
|
+
exports.getSignalChartData = getSignalChartData;
|
|
9693
|
+
exports.getSignalName = getSignalName;
|
|
8914
9694
|
exports.getSpanDescendantIds = getSpanDescendantIds;
|
|
8915
9695
|
exports.getSpanTypeUi = getSpanTypeUi;
|
|
8916
9696
|
exports.getTokenLimitMessage = getTokenLimitMessage;
|
|
9697
|
+
exports.getTopicColor = getTopicColor;
|
|
9698
|
+
exports.getTopicTraceCount = getTopicTraceCount;
|
|
9699
|
+
exports.getTraceCount = getTraceCount;
|
|
8917
9700
|
exports.getTracePropertyFilterTokens = getTracePropertyFilterTokens;
|
|
9701
|
+
exports.getTraceShare = getTraceShare$1;
|
|
9702
|
+
exports.getVisibleTraceSummaries = getVisibleTraceSummaries;
|
|
8918
9703
|
exports.hasAnyLogsFilterParams = hasAnyLogsFilterParams;
|
|
8919
9704
|
exports.hasAnyMetricsFilterParams = hasAnyMetricsFilterParams;
|
|
8920
9705
|
exports.hasAnyTraceFilterParams = hasAnyTraceFilterParams;
|
|
@@ -8930,6 +9715,7 @@ exports.isRemoteUrl = isRemoteUrl;
|
|
|
8930
9715
|
exports.isRule = isRule;
|
|
8931
9716
|
exports.isRuleGroup = isRuleGroup;
|
|
8932
9717
|
exports.isTokenLimitExceeded = isTokenLimitExceeded;
|
|
9718
|
+
exports.isUnsupportedObservabilityOperationError = isUnsupportedObservabilityOperationError;
|
|
8933
9719
|
exports.isValidJson = isValidJson;
|
|
8934
9720
|
exports.isValidPreset = isValidPreset;
|
|
8935
9721
|
exports.loadLogsFiltersFromStorage = loadLogsFiltersFromStorage;
|
|
@@ -8945,6 +9731,8 @@ exports.saveLogsFiltersToStorage = saveLogsFiltersToStorage;
|
|
|
8945
9731
|
exports.saveMetricsFiltersToStorage = saveMetricsFiltersToStorage;
|
|
8946
9732
|
exports.saveTraceFiltersToStorage = saveTraceFiltersToStorage;
|
|
8947
9733
|
exports.shouldRetryQuery = shouldRetryQuery;
|
|
9734
|
+
exports.signals = signals;
|
|
9735
|
+
exports.sortTraceSummaries = sortTraceSummaries;
|
|
8948
9736
|
exports.spanTypePrefixes = spanTypePrefixes;
|
|
8949
9737
|
exports.stringToColor = stringToColor;
|
|
8950
9738
|
exports.toSigFigs = toSigFigs;
|