@copilotz/admin 0.9.25 → 0.9.27
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/dist/index.cjs +1070 -950
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +1098 -961
- package/dist/index.js.map +1 -1
- package/dist/styles.css +166 -65
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -307,6 +307,7 @@ async function fetchAdminUsage(filters, options) {
|
|
|
307
307
|
interval: filters.interval,
|
|
308
308
|
metric: filters.metric,
|
|
309
309
|
groupBy: filters.groupBy,
|
|
310
|
+
attribution: filters.attribution,
|
|
310
311
|
threadId: filters.threadId,
|
|
311
312
|
participantId: filters.participantId,
|
|
312
313
|
participantType: filters.participantType,
|
|
@@ -579,6 +580,16 @@ function CardHeader({ className, ...props }) {
|
|
|
579
580
|
}
|
|
580
581
|
);
|
|
581
582
|
}
|
|
583
|
+
function CardTitle({ className, ...props }) {
|
|
584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
585
|
+
"div",
|
|
586
|
+
{
|
|
587
|
+
"data-slot": "card-title",
|
|
588
|
+
className: cn("leading-none font-semibold", className),
|
|
589
|
+
...props
|
|
590
|
+
}
|
|
591
|
+
);
|
|
592
|
+
}
|
|
582
593
|
function CardContent({ className, ...props }) {
|
|
583
594
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
584
595
|
"div",
|
|
@@ -1565,6 +1576,8 @@ var AdminHeader = ({
|
|
|
1565
1576
|
|
|
1566
1577
|
// src/components/views/DashboardView.tsx
|
|
1567
1578
|
var import_react2 = __toESM(require("react"), 1);
|
|
1579
|
+
var import_recharts = require("recharts");
|
|
1580
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1568
1581
|
|
|
1569
1582
|
// src/components/ui/badge.tsx
|
|
1570
1583
|
var import_react_slot3 = require("@radix-ui/react-slot");
|
|
@@ -1603,8 +1616,124 @@ function Badge({
|
|
|
1603
1616
|
);
|
|
1604
1617
|
}
|
|
1605
1618
|
|
|
1606
|
-
// src/components/
|
|
1619
|
+
// src/components/ui/chart.tsx
|
|
1620
|
+
var React5 = __toESM(require("react"), 1);
|
|
1621
|
+
var RechartsPrimitive = __toESM(require("recharts"), 1);
|
|
1607
1622
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
1623
|
+
var ChartContext = React5.createContext(null);
|
|
1624
|
+
function useChart() {
|
|
1625
|
+
const context = React5.useContext(ChartContext);
|
|
1626
|
+
if (!context) {
|
|
1627
|
+
throw new Error("useChart must be used within a ChartContainer");
|
|
1628
|
+
}
|
|
1629
|
+
return context;
|
|
1630
|
+
}
|
|
1631
|
+
function ChartContainer({
|
|
1632
|
+
id,
|
|
1633
|
+
className,
|
|
1634
|
+
config,
|
|
1635
|
+
children,
|
|
1636
|
+
...props
|
|
1637
|
+
}) {
|
|
1638
|
+
const uniqueId = React5.useId();
|
|
1639
|
+
const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
|
|
1640
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ChartContext.Provider, { value: config, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1641
|
+
"div",
|
|
1642
|
+
{
|
|
1643
|
+
"data-chart": chartId,
|
|
1644
|
+
className: cn(
|
|
1645
|
+
"flex aspect-auto justify-center text-xs text-muted-foreground [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/70 [&_.recharts-cursor]:fill-muted [&_.recharts-legend-wrapper]:text-muted-foreground [&_.recharts-tooltip-cursor]:fill-muted",
|
|
1646
|
+
className
|
|
1647
|
+
),
|
|
1648
|
+
...props,
|
|
1649
|
+
children: [
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("style", { children: Object.entries(config).map(([key, item]) => {
|
|
1651
|
+
return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
|
|
1652
|
+
}).join("\n") }),
|
|
1653
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(RechartsPrimitive.ResponsiveContainer, { children })
|
|
1654
|
+
]
|
|
1655
|
+
}
|
|
1656
|
+
) });
|
|
1657
|
+
}
|
|
1658
|
+
function ChartTooltipContent({
|
|
1659
|
+
active,
|
|
1660
|
+
payload,
|
|
1661
|
+
label,
|
|
1662
|
+
className,
|
|
1663
|
+
formatter,
|
|
1664
|
+
labelFormatter
|
|
1665
|
+
}) {
|
|
1666
|
+
const config = useChart();
|
|
1667
|
+
if (!active || !payload?.length) return null;
|
|
1668
|
+
const total = payload.reduce((sum, item) => {
|
|
1669
|
+
const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
|
|
1670
|
+
return sum + (Number.isFinite(value) ? value : 0);
|
|
1671
|
+
}, 0);
|
|
1672
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1673
|
+
"div",
|
|
1674
|
+
{
|
|
1675
|
+
className: cn(
|
|
1676
|
+
"min-w-44 rounded-lg border bg-popover px-3 py-2 text-popover-foreground shadow-md",
|
|
1677
|
+
className
|
|
1678
|
+
),
|
|
1679
|
+
children: [
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-2 flex items-center justify-between gap-4 border-b pb-2", children: [
|
|
1681
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium text-muted-foreground", children: labelFormatter ? labelFormatter(label) : label }),
|
|
1682
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-semibold text-foreground", children: formatter ? formatter(total) : total })
|
|
1683
|
+
] }),
|
|
1684
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
|
|
1685
|
+
const key = String(item.dataKey ?? item.name ?? "");
|
|
1686
|
+
const itemConfig = config[key];
|
|
1687
|
+
const color = item.color ?? itemConfig?.color ?? "currentColor";
|
|
1688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1689
|
+
"div",
|
|
1690
|
+
{
|
|
1691
|
+
className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
|
|
1692
|
+
children: [
|
|
1693
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1694
|
+
"span",
|
|
1695
|
+
{
|
|
1696
|
+
className: "size-2 rounded-[2px]",
|
|
1697
|
+
style: { backgroundColor: color }
|
|
1698
|
+
}
|
|
1699
|
+
),
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "max-w-48 truncate text-muted-foreground", children: itemConfig?.label ?? item.name ?? key }),
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "font-medium text-foreground", children: formatter ? formatter(item.value ?? 0) : item.value })
|
|
1702
|
+
]
|
|
1703
|
+
},
|
|
1704
|
+
key
|
|
1705
|
+
);
|
|
1706
|
+
}) })
|
|
1707
|
+
]
|
|
1708
|
+
}
|
|
1709
|
+
);
|
|
1710
|
+
}
|
|
1711
|
+
function ChartLegendContent({
|
|
1712
|
+
payload,
|
|
1713
|
+
className
|
|
1714
|
+
}) {
|
|
1715
|
+
const config = useChart();
|
|
1716
|
+
if (!payload?.length) return null;
|
|
1717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex flex-wrap items-center gap-x-4 gap-y-2", className), children: payload.map((item) => {
|
|
1718
|
+
const key = String(item.dataKey ?? item.value ?? "");
|
|
1719
|
+
const itemConfig = config[key];
|
|
1720
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1721
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1722
|
+
"span",
|
|
1723
|
+
{
|
|
1724
|
+
className: "size-2 rounded-[2px]",
|
|
1725
|
+
style: {
|
|
1726
|
+
backgroundColor: item.color ?? itemConfig?.color ?? "currentColor"
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
),
|
|
1730
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
|
|
1731
|
+
] }, key);
|
|
1732
|
+
}) });
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// src/components/views/DashboardView.tsx
|
|
1736
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1608
1737
|
var DashboardView = ({
|
|
1609
1738
|
config,
|
|
1610
1739
|
overview,
|
|
@@ -1622,154 +1751,52 @@ var DashboardView = ({
|
|
|
1622
1751
|
onThreadClick,
|
|
1623
1752
|
namespace
|
|
1624
1753
|
}) => {
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
detail: `${overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
|
|
1642
|
-
},
|
|
1643
|
-
{
|
|
1644
|
-
label: config.labels.activeThreadsCard,
|
|
1645
|
-
value: overview?.threadTotals.active ?? 0,
|
|
1646
|
-
detail: `${overview?.threadTotals.total ?? 0} total threads`
|
|
1647
|
-
},
|
|
1648
|
-
{
|
|
1649
|
-
label: config.labels.participantsCard,
|
|
1650
|
-
value: overview?.participantTotals.total ?? 0,
|
|
1651
|
-
detail: `${overview?.participantTotals.agents ?? 0} agents, ${overview?.participantTotals.jobs ?? 0} jobs`
|
|
1652
|
-
},
|
|
1653
|
-
{
|
|
1654
|
-
label: llmSummaryLabel,
|
|
1655
|
-
value: llmSummaryValue,
|
|
1656
|
-
detail: `${overview?.llmTotals.totalCalls ?? 0} ${config.labels.usageCallsDetail}`,
|
|
1657
|
-
metricKind: usageMetricKind
|
|
1658
|
-
},
|
|
1659
|
-
{
|
|
1660
|
-
label: config.labels.queueCard,
|
|
1661
|
-
value: overview?.queueTotals.pending ?? 0,
|
|
1662
|
-
detail: `${overview?.queueTotals.failed ?? 0} failed`
|
|
1663
|
-
}
|
|
1664
|
-
];
|
|
1665
|
-
const isEmpty = cards.every((card) => card.value === 0) && activity.length === 0 && threads.length === 0 && participants.length === 0 && agents.length === 0;
|
|
1666
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-6", children: [
|
|
1667
|
-
isEmpty && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
1668
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold", children: config.labels.emptyTitle }),
|
|
1669
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-sm text-muted-foreground", children: config.labels.emptyDescription })
|
|
1670
|
-
] }),
|
|
1671
|
-
config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
|
|
1672
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.overviewTitle }),
|
|
1673
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1674
|
-
"div",
|
|
1675
|
-
{
|
|
1676
|
-
className: "rounded-xl border bg-card p-5 shadow-sm",
|
|
1677
|
-
children: [
|
|
1678
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
|
|
1679
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatMetricValue(
|
|
1680
|
-
card.value,
|
|
1681
|
-
card.metricKind ?? "tokens"
|
|
1682
|
-
) }),
|
|
1683
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
|
|
1684
|
-
]
|
|
1685
|
-
},
|
|
1686
|
-
card.label
|
|
1687
|
-
)) })
|
|
1688
|
-
] }),
|
|
1689
|
-
config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1690
|
-
UsageExplorer,
|
|
1754
|
+
void overview;
|
|
1755
|
+
void activity;
|
|
1756
|
+
void threads;
|
|
1757
|
+
void participants;
|
|
1758
|
+
void agents;
|
|
1759
|
+
void interval;
|
|
1760
|
+
void threadSearch;
|
|
1761
|
+
void participantSearch;
|
|
1762
|
+
void agentSearch;
|
|
1763
|
+
void onThreadSearchChange;
|
|
1764
|
+
void onParticipantSearchChange;
|
|
1765
|
+
void onAgentSearchChange;
|
|
1766
|
+
void onThreadClick;
|
|
1767
|
+
if (!config.features.showOverview) {
|
|
1768
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1769
|
+
EmptyDashboard,
|
|
1691
1770
|
{
|
|
1692
|
-
config,
|
|
1693
|
-
|
|
1694
|
-
namespace,
|
|
1695
|
-
onDimensionChange: setUsageDimension,
|
|
1696
|
-
onMetricKindChange: setUsageMetricKind,
|
|
1697
|
-
selectedDimension: usageDimension
|
|
1771
|
+
description: config.labels.emptyDescription,
|
|
1772
|
+
title: config.labels.emptyTitle
|
|
1698
1773
|
}
|
|
1699
|
-
)
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
points: activity,
|
|
1709
|
-
usageDimension,
|
|
1710
|
-
usageMetricKind
|
|
1711
|
-
}
|
|
1712
|
-
)
|
|
1713
|
-
] }),
|
|
1714
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-6 lg:grid-cols-3", children: [
|
|
1715
|
-
config.features.showThreads && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1716
|
-
DataTable,
|
|
1717
|
-
{
|
|
1718
|
-
rows: threads,
|
|
1719
|
-
searchPlaceholder: config.labels.threadSearchPlaceholder,
|
|
1720
|
-
searchValue: threadSearch,
|
|
1721
|
-
setSearchValue: onThreadSearchChange,
|
|
1722
|
-
title: config.labels.threadsTitle,
|
|
1723
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1724
|
-
ThreadsTable,
|
|
1725
|
-
{
|
|
1726
|
-
rows: threads,
|
|
1727
|
-
labels: config.labels,
|
|
1728
|
-
onThreadClick
|
|
1729
|
-
}
|
|
1730
|
-
)
|
|
1731
|
-
}
|
|
1732
|
-
),
|
|
1733
|
-
config.features.showParticipants && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1734
|
-
DataTable,
|
|
1735
|
-
{
|
|
1736
|
-
rows: participants,
|
|
1737
|
-
searchPlaceholder: config.labels.participantSearchPlaceholder,
|
|
1738
|
-
searchValue: participantSearch,
|
|
1739
|
-
setSearchValue: onParticipantSearchChange,
|
|
1740
|
-
title: config.labels.participantsTitle,
|
|
1741
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ParticipantsTable, { rows: participants, labels: config.labels })
|
|
1742
|
-
}
|
|
1743
|
-
),
|
|
1744
|
-
config.features.showAgents && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1745
|
-
DataTable,
|
|
1746
|
-
{
|
|
1747
|
-
rows: agents,
|
|
1748
|
-
searchPlaceholder: config.labels.agentSearchPlaceholder,
|
|
1749
|
-
searchValue: agentSearch,
|
|
1750
|
-
setSearchValue: onAgentSearchChange,
|
|
1751
|
-
title: config.labels.agentsTitle,
|
|
1752
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1753
|
-
AgentsTable,
|
|
1754
|
-
{
|
|
1755
|
-
rows: agents,
|
|
1756
|
-
labels: config.labels,
|
|
1757
|
-
usageMetricKind,
|
|
1758
|
-
usageDimension
|
|
1759
|
-
}
|
|
1760
|
-
)
|
|
1761
|
-
}
|
|
1762
|
-
)
|
|
1763
|
-
] })
|
|
1764
|
-
] });
|
|
1774
|
+
);
|
|
1775
|
+
}
|
|
1776
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1777
|
+
UsageDashboard,
|
|
1778
|
+
{
|
|
1779
|
+
config,
|
|
1780
|
+
namespace
|
|
1781
|
+
}
|
|
1782
|
+
);
|
|
1765
1783
|
};
|
|
1766
|
-
function
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1784
|
+
function UsageDashboard({
|
|
1785
|
+
config,
|
|
1786
|
+
namespace
|
|
1787
|
+
}) {
|
|
1770
1788
|
const [period, setPeriod] = import_react2.default.useState("7d");
|
|
1771
1789
|
const [bucket, setBucket] = import_react2.default.useState("day");
|
|
1772
|
-
const [
|
|
1790
|
+
const [metricKind, setMetricKind] = import_react2.default.useState(
|
|
1791
|
+
"cost"
|
|
1792
|
+
);
|
|
1793
|
+
const [dimension, setDimension] = import_react2.default.useState("total");
|
|
1794
|
+
const [groupBy, setGroupBy] = import_react2.default.useState(
|
|
1795
|
+
"participant"
|
|
1796
|
+
);
|
|
1797
|
+
const [attribution, setAttribution] = import_react2.default.useState(
|
|
1798
|
+
"initiatedBy"
|
|
1799
|
+
);
|
|
1773
1800
|
const [participantType, setParticipantType] = import_react2.default.useState("all");
|
|
1774
1801
|
const [threadId, setThreadId] = import_react2.default.useState("");
|
|
1775
1802
|
const [participantId, setParticipantId] = import_react2.default.useState("");
|
|
@@ -1793,17 +1820,18 @@ function UsageExplorer(props) {
|
|
|
1793
1820
|
from: range.from,
|
|
1794
1821
|
to: range.to,
|
|
1795
1822
|
interval: bucket,
|
|
1796
|
-
metric:
|
|
1823
|
+
metric: metricKind,
|
|
1797
1824
|
groupBy,
|
|
1798
|
-
|
|
1825
|
+
attribution,
|
|
1826
|
+
namespace: namespace || void 0,
|
|
1799
1827
|
participantType,
|
|
1800
1828
|
threadId: emptyToUndefined(threadId),
|
|
1801
1829
|
participantId: emptyToUndefined(participantId),
|
|
1802
1830
|
provider: emptyToUndefined(provider),
|
|
1803
1831
|
model: emptyToUndefined(model)
|
|
1804
1832
|
}, {
|
|
1805
|
-
baseUrl:
|
|
1806
|
-
getRequestHeaders:
|
|
1833
|
+
baseUrl: config.baseUrl,
|
|
1834
|
+
getRequestHeaders: config.getRequestHeaders
|
|
1807
1835
|
});
|
|
1808
1836
|
setUsage(next);
|
|
1809
1837
|
} catch (err) {
|
|
@@ -1813,15 +1841,16 @@ function UsageExplorer(props) {
|
|
|
1813
1841
|
setIsLoading(false);
|
|
1814
1842
|
}
|
|
1815
1843
|
}, [
|
|
1844
|
+
attribution,
|
|
1816
1845
|
bucket,
|
|
1846
|
+
config.baseUrl,
|
|
1847
|
+
config.getRequestHeaders,
|
|
1817
1848
|
groupBy,
|
|
1849
|
+
metricKind,
|
|
1818
1850
|
model,
|
|
1851
|
+
namespace,
|
|
1819
1852
|
participantId,
|
|
1820
1853
|
participantType,
|
|
1821
|
-
props.config.baseUrl,
|
|
1822
|
-
props.config.getRequestHeaders,
|
|
1823
|
-
props.metricKind,
|
|
1824
|
-
props.namespace,
|
|
1825
1854
|
provider,
|
|
1826
1855
|
range.from,
|
|
1827
1856
|
range.to,
|
|
@@ -1830,29 +1859,82 @@ function UsageExplorer(props) {
|
|
|
1830
1859
|
import_react2.default.useEffect(() => {
|
|
1831
1860
|
void loadUsage();
|
|
1832
1861
|
}, [loadUsage]);
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1862
|
+
const points = usage?.points ?? [];
|
|
1863
|
+
const totals = usage?.totals ?? EMPTY_TOTALS;
|
|
1864
|
+
const chartState = import_react2.default.useMemo(() => buildChartState(points, metricKind, dimension, bucket), [
|
|
1865
|
+
bucket,
|
|
1866
|
+
dimension,
|
|
1867
|
+
metricKind,
|
|
1868
|
+
points
|
|
1869
|
+
]);
|
|
1870
|
+
const groupedRows = import_react2.default.useMemo(() => aggregateUsageRows(points, metricKind, dimension), [
|
|
1871
|
+
dimension,
|
|
1872
|
+
metricKind,
|
|
1873
|
+
points
|
|
1874
|
+
]);
|
|
1875
|
+
const activeFilterCount = [
|
|
1876
|
+
participantType !== "all" ? participantType : "",
|
|
1877
|
+
threadId,
|
|
1878
|
+
participantId,
|
|
1879
|
+
provider,
|
|
1880
|
+
model,
|
|
1881
|
+
period === "custom" ? customFrom : "",
|
|
1882
|
+
period === "custom" ? customTo : ""
|
|
1883
|
+
].filter((value) => value.trim().length > 0).length;
|
|
1884
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-4", children: [
|
|
1885
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
|
|
1886
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
1887
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "text-2xl font-semibold tracking-tight", children: config.labels.llmUsageTitle }),
|
|
1888
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [
|
|
1889
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "outline", children: formatUsageRangeLabel(period, range) }),
|
|
1890
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "secondary", children: getGroupByLabel(groupBy) }),
|
|
1891
|
+
groupBy === "participant" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "outline", children: attribution === "initiatedBy" ? "Initiated by sender" : "Generated by caller" })
|
|
1892
|
+
] })
|
|
1893
|
+
] }),
|
|
1894
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
1895
|
+
Button,
|
|
1896
|
+
{
|
|
1897
|
+
className: "w-full sm:w-auto",
|
|
1898
|
+
disabled: isLoading,
|
|
1899
|
+
onClick: () => void loadUsage(),
|
|
1900
|
+
size: "sm",
|
|
1901
|
+
variant: "outline",
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.RefreshCw, { className: cn("size-4", isLoading && "animate-spin") }),
|
|
1904
|
+
config.labels.refresh
|
|
1905
|
+
]
|
|
1906
|
+
}
|
|
1907
|
+
)
|
|
1908
|
+
] }),
|
|
1909
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1910
|
+
UsageSummary,
|
|
1911
|
+
{
|
|
1912
|
+
dimension,
|
|
1913
|
+
labels: config.labels,
|
|
1914
|
+
metricKind,
|
|
1915
|
+
totals
|
|
1916
|
+
}
|
|
1917
|
+
),
|
|
1918
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Card, { className: "gap-4 overflow-hidden py-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(CardContent, { className: "space-y-4 px-4 lg:px-5", children: [
|
|
1919
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid gap-2 md:grid-cols-2 xl:grid-cols-6", children: [
|
|
1920
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1838
1921
|
UsageSelect,
|
|
1839
1922
|
{
|
|
1840
1923
|
label: "Period",
|
|
1841
|
-
value: period,
|
|
1842
1924
|
onValueChange: (value) => setPeriod(value),
|
|
1843
1925
|
options: [
|
|
1844
|
-
["24h",
|
|
1845
|
-
["7d",
|
|
1846
|
-
["30d",
|
|
1926
|
+
["24h", config.labels.range24h],
|
|
1927
|
+
["7d", config.labels.range7d],
|
|
1928
|
+
["30d", config.labels.range30d],
|
|
1847
1929
|
["custom", "Custom"]
|
|
1848
|
-
]
|
|
1930
|
+
],
|
|
1931
|
+
value: period
|
|
1849
1932
|
}
|
|
1850
1933
|
),
|
|
1851
|
-
/* @__PURE__ */ (0,
|
|
1934
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1852
1935
|
UsageSelect,
|
|
1853
1936
|
{
|
|
1854
1937
|
label: "Bucket",
|
|
1855
|
-
value: bucket,
|
|
1856
1938
|
onValueChange: (value) => setBucket(value),
|
|
1857
1939
|
options: [
|
|
1858
1940
|
["minute", "Minute"],
|
|
@@ -1860,27 +1942,27 @@ function UsageExplorer(props) {
|
|
|
1860
1942
|
["day", "Day"],
|
|
1861
1943
|
["week", "Week"],
|
|
1862
1944
|
["month", "Month"]
|
|
1863
|
-
]
|
|
1945
|
+
],
|
|
1946
|
+
value: bucket
|
|
1864
1947
|
}
|
|
1865
1948
|
),
|
|
1866
|
-
/* @__PURE__ */ (0,
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1867
1950
|
UsageSelect,
|
|
1868
1951
|
{
|
|
1869
|
-
label:
|
|
1870
|
-
|
|
1871
|
-
onValueChange: (value) => props.onMetricKindChange(value),
|
|
1952
|
+
label: config.labels.usageMetricLabel,
|
|
1953
|
+
onValueChange: (value) => setMetricKind(value),
|
|
1872
1954
|
options: [
|
|
1873
|
-
["cost",
|
|
1874
|
-
["tokens",
|
|
1955
|
+
["cost", config.labels.usageMetricCost],
|
|
1956
|
+
["tokens", config.labels.usageMetricTokens],
|
|
1875
1957
|
["calls", "Calls"]
|
|
1876
|
-
]
|
|
1958
|
+
],
|
|
1959
|
+
value: metricKind
|
|
1877
1960
|
}
|
|
1878
1961
|
),
|
|
1879
|
-
/* @__PURE__ */ (0,
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1880
1963
|
UsageSelect,
|
|
1881
1964
|
{
|
|
1882
|
-
label: "Group
|
|
1883
|
-
value: groupBy,
|
|
1965
|
+
label: "Group",
|
|
1884
1966
|
onValueChange: (value) => setGroupBy(value),
|
|
1885
1967
|
options: [
|
|
1886
1968
|
["participant", "Participant"],
|
|
@@ -1888,430 +1970,428 @@ function UsageExplorer(props) {
|
|
|
1888
1970
|
["namespace", "Namespace"],
|
|
1889
1971
|
["provider", "Provider"],
|
|
1890
1972
|
["model", "Model"]
|
|
1891
|
-
]
|
|
1973
|
+
],
|
|
1974
|
+
value: groupBy
|
|
1975
|
+
}
|
|
1976
|
+
),
|
|
1977
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1978
|
+
UsageSelect,
|
|
1979
|
+
{
|
|
1980
|
+
label: "Attribution",
|
|
1981
|
+
onValueChange: (value) => setAttribution(value),
|
|
1982
|
+
options: [
|
|
1983
|
+
["initiatedBy", "Initiated by"],
|
|
1984
|
+
["generatedBy", "Generated by"]
|
|
1985
|
+
],
|
|
1986
|
+
value: attribution
|
|
1892
1987
|
}
|
|
1893
1988
|
),
|
|
1894
|
-
/* @__PURE__ */ (0,
|
|
1989
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1895
1990
|
UsageSelect,
|
|
1896
1991
|
{
|
|
1897
|
-
label:
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1992
|
+
label: config.labels.usageDimensionLabel,
|
|
1993
|
+
onValueChange: (value) => setDimension(value),
|
|
1994
|
+
options: USAGE_DIMENSIONS.map((nextDimension) => [
|
|
1995
|
+
nextDimension,
|
|
1996
|
+
getUsageDimensionLabel(config.labels, nextDimension)
|
|
1997
|
+
]),
|
|
1998
|
+
value: dimension
|
|
1904
1999
|
}
|
|
1905
2000
|
)
|
|
1906
|
-
] })
|
|
1907
|
-
] }),
|
|
1908
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-6", children: [
|
|
1909
|
-
period === "custom" && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1910
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FilterInput, { label: "From", type: "datetime-local", value: customFrom, onChange: setCustomFrom }),
|
|
1911
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FilterInput, { label: "To", type: "datetime-local", value: customTo, onChange: setCustomTo })
|
|
1912
2001
|
] }),
|
|
1913
|
-
/* @__PURE__ */ (0,
|
|
1914
|
-
|
|
2002
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "rounded-lg border bg-muted/30 p-3", children: [
|
|
2003
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mb-3 flex items-center justify-between gap-3", children: [
|
|
2004
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2 text-sm font-medium", children: [
|
|
2005
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Filter, { className: "size-4" }),
|
|
2006
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: "Filters" }),
|
|
2007
|
+
activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "secondary", children: activeFilterCount })
|
|
2008
|
+
] }),
|
|
2009
|
+
activeFilterCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2010
|
+
Button,
|
|
2011
|
+
{
|
|
2012
|
+
onClick: () => {
|
|
2013
|
+
setParticipantType("all");
|
|
2014
|
+
setThreadId("");
|
|
2015
|
+
setParticipantId("");
|
|
2016
|
+
setProvider("");
|
|
2017
|
+
setModel("");
|
|
2018
|
+
setCustomFrom("");
|
|
2019
|
+
setCustomTo("");
|
|
2020
|
+
},
|
|
2021
|
+
size: "sm",
|
|
2022
|
+
variant: "ghost",
|
|
2023
|
+
children: "Clear"
|
|
2024
|
+
}
|
|
2025
|
+
)
|
|
2026
|
+
] }),
|
|
2027
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "grid gap-2 md:grid-cols-2 xl:grid-cols-6", children: [
|
|
2028
|
+
period === "custom" && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
2029
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2030
|
+
FilterInput,
|
|
2031
|
+
{
|
|
2032
|
+
label: "From",
|
|
2033
|
+
onChange: setCustomFrom,
|
|
2034
|
+
type: "datetime-local",
|
|
2035
|
+
value: customFrom
|
|
2036
|
+
}
|
|
2037
|
+
),
|
|
2038
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2039
|
+
FilterInput,
|
|
2040
|
+
{
|
|
2041
|
+
label: "To",
|
|
2042
|
+
onChange: setCustomTo,
|
|
2043
|
+
type: "datetime-local",
|
|
2044
|
+
value: customTo
|
|
2045
|
+
}
|
|
2046
|
+
)
|
|
2047
|
+
] }),
|
|
2048
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2049
|
+
UsageSelect,
|
|
2050
|
+
{
|
|
2051
|
+
label: "Type",
|
|
2052
|
+
onValueChange: (value) => setParticipantType(
|
|
2053
|
+
value
|
|
2054
|
+
),
|
|
2055
|
+
options: [
|
|
2056
|
+
["all", "All"],
|
|
2057
|
+
["human", "Human"],
|
|
2058
|
+
["agent", "Agent"],
|
|
2059
|
+
["job", "Job"]
|
|
2060
|
+
],
|
|
2061
|
+
value: participantType
|
|
2062
|
+
}
|
|
2063
|
+
),
|
|
2064
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2065
|
+
FilterInput,
|
|
2066
|
+
{
|
|
2067
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Search, { className: "size-3.5" }),
|
|
2068
|
+
label: "Thread",
|
|
2069
|
+
onChange: setThreadId,
|
|
2070
|
+
value: threadId
|
|
2071
|
+
}
|
|
2072
|
+
),
|
|
2073
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2074
|
+
FilterInput,
|
|
2075
|
+
{
|
|
2076
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Users, { className: "size-3.5" }),
|
|
2077
|
+
label: "Participant",
|
|
2078
|
+
onChange: setParticipantId,
|
|
2079
|
+
value: participantId
|
|
2080
|
+
}
|
|
2081
|
+
),
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2083
|
+
FilterInput,
|
|
2084
|
+
{
|
|
2085
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Database, { className: "size-3.5" }),
|
|
2086
|
+
label: "Provider",
|
|
2087
|
+
onChange: setProvider,
|
|
2088
|
+
value: provider
|
|
2089
|
+
}
|
|
2090
|
+
),
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2092
|
+
FilterInput,
|
|
2093
|
+
{
|
|
2094
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Sparkles, { className: "size-3.5" }),
|
|
2095
|
+
label: "Model",
|
|
2096
|
+
onChange: setModel,
|
|
2097
|
+
value: model
|
|
2098
|
+
}
|
|
2099
|
+
)
|
|
2100
|
+
] })
|
|
2101
|
+
] })
|
|
2102
|
+
] }) }),
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Card, { className: "gap-3 overflow-hidden py-4", children: [
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardHeader, { className: "px-4 lg:px-5", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-2 md:flex-row md:items-start md:justify-between", children: [
|
|
2105
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
|
|
2106
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardTitle, { className: "text-base", children: getUsageSummaryLabel(config.labels, metricKind, dimension) }),
|
|
2107
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { className: "mt-1 text-sm text-muted-foreground", children: [
|
|
2108
|
+
formatMetricValue(
|
|
2109
|
+
getUsageTotalValue(totals, metricKind, dimension),
|
|
2110
|
+
metricKind
|
|
2111
|
+
),
|
|
2112
|
+
" ",
|
|
2113
|
+
"across ",
|
|
2114
|
+
formatNumber(totals.totalCalls),
|
|
2115
|
+
" calls"
|
|
2116
|
+
] })
|
|
2117
|
+
] }),
|
|
2118
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Badge, { variant: "outline", children: config.labels.loading })
|
|
2119
|
+
] }) }),
|
|
2120
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardContent, { className: "px-2 lg:px-4", children: error ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive", children: error }) : chartState.data.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2121
|
+
EmptyDashboard,
|
|
1915
2122
|
{
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
onValueChange: (value) => setParticipantType(value),
|
|
1919
|
-
options: [
|
|
1920
|
-
["all", "All"],
|
|
1921
|
-
["human", "Human"],
|
|
1922
|
-
["agent", "Agent"],
|
|
1923
|
-
["job", "Job"]
|
|
1924
|
-
]
|
|
2123
|
+
description: config.labels.noResults,
|
|
2124
|
+
title: "No usage"
|
|
1925
2125
|
}
|
|
1926
|
-
),
|
|
1927
|
-
|
|
1928
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FilterInput, { label: "Participant", value: participantId, onChange: setParticipantId }),
|
|
1929
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FilterInput, { label: "Provider", value: provider, onChange: setProvider }),
|
|
1930
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(FilterInput, { label: "Model", value: model, onChange: setModel }),
|
|
1931
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex items-end", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1932
|
-
Button,
|
|
2126
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2127
|
+
UsageChart,
|
|
1933
2128
|
{
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
disabled: isLoading,
|
|
1937
|
-
variant: "outline",
|
|
1938
|
-
children: props.config.labels.refresh
|
|
2129
|
+
chartState,
|
|
2130
|
+
metricKind
|
|
1939
2131
|
}
|
|
1940
2132
|
) })
|
|
1941
|
-
] })
|
|
1942
|
-
/* @__PURE__ */ (0,
|
|
1943
|
-
UsageChart,
|
|
1944
|
-
{
|
|
1945
|
-
labels: props.config.labels,
|
|
1946
|
-
metricKind: props.metricKind,
|
|
1947
|
-
dimension: props.selectedDimension,
|
|
1948
|
-
points: usage?.points ?? [],
|
|
1949
|
-
bucket,
|
|
1950
|
-
isLoading,
|
|
1951
|
-
error
|
|
1952
|
-
}
|
|
1953
|
-
),
|
|
1954
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2133
|
+
] }),
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1955
2135
|
UsageTable,
|
|
1956
2136
|
{
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
2137
|
+
dimension,
|
|
2138
|
+
groupBy,
|
|
2139
|
+
labels: config.labels,
|
|
2140
|
+
metricKind,
|
|
2141
|
+
onRowFilter: (row) => {
|
|
2142
|
+
if (groupBy === "thread") setThreadId(row.groupKey);
|
|
2143
|
+
if (groupBy === "participant") setParticipantId(row.groupKey);
|
|
2144
|
+
if (groupBy === "provider") setProvider(row.groupKey);
|
|
2145
|
+
if (groupBy === "model") setModel(row.groupKey);
|
|
2146
|
+
},
|
|
2147
|
+
rows: groupedRows,
|
|
2148
|
+
totals
|
|
1962
2149
|
}
|
|
1963
2150
|
)
|
|
1964
2151
|
] });
|
|
1965
2152
|
}
|
|
2153
|
+
function UsageSummary({
|
|
2154
|
+
dimension,
|
|
2155
|
+
labels,
|
|
2156
|
+
metricKind,
|
|
2157
|
+
totals
|
|
2158
|
+
}) {
|
|
2159
|
+
const summary = [
|
|
2160
|
+
{
|
|
2161
|
+
label: labels.usageMetricCost,
|
|
2162
|
+
value: formatMetricValue(totals.totalCostUsd, "cost"),
|
|
2163
|
+
detail: `${formatNumber(totals.totalCalls)} ${labels.usageCallsDetail}`,
|
|
2164
|
+
icon: import_lucide_react6.Wallet
|
|
2165
|
+
},
|
|
2166
|
+
{
|
|
2167
|
+
label: labels.usageMetricTokens,
|
|
2168
|
+
value: formatMetricValue(totals.totalTokens, "tokens"),
|
|
2169
|
+
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
2170
|
+
icon: import_lucide_react6.Activity
|
|
2171
|
+
},
|
|
2172
|
+
{
|
|
2173
|
+
label: labels.usageCacheRead,
|
|
2174
|
+
value: formatMetricValue(totals.cacheReadInputCostUsd, "cost"),
|
|
2175
|
+
detail: `${formatMetricValue(totals.cacheReadInputTokens, "tokens")} tokens`,
|
|
2176
|
+
icon: import_lucide_react6.Database
|
|
2177
|
+
},
|
|
2178
|
+
{
|
|
2179
|
+
label: getUsageSummaryLabel(labels, metricKind, dimension),
|
|
2180
|
+
value: formatMetricValue(
|
|
2181
|
+
getUsageTotalValue(totals, metricKind, dimension),
|
|
2182
|
+
metricKind
|
|
2183
|
+
),
|
|
2184
|
+
detail: labels.usageTotal,
|
|
2185
|
+
icon: import_lucide_react6.Sparkles
|
|
2186
|
+
}
|
|
2187
|
+
];
|
|
2188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-4", children: summary.map((item) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(Card, { className: "gap-3 py-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardContent, { className: "px-4", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2189
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "min-w-0", children: [
|
|
2190
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "truncate text-sm text-muted-foreground", children: item.label }),
|
|
2191
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 truncate text-2xl font-semibold tracking-tight", children: item.value }),
|
|
2192
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: item.detail })
|
|
2193
|
+
] }),
|
|
2194
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "rounded-md border bg-muted/50 p-2 text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(item.icon, { className: "size-4" }) })
|
|
2195
|
+
] }) }) }, item.label)) });
|
|
2196
|
+
}
|
|
2197
|
+
function UsageChart({
|
|
2198
|
+
chartState,
|
|
2199
|
+
metricKind
|
|
2200
|
+
}) {
|
|
2201
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2202
|
+
ChartContainer,
|
|
2203
|
+
{
|
|
2204
|
+
className: "h-[320px] w-full",
|
|
2205
|
+
config: chartState.config,
|
|
2206
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2207
|
+
import_recharts.BarChart,
|
|
2208
|
+
{
|
|
2209
|
+
accessibilityLayer: true,
|
|
2210
|
+
data: chartState.data,
|
|
2211
|
+
margin: { left: 8, right: 8, top: 12 },
|
|
2212
|
+
children: [
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_recharts.CartesianGrid, { vertical: false }),
|
|
2214
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2215
|
+
import_recharts.XAxis,
|
|
2216
|
+
{
|
|
2217
|
+
axisLine: false,
|
|
2218
|
+
dataKey: "label",
|
|
2219
|
+
tickLine: false,
|
|
2220
|
+
tickMargin: 10
|
|
2221
|
+
}
|
|
2222
|
+
),
|
|
2223
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2224
|
+
import_recharts.YAxis,
|
|
2225
|
+
{
|
|
2226
|
+
axisLine: false,
|
|
2227
|
+
tickFormatter: (value) => formatCompactMetric(value, metricKind),
|
|
2228
|
+
tickLine: false,
|
|
2229
|
+
width: 60
|
|
2230
|
+
}
|
|
2231
|
+
),
|
|
2232
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2233
|
+
import_recharts.Tooltip,
|
|
2234
|
+
{
|
|
2235
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2236
|
+
ChartTooltipContent,
|
|
2237
|
+
{
|
|
2238
|
+
formatter: (value) => formatMetricValue(Number(value), metricKind),
|
|
2239
|
+
labelFormatter: (value) => String(value ?? "")
|
|
2240
|
+
}
|
|
2241
|
+
),
|
|
2242
|
+
cursor: false
|
|
2243
|
+
}
|
|
2244
|
+
),
|
|
2245
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2246
|
+
import_recharts.Legend,
|
|
2247
|
+
{
|
|
2248
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(ChartLegendContent, { className: "justify-center pt-3" })
|
|
2249
|
+
}
|
|
2250
|
+
),
|
|
2251
|
+
chartState.series.map((series) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2252
|
+
import_recharts.Bar,
|
|
2253
|
+
{
|
|
2254
|
+
dataKey: series.id,
|
|
2255
|
+
fill: `var(--color-${series.id})`,
|
|
2256
|
+
radius: [4, 4, 0, 0],
|
|
2257
|
+
stackId: "usage"
|
|
2258
|
+
},
|
|
2259
|
+
series.id
|
|
2260
|
+
))
|
|
2261
|
+
]
|
|
2262
|
+
}
|
|
2263
|
+
)
|
|
2264
|
+
}
|
|
2265
|
+
);
|
|
2266
|
+
}
|
|
2267
|
+
function UsageTable({
|
|
2268
|
+
dimension,
|
|
2269
|
+
groupBy,
|
|
2270
|
+
labels,
|
|
2271
|
+
metricKind,
|
|
2272
|
+
onRowFilter,
|
|
2273
|
+
rows,
|
|
2274
|
+
totals
|
|
2275
|
+
}) {
|
|
2276
|
+
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
2277
|
+
const filterable = groupBy !== "namespace";
|
|
2278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Card, { className: "gap-3 py-4", children: [
|
|
2279
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardHeader, { className: "px-4 lg:px-5", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
|
|
2280
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardTitle, { className: "text-base", children: "Usage detail" }),
|
|
2281
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Badge, { variant: "outline", children: [
|
|
2282
|
+
formatNumber(rows.length),
|
|
2283
|
+
" ",
|
|
2284
|
+
getGroupByLabel(groupBy).toLowerCase()
|
|
2285
|
+
] })
|
|
2286
|
+
] }) }),
|
|
2287
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(CardContent, { className: "px-0", children: rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "px-5 py-4 text-sm text-muted-foreground", children: labels.noResults }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("table", { className: "w-full min-w-[940px] text-sm", children: [
|
|
2288
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("tr", { className: "border-b text-left text-xs uppercase tracking-[0.12em] text-muted-foreground", children: [
|
|
2289
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-5 py-2.5 font-medium", children: getGroupByLabel(groupBy) }),
|
|
2290
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: getUsageSummaryLabel(labels, metricKind, dimension) }),
|
|
2291
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Share" }),
|
|
2292
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Calls" }),
|
|
2293
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Input" }),
|
|
2294
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Output" }),
|
|
2295
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Reasoning" }),
|
|
2296
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-3 py-2.5 text-right font-medium", children: "Cache read" }),
|
|
2297
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("th", { className: "px-5 py-2.5 text-right font-medium", children: "Avg/call" })
|
|
2298
|
+
] }) }),
|
|
2299
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("tbody", { children: rows.slice(0, 60).map((row) => {
|
|
2300
|
+
const share = totalValue > 0 ? row.value / totalValue : 0;
|
|
2301
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
|
|
2302
|
+
"tr",
|
|
2303
|
+
{
|
|
2304
|
+
className: cn(
|
|
2305
|
+
"border-b last:border-0",
|
|
2306
|
+
filterable && "cursor-pointer transition-colors hover:bg-muted/50"
|
|
2307
|
+
),
|
|
2308
|
+
onClick: () => filterable && onRowFilter(row),
|
|
2309
|
+
children: [
|
|
2310
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("td", { className: "px-5 py-3", children: [
|
|
2311
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
|
|
2312
|
+
row.groupKey !== row.groupLabel && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "mt-0.5 max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
|
|
2313
|
+
] }),
|
|
2314
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right font-medium", children: formatMetricValue(row.value, metricKind) }),
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatPercent(share) }),
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatNumber(row.totalCalls) }),
|
|
2317
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
|
|
2318
|
+
getUsageTotalValue(row, metricKind, "input"),
|
|
2319
|
+
metricKind
|
|
2320
|
+
) }),
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
|
|
2322
|
+
getUsageTotalValue(row, metricKind, "output"),
|
|
2323
|
+
metricKind
|
|
2324
|
+
) }),
|
|
2325
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
|
|
2326
|
+
getUsageTotalValue(row, metricKind, "reasoning"),
|
|
2327
|
+
metricKind
|
|
2328
|
+
) }),
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
|
|
2330
|
+
getUsageTotalValue(row, metricKind, "cacheRead"),
|
|
2331
|
+
metricKind
|
|
2332
|
+
) }),
|
|
2333
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("td", { className: "px-5 py-3 text-right", children: formatMetricValue(
|
|
2334
|
+
row.totalCalls > 0 ? row.value / row.totalCalls : 0,
|
|
2335
|
+
metricKind
|
|
2336
|
+
) })
|
|
2337
|
+
]
|
|
2338
|
+
},
|
|
2339
|
+
row.groupKey
|
|
2340
|
+
);
|
|
2341
|
+
}) })
|
|
2342
|
+
] }) }) })
|
|
2343
|
+
] });
|
|
2344
|
+
}
|
|
1966
2345
|
function UsageSelect(props) {
|
|
1967
|
-
return /* @__PURE__ */ (0,
|
|
1968
|
-
/* @__PURE__ */ (0,
|
|
1969
|
-
/* @__PURE__ */ (0,
|
|
1970
|
-
/* @__PURE__ */ (0,
|
|
1971
|
-
/* @__PURE__ */ (0,
|
|
2346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "space-y-1", children: [
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground", children: props.label }),
|
|
2348
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(Select, { value: props.value, onValueChange: props.onValueChange, children: [
|
|
2349
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectTrigger, { className: "h-9 w-full min-w-0 bg-background", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectValue, {}) }),
|
|
2350
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(SelectItem, { value, children: label }, value)) })
|
|
1972
2351
|
] })
|
|
1973
2352
|
] });
|
|
1974
2353
|
}
|
|
1975
2354
|
function FilterInput(props) {
|
|
1976
|
-
return /* @__PURE__ */ (0,
|
|
1977
|
-
/* @__PURE__ */ (0,
|
|
1978
|
-
/* @__PURE__ */ (0,
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
className: "h-9",
|
|
1982
|
-
type: props.type ?? "text",
|
|
1983
|
-
value: props.value,
|
|
1984
|
-
onChange: (event) => props.onChange(event.target.value)
|
|
1985
|
-
}
|
|
1986
|
-
)
|
|
1987
|
-
] });
|
|
1988
|
-
}
|
|
1989
|
-
function UsageChart(props) {
|
|
1990
|
-
const buckets = import_react2.default.useMemo(() => buildUsageBuckets(props.points), [props.points]);
|
|
1991
|
-
const visibleBuckets = buckets.slice(-18);
|
|
1992
|
-
const groups = import_react2.default.useMemo(() => topUsageGroups(props.points, props.metricKind, props.dimension), [
|
|
1993
|
-
props.dimension,
|
|
1994
|
-
props.metricKind,
|
|
1995
|
-
props.points
|
|
1996
|
-
]);
|
|
1997
|
-
const maxBucketValue = Math.max(
|
|
1998
|
-
...visibleBuckets.map(
|
|
1999
|
-
(bucket) => bucket.points.reduce((sum, point) => sum + getUsagePointValue(point, props.metricKind, props.dimension), 0)
|
|
2000
|
-
),
|
|
2001
|
-
1
|
|
2002
|
-
);
|
|
2003
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: props.error ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-destructive", children: props.error }) : props.isLoading && props.points.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: props.labels.loading }) : visibleBuckets.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-4", children: [
|
|
2004
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex min-h-56 items-end gap-2", children: visibleBuckets.map((bucket) => {
|
|
2005
|
-
const bucketTotal = bucket.points.reduce((sum, point) => sum + getUsagePointValue(point, props.metricKind, props.dimension), 0);
|
|
2006
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col items-center gap-2", children: [
|
|
2007
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex h-40 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2008
|
-
"div",
|
|
2009
|
-
{
|
|
2010
|
-
className: "flex w-full flex-col-reverse overflow-hidden rounded-md",
|
|
2011
|
-
style: {
|
|
2012
|
-
height: `${Math.max(bucketTotal / maxBucketValue * 100, 6)}%`
|
|
2013
|
-
},
|
|
2014
|
-
children: groups.map((group, index) => {
|
|
2015
|
-
const point = bucket.points.find((item) => item.groupKey === group.key);
|
|
2016
|
-
const value = point ? getUsagePointValue(point, props.metricKind, props.dimension) : 0;
|
|
2017
|
-
if (value <= 0 || bucketTotal <= 0) return null;
|
|
2018
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2019
|
-
"div",
|
|
2020
|
-
{
|
|
2021
|
-
title: `${group.label}: ${formatMetricValue(value, props.metricKind)}`,
|
|
2022
|
-
style: {
|
|
2023
|
-
height: `${value / bucketTotal * 100}%`,
|
|
2024
|
-
backgroundColor: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length]
|
|
2025
|
-
}
|
|
2026
|
-
},
|
|
2027
|
-
group.key
|
|
2028
|
-
);
|
|
2029
|
-
})
|
|
2030
|
-
}
|
|
2031
|
-
) }),
|
|
2032
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
|
|
2033
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatUsageBucket(bucket.bucket, props.bucket) }),
|
|
2034
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(bucketTotal, props.metricKind) })
|
|
2035
|
-
] })
|
|
2036
|
-
] }, bucket.bucket);
|
|
2037
|
-
}) }),
|
|
2038
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex flex-wrap gap-3", children: groups.map((group, index) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2039
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2040
|
-
"span",
|
|
2041
|
-
{
|
|
2042
|
-
className: "size-2 rounded-sm",
|
|
2043
|
-
style: { backgroundColor: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length] }
|
|
2044
|
-
}
|
|
2045
|
-
),
|
|
2046
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "max-w-48 truncate text-muted-foreground", children: group.label })
|
|
2047
|
-
] }, group.key)) })
|
|
2048
|
-
] }) });
|
|
2049
|
-
}
|
|
2050
|
-
function UsageTable(props) {
|
|
2051
|
-
const rows = props.rows.slice(0, 40);
|
|
2052
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
2053
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
|
|
2054
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: "Usage detail" }),
|
|
2055
|
-
props.isLoading && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: props.labels.loading })
|
|
2056
|
-
] }),
|
|
2057
|
-
rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("table", { className: "w-full min-w-[720px] text-sm", children: [
|
|
2058
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { className: "border-b text-left text-xs uppercase tracking-[0.14em] text-muted-foreground", children: [
|
|
2059
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 font-medium", children: "Interval" }),
|
|
2060
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 font-medium", children: "Group" }),
|
|
2061
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 text-right font-medium", children: "Input" }),
|
|
2062
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 text-right font-medium", children: "Output" }),
|
|
2063
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 text-right font-medium", children: "Reasoning" }),
|
|
2064
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 text-right font-medium", children: "Cache read" }),
|
|
2065
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 pr-4 text-right font-medium", children: "Cache write" }),
|
|
2066
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("th", { className: "py-2 text-right font-medium", children: getUsageSummaryLabel(props.labels, props.metricKind, props.dimension) })
|
|
2067
|
-
] }) }),
|
|
2068
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("tbody", { children: rows.map((row) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("tr", { className: "border-b last:border-0", children: [
|
|
2069
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-muted-foreground", children: formatDate(row.bucket) }),
|
|
2070
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "max-w-72 truncate py-2 pr-4 font-medium", children: row.groupLabel }),
|
|
2071
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "input"), props.metricKind) }),
|
|
2072
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "output"), props.metricKind) }),
|
|
2073
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "reasoning"), props.metricKind) }),
|
|
2074
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "cacheRead"), props.metricKind) }),
|
|
2075
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "cacheWrite"), props.metricKind) }),
|
|
2076
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("td", { className: "py-2 text-right font-medium", children: formatMetricValue(getUsagePointValue(row, props.metricKind, props.dimension), props.metricKind) })
|
|
2077
|
-
] }, `${row.bucket}:${row.groupKey}`)) })
|
|
2078
|
-
] }) })
|
|
2079
|
-
] });
|
|
2080
|
-
}
|
|
2081
|
-
function ActivityChart(props) {
|
|
2082
|
-
const trimmedPoints = props.points.slice(-props.maxBars);
|
|
2083
|
-
const maxUsageValue = Math.max(
|
|
2084
|
-
...trimmedPoints.map(
|
|
2085
|
-
(point) => getActivityUsageValue(
|
|
2086
|
-
point,
|
|
2087
|
-
props.usageMetricKind,
|
|
2088
|
-
props.usageDimension
|
|
2089
|
-
)
|
|
2090
|
-
),
|
|
2091
|
-
1
|
|
2092
|
-
);
|
|
2093
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: trimmedPoints.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex min-h-48 items-end gap-2", children: trimmedPoints.map((point) => {
|
|
2094
|
-
const usageValue = getActivityUsageValue(
|
|
2095
|
-
point,
|
|
2096
|
-
props.usageMetricKind,
|
|
2097
|
-
props.usageDimension
|
|
2098
|
-
);
|
|
2099
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2100
|
-
"div",
|
|
2101
|
-
{
|
|
2102
|
-
className: "flex min-w-0 flex-1 flex-col items-center gap-2",
|
|
2103
|
-
children: [
|
|
2104
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex h-36 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2105
|
-
"div",
|
|
2106
|
-
{
|
|
2107
|
-
className: "w-full rounded-md bg-primary transition-all",
|
|
2108
|
-
style: {
|
|
2109
|
-
height: `${Math.max(usageValue / maxUsageValue * 100, 8)}%`
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
) }),
|
|
2113
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
|
|
2114
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
|
|
2115
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(usageValue, props.usageMetricKind) }),
|
|
2116
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
|
|
2117
|
-
formatNumber(point.totalCalls),
|
|
2118
|
-
" ",
|
|
2119
|
-
props.labels.usageCallsDetail
|
|
2120
|
-
] })
|
|
2121
|
-
] })
|
|
2122
|
-
]
|
|
2123
|
-
},
|
|
2124
|
-
point.bucket
|
|
2125
|
-
);
|
|
2126
|
-
}) }) });
|
|
2127
|
-
}
|
|
2128
|
-
function DataTable(props) {
|
|
2129
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
2130
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
|
|
2131
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: props.title }),
|
|
2132
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("label", { className: "space-y-1", children: [
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground", children: props.label }),
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative", children: [
|
|
2358
|
+
props.icon && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground", children: props.icon }),
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
2133
2360
|
Input,
|
|
2134
2361
|
{
|
|
2135
|
-
className: "h-
|
|
2136
|
-
onChange: (event) => props.
|
|
2137
|
-
|
|
2138
|
-
value: props.
|
|
2362
|
+
className: cn("h-9 bg-background", props.icon && "pl-8"),
|
|
2363
|
+
onChange: (event) => props.onChange(event.target.value),
|
|
2364
|
+
type: props.type ?? "text",
|
|
2365
|
+
value: props.value
|
|
2139
2366
|
}
|
|
2140
2367
|
)
|
|
2141
|
-
] })
|
|
2142
|
-
props.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
|
|
2368
|
+
] })
|
|
2143
2369
|
] });
|
|
2144
2370
|
}
|
|
2145
|
-
function
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
onThreadClick
|
|
2149
|
-
}) {
|
|
2150
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2151
|
-
"div",
|
|
2152
|
-
{
|
|
2153
|
-
className: cn(
|
|
2154
|
-
"rounded-lg border bg-muted/50 p-4",
|
|
2155
|
-
onThreadClick && "cursor-pointer hover:bg-muted transition-colors"
|
|
2156
|
-
),
|
|
2157
|
-
onClick: () => onThreadClick?.(thread.threadId),
|
|
2158
|
-
children: [
|
|
2159
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2160
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
2161
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: thread.name }),
|
|
2162
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
2163
|
-
] }),
|
|
2164
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2165
|
-
Badge,
|
|
2166
|
-
{
|
|
2167
|
-
variant: thread.status === "archived" ? "secondary" : "default",
|
|
2168
|
-
children: thread.status === "archived" ? labels.statusArchived : labels.statusActive
|
|
2169
|
-
}
|
|
2170
|
-
)
|
|
2171
|
-
] }),
|
|
2172
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
2173
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
2174
|
-
formatNumber(thread.messageCount),
|
|
2175
|
-
" messages"
|
|
2176
|
-
] }),
|
|
2177
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
2178
|
-
thread.participantIds.length,
|
|
2179
|
-
" participants"
|
|
2180
|
-
] }),
|
|
2181
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(thread.lastActivityAt) })
|
|
2182
|
-
] })
|
|
2183
|
-
]
|
|
2184
|
-
},
|
|
2185
|
-
thread.threadId
|
|
2186
|
-
)) });
|
|
2187
|
-
}
|
|
2188
|
-
function ParticipantsTable({
|
|
2189
|
-
rows,
|
|
2190
|
-
labels
|
|
2191
|
-
}) {
|
|
2192
|
-
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
2193
|
-
"div",
|
|
2194
|
-
{
|
|
2195
|
-
className: "rounded-lg border bg-muted/50 p-4",
|
|
2196
|
-
children: [
|
|
2197
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2198
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
2199
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: participant.displayName }),
|
|
2200
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs uppercase tracking-[0.18em] text-muted-foreground", children: participant.participantType })
|
|
2201
|
-
] }),
|
|
2202
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
|
|
2203
|
-
] }),
|
|
2204
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
|
|
2205
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
2206
|
-
formatNumber(participant.messageCount),
|
|
2207
|
-
" messages"
|
|
2208
|
-
] }),
|
|
2209
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
|
|
2210
|
-
formatNumber(participant.threadCount),
|
|
2211
|
-
" threads"
|
|
2212
|
-
] }),
|
|
2213
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(participant.lastActivityAt) })
|
|
2214
|
-
] })
|
|
2215
|
-
]
|
|
2216
|
-
},
|
|
2217
|
-
`${participant.namespace}:${participant.externalId}`
|
|
2218
|
-
)) });
|
|
2219
|
-
}
|
|
2220
|
-
function AgentsTable({
|
|
2221
|
-
rows,
|
|
2222
|
-
labels,
|
|
2223
|
-
usageMetricKind,
|
|
2224
|
-
usageDimension
|
|
2371
|
+
function EmptyDashboard({
|
|
2372
|
+
description,
|
|
2373
|
+
title
|
|
2225
2374
|
}) {
|
|
2226
|
-
return /* @__PURE__ */ (0,
|
|
2227
|
-
"
|
|
2228
|
-
{
|
|
2229
|
-
|
|
2230
|
-
children: [
|
|
2231
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2232
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
|
|
2233
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: agent.displayName }),
|
|
2234
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
|
|
2235
|
-
] }),
|
|
2236
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
|
|
2237
|
-
] }),
|
|
2238
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs", children: [
|
|
2239
|
-
{
|
|
2240
|
-
label: "Messages",
|
|
2241
|
-
value: formatNumber(agent.messageCount)
|
|
2242
|
-
},
|
|
2243
|
-
{
|
|
2244
|
-
label: "LLM calls",
|
|
2245
|
-
value: formatNumber(agent.llmCallCount)
|
|
2246
|
-
},
|
|
2247
|
-
{
|
|
2248
|
-
label: "Tool calls",
|
|
2249
|
-
value: formatNumber(agent.toolCallMessageCount)
|
|
2250
|
-
},
|
|
2251
|
-
{
|
|
2252
|
-
label: getUsageSummaryLabel(labels, usageMetricKind, usageDimension),
|
|
2253
|
-
value: formatMetricValue(
|
|
2254
|
-
getAgentUsageValue(agent, usageMetricKind, usageDimension),
|
|
2255
|
-
usageMetricKind
|
|
2256
|
-
)
|
|
2257
|
-
}
|
|
2258
|
-
].map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
|
|
2259
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium text-foreground", children: item.value }),
|
|
2260
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-muted-foreground", children: item.label })
|
|
2261
|
-
] }, item.label)) })
|
|
2262
|
-
]
|
|
2263
|
-
},
|
|
2264
|
-
`${agent.namespace}:${agent.agentId}`
|
|
2265
|
-
)) });
|
|
2266
|
-
}
|
|
2267
|
-
function formatBucket(bucket, interval) {
|
|
2268
|
-
const date = new Date(bucket);
|
|
2269
|
-
if (Number.isNaN(date.getTime())) return bucket;
|
|
2270
|
-
return interval === "hour" ? date.toLocaleString(void 0, {
|
|
2271
|
-
hour: "numeric",
|
|
2272
|
-
month: "short",
|
|
2273
|
-
day: "numeric"
|
|
2274
|
-
}) : date.toLocaleDateString(void 0, {
|
|
2275
|
-
month: "short",
|
|
2276
|
-
day: "numeric"
|
|
2277
|
-
});
|
|
2278
|
-
}
|
|
2279
|
-
function formatUsageBucket(bucket, interval) {
|
|
2280
|
-
const date = new Date(bucket);
|
|
2281
|
-
if (Number.isNaN(date.getTime())) return bucket;
|
|
2282
|
-
if (interval === "minute" || interval === "hour") {
|
|
2283
|
-
return date.toLocaleString(void 0, {
|
|
2284
|
-
month: "short",
|
|
2285
|
-
day: "numeric",
|
|
2286
|
-
hour: "numeric",
|
|
2287
|
-
minute: interval === "minute" ? "2-digit" : void 0
|
|
2288
|
-
});
|
|
2289
|
-
}
|
|
2290
|
-
if (interval === "month") {
|
|
2291
|
-
return date.toLocaleDateString(void 0, {
|
|
2292
|
-
month: "short",
|
|
2293
|
-
year: "numeric"
|
|
2294
|
-
});
|
|
2295
|
-
}
|
|
2296
|
-
return date.toLocaleDateString(void 0, {
|
|
2297
|
-
month: "short",
|
|
2298
|
-
day: "numeric"
|
|
2299
|
-
});
|
|
2300
|
-
}
|
|
2301
|
-
function formatDate(value) {
|
|
2302
|
-
if (!value) return "No activity";
|
|
2303
|
-
const date = new Date(value);
|
|
2304
|
-
if (Number.isNaN(date.getTime())) return value;
|
|
2305
|
-
return date.toLocaleString(void 0, {
|
|
2306
|
-
month: "short",
|
|
2307
|
-
day: "numeric",
|
|
2308
|
-
hour: "numeric",
|
|
2309
|
-
minute: "2-digit"
|
|
2310
|
-
});
|
|
2311
|
-
}
|
|
2312
|
-
function formatNumber(value) {
|
|
2313
|
-
return new Intl.NumberFormat().format(value);
|
|
2375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "rounded-lg border border-dashed bg-muted/20 p-8 text-center", children: [
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h3", { className: "text-base font-semibold", children: title }),
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
|
|
2378
|
+
] });
|
|
2314
2379
|
}
|
|
2380
|
+
var EMPTY_TOTALS = {
|
|
2381
|
+
inputTokens: 0,
|
|
2382
|
+
outputTokens: 0,
|
|
2383
|
+
reasoningTokens: 0,
|
|
2384
|
+
cacheReadInputTokens: 0,
|
|
2385
|
+
cacheCreationInputTokens: 0,
|
|
2386
|
+
totalTokens: 0,
|
|
2387
|
+
inputCostUsd: 0,
|
|
2388
|
+
outputCostUsd: 0,
|
|
2389
|
+
reasoningCostUsd: 0,
|
|
2390
|
+
cacheReadInputCostUsd: 0,
|
|
2391
|
+
cacheCreationInputCostUsd: 0,
|
|
2392
|
+
totalCostUsd: 0,
|
|
2393
|
+
totalCalls: 0
|
|
2394
|
+
};
|
|
2315
2395
|
var USAGE_DIMENSIONS = [
|
|
2316
2396
|
"total",
|
|
2317
2397
|
"input",
|
|
@@ -2328,27 +2408,43 @@ var USAGE_CHART_COLORS = [
|
|
|
2328
2408
|
"hsl(var(--chart-5, 346 77% 49%))",
|
|
2329
2409
|
"hsl(var(--muted-foreground))"
|
|
2330
2410
|
];
|
|
2331
|
-
function
|
|
2332
|
-
const
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2411
|
+
function buildChartState(points, metricKind, dimension, interval) {
|
|
2412
|
+
const topGroups = topUsageGroups(points, metricKind, dimension);
|
|
2413
|
+
const groupIdByKey = new Map(topGroups.map((group, index) => [
|
|
2414
|
+
group.key,
|
|
2415
|
+
`series${index + 1}`
|
|
2416
|
+
]));
|
|
2417
|
+
const series = topGroups.map((group, index) => ({
|
|
2418
|
+
color: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length],
|
|
2419
|
+
id: groupIdByKey.get(group.key) ?? `series${index + 1}`,
|
|
2420
|
+
key: group.key,
|
|
2421
|
+
label: group.label
|
|
2422
|
+
}));
|
|
2423
|
+
const config = Object.fromEntries(
|
|
2424
|
+
series.map((item) => [item.id, {
|
|
2425
|
+
color: item.color,
|
|
2426
|
+
label: item.label
|
|
2427
|
+
}])
|
|
2428
|
+
);
|
|
2429
|
+
const buckets = buildUsageBuckets(points);
|
|
2430
|
+
const data = buckets.map((bucket) => {
|
|
2431
|
+
const row = {
|
|
2432
|
+
bucket: bucket.bucket,
|
|
2433
|
+
label: formatUsageBucket(bucket.bucket, interval)
|
|
2340
2434
|
};
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
}
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2435
|
+
for (const item of series) row[item.id] = 0;
|
|
2436
|
+
for (const point of bucket.points) {
|
|
2437
|
+
const seriesId = groupIdByKey.get(point.groupKey);
|
|
2438
|
+
if (!seriesId) continue;
|
|
2439
|
+
row[seriesId] = Number(row[seriesId] ?? 0) + getUsageTotalValue(point, metricKind, dimension);
|
|
2440
|
+
}
|
|
2441
|
+
return row;
|
|
2442
|
+
});
|
|
2443
|
+
return {
|
|
2444
|
+
config,
|
|
2445
|
+
data,
|
|
2446
|
+
series
|
|
2447
|
+
};
|
|
2352
2448
|
}
|
|
2353
2449
|
function buildUsageBuckets(points) {
|
|
2354
2450
|
const byBucket = /* @__PURE__ */ new Map();
|
|
@@ -2357,7 +2453,39 @@ function buildUsageBuckets(points) {
|
|
|
2357
2453
|
rows.push(point);
|
|
2358
2454
|
byBucket.set(point.bucket, rows);
|
|
2359
2455
|
}
|
|
2360
|
-
return Array.from(byBucket.entries()).map(([bucket, bucketPoints]) => ({ bucket, points: bucketPoints })).sort(
|
|
2456
|
+
return Array.from(byBucket.entries()).map(([bucket, bucketPoints]) => ({ bucket, points: bucketPoints })).sort(
|
|
2457
|
+
(a, b) => new Date(a.bucket).getTime() - new Date(b.bucket).getTime()
|
|
2458
|
+
);
|
|
2459
|
+
}
|
|
2460
|
+
function aggregateUsageRows(points, metricKind, dimension) {
|
|
2461
|
+
const totals = /* @__PURE__ */ new Map();
|
|
2462
|
+
for (const point of points) {
|
|
2463
|
+
const existing = totals.get(point.groupKey) ?? {
|
|
2464
|
+
...EMPTY_TOTALS,
|
|
2465
|
+
groupKey: point.groupKey,
|
|
2466
|
+
groupLabel: point.groupLabel,
|
|
2467
|
+
value: 0
|
|
2468
|
+
};
|
|
2469
|
+
addUsageTotals(existing, point);
|
|
2470
|
+
existing.value = getUsageTotalValue(existing, metricKind, dimension);
|
|
2471
|
+
totals.set(point.groupKey, existing);
|
|
2472
|
+
}
|
|
2473
|
+
return Array.from(totals.values()).sort((a, b) => b.value - a.value);
|
|
2474
|
+
}
|
|
2475
|
+
function addUsageTotals(target, source) {
|
|
2476
|
+
target.inputTokens += source.inputTokens;
|
|
2477
|
+
target.outputTokens += source.outputTokens;
|
|
2478
|
+
target.reasoningTokens += source.reasoningTokens;
|
|
2479
|
+
target.cacheReadInputTokens += source.cacheReadInputTokens;
|
|
2480
|
+
target.cacheCreationInputTokens += source.cacheCreationInputTokens;
|
|
2481
|
+
target.totalTokens += source.totalTokens;
|
|
2482
|
+
target.inputCostUsd += source.inputCostUsd;
|
|
2483
|
+
target.outputCostUsd += source.outputCostUsd;
|
|
2484
|
+
target.reasoningCostUsd += source.reasoningCostUsd;
|
|
2485
|
+
target.cacheReadInputCostUsd += source.cacheReadInputCostUsd;
|
|
2486
|
+
target.cacheCreationInputCostUsd += source.cacheCreationInputCostUsd;
|
|
2487
|
+
target.totalCostUsd += source.totalCostUsd;
|
|
2488
|
+
target.totalCalls += source.totalCalls;
|
|
2361
2489
|
}
|
|
2362
2490
|
function topUsageGroups(points, metricKind, dimension) {
|
|
2363
2491
|
const totals = /* @__PURE__ */ new Map();
|
|
@@ -2367,11 +2495,33 @@ function topUsageGroups(points, metricKind, dimension) {
|
|
|
2367
2495
|
label: point.groupLabel,
|
|
2368
2496
|
value: 0
|
|
2369
2497
|
};
|
|
2370
|
-
existing.value +=
|
|
2498
|
+
existing.value += getUsageTotalValue(point, metricKind, dimension);
|
|
2371
2499
|
totals.set(point.groupKey, existing);
|
|
2372
2500
|
}
|
|
2373
2501
|
return Array.from(totals.values()).sort((a, b) => b.value - a.value).slice(0, 6);
|
|
2374
2502
|
}
|
|
2503
|
+
function getUsageRange(period, customFrom, customTo) {
|
|
2504
|
+
if (period === "custom") {
|
|
2505
|
+
return {
|
|
2506
|
+
from: customFrom ? new Date(customFrom).toISOString() : void 0,
|
|
2507
|
+
to: customTo ? new Date(customTo).toISOString() : void 0
|
|
2508
|
+
};
|
|
2509
|
+
}
|
|
2510
|
+
const to = /* @__PURE__ */ new Date();
|
|
2511
|
+
const from = new Date(to);
|
|
2512
|
+
if (period === "24h") {
|
|
2513
|
+
from.setHours(from.getHours() - 24);
|
|
2514
|
+
} else if (period === "30d") {
|
|
2515
|
+
from.setDate(from.getDate() - 30);
|
|
2516
|
+
} else {
|
|
2517
|
+
from.setDate(from.getDate() - 7);
|
|
2518
|
+
}
|
|
2519
|
+
return { from: from.toISOString(), to: to.toISOString() };
|
|
2520
|
+
}
|
|
2521
|
+
function emptyToUndefined(value) {
|
|
2522
|
+
const trimmed = value.trim();
|
|
2523
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
2524
|
+
}
|
|
2375
2525
|
function getUsageDimensionLabel(labels, dimension) {
|
|
2376
2526
|
switch (dimension) {
|
|
2377
2527
|
case "input":
|
|
@@ -2393,146 +2543,100 @@ function getUsageSummaryLabel(labels, metricKind, dimension) {
|
|
|
2393
2543
|
const metricLabel = metricKind === "cost" ? labels.usageMetricCost : metricKind === "calls" ? "Calls" : labels.usageMetricTokens;
|
|
2394
2544
|
return `${getUsageDimensionLabel(labels, dimension)} ${metricLabel}`;
|
|
2395
2545
|
}
|
|
2396
|
-
function
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
case "cacheRead":
|
|
2408
|
-
return llmTotals.cacheReadInputCostUsd;
|
|
2409
|
-
case "cacheWrite":
|
|
2410
|
-
return llmTotals.cacheCreationInputCostUsd;
|
|
2411
|
-
case "total":
|
|
2412
|
-
default:
|
|
2413
|
-
return llmTotals.totalCostUsd;
|
|
2414
|
-
}
|
|
2415
|
-
}
|
|
2416
|
-
switch (dimension) {
|
|
2417
|
-
case "input":
|
|
2418
|
-
return llmTotals.inputTokens;
|
|
2419
|
-
case "output":
|
|
2420
|
-
return llmTotals.outputTokens;
|
|
2421
|
-
case "reasoning":
|
|
2422
|
-
return llmTotals.reasoningTokens;
|
|
2423
|
-
case "cacheRead":
|
|
2424
|
-
return llmTotals.cacheReadInputTokens;
|
|
2425
|
-
case "cacheWrite":
|
|
2426
|
-
return llmTotals.cacheCreationInputTokens;
|
|
2427
|
-
case "total":
|
|
2546
|
+
function getGroupByLabel(groupBy) {
|
|
2547
|
+
switch (groupBy) {
|
|
2548
|
+
case "thread":
|
|
2549
|
+
return "Thread";
|
|
2550
|
+
case "namespace":
|
|
2551
|
+
return "Namespace";
|
|
2552
|
+
case "provider":
|
|
2553
|
+
return "Provider";
|
|
2554
|
+
case "model":
|
|
2555
|
+
return "Model";
|
|
2556
|
+
case "participant":
|
|
2428
2557
|
default:
|
|
2429
|
-
return
|
|
2558
|
+
return "Participant";
|
|
2430
2559
|
}
|
|
2431
2560
|
}
|
|
2432
|
-
function
|
|
2561
|
+
function getUsageTotalValue(totals, metricKind, dimension) {
|
|
2562
|
+
if (metricKind === "calls") return totals.totalCalls;
|
|
2433
2563
|
if (metricKind === "cost") {
|
|
2434
2564
|
switch (dimension) {
|
|
2435
2565
|
case "input":
|
|
2436
|
-
return
|
|
2566
|
+
return totals.inputCostUsd;
|
|
2437
2567
|
case "output":
|
|
2438
|
-
return
|
|
2568
|
+
return totals.outputCostUsd;
|
|
2439
2569
|
case "reasoning":
|
|
2440
|
-
return
|
|
2570
|
+
return totals.reasoningCostUsd;
|
|
2441
2571
|
case "cacheRead":
|
|
2442
|
-
return
|
|
2572
|
+
return totals.cacheReadInputCostUsd;
|
|
2443
2573
|
case "cacheWrite":
|
|
2444
|
-
return
|
|
2574
|
+
return totals.cacheCreationInputCostUsd;
|
|
2445
2575
|
case "total":
|
|
2446
2576
|
default:
|
|
2447
|
-
return
|
|
2577
|
+
return totals.totalCostUsd;
|
|
2448
2578
|
}
|
|
2449
2579
|
}
|
|
2450
|
-
if (metricKind === "calls") return agent.llmCallCount;
|
|
2451
2580
|
switch (dimension) {
|
|
2452
2581
|
case "input":
|
|
2453
|
-
return
|
|
2582
|
+
return totals.inputTokens;
|
|
2454
2583
|
case "output":
|
|
2455
|
-
return
|
|
2584
|
+
return totals.outputTokens;
|
|
2456
2585
|
case "reasoning":
|
|
2457
|
-
return
|
|
2586
|
+
return totals.reasoningTokens;
|
|
2458
2587
|
case "cacheRead":
|
|
2459
|
-
return
|
|
2588
|
+
return totals.cacheReadInputTokens;
|
|
2460
2589
|
case "cacheWrite":
|
|
2461
|
-
return
|
|
2590
|
+
return totals.cacheCreationInputTokens;
|
|
2462
2591
|
case "total":
|
|
2463
2592
|
default:
|
|
2464
|
-
return
|
|
2593
|
+
return totals.totalTokens;
|
|
2465
2594
|
}
|
|
2466
2595
|
}
|
|
2467
|
-
function
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
return point.cacheReadInputCostUsd;
|
|
2478
|
-
case "cacheWrite":
|
|
2479
|
-
return point.cacheCreationInputCostUsd;
|
|
2480
|
-
case "total":
|
|
2481
|
-
default:
|
|
2482
|
-
return point.totalCostUsd;
|
|
2483
|
-
}
|
|
2596
|
+
function formatUsageBucket(bucket, interval) {
|
|
2597
|
+
const date = new Date(bucket);
|
|
2598
|
+
if (Number.isNaN(date.getTime())) return bucket;
|
|
2599
|
+
if (interval === "minute" || interval === "hour") {
|
|
2600
|
+
return date.toLocaleString(void 0, {
|
|
2601
|
+
month: "short",
|
|
2602
|
+
day: "numeric",
|
|
2603
|
+
hour: "numeric",
|
|
2604
|
+
minute: interval === "minute" ? "2-digit" : void 0
|
|
2605
|
+
});
|
|
2484
2606
|
}
|
|
2485
|
-
if (
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
return point.outputTokens;
|
|
2491
|
-
case "reasoning":
|
|
2492
|
-
return point.reasoningTokens;
|
|
2493
|
-
case "cacheRead":
|
|
2494
|
-
return point.cacheReadInputTokens;
|
|
2495
|
-
case "cacheWrite":
|
|
2496
|
-
return point.cacheCreationInputTokens;
|
|
2497
|
-
case "total":
|
|
2498
|
-
default:
|
|
2499
|
-
return point.totalTokens;
|
|
2607
|
+
if (interval === "month") {
|
|
2608
|
+
return date.toLocaleDateString(void 0, {
|
|
2609
|
+
month: "short",
|
|
2610
|
+
year: "numeric"
|
|
2611
|
+
});
|
|
2500
2612
|
}
|
|
2613
|
+
return date.toLocaleDateString(void 0, {
|
|
2614
|
+
month: "short",
|
|
2615
|
+
day: "numeric"
|
|
2616
|
+
});
|
|
2501
2617
|
}
|
|
2502
|
-
function
|
|
2503
|
-
if (
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
case "output":
|
|
2525
|
-
return point.outputTokens;
|
|
2526
|
-
case "reasoning":
|
|
2527
|
-
return point.reasoningTokens;
|
|
2528
|
-
case "cacheRead":
|
|
2529
|
-
return point.cacheReadInputTokens;
|
|
2530
|
-
case "cacheWrite":
|
|
2531
|
-
return point.cacheCreationInputTokens;
|
|
2532
|
-
case "total":
|
|
2533
|
-
default:
|
|
2534
|
-
return point.totalTokens;
|
|
2535
|
-
}
|
|
2618
|
+
function formatUsageRangeLabel(period, range) {
|
|
2619
|
+
if (period !== "custom") return period;
|
|
2620
|
+
if (!range.from && !range.to) return "Custom";
|
|
2621
|
+
return `${formatShortDate(range.from)} - ${formatShortDate(range.to)}`;
|
|
2622
|
+
}
|
|
2623
|
+
function formatShortDate(value) {
|
|
2624
|
+
if (!value) return "Open";
|
|
2625
|
+
const date = new Date(value);
|
|
2626
|
+
if (Number.isNaN(date.getTime())) return value;
|
|
2627
|
+
return date.toLocaleDateString(void 0, {
|
|
2628
|
+
month: "short",
|
|
2629
|
+
day: "numeric"
|
|
2630
|
+
});
|
|
2631
|
+
}
|
|
2632
|
+
function formatNumber(value) {
|
|
2633
|
+
return new Intl.NumberFormat().format(value);
|
|
2634
|
+
}
|
|
2635
|
+
function formatPercent(value) {
|
|
2636
|
+
return new Intl.NumberFormat(void 0, {
|
|
2637
|
+
maximumFractionDigits: 1,
|
|
2638
|
+
style: "percent"
|
|
2639
|
+
}).format(value);
|
|
2536
2640
|
}
|
|
2537
2641
|
function formatMetricValue(value, metricKind) {
|
|
2538
2642
|
if (metricKind === "cost") {
|
|
@@ -2547,10 +2651,26 @@ function formatMetricValue(value, metricKind) {
|
|
|
2547
2651
|
}
|
|
2548
2652
|
return formatNumber(value);
|
|
2549
2653
|
}
|
|
2654
|
+
function formatCompactMetric(value, metricKind) {
|
|
2655
|
+
if (metricKind === "cost") {
|
|
2656
|
+
return new Intl.NumberFormat(void 0, {
|
|
2657
|
+
compactDisplay: "short",
|
|
2658
|
+
currency: "USD",
|
|
2659
|
+
maximumFractionDigits: 1,
|
|
2660
|
+
notation: "compact",
|
|
2661
|
+
style: "currency"
|
|
2662
|
+
}).format(value);
|
|
2663
|
+
}
|
|
2664
|
+
return new Intl.NumberFormat(void 0, {
|
|
2665
|
+
compactDisplay: "short",
|
|
2666
|
+
maximumFractionDigits: 1,
|
|
2667
|
+
notation: "compact"
|
|
2668
|
+
}).format(value);
|
|
2669
|
+
}
|
|
2550
2670
|
|
|
2551
2671
|
// src/components/views/ThreadsView.tsx
|
|
2552
|
-
var
|
|
2553
|
-
var
|
|
2672
|
+
var import_lucide_react7 = require("lucide-react");
|
|
2673
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
2554
2674
|
var ThreadsView = ({
|
|
2555
2675
|
config,
|
|
2556
2676
|
threads,
|
|
@@ -2558,10 +2678,10 @@ var ThreadsView = ({
|
|
|
2558
2678
|
onSearchChange,
|
|
2559
2679
|
onThreadClick
|
|
2560
2680
|
}) => {
|
|
2561
|
-
return /* @__PURE__ */ (0,
|
|
2562
|
-
/* @__PURE__ */ (0,
|
|
2563
|
-
/* @__PURE__ */ (0,
|
|
2564
|
-
/* @__PURE__ */ (0,
|
|
2681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-4", children: [
|
|
2682
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2565
2685
|
Input,
|
|
2566
2686
|
{
|
|
2567
2687
|
className: "pl-9",
|
|
@@ -2571,19 +2691,19 @@ var ThreadsView = ({
|
|
|
2571
2691
|
}
|
|
2572
2692
|
)
|
|
2573
2693
|
] }),
|
|
2574
|
-
threads.length === 0 ? /* @__PURE__ */ (0,
|
|
2575
|
-
/* @__PURE__ */ (0,
|
|
2576
|
-
/* @__PURE__ */ (0,
|
|
2577
|
-
] }) : /* @__PURE__ */ (0,
|
|
2694
|
+
threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.MessageSquare, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
2697
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
2578
2698
|
"div",
|
|
2579
2699
|
{
|
|
2580
2700
|
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
2581
2701
|
onClick: () => onThreadClick?.(thread.threadId),
|
|
2582
2702
|
children: [
|
|
2583
|
-
/* @__PURE__ */ (0,
|
|
2584
|
-
/* @__PURE__ */ (0,
|
|
2585
|
-
/* @__PURE__ */ (0,
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
2703
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2704
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "font-medium truncate", children: thread.name }),
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
2587
2707
|
Badge,
|
|
2588
2708
|
{
|
|
2589
2709
|
variant: thread.status === "archived" ? "secondary" : "default",
|
|
@@ -2592,18 +2712,18 @@ var ThreadsView = ({
|
|
|
2592
2712
|
}
|
|
2593
2713
|
)
|
|
2594
2714
|
] }),
|
|
2595
|
-
/* @__PURE__ */ (0,
|
|
2715
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
|
|
2596
2716
|
] }),
|
|
2597
|
-
/* @__PURE__ */ (0,
|
|
2598
|
-
/* @__PURE__ */ (0,
|
|
2717
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
|
|
2718
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
|
|
2599
2719
|
formatNumber2(thread.messageCount),
|
|
2600
2720
|
" messages"
|
|
2601
2721
|
] }),
|
|
2602
|
-
/* @__PURE__ */ (0,
|
|
2722
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
|
|
2603
2723
|
thread.participantIds.length,
|
|
2604
2724
|
" participants"
|
|
2605
2725
|
] }),
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
2726
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: formatDate(thread.lastActivityAt) })
|
|
2607
2727
|
] })
|
|
2608
2728
|
]
|
|
2609
2729
|
},
|
|
@@ -2611,7 +2731,7 @@ var ThreadsView = ({
|
|
|
2611
2731
|
)) })
|
|
2612
2732
|
] });
|
|
2613
2733
|
};
|
|
2614
|
-
function
|
|
2734
|
+
function formatDate(value) {
|
|
2615
2735
|
if (!value) return "No activity";
|
|
2616
2736
|
const date = new Date(value);
|
|
2617
2737
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2628,8 +2748,8 @@ function formatNumber2(value) {
|
|
|
2628
2748
|
|
|
2629
2749
|
// src/components/views/ThreadDetailView.tsx
|
|
2630
2750
|
var import_react3 = require("react");
|
|
2631
|
-
var
|
|
2632
|
-
var
|
|
2751
|
+
var import_lucide_react8 = require("lucide-react");
|
|
2752
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
2633
2753
|
var MESSAGES_PAGE_SIZE = 50;
|
|
2634
2754
|
var ThreadDetailView = ({
|
|
2635
2755
|
threadId,
|
|
@@ -2687,36 +2807,36 @@ var ThreadDetailView = ({
|
|
|
2687
2807
|
}
|
|
2688
2808
|
}, [threadId, pageInfo, isLoadingMore, config.baseUrl, config.getRequestHeaders]);
|
|
2689
2809
|
if (isLoading) {
|
|
2690
|
-
return /* @__PURE__ */ (0,
|
|
2810
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
2691
2811
|
}
|
|
2692
2812
|
if (error) {
|
|
2693
|
-
return /* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2696
|
-
/* @__PURE__ */ (0,
|
|
2697
|
-
/* @__PURE__ */ (0,
|
|
2813
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
|
|
2814
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "text-destructive font-medium", children: error.message }),
|
|
2815
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex justify-center gap-2", children: [
|
|
2816
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
|
|
2817
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.ArrowLeft, { className: "mr-2 h-4 w-4" }),
|
|
2698
2818
|
"Back"
|
|
2699
2819
|
] }),
|
|
2700
|
-
/* @__PURE__ */ (0,
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
|
|
2701
2821
|
] })
|
|
2702
2822
|
] });
|
|
2703
2823
|
}
|
|
2704
|
-
return /* @__PURE__ */ (0,
|
|
2705
|
-
/* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-6", children: [
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
2826
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2707
2827
|
Button,
|
|
2708
2828
|
{
|
|
2709
2829
|
variant: "ghost",
|
|
2710
2830
|
size: "icon",
|
|
2711
2831
|
className: "mt-1 shrink-0",
|
|
2712
2832
|
onClick: onBack,
|
|
2713
|
-
children: /* @__PURE__ */ (0,
|
|
2833
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.ArrowLeft, { className: "h-4 w-4" })
|
|
2714
2834
|
}
|
|
2715
2835
|
),
|
|
2716
|
-
/* @__PURE__ */ (0,
|
|
2717
|
-
/* @__PURE__ */ (0,
|
|
2718
|
-
/* @__PURE__ */ (0,
|
|
2719
|
-
/* @__PURE__ */ (0,
|
|
2836
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2837
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
2838
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
|
|
2839
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
2720
2840
|
Badge,
|
|
2721
2841
|
{
|
|
2722
2842
|
variant: thread?.status === "archived" ? "secondary" : "default",
|
|
@@ -2724,31 +2844,31 @@ var ThreadDetailView = ({
|
|
|
2724
2844
|
}
|
|
2725
2845
|
)
|
|
2726
2846
|
] }),
|
|
2727
|
-
thread?.summary && /* @__PURE__ */ (0,
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
thread?.createdAt && /* @__PURE__ */ (0,
|
|
2847
|
+
thread?.summary && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
|
|
2849
|
+
thread?.createdAt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { children: [
|
|
2730
2850
|
"Created ",
|
|
2731
|
-
|
|
2851
|
+
formatDate2(thread.createdAt)
|
|
2732
2852
|
] }),
|
|
2733
|
-
thread?.updatedAt && /* @__PURE__ */ (0,
|
|
2853
|
+
thread?.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { children: [
|
|
2734
2854
|
"Updated ",
|
|
2735
|
-
|
|
2855
|
+
formatDate2(thread.updatedAt)
|
|
2736
2856
|
] }),
|
|
2737
|
-
thread?.participants && /* @__PURE__ */ (0,
|
|
2857
|
+
thread?.participants && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { children: [
|
|
2738
2858
|
thread.participants.length,
|
|
2739
2859
|
" participants"
|
|
2740
2860
|
] })
|
|
2741
2861
|
] })
|
|
2742
2862
|
] })
|
|
2743
2863
|
] }),
|
|
2744
|
-
/* @__PURE__ */ (0,
|
|
2745
|
-
/* @__PURE__ */ (0,
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-1", children: [
|
|
2865
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("h3", { className: "text-sm font-medium text-muted-foreground", children: [
|
|
2746
2866
|
"Messages (",
|
|
2747
2867
|
messages.length,
|
|
2748
2868
|
pageInfo?.hasMoreBefore ? "+" : "",
|
|
2749
2869
|
")"
|
|
2750
2870
|
] }) }),
|
|
2751
|
-
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0,
|
|
2871
|
+
pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2752
2872
|
Button,
|
|
2753
2873
|
{
|
|
2754
2874
|
variant: "ghost",
|
|
@@ -2756,12 +2876,12 @@ var ThreadDetailView = ({
|
|
|
2756
2876
|
onClick: () => void loadMore(),
|
|
2757
2877
|
disabled: isLoadingMore,
|
|
2758
2878
|
children: [
|
|
2759
|
-
isLoadingMore ? /* @__PURE__ */ (0,
|
|
2879
|
+
isLoadingMore ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.ChevronUp, { className: "mr-2 h-3 w-3" }),
|
|
2760
2880
|
"Load older messages"
|
|
2761
2881
|
]
|
|
2762
2882
|
}
|
|
2763
2883
|
) }),
|
|
2764
|
-
/* @__PURE__ */ (0,
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(MessageRow, { message }, message.id)) }) })
|
|
2765
2885
|
] })
|
|
2766
2886
|
] });
|
|
2767
2887
|
};
|
|
@@ -2769,43 +2889,43 @@ function MessageRow({ message }) {
|
|
|
2769
2889
|
const [expanded, setExpanded] = (0, import_react3.useState)(false);
|
|
2770
2890
|
const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
|
|
2771
2891
|
const hasReasoning = !!message.reasoning;
|
|
2772
|
-
return /* @__PURE__ */ (0,
|
|
2773
|
-
/* @__PURE__ */ (0,
|
|
2774
|
-
/* @__PURE__ */ (0,
|
|
2775
|
-
/* @__PURE__ */ (0,
|
|
2776
|
-
/* @__PURE__ */ (0,
|
|
2777
|
-
/* @__PURE__ */ (0,
|
|
2778
|
-
message.createdAt && /* @__PURE__ */ (0,
|
|
2892
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-start gap-3", children: [
|
|
2893
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SenderIcon, { senderType: message.senderType }),
|
|
2894
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
2896
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
|
|
2898
|
+
message.createdAt && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
|
|
2779
2899
|
] }),
|
|
2780
|
-
message.content && /* @__PURE__ */ (0,
|
|
2781
|
-
(hasToolCalls || hasReasoning) && /* @__PURE__ */ (0,
|
|
2782
|
-
hasToolCalls && /* @__PURE__ */ (0,
|
|
2900
|
+
message.content && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
|
|
2901
|
+
(hasToolCalls || hasReasoning) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "mt-2 space-y-2", children: [
|
|
2902
|
+
hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2783
2903
|
"button",
|
|
2784
2904
|
{
|
|
2785
2905
|
type: "button",
|
|
2786
2906
|
onClick: () => setExpanded(!expanded),
|
|
2787
2907
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
2788
2908
|
children: [
|
|
2789
|
-
/* @__PURE__ */ (0,
|
|
2909
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Wrench, { className: "h-3 w-3" }),
|
|
2790
2910
|
message.toolCalls.length,
|
|
2791
2911
|
" tool call",
|
|
2792
2912
|
message.toolCalls.length > 1 ? "s" : ""
|
|
2793
2913
|
]
|
|
2794
2914
|
}
|
|
2795
2915
|
),
|
|
2796
|
-
hasReasoning && /* @__PURE__ */ (0,
|
|
2916
|
+
hasReasoning && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
|
|
2797
2917
|
"button",
|
|
2798
2918
|
{
|
|
2799
2919
|
type: "button",
|
|
2800
2920
|
onClick: () => setExpanded(!expanded),
|
|
2801
2921
|
className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
|
|
2802
2922
|
children: [
|
|
2803
|
-
/* @__PURE__ */ (0,
|
|
2923
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Cpu, { className: "h-3 w-3" }),
|
|
2804
2924
|
"Reasoning"
|
|
2805
2925
|
]
|
|
2806
2926
|
}
|
|
2807
2927
|
),
|
|
2808
|
-
expanded && /* @__PURE__ */ (0,
|
|
2928
|
+
expanded && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
|
|
2809
2929
|
{
|
|
2810
2930
|
...hasToolCalls ? { toolCalls: message.toolCalls } : {},
|
|
2811
2931
|
...hasReasoning ? { reasoning: message.reasoning } : {}
|
|
@@ -2821,16 +2941,16 @@ function SenderIcon({ senderType }) {
|
|
|
2821
2941
|
const base = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full";
|
|
2822
2942
|
switch (senderType) {
|
|
2823
2943
|
case "agent":
|
|
2824
|
-
return /* @__PURE__ */ (0,
|
|
2944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Bot, { className: "h-3.5 w-3.5" }) });
|
|
2825
2945
|
case "user":
|
|
2826
|
-
return /* @__PURE__ */ (0,
|
|
2946
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.User, { className: "h-3.5 w-3.5" }) });
|
|
2827
2947
|
case "tool":
|
|
2828
|
-
return /* @__PURE__ */ (0,
|
|
2948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Wrench, { className: "h-3.5 w-3.5" }) });
|
|
2829
2949
|
default:
|
|
2830
|
-
return /* @__PURE__ */ (0,
|
|
2950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Cpu, { className: "h-3.5 w-3.5" }) });
|
|
2831
2951
|
}
|
|
2832
2952
|
}
|
|
2833
|
-
function
|
|
2953
|
+
function formatDate2(value) {
|
|
2834
2954
|
const date = new Date(value);
|
|
2835
2955
|
if (Number.isNaN(date.getTime())) return value;
|
|
2836
2956
|
return date.toLocaleDateString(void 0, {
|
|
@@ -2852,8 +2972,8 @@ function formatTimestamp(value) {
|
|
|
2852
2972
|
}
|
|
2853
2973
|
|
|
2854
2974
|
// src/components/views/ParticipantsView.tsx
|
|
2855
|
-
var
|
|
2856
|
-
var
|
|
2975
|
+
var import_lucide_react9 = require("lucide-react");
|
|
2976
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
2857
2977
|
var ParticipantsView = ({
|
|
2858
2978
|
config,
|
|
2859
2979
|
participants,
|
|
@@ -2861,10 +2981,10 @@ var ParticipantsView = ({
|
|
|
2861
2981
|
onSearchChange,
|
|
2862
2982
|
onParticipantClick
|
|
2863
2983
|
}) => {
|
|
2864
|
-
return /* @__PURE__ */ (0,
|
|
2865
|
-
/* @__PURE__ */ (0,
|
|
2866
|
-
/* @__PURE__ */ (0,
|
|
2867
|
-
/* @__PURE__ */ (0,
|
|
2984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-4", children: [
|
|
2985
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
2986
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
2987
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
2868
2988
|
Input,
|
|
2869
2989
|
{
|
|
2870
2990
|
className: "pl-9",
|
|
@@ -2874,33 +2994,33 @@ var ParticipantsView = ({
|
|
|
2874
2994
|
}
|
|
2875
2995
|
)
|
|
2876
2996
|
] }),
|
|
2877
|
-
participants.length === 0 ? /* @__PURE__ */ (0,
|
|
2878
|
-
/* @__PURE__ */ (0,
|
|
2879
|
-
/* @__PURE__ */ (0,
|
|
2880
|
-
] }) : /* @__PURE__ */ (0,
|
|
2997
|
+
participants.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
2998
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Users, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
2999
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
3000
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "space-y-2", children: participants.map((p) => /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(
|
|
2881
3001
|
"div",
|
|
2882
3002
|
{
|
|
2883
3003
|
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
2884
3004
|
onClick: () => onParticipantClick?.(p.externalId),
|
|
2885
3005
|
children: [
|
|
2886
|
-
/* @__PURE__ */ (0,
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
2888
|
-
/* @__PURE__ */ (0,
|
|
2889
|
-
/* @__PURE__ */ (0,
|
|
2890
|
-
/* @__PURE__ */ (0,
|
|
3006
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3007
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3008
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "font-medium truncate", children: p.displayName }),
|
|
3009
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Badge, { variant: "outline", className: "shrink-0 text-xs", children: p.participantType }),
|
|
3010
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Badge, { variant: p.isGlobal ? "default" : "secondary", className: "shrink-0 text-xs", children: p.isGlobal ? config.labels.scopeGlobal : config.labels.scopeScoped })
|
|
2891
3011
|
] }),
|
|
2892
|
-
/* @__PURE__ */ (0,
|
|
3012
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
|
|
2893
3013
|
] }),
|
|
2894
|
-
/* @__PURE__ */ (0,
|
|
2895
|
-
/* @__PURE__ */ (0,
|
|
3014
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
|
|
3015
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { children: [
|
|
2896
3016
|
formatNumber3(p.messageCount),
|
|
2897
3017
|
" messages"
|
|
2898
3018
|
] }),
|
|
2899
|
-
/* @__PURE__ */ (0,
|
|
3019
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { children: [
|
|
2900
3020
|
formatNumber3(p.threadCount),
|
|
2901
3021
|
" threads"
|
|
2902
3022
|
] }),
|
|
2903
|
-
/* @__PURE__ */ (0,
|
|
3023
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: formatDate3(p.lastActivityAt) })
|
|
2904
3024
|
] })
|
|
2905
3025
|
]
|
|
2906
3026
|
},
|
|
@@ -2908,7 +3028,7 @@ var ParticipantsView = ({
|
|
|
2908
3028
|
)) })
|
|
2909
3029
|
] });
|
|
2910
3030
|
};
|
|
2911
|
-
function
|
|
3031
|
+
function formatDate3(value) {
|
|
2912
3032
|
if (!value) return "No activity";
|
|
2913
3033
|
const date = new Date(value);
|
|
2914
3034
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -2920,8 +3040,8 @@ function formatNumber3(value) {
|
|
|
2920
3040
|
|
|
2921
3041
|
// src/components/views/ParticipantDetailView.tsx
|
|
2922
3042
|
var import_react4 = require("react");
|
|
2923
|
-
var
|
|
2924
|
-
var
|
|
3043
|
+
var import_lucide_react10 = require("lucide-react");
|
|
3044
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
2925
3045
|
var ParticipantDetailView = ({
|
|
2926
3046
|
participantId,
|
|
2927
3047
|
config,
|
|
@@ -2971,25 +3091,25 @@ var ParticipantDetailView = ({
|
|
|
2971
3091
|
}
|
|
2972
3092
|
};
|
|
2973
3093
|
if (isLoading) {
|
|
2974
|
-
return /* @__PURE__ */ (0,
|
|
3094
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
2975
3095
|
}
|
|
2976
|
-
return /* @__PURE__ */ (0,
|
|
2977
|
-
/* @__PURE__ */ (0,
|
|
2978
|
-
/* @__PURE__ */ (0,
|
|
2979
|
-
/* @__PURE__ */ (0,
|
|
2980
|
-
/* @__PURE__ */ (0,
|
|
2981
|
-
/* @__PURE__ */ (0,
|
|
3096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-6", children: [
|
|
3097
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
3098
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
3099
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3100
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("h2", { className: "text-xl font-semibold truncate", children: participantId }),
|
|
3101
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "text-sm text-muted-foreground", children: "Participant Detail" })
|
|
2982
3102
|
] }),
|
|
2983
|
-
/* @__PURE__ */ (0,
|
|
2984
|
-
saveMessage && /* @__PURE__ */ (0,
|
|
2985
|
-
/* @__PURE__ */ (0,
|
|
2986
|
-
isSaving ? /* @__PURE__ */ (0,
|
|
3103
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3104
|
+
saveMessage && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
|
|
3105
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
|
|
3106
|
+
isSaving ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Save, { className: "mr-2 h-3 w-3" }),
|
|
2987
3107
|
"Save"
|
|
2988
3108
|
] })
|
|
2989
3109
|
] })
|
|
2990
3110
|
] }),
|
|
2991
|
-
error && /* @__PURE__ */ (0,
|
|
2992
|
-
/* @__PURE__ */ (0,
|
|
3111
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
3112
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2993
3113
|
"textarea",
|
|
2994
3114
|
{
|
|
2995
3115
|
className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
|
|
@@ -3002,8 +3122,8 @@ var ParticipantDetailView = ({
|
|
|
3002
3122
|
};
|
|
3003
3123
|
|
|
3004
3124
|
// src/components/views/AgentsView.tsx
|
|
3005
|
-
var
|
|
3006
|
-
var
|
|
3125
|
+
var import_lucide_react11 = require("lucide-react");
|
|
3126
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
3007
3127
|
var AgentsView = ({
|
|
3008
3128
|
config,
|
|
3009
3129
|
agents,
|
|
@@ -3011,10 +3131,10 @@ var AgentsView = ({
|
|
|
3011
3131
|
onSearchChange,
|
|
3012
3132
|
onAgentClick
|
|
3013
3133
|
}) => {
|
|
3014
|
-
return /* @__PURE__ */ (0,
|
|
3015
|
-
/* @__PURE__ */ (0,
|
|
3016
|
-
/* @__PURE__ */ (0,
|
|
3017
|
-
/* @__PURE__ */ (0,
|
|
3134
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4", children: [
|
|
3135
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
3136
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
3137
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
3018
3138
|
Input,
|
|
3019
3139
|
{
|
|
3020
3140
|
className: "pl-9",
|
|
@@ -3024,48 +3144,48 @@ var AgentsView = ({
|
|
|
3024
3144
|
}
|
|
3025
3145
|
)
|
|
3026
3146
|
] }),
|
|
3027
|
-
agents.length === 0 ? /* @__PURE__ */ (0,
|
|
3028
|
-
/* @__PURE__ */ (0,
|
|
3029
|
-
/* @__PURE__ */ (0,
|
|
3030
|
-
] }) : /* @__PURE__ */ (0,
|
|
3147
|
+
agents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
3148
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.Bot, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
3149
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
|
|
3150
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(
|
|
3031
3151
|
"div",
|
|
3032
3152
|
{
|
|
3033
3153
|
className: "rounded-lg border bg-card p-5 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
3034
3154
|
onClick: () => onAgentClick?.(agent.agentId),
|
|
3035
3155
|
children: [
|
|
3036
|
-
/* @__PURE__ */ (0,
|
|
3037
|
-
/* @__PURE__ */ (0,
|
|
3038
|
-
/* @__PURE__ */ (0,
|
|
3039
|
-
/* @__PURE__ */ (0,
|
|
3156
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
3157
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "min-w-0", children: [
|
|
3158
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "font-medium truncate", children: agent.displayName }),
|
|
3159
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
|
|
3040
3160
|
] }),
|
|
3041
|
-
/* @__PURE__ */ (0,
|
|
3161
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
|
|
3042
3162
|
] }),
|
|
3043
|
-
/* @__PURE__ */ (0,
|
|
3044
|
-
/* @__PURE__ */ (0,
|
|
3163
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
3045
3165
|
formatNumber4(agent.messageCount),
|
|
3046
3166
|
" messages"
|
|
3047
3167
|
] }),
|
|
3048
|
-
/* @__PURE__ */ (0,
|
|
3168
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
3049
3169
|
formatNumber4(agent.llmCallCount),
|
|
3050
3170
|
" LLM calls"
|
|
3051
3171
|
] }),
|
|
3052
|
-
/* @__PURE__ */ (0,
|
|
3172
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
3053
3173
|
formatNumber4(agent.toolCallMessageCount),
|
|
3054
3174
|
" tool calls"
|
|
3055
3175
|
] }),
|
|
3056
|
-
/* @__PURE__ */ (0,
|
|
3176
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
|
|
3057
3177
|
formatNumber4(agent.totalTokens),
|
|
3058
3178
|
" tokens"
|
|
3059
3179
|
] })
|
|
3060
3180
|
] }),
|
|
3061
|
-
/* @__PURE__ */ (0,
|
|
3181
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate4(agent.lastActivityAt) })
|
|
3062
3182
|
]
|
|
3063
3183
|
},
|
|
3064
3184
|
`${agent.namespace}:${agent.agentId}`
|
|
3065
3185
|
)) })
|
|
3066
3186
|
] });
|
|
3067
3187
|
};
|
|
3068
|
-
function
|
|
3188
|
+
function formatDate4(value) {
|
|
3069
3189
|
if (!value) return "No activity";
|
|
3070
3190
|
const date = new Date(value);
|
|
3071
3191
|
if (Number.isNaN(date.getTime())) return value;
|
|
@@ -3076,8 +3196,8 @@ function formatNumber4(value) {
|
|
|
3076
3196
|
}
|
|
3077
3197
|
|
|
3078
3198
|
// src/components/views/AgentDetailView.tsx
|
|
3079
|
-
var
|
|
3080
|
-
var
|
|
3199
|
+
var import_lucide_react12 = require("lucide-react");
|
|
3200
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
3081
3201
|
var AgentDetailView = ({
|
|
3082
3202
|
agentId,
|
|
3083
3203
|
config,
|
|
@@ -3086,13 +3206,13 @@ var AgentDetailView = ({
|
|
|
3086
3206
|
}) => {
|
|
3087
3207
|
const agent = agents.find((a) => a.agentId === agentId);
|
|
3088
3208
|
if (!agent) {
|
|
3089
|
-
return /* @__PURE__ */ (0,
|
|
3090
|
-
/* @__PURE__ */ (0,
|
|
3209
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
|
|
3210
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("p", { className: "text-muted-foreground", children: [
|
|
3091
3211
|
"Agent not found: ",
|
|
3092
3212
|
agentId
|
|
3093
3213
|
] }),
|
|
3094
|
-
/* @__PURE__ */ (0,
|
|
3095
|
-
/* @__PURE__ */ (0,
|
|
3214
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
|
|
3215
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.ArrowLeft, { className: "mr-2 h-4 w-4" }),
|
|
3096
3216
|
" Back"
|
|
3097
3217
|
] })
|
|
3098
3218
|
] });
|
|
@@ -3108,43 +3228,43 @@ var AgentDetailView = ({
|
|
|
3108
3228
|
{ label: "Cache Created", value: agent.cacheCreationInputTokens },
|
|
3109
3229
|
{ label: "Total Tokens", value: agent.totalTokens }
|
|
3110
3230
|
];
|
|
3111
|
-
return /* @__PURE__ */ (0,
|
|
3112
|
-
/* @__PURE__ */ (0,
|
|
3113
|
-
/* @__PURE__ */ (0,
|
|
3114
|
-
/* @__PURE__ */ (0,
|
|
3115
|
-
/* @__PURE__ */ (0,
|
|
3116
|
-
/* @__PURE__ */ (0,
|
|
3117
|
-
/* @__PURE__ */ (0,
|
|
3118
|
-
/* @__PURE__ */ (0,
|
|
3119
|
-
/* @__PURE__ */ (0,
|
|
3120
|
-
/* @__PURE__ */ (0,
|
|
3231
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "space-y-6", children: [
|
|
3232
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-start gap-4", children: [
|
|
3233
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Button, { variant: "ghost", size: "icon", className: "mt-1 shrink-0", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
3234
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3235
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
3236
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Bot, { className: "h-5 w-5" }) }),
|
|
3237
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { children: [
|
|
3238
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3239
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { className: "text-xl font-semibold", children: agent.displayName }),
|
|
3240
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
|
|
3121
3241
|
] }),
|
|
3122
|
-
agent.description && /* @__PURE__ */ (0,
|
|
3242
|
+
agent.description && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground", children: agent.description })
|
|
3123
3243
|
] })
|
|
3124
3244
|
] }),
|
|
3125
|
-
/* @__PURE__ */ (0,
|
|
3126
|
-
/* @__PURE__ */ (0,
|
|
3245
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
|
|
3246
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
|
|
3127
3247
|
"ID: ",
|
|
3128
3248
|
agent.agentId
|
|
3129
3249
|
] }),
|
|
3130
|
-
/* @__PURE__ */ (0,
|
|
3250
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
|
|
3131
3251
|
"Namespace: ",
|
|
3132
3252
|
agent.namespace
|
|
3133
3253
|
] }),
|
|
3134
|
-
agent.lastActivityAt && /* @__PURE__ */ (0,
|
|
3254
|
+
agent.lastActivityAt && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
|
|
3135
3255
|
"Last active: ",
|
|
3136
|
-
|
|
3256
|
+
formatDate5(agent.lastActivityAt)
|
|
3137
3257
|
] })
|
|
3138
3258
|
] })
|
|
3139
3259
|
] })
|
|
3140
3260
|
] }),
|
|
3141
|
-
/* @__PURE__ */ (0,
|
|
3142
|
-
/* @__PURE__ */ (0,
|
|
3143
|
-
/* @__PURE__ */ (0,
|
|
3261
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "grid gap-4 sm:grid-cols-3 lg:grid-cols-3", children: stats.map((stat) => /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
|
|
3262
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
|
|
3263
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-2 text-2xl font-semibold tracking-tight", children: new Intl.NumberFormat().format(stat.value) })
|
|
3144
3264
|
] }, stat.label)) })
|
|
3145
3265
|
] });
|
|
3146
3266
|
};
|
|
3147
|
-
function
|
|
3267
|
+
function formatDate5(value) {
|
|
3148
3268
|
const date = new Date(value);
|
|
3149
3269
|
if (Number.isNaN(date.getTime())) return value;
|
|
3150
3270
|
return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
|
|
@@ -3152,8 +3272,8 @@ function formatDate6(value) {
|
|
|
3152
3272
|
|
|
3153
3273
|
// src/components/views/CollectionItemsView.tsx
|
|
3154
3274
|
var import_react5 = require("react");
|
|
3155
|
-
var
|
|
3156
|
-
var
|
|
3275
|
+
var import_lucide_react13 = require("lucide-react");
|
|
3276
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
3157
3277
|
var CollectionItemsView = ({
|
|
3158
3278
|
collection,
|
|
3159
3279
|
config,
|
|
@@ -3199,17 +3319,17 @@ var CollectionItemsView = ({
|
|
|
3199
3319
|
if (keys.length === 0) return "(empty)";
|
|
3200
3320
|
return keys.slice(0, 3).map((k) => `${k}: ${JSON.stringify(rest[k])?.slice(0, 30)}`).join(", ");
|
|
3201
3321
|
};
|
|
3202
|
-
return /* @__PURE__ */ (0,
|
|
3203
|
-
/* @__PURE__ */ (0,
|
|
3204
|
-
/* @__PURE__ */ (0,
|
|
3205
|
-
onCreateNew && /* @__PURE__ */ (0,
|
|
3206
|
-
/* @__PURE__ */ (0,
|
|
3322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-4", children: [
|
|
3323
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
|
|
3324
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "text-lg font-semibold capitalize", children: collection }),
|
|
3325
|
+
onCreateNew && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Button, { size: "sm", onClick: onCreateNew, children: [
|
|
3326
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Plus, { className: "mr-2 h-3 w-3" }),
|
|
3207
3327
|
" New"
|
|
3208
3328
|
] })
|
|
3209
3329
|
] }),
|
|
3210
|
-
/* @__PURE__ */ (0,
|
|
3211
|
-
/* @__PURE__ */ (0,
|
|
3212
|
-
/* @__PURE__ */ (0,
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "relative max-w-sm", children: [
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
3332
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3213
3333
|
Input,
|
|
3214
3334
|
{
|
|
3215
3335
|
className: "pl-9",
|
|
@@ -3219,20 +3339,20 @@ var CollectionItemsView = ({
|
|
|
3219
3339
|
}
|
|
3220
3340
|
)
|
|
3221
3341
|
] }),
|
|
3222
|
-
error && /* @__PURE__ */ (0,
|
|
3223
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3224
|
-
/* @__PURE__ */ (0,
|
|
3225
|
-
/* @__PURE__ */ (0,
|
|
3226
|
-
] }) : /* @__PURE__ */ (0,
|
|
3342
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
3343
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
3344
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Database, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
3345
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: search ? config.labels.noResults : `No items in ${collection}` })
|
|
3346
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "space-y-2", children: items.map((item, idx) => {
|
|
3227
3347
|
const itemId = getItemId(item);
|
|
3228
|
-
return /* @__PURE__ */ (0,
|
|
3348
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
3229
3349
|
"div",
|
|
3230
3350
|
{
|
|
3231
3351
|
className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
|
|
3232
3352
|
onClick: () => onItemClick?.(itemId),
|
|
3233
|
-
children: /* @__PURE__ */ (0,
|
|
3234
|
-
/* @__PURE__ */ (0,
|
|
3235
|
-
/* @__PURE__ */ (0,
|
|
3353
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex-1 min-w-0", children: [
|
|
3354
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "font-medium font-mono text-sm truncate", children: itemId }),
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("p", { className: "mt-1 text-xs text-muted-foreground truncate", children: getItemPreview(item) })
|
|
3236
3356
|
] })
|
|
3237
3357
|
},
|
|
3238
3358
|
itemId + idx
|
|
@@ -3243,8 +3363,8 @@ var CollectionItemsView = ({
|
|
|
3243
3363
|
|
|
3244
3364
|
// src/components/views/CollectionItemDetailView.tsx
|
|
3245
3365
|
var import_react6 = require("react");
|
|
3246
|
-
var
|
|
3247
|
-
var
|
|
3366
|
+
var import_lucide_react14 = require("lucide-react");
|
|
3367
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
3248
3368
|
var CollectionItemDetailView = ({
|
|
3249
3369
|
collection,
|
|
3250
3370
|
itemId,
|
|
@@ -3318,15 +3438,15 @@ var CollectionItemDetailView = ({
|
|
|
3318
3438
|
}
|
|
3319
3439
|
};
|
|
3320
3440
|
if (isLoading) {
|
|
3321
|
-
return /* @__PURE__ */ (0,
|
|
3441
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
|
|
3322
3442
|
}
|
|
3323
|
-
return /* @__PURE__ */ (0,
|
|
3324
|
-
/* @__PURE__ */ (0,
|
|
3325
|
-
/* @__PURE__ */ (0,
|
|
3326
|
-
/* @__PURE__ */ (0,
|
|
3327
|
-
/* @__PURE__ */ (0,
|
|
3328
|
-
saveMessage && /* @__PURE__ */ (0,
|
|
3329
|
-
!isNew && /* @__PURE__ */ (0,
|
|
3443
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-6", children: [
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
3445
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.ArrowLeft, { className: "h-4 w-4" }) }),
|
|
3446
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("h2", { className: "text-xl font-semibold truncate capitalize", children: isNew ? `New ${collection} item` : `${collection} / ${itemId}` }) }),
|
|
3447
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3448
|
+
saveMessage && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
|
|
3449
|
+
!isNew && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
3330
3450
|
Button,
|
|
3331
3451
|
{
|
|
3332
3452
|
variant: "destructive",
|
|
@@ -3334,19 +3454,19 @@ var CollectionItemDetailView = ({
|
|
|
3334
3454
|
onClick: () => void handleDelete(),
|
|
3335
3455
|
disabled: isDeleting,
|
|
3336
3456
|
children: [
|
|
3337
|
-
isDeleting ? /* @__PURE__ */ (0,
|
|
3457
|
+
isDeleting ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Trash2, { className: "mr-2 h-3 w-3" }),
|
|
3338
3458
|
"Delete"
|
|
3339
3459
|
]
|
|
3340
3460
|
}
|
|
3341
3461
|
),
|
|
3342
|
-
/* @__PURE__ */ (0,
|
|
3343
|
-
isSaving ? /* @__PURE__ */ (0,
|
|
3462
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
|
|
3463
|
+
isSaving ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Save, { className: "mr-2 h-3 w-3" }),
|
|
3344
3464
|
isNew ? "Create" : "Save"
|
|
3345
3465
|
] })
|
|
3346
3466
|
] })
|
|
3347
3467
|
] }),
|
|
3348
|
-
error && /* @__PURE__ */ (0,
|
|
3349
|
-
/* @__PURE__ */ (0,
|
|
3468
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
3469
|
+
/* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
3350
3470
|
"textarea",
|
|
3351
3471
|
{
|
|
3352
3472
|
className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
|
|
@@ -3360,8 +3480,8 @@ var CollectionItemDetailView = ({
|
|
|
3360
3480
|
|
|
3361
3481
|
// src/components/views/EventsView.tsx
|
|
3362
3482
|
var import_react7 = require("react");
|
|
3363
|
-
var
|
|
3364
|
-
var
|
|
3483
|
+
var import_lucide_react15 = require("lucide-react");
|
|
3484
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
3365
3485
|
var STATUS_VARIANTS = {
|
|
3366
3486
|
pending: "outline",
|
|
3367
3487
|
processing: "default",
|
|
@@ -3394,13 +3514,13 @@ var EventsView = ({ config }) => {
|
|
|
3394
3514
|
setIsLoading(false);
|
|
3395
3515
|
}
|
|
3396
3516
|
}, [threadId, config.baseUrl, config.getRequestHeaders]);
|
|
3397
|
-
return /* @__PURE__ */ (0,
|
|
3398
|
-
/* @__PURE__ */ (0,
|
|
3399
|
-
/* @__PURE__ */ (0,
|
|
3400
|
-
/* @__PURE__ */ (0,
|
|
3401
|
-
/* @__PURE__ */ (0,
|
|
3402
|
-
/* @__PURE__ */ (0,
|
|
3403
|
-
/* @__PURE__ */ (0,
|
|
3517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-6", children: [
|
|
3518
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-end gap-3 max-w-lg", children: [
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex-1", children: [
|
|
3520
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("label", { className: "text-sm font-medium mb-1 block", children: "Thread ID" }),
|
|
3521
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
3522
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react15.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
3523
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
3404
3524
|
Input,
|
|
3405
3525
|
{
|
|
3406
3526
|
className: "pl-9",
|
|
@@ -3412,55 +3532,55 @@ var EventsView = ({ config }) => {
|
|
|
3412
3532
|
)
|
|
3413
3533
|
] })
|
|
3414
3534
|
] }),
|
|
3415
|
-
/* @__PURE__ */ (0,
|
|
3416
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3535
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Button, { onClick: () => void handleSearch(), disabled: isLoading || !threadId.trim(), children: [
|
|
3536
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react15.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
|
|
3417
3537
|
"Inspect"
|
|
3418
3538
|
] })
|
|
3419
3539
|
] }),
|
|
3420
|
-
error && /* @__PURE__ */ (0,
|
|
3421
|
-
!hasSearched ? /* @__PURE__ */ (0,
|
|
3422
|
-
/* @__PURE__ */ (0,
|
|
3423
|
-
/* @__PURE__ */ (0,
|
|
3424
|
-
] }) : isLoading ? /* @__PURE__ */ (0,
|
|
3425
|
-
/* @__PURE__ */ (0,
|
|
3426
|
-
/* @__PURE__ */ (0,
|
|
3427
|
-
] }) : /* @__PURE__ */ (0,
|
|
3428
|
-
/* @__PURE__ */ (0,
|
|
3429
|
-
/* @__PURE__ */ (0,
|
|
3430
|
-
/* @__PURE__ */ (0,
|
|
3431
|
-
/* @__PURE__ */ (0,
|
|
3540
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
|
|
3541
|
+
!hasSearched ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
3542
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react15.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
3543
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "Enter a thread ID to inspect its next pending queue event." })
|
|
3544
|
+
] }) : isLoading ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react15.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : !event ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
|
|
3545
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react15.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
|
|
3546
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "No pending events found for this thread." })
|
|
3547
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
|
|
3548
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
|
|
3549
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3550
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "font-medium", children: event.eventType }),
|
|
3551
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs text-muted-foreground font-mono mt-1", children: event.id })
|
|
3432
3552
|
] }),
|
|
3433
|
-
/* @__PURE__ */ (0,
|
|
3553
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
|
|
3434
3554
|
] }),
|
|
3435
|
-
/* @__PURE__ */ (0,
|
|
3436
|
-
event.traceId && /* @__PURE__ */ (0,
|
|
3437
|
-
/* @__PURE__ */ (0,
|
|
3555
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2 text-sm", children: [
|
|
3556
|
+
event.traceId && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3557
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-muted-foreground", children: "Trace:" }),
|
|
3438
3558
|
" ",
|
|
3439
|
-
/* @__PURE__ */ (0,
|
|
3559
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "font-mono text-xs", children: event.traceId })
|
|
3440
3560
|
] }),
|
|
3441
|
-
event.parentEventId && /* @__PURE__ */ (0,
|
|
3442
|
-
/* @__PURE__ */ (0,
|
|
3561
|
+
event.parentEventId && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3562
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-muted-foreground", children: "Parent:" }),
|
|
3443
3563
|
" ",
|
|
3444
|
-
/* @__PURE__ */ (0,
|
|
3564
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "font-mono text-xs", children: event.parentEventId })
|
|
3445
3565
|
] }),
|
|
3446
|
-
event.priority != null && /* @__PURE__ */ (0,
|
|
3447
|
-
/* @__PURE__ */ (0,
|
|
3566
|
+
event.priority != null && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3567
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-muted-foreground", children: "Priority:" }),
|
|
3448
3568
|
" ",
|
|
3449
3569
|
event.priority
|
|
3450
3570
|
] }),
|
|
3451
|
-
event.createdAt && /* @__PURE__ */ (0,
|
|
3452
|
-
/* @__PURE__ */ (0,
|
|
3571
|
+
event.createdAt && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3572
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "text-muted-foreground", children: "Created:" }),
|
|
3453
3573
|
" ",
|
|
3454
3574
|
formatTimestamp2(event.createdAt)
|
|
3455
3575
|
] })
|
|
3456
3576
|
] }),
|
|
3457
|
-
event.payload != null && /* @__PURE__ */ (0,
|
|
3458
|
-
/* @__PURE__ */ (0,
|
|
3459
|
-
/* @__PURE__ */ (0,
|
|
3577
|
+
event.payload != null && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3578
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Payload" }),
|
|
3579
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(event.payload, null, 2) })
|
|
3460
3580
|
] }),
|
|
3461
|
-
event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ (0,
|
|
3462
|
-
/* @__PURE__ */ (0,
|
|
3463
|
-
/* @__PURE__ */ (0,
|
|
3581
|
+
event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
3582
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
|
|
3583
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-40", children: JSON.stringify(event.metadata, null, 2) })
|
|
3464
3584
|
] })
|
|
3465
3585
|
] })
|
|
3466
3586
|
] });
|
|
@@ -3478,7 +3598,7 @@ function formatTimestamp2(value) {
|
|
|
3478
3598
|
}
|
|
3479
3599
|
|
|
3480
3600
|
// src/CopilotzAdmin.tsx
|
|
3481
|
-
var
|
|
3601
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
3482
3602
|
var CopilotzAdmin = ({
|
|
3483
3603
|
config: userConfig,
|
|
3484
3604
|
className
|
|
@@ -3570,18 +3690,18 @@ var CopilotzAdmin = ({
|
|
|
3570
3690
|
}
|
|
3571
3691
|
})();
|
|
3572
3692
|
if (admin.isLoading && !admin.overview) {
|
|
3573
|
-
return /* @__PURE__ */ (0,
|
|
3693
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Card, { className: cn("border-border", className), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
|
|
3574
3694
|
}
|
|
3575
3695
|
if (admin.error && !admin.overview) {
|
|
3576
|
-
return /* @__PURE__ */ (0,
|
|
3577
|
-
/* @__PURE__ */ (0,
|
|
3578
|
-
/* @__PURE__ */ (0,
|
|
3696
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Card, { className: cn("border-destructive/50 bg-destructive/10", className), children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(CardContent, { className: "space-y-4", children: [
|
|
3697
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
|
|
3698
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Button, { variant: "destructive", onClick: () => void admin.refresh(), children: config.labels.retry })
|
|
3579
3699
|
] }) });
|
|
3580
3700
|
}
|
|
3581
3701
|
const renderCurrentView = () => {
|
|
3582
3702
|
switch (route.page) {
|
|
3583
3703
|
case "dashboard":
|
|
3584
|
-
return /* @__PURE__ */ (0,
|
|
3704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3585
3705
|
DashboardView,
|
|
3586
3706
|
{
|
|
3587
3707
|
config,
|
|
@@ -3602,7 +3722,7 @@ var CopilotzAdmin = ({
|
|
|
3602
3722
|
}
|
|
3603
3723
|
);
|
|
3604
3724
|
case "threads":
|
|
3605
|
-
return /* @__PURE__ */ (0,
|
|
3725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3606
3726
|
ThreadsView,
|
|
3607
3727
|
{
|
|
3608
3728
|
config,
|
|
@@ -3613,9 +3733,9 @@ var CopilotzAdmin = ({
|
|
|
3613
3733
|
}
|
|
3614
3734
|
);
|
|
3615
3735
|
case "thread-detail":
|
|
3616
|
-
return route.resourceId ? /* @__PURE__ */ (0,
|
|
3736
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
|
|
3617
3737
|
case "participants":
|
|
3618
|
-
return /* @__PURE__ */ (0,
|
|
3738
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3619
3739
|
ParticipantsView,
|
|
3620
3740
|
{
|
|
3621
3741
|
config,
|
|
@@ -3626,9 +3746,9 @@ var CopilotzAdmin = ({
|
|
|
3626
3746
|
}
|
|
3627
3747
|
);
|
|
3628
3748
|
case "participant-detail":
|
|
3629
|
-
return route.resourceId ? /* @__PURE__ */ (0,
|
|
3749
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
|
|
3630
3750
|
case "agents":
|
|
3631
|
-
return /* @__PURE__ */ (0,
|
|
3751
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3632
3752
|
AgentsView,
|
|
3633
3753
|
{
|
|
3634
3754
|
config,
|
|
@@ -3639,9 +3759,9 @@ var CopilotzAdmin = ({
|
|
|
3639
3759
|
}
|
|
3640
3760
|
);
|
|
3641
3761
|
case "agent-detail":
|
|
3642
|
-
return route.resourceId ? /* @__PURE__ */ (0,
|
|
3762
|
+
return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
|
|
3643
3763
|
case "collection-items":
|
|
3644
|
-
return route.collection ? /* @__PURE__ */ (0,
|
|
3764
|
+
return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3645
3765
|
CollectionItemsView,
|
|
3646
3766
|
{
|
|
3647
3767
|
collection: route.collection,
|
|
@@ -3652,7 +3772,7 @@ var CopilotzAdmin = ({
|
|
|
3652
3772
|
}
|
|
3653
3773
|
) : null;
|
|
3654
3774
|
case "collection-item-detail":
|
|
3655
|
-
return route.collection ? /* @__PURE__ */ (0,
|
|
3775
|
+
return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3656
3776
|
CollectionItemDetailView,
|
|
3657
3777
|
{
|
|
3658
3778
|
collection: route.collection,
|
|
@@ -3663,12 +3783,12 @@ var CopilotzAdmin = ({
|
|
|
3663
3783
|
}
|
|
3664
3784
|
) : null;
|
|
3665
3785
|
case "events":
|
|
3666
|
-
return /* @__PURE__ */ (0,
|
|
3786
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EventsView, { config });
|
|
3667
3787
|
default:
|
|
3668
3788
|
return null;
|
|
3669
3789
|
}
|
|
3670
3790
|
};
|
|
3671
|
-
return /* @__PURE__ */ (0,
|
|
3791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
3672
3792
|
"div",
|
|
3673
3793
|
{
|
|
3674
3794
|
className: cn(
|
|
@@ -3676,7 +3796,7 @@ var CopilotzAdmin = ({
|
|
|
3676
3796
|
className
|
|
3677
3797
|
),
|
|
3678
3798
|
children: [
|
|
3679
|
-
/* @__PURE__ */ (0,
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3680
3800
|
AdminSidebar,
|
|
3681
3801
|
{
|
|
3682
3802
|
config,
|
|
@@ -3689,8 +3809,8 @@ var CopilotzAdmin = ({
|
|
|
3689
3809
|
onNamespaceChange: setNamespace
|
|
3690
3810
|
}
|
|
3691
3811
|
),
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3693
|
-
/* @__PURE__ */ (0,
|
|
3812
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
|
|
3813
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
3694
3814
|
AdminHeader,
|
|
3695
3815
|
{
|
|
3696
3816
|
config,
|
|
@@ -3703,7 +3823,7 @@ var CopilotzAdmin = ({
|
|
|
3703
3823
|
isLoading: admin.isLoading
|
|
3704
3824
|
}
|
|
3705
3825
|
),
|
|
3706
|
-
/* @__PURE__ */ (0,
|
|
3826
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
|
|
3707
3827
|
] }) })
|
|
3708
3828
|
]
|
|
3709
3829
|
}
|