@copilotz/admin 0.9.24 → 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 CHANGED
@@ -39,6 +39,7 @@ __export(index_exports, {
39
39
  fetchAdminOverview: () => fetchAdminOverview,
40
40
  fetchAdminParticipants: () => fetchAdminParticipants,
41
41
  fetchAdminThreads: () => fetchAdminThreads,
42
+ fetchAdminUsage: () => fetchAdminUsage,
42
43
  fetchCollectionItem: () => fetchCollectionItem,
43
44
  fetchCollectionItems: () => fetchCollectionItems,
44
45
  fetchCollectionNames: () => fetchCollectionNames,
@@ -299,6 +300,22 @@ async function fetchAdminAgents(search, namespace, options) {
299
300
  limit: "8"
300
301
  }, options);
301
302
  }
303
+ async function fetchAdminUsage(filters, options) {
304
+ return await fetchAdminJson("/v1/admin/usage", {
305
+ from: filters.from,
306
+ to: filters.to,
307
+ interval: filters.interval,
308
+ metric: filters.metric,
309
+ groupBy: filters.groupBy,
310
+ attribution: filters.attribution,
311
+ threadId: filters.threadId,
312
+ participantId: filters.participantId,
313
+ participantType: filters.participantType,
314
+ namespace: filters.namespace,
315
+ provider: filters.provider,
316
+ model: filters.model
317
+ }, options);
318
+ }
302
319
  async function fetchThreadDetail(threadId, options) {
303
320
  return await fetchAdminJson(
304
321
  `/v1/threads/${encodeURIComponent(threadId)}`,
@@ -563,6 +580,16 @@ function CardHeader({ className, ...props }) {
563
580
  }
564
581
  );
565
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
+ }
566
593
  function CardContent({ className, ...props }) {
567
594
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
568
595
  "div",
@@ -1549,6 +1576,8 @@ var AdminHeader = ({
1549
1576
 
1550
1577
  // src/components/views/DashboardView.tsx
1551
1578
  var import_react2 = __toESM(require("react"), 1);
1579
+ var import_recharts = require("recharts");
1580
+ var import_lucide_react6 = require("lucide-react");
1552
1581
 
1553
1582
  // src/components/ui/badge.tsx
1554
1583
  var import_react_slot3 = require("@radix-ui/react-slot");
@@ -1587,8 +1616,124 @@ function Badge({
1587
1616
  );
1588
1617
  }
1589
1618
 
1590
- // src/components/views/DashboardView.tsx
1619
+ // src/components/ui/chart.tsx
1620
+ var React5 = __toESM(require("react"), 1);
1621
+ var RechartsPrimitive = __toESM(require("recharts"), 1);
1591
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");
1592
1737
  var DashboardView = ({
1593
1738
  config,
1594
1739
  overview,
@@ -1603,423 +1748,650 @@ var DashboardView = ({
1603
1748
  onThreadSearchChange,
1604
1749
  onParticipantSearchChange,
1605
1750
  onAgentSearchChange,
1606
- onThreadClick
1751
+ onThreadClick,
1752
+ namespace
1607
1753
  }) => {
1608
- const [usageMetricKind, setUsageMetricKind] = import_react2.default.useState(
1609
- "tokens"
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,
1770
+ {
1771
+ description: config.labels.emptyDescription,
1772
+ title: config.labels.emptyTitle
1773
+ }
1774
+ );
1775
+ }
1776
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1777
+ UsageDashboard,
1778
+ {
1779
+ config,
1780
+ namespace
1781
+ }
1610
1782
  );
1611
- const [usageDimension, setUsageDimension] = import_react2.default.useState(
1612
- "total"
1783
+ };
1784
+ function UsageDashboard({
1785
+ config,
1786
+ namespace
1787
+ }) {
1788
+ const [period, setPeriod] = import_react2.default.useState("7d");
1789
+ const [bucket, setBucket] = import_react2.default.useState("day");
1790
+ const [metricKind, setMetricKind] = import_react2.default.useState(
1791
+ "cost"
1613
1792
  );
1614
- const llmSummaryValue = overview ? getOverviewUsageValue(overview, usageMetricKind, usageDimension) : 0;
1615
- const llmSummaryLabel = getUsageSummaryLabel(
1616
- config.labels,
1617
- usageMetricKind,
1618
- usageDimension
1793
+ const [dimension, setDimension] = import_react2.default.useState("total");
1794
+ const [groupBy, setGroupBy] = import_react2.default.useState(
1795
+ "participant"
1619
1796
  );
1620
- const usageBreakdownCards = USAGE_DIMENSIONS.map((dimension) => ({
1621
- dimension,
1622
- label: getUsageDimensionLabel(config.labels, dimension),
1623
- value: overview ? getOverviewUsageValue(overview, usageMetricKind, dimension) : 0
1624
- }));
1625
- const cards = [
1626
- {
1627
- label: config.labels.messagesCard,
1628
- value: overview?.messageTotals.total ?? 0,
1629
- detail: `${overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
1630
- },
1631
- {
1632
- label: config.labels.activeThreadsCard,
1633
- value: overview?.threadTotals.active ?? 0,
1634
- detail: `${overview?.threadTotals.total ?? 0} total threads`
1635
- },
1636
- {
1637
- label: config.labels.participantsCard,
1638
- value: overview?.participantTotals.total ?? 0,
1639
- detail: `${overview?.participantTotals.agents ?? 0} agents`
1640
- },
1641
- {
1642
- label: llmSummaryLabel,
1643
- value: llmSummaryValue,
1644
- detail: `${overview?.llmTotals.totalCalls ?? 0} ${config.labels.usageCallsDetail}`,
1645
- metricKind: usageMetricKind
1646
- },
1647
- {
1648
- label: config.labels.queueCard,
1649
- value: overview?.queueTotals.pending ?? 0,
1650
- detail: `${overview?.queueTotals.failed ?? 0} failed`
1797
+ const [attribution, setAttribution] = import_react2.default.useState(
1798
+ "initiatedBy"
1799
+ );
1800
+ const [participantType, setParticipantType] = import_react2.default.useState("all");
1801
+ const [threadId, setThreadId] = import_react2.default.useState("");
1802
+ const [participantId, setParticipantId] = import_react2.default.useState("");
1803
+ const [provider, setProvider] = import_react2.default.useState("");
1804
+ const [model, setModel] = import_react2.default.useState("");
1805
+ const [customFrom, setCustomFrom] = import_react2.default.useState("");
1806
+ const [customTo, setCustomTo] = import_react2.default.useState("");
1807
+ const [usage, setUsage] = import_react2.default.useState(null);
1808
+ const [isLoading, setIsLoading] = import_react2.default.useState(false);
1809
+ const [error, setError] = import_react2.default.useState(null);
1810
+ const range = import_react2.default.useMemo(() => getUsageRange(period, customFrom, customTo), [
1811
+ customFrom,
1812
+ customTo,
1813
+ period
1814
+ ]);
1815
+ const loadUsage = import_react2.default.useCallback(async () => {
1816
+ setIsLoading(true);
1817
+ setError(null);
1818
+ try {
1819
+ const next = await fetchAdminUsage({
1820
+ from: range.from,
1821
+ to: range.to,
1822
+ interval: bucket,
1823
+ metric: metricKind,
1824
+ groupBy,
1825
+ attribution,
1826
+ namespace: namespace || void 0,
1827
+ participantType,
1828
+ threadId: emptyToUndefined(threadId),
1829
+ participantId: emptyToUndefined(participantId),
1830
+ provider: emptyToUndefined(provider),
1831
+ model: emptyToUndefined(model)
1832
+ }, {
1833
+ baseUrl: config.baseUrl,
1834
+ getRequestHeaders: config.getRequestHeaders
1835
+ });
1836
+ setUsage(next);
1837
+ } catch (err) {
1838
+ setError(err instanceof Error ? err.message : "Failed to load usage");
1839
+ setUsage(null);
1840
+ } finally {
1841
+ setIsLoading(false);
1651
1842
  }
1652
- ];
1653
- const isEmpty = cards.every((card) => card.value === 0) && activity.length === 0 && threads.length === 0 && participants.length === 0 && agents.length === 0;
1654
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-6", children: [
1655
- isEmpty && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
1656
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold", children: config.labels.emptyTitle }),
1657
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-sm text-muted-foreground", children: config.labels.emptyDescription })
1658
- ] }),
1659
- config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
1660
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.overviewTitle }),
1661
- /* @__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)(
1662
- "div",
1843
+ }, [
1844
+ attribution,
1845
+ bucket,
1846
+ config.baseUrl,
1847
+ config.getRequestHeaders,
1848
+ groupBy,
1849
+ metricKind,
1850
+ model,
1851
+ namespace,
1852
+ participantId,
1853
+ participantType,
1854
+ provider,
1855
+ range.from,
1856
+ range.to,
1857
+ threadId
1858
+ ]);
1859
+ import_react2.default.useEffect(() => {
1860
+ void loadUsage();
1861
+ }, [loadUsage]);
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,
1663
1896
  {
1664
- className: "rounded-xl border bg-card p-5 shadow-sm",
1897
+ className: "w-full sm:w-auto",
1898
+ disabled: isLoading,
1899
+ onClick: () => void loadUsage(),
1900
+ size: "sm",
1901
+ variant: "outline",
1665
1902
  children: [
1666
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
1667
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatMetricValue(
1668
- card.value,
1669
- card.metricKind ?? "tokens"
1670
- ) }),
1671
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
1903
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.RefreshCw, { className: cn("size-4", isLoading && "animate-spin") }),
1904
+ config.labels.refresh
1672
1905
  ]
1673
- },
1674
- card.label
1675
- )) })
1906
+ }
1907
+ )
1676
1908
  ] }),
1677
- config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
1678
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between", children: [
1679
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.llmUsageTitle }),
1680
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2", children: [
1681
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
1682
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: config.labels.usageMetricLabel }),
1683
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1684
- Select,
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)(
1921
+ UsageSelect,
1922
+ {
1923
+ label: "Period",
1924
+ onValueChange: (value) => setPeriod(value),
1925
+ options: [
1926
+ ["24h", config.labels.range24h],
1927
+ ["7d", config.labels.range7d],
1928
+ ["30d", config.labels.range30d],
1929
+ ["custom", "Custom"]
1930
+ ],
1931
+ value: period
1932
+ }
1933
+ ),
1934
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1935
+ UsageSelect,
1936
+ {
1937
+ label: "Bucket",
1938
+ onValueChange: (value) => setBucket(value),
1939
+ options: [
1940
+ ["minute", "Minute"],
1941
+ ["hour", "Hour"],
1942
+ ["day", "Day"],
1943
+ ["week", "Week"],
1944
+ ["month", "Month"]
1945
+ ],
1946
+ value: bucket
1947
+ }
1948
+ ),
1949
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1950
+ UsageSelect,
1951
+ {
1952
+ label: config.labels.usageMetricLabel,
1953
+ onValueChange: (value) => setMetricKind(value),
1954
+ options: [
1955
+ ["cost", config.labels.usageMetricCost],
1956
+ ["tokens", config.labels.usageMetricTokens],
1957
+ ["calls", "Calls"]
1958
+ ],
1959
+ value: metricKind
1960
+ }
1961
+ ),
1962
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1963
+ UsageSelect,
1964
+ {
1965
+ label: "Group",
1966
+ onValueChange: (value) => setGroupBy(value),
1967
+ options: [
1968
+ ["participant", "Participant"],
1969
+ ["thread", "Thread"],
1970
+ ["namespace", "Namespace"],
1971
+ ["provider", "Provider"],
1972
+ ["model", "Model"]
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
1987
+ }
1988
+ ),
1989
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
1990
+ UsageSelect,
1991
+ {
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
1999
+ }
2000
+ )
2001
+ ] }),
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,
1685
2031
  {
1686
- value: usageMetricKind,
1687
- onValueChange: (value) => setUsageMetricKind(value),
1688
- children: [
1689
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectTrigger, { className: "h-9 w-full min-w-[160px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectValue, {}) }),
1690
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SelectContent, { children: [
1691
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: "tokens", children: config.labels.usageMetricTokens }),
1692
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: "cost", children: config.labels.usageMetricCost })
1693
- ] })
1694
- ]
2032
+ label: "From",
2033
+ onChange: setCustomFrom,
2034
+ type: "datetime-local",
2035
+ value: customFrom
1695
2036
  }
1696
- )
1697
- ] }),
1698
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
1699
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: config.labels.usageDimensionLabel }),
1700
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1701
- Select,
2037
+ ),
2038
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2039
+ FilterInput,
1702
2040
  {
1703
- value: usageDimension,
1704
- onValueChange: (value) => setUsageDimension(value),
1705
- children: [
1706
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectTrigger, { className: "h-9 w-full min-w-[160px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectValue, {}) }),
1707
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectContent, { children: USAGE_DIMENSIONS.map((dimension) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: dimension, children: getUsageDimensionLabel(config.labels, dimension) }, dimension)) })
1708
- ]
2041
+ label: "To",
2042
+ onChange: setCustomTo,
2043
+ type: "datetime-local",
2044
+ value: customTo
1709
2045
  }
1710
2046
  )
1711
- ] })
1712
- ] })
1713
- ] }),
1714
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: usageBreakdownCards.map((card) => {
1715
- const isSelected = card.dimension === usageDimension;
1716
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1717
- "div",
1718
- {
1719
- className: cn(
1720
- "rounded-xl border bg-card p-5 shadow-sm transition-colors",
1721
- isSelected && "border-primary/60 ring-1 ring-primary/15"
1722
- ),
1723
- children: [
1724
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
1725
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1726
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
1727
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-2xl font-semibold tracking-tight", children: formatMetricValue(card.value, usageMetricKind) })
1728
- ] }),
1729
- isSelected && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: config.labels.usageDimensionLabel })
1730
- ] }),
1731
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "mt-2 text-xs text-muted-foreground", children: [
1732
- overview?.llmTotals.totalCalls ?? 0,
1733
- " ",
1734
- config.labels.usageCallsDetail
1735
- ] })
1736
- ]
1737
- },
1738
- card.dimension
1739
- );
1740
- }) })
1741
- ] }),
1742
- config.features.showActivity && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
1743
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.activityTitle }),
1744
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1745
- ActivityChart,
1746
- {
1747
- interval,
1748
- labels: config.labels,
1749
- maxBars: config.ui.maxActivityBars,
1750
- points: activity,
1751
- usageDimension,
1752
- usageMetricKind
1753
- }
1754
- )
1755
- ] }),
1756
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-6 lg:grid-cols-3", children: [
1757
- config.features.showThreads && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1758
- DataTable,
1759
- {
1760
- rows: threads,
1761
- searchPlaceholder: config.labels.threadSearchPlaceholder,
1762
- searchValue: threadSearch,
1763
- setSearchValue: onThreadSearchChange,
1764
- title: config.labels.threadsTitle,
1765
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1766
- ThreadsTable,
2047
+ ] }),
2048
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2049
+ UsageSelect,
1767
2050
  {
1768
- rows: threads,
1769
- labels: config.labels,
1770
- onThreadClick
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
1771
2062
  }
1772
- )
1773
- }
1774
- ),
1775
- config.features.showParticipants && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1776
- DataTable,
1777
- {
1778
- rows: participants,
1779
- searchPlaceholder: config.labels.participantSearchPlaceholder,
1780
- searchValue: participantSearch,
1781
- setSearchValue: onParticipantSearchChange,
1782
- title: config.labels.participantsTitle,
1783
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ParticipantsTable, { rows: participants, labels: config.labels })
1784
- }
1785
- ),
1786
- config.features.showAgents && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1787
- DataTable,
1788
- {
1789
- rows: agents,
1790
- searchPlaceholder: config.labels.agentSearchPlaceholder,
1791
- searchValue: agentSearch,
1792
- setSearchValue: onAgentSearchChange,
1793
- title: config.labels.agentsTitle,
1794
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1795
- AgentsTable,
2063
+ ),
2064
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2065
+ FilterInput,
1796
2066
  {
1797
- rows: agents,
1798
- labels: config.labels,
1799
- usageMetricKind,
1800
- usageDimension
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
1801
2071
  }
1802
- )
1803
- }
1804
- )
1805
- ] })
1806
- ] });
1807
- };
1808
- function SectionHeading({ title }) {
1809
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("h3", { className: "text-lg font-semibold tracking-tight", children: title });
1810
- }
1811
- function ActivityChart(props) {
1812
- const trimmedPoints = props.points.slice(-props.maxBars);
1813
- const maxUsageValue = Math.max(
1814
- ...trimmedPoints.map(
1815
- (point) => getActivityUsageValue(
1816
- point,
1817
- props.usageMetricKind,
1818
- props.usageDimension
1819
- )
1820
- ),
1821
- 1
1822
- );
1823
- 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) => {
1824
- const usageValue = getActivityUsageValue(
1825
- point,
1826
- props.usageMetricKind,
1827
- props.usageDimension
1828
- );
1829
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1830
- "div",
1831
- {
1832
- className: "flex min-w-0 flex-1 flex-col items-center gap-2",
1833
- children: [
1834
- /* @__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)(
1835
- "div",
2072
+ ),
2073
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2074
+ FilterInput,
1836
2075
  {
1837
- className: "w-full rounded-md bg-primary transition-all",
1838
- style: {
1839
- height: `${Math.max(usageValue / maxUsageValue * 100, 8)}%`
1840
- }
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
1841
2080
  }
1842
- ) }),
1843
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
1844
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
1845
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(usageValue, props.usageMetricKind) }),
1846
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
1847
- formatNumber(point.totalCalls),
1848
- " ",
1849
- props.labels.usageCallsDetail
1850
- ] })
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"
1851
2116
  ] })
1852
- ]
1853
- },
1854
- point.bucket
1855
- );
1856
- }) }) });
1857
- }
1858
- function DataTable(props) {
1859
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
1860
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
1861
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: props.title }),
1862
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1863
- Input,
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,
1864
2122
  {
1865
- className: "h-8 w-full max-w-44",
1866
- onChange: (event) => props.setSearchValue(event.target.value),
1867
- placeholder: props.searchPlaceholder,
1868
- value: props.searchValue
2123
+ description: config.labels.noResults,
2124
+ title: "No usage"
1869
2125
  }
1870
- )
2126
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2127
+ UsageChart,
2128
+ {
2129
+ chartState,
2130
+ metricKind
2131
+ }
2132
+ ) })
1871
2133
  ] }),
1872
- props.rows.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
2134
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2135
+ UsageTable,
2136
+ {
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
2149
+ }
2150
+ )
1873
2151
  ] });
1874
2152
  }
1875
- function ThreadsTable({
1876
- rows,
2153
+ function UsageSummary({
2154
+ dimension,
1877
2155
  labels,
1878
- onThreadClick
2156
+ metricKind,
2157
+ totals
1879
2158
  }) {
1880
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1881
- "div",
2159
+ const summary = [
1882
2160
  {
1883
- className: cn(
1884
- "rounded-lg border bg-muted/50 p-4",
1885
- onThreadClick && "cursor-pointer hover:bg-muted transition-colors"
1886
- ),
1887
- onClick: () => onThreadClick?.(thread.threadId),
1888
- children: [
1889
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
1890
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
1891
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: thread.name }),
1892
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
1893
- ] }),
1894
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1895
- Badge,
1896
- {
1897
- variant: thread.status === "archived" ? "secondary" : "default",
1898
- children: thread.status === "archived" ? labels.statusArchived : labels.statusActive
1899
- }
1900
- )
1901
- ] }),
1902
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
1903
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1904
- formatNumber(thread.messageCount),
1905
- " messages"
1906
- ] }),
1907
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1908
- thread.participantIds.length,
1909
- " participants"
1910
- ] }),
1911
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(thread.lastActivityAt) })
1912
- ] })
1913
- ]
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
1914
2177
  },
1915
- thread.threadId
1916
- )) });
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)) });
1917
2196
  }
1918
- function ParticipantsTable({
1919
- rows,
1920
- labels
2197
+ function UsageChart({
2198
+ chartState,
2199
+ metricKind
1921
2200
  }) {
1922
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1923
- "div",
2201
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2202
+ ChartContainer,
1924
2203
  {
1925
- className: "rounded-lg border bg-muted/50 p-4",
1926
- children: [
1927
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
1928
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
1929
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: participant.displayName }),
1930
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 text-xs uppercase tracking-[0.18em] text-muted-foreground", children: participant.participantType })
1931
- ] }),
1932
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
1933
- ] }),
1934
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
1935
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1936
- formatNumber(participant.messageCount),
1937
- " messages"
1938
- ] }),
1939
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1940
- formatNumber(participant.threadCount),
1941
- " threads"
1942
- ] }),
1943
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { children: formatDate(participant.lastActivityAt) })
1944
- ] })
1945
- ]
1946
- },
1947
- `${participant.namespace}:${participant.externalId}`
1948
- )) });
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
+ );
1949
2266
  }
1950
- function AgentsTable({
1951
- rows,
2267
+ function UsageTable({
2268
+ dimension,
2269
+ groupBy,
1952
2270
  labels,
1953
- usageMetricKind,
1954
- usageDimension
2271
+ metricKind,
2272
+ onRowFilter,
2273
+ rows,
2274
+ totals
1955
2275
  }) {
1956
- return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1957
- "div",
1958
- {
1959
- className: "rounded-lg border bg-muted/50 p-4",
1960
- children: [
1961
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
1962
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "min-w-0", children: [
1963
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium", children: agent.displayName }),
1964
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
1965
- ] }),
1966
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
1967
- ] }),
1968
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs", children: [
1969
- {
1970
- label: "Messages",
1971
- value: formatNumber(agent.messageCount)
1972
- },
1973
- {
1974
- label: "LLM calls",
1975
- value: formatNumber(agent.llmCallCount)
1976
- },
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",
1977
2303
  {
1978
- label: "Tool calls",
1979
- value: formatNumber(agent.toolCallMessageCount)
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
+ ]
1980
2338
  },
1981
- {
1982
- label: getUsageSummaryLabel(labels, usageMetricKind, usageDimension),
1983
- value: formatMetricValue(
1984
- getAgentUsageValue(agent, usageMetricKind, usageDimension),
1985
- usageMetricKind
1986
- )
1987
- }
1988
- ].map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1989
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium text-foreground", children: item.value }),
1990
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-muted-foreground", children: item.label })
1991
- ] }, item.label)) })
1992
- ]
1993
- },
1994
- `${agent.namespace}:${agent.agentId}`
1995
- )) });
2339
+ row.groupKey
2340
+ );
2341
+ }) })
2342
+ ] }) }) })
2343
+ ] });
1996
2344
  }
1997
- function formatBucket(bucket, interval) {
1998
- const date = new Date(bucket);
1999
- if (Number.isNaN(date.getTime())) return bucket;
2000
- return interval === "hour" ? date.toLocaleString(void 0, {
2001
- hour: "numeric",
2002
- month: "short",
2003
- day: "numeric"
2004
- }) : date.toLocaleDateString(void 0, {
2005
- month: "short",
2006
- day: "numeric"
2007
- });
2345
+ function UsageSelect(props) {
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)) })
2351
+ ] })
2352
+ ] });
2008
2353
  }
2009
- function formatDate(value) {
2010
- if (!value) return "No activity";
2011
- const date = new Date(value);
2012
- if (Number.isNaN(date.getTime())) return value;
2013
- return date.toLocaleString(void 0, {
2014
- month: "short",
2015
- day: "numeric",
2016
- hour: "numeric",
2017
- minute: "2-digit"
2018
- });
2354
+ function FilterInput(props) {
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)(
2360
+ Input,
2361
+ {
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
2366
+ }
2367
+ )
2368
+ ] })
2369
+ ] });
2019
2370
  }
2020
- function formatNumber(value) {
2021
- return new Intl.NumberFormat().format(value);
2371
+ function EmptyDashboard({
2372
+ description,
2373
+ title
2374
+ }) {
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
+ ] });
2022
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
+ };
2023
2395
  var USAGE_DIMENSIONS = [
2024
2396
  "total",
2025
2397
  "input",
@@ -2028,6 +2400,128 @@ var USAGE_DIMENSIONS = [
2028
2400
  "cacheRead",
2029
2401
  "cacheWrite"
2030
2402
  ];
2403
+ var USAGE_CHART_COLORS = [
2404
+ "hsl(var(--primary))",
2405
+ "hsl(var(--chart-2, 142 76% 36%))",
2406
+ "hsl(var(--chart-3, 38 92% 50%))",
2407
+ "hsl(var(--chart-4, 199 89% 48%))",
2408
+ "hsl(var(--chart-5, 346 77% 49%))",
2409
+ "hsl(var(--muted-foreground))"
2410
+ ];
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)
2434
+ };
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
+ };
2448
+ }
2449
+ function buildUsageBuckets(points) {
2450
+ const byBucket = /* @__PURE__ */ new Map();
2451
+ for (const point of points) {
2452
+ const rows = byBucket.get(point.bucket) ?? [];
2453
+ rows.push(point);
2454
+ byBucket.set(point.bucket, rows);
2455
+ }
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;
2489
+ }
2490
+ function topUsageGroups(points, metricKind, dimension) {
2491
+ const totals = /* @__PURE__ */ new Map();
2492
+ for (const point of points) {
2493
+ const existing = totals.get(point.groupKey) ?? {
2494
+ key: point.groupKey,
2495
+ label: point.groupLabel,
2496
+ value: 0
2497
+ };
2498
+ existing.value += getUsageTotalValue(point, metricKind, dimension);
2499
+ totals.set(point.groupKey, existing);
2500
+ }
2501
+ return Array.from(totals.values()).sort((a, b) => b.value - a.value).slice(0, 6);
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
+ }
2031
2525
  function getUsageDimensionLabel(labels, dimension) {
2032
2526
  switch (dimension) {
2033
2527
  case "input":
@@ -2046,111 +2540,103 @@ function getUsageDimensionLabel(labels, dimension) {
2046
2540
  }
2047
2541
  }
2048
2542
  function getUsageSummaryLabel(labels, metricKind, dimension) {
2049
- const metricLabel = metricKind === "cost" ? labels.usageMetricCost : labels.usageMetricTokens;
2543
+ const metricLabel = metricKind === "cost" ? labels.usageMetricCost : metricKind === "calls" ? "Calls" : labels.usageMetricTokens;
2050
2544
  return `${getUsageDimensionLabel(labels, dimension)} ${metricLabel}`;
2051
2545
  }
2052
- function getOverviewUsageValue(overview, metricKind, dimension) {
2053
- const llmTotals = overview.llmTotals;
2054
- if (metricKind === "cost") {
2055
- switch (dimension) {
2056
- case "input":
2057
- return llmTotals.inputCostUsd;
2058
- case "output":
2059
- return llmTotals.outputCostUsd;
2060
- case "reasoning":
2061
- return llmTotals.reasoningCostUsd;
2062
- case "cacheRead":
2063
- return llmTotals.cacheReadInputCostUsd;
2064
- case "cacheWrite":
2065
- return llmTotals.cacheCreationInputCostUsd;
2066
- case "total":
2067
- default:
2068
- return llmTotals.totalCostUsd;
2069
- }
2070
- }
2071
- switch (dimension) {
2072
- case "input":
2073
- return llmTotals.inputTokens;
2074
- case "output":
2075
- return llmTotals.outputTokens;
2076
- case "reasoning":
2077
- return llmTotals.reasoningTokens;
2078
- case "cacheRead":
2079
- return llmTotals.cacheReadInputTokens;
2080
- case "cacheWrite":
2081
- return llmTotals.cacheCreationInputTokens;
2082
- 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":
2083
2557
  default:
2084
- return llmTotals.totalTokens;
2558
+ return "Participant";
2085
2559
  }
2086
2560
  }
2087
- function getAgentUsageValue(agent, metricKind, dimension) {
2561
+ function getUsageTotalValue(totals, metricKind, dimension) {
2562
+ if (metricKind === "calls") return totals.totalCalls;
2088
2563
  if (metricKind === "cost") {
2089
2564
  switch (dimension) {
2090
2565
  case "input":
2091
- return agent.inputCostUsd;
2566
+ return totals.inputCostUsd;
2092
2567
  case "output":
2093
- return agent.outputCostUsd;
2568
+ return totals.outputCostUsd;
2094
2569
  case "reasoning":
2095
- return agent.reasoningCostUsd;
2570
+ return totals.reasoningCostUsd;
2096
2571
  case "cacheRead":
2097
- return agent.cacheReadInputCostUsd;
2572
+ return totals.cacheReadInputCostUsd;
2098
2573
  case "cacheWrite":
2099
- return agent.cacheCreationInputCostUsd;
2574
+ return totals.cacheCreationInputCostUsd;
2100
2575
  case "total":
2101
2576
  default:
2102
- return agent.totalCostUsd;
2577
+ return totals.totalCostUsd;
2103
2578
  }
2104
2579
  }
2105
2580
  switch (dimension) {
2106
2581
  case "input":
2107
- return agent.inputTokens;
2582
+ return totals.inputTokens;
2108
2583
  case "output":
2109
- return agent.outputTokens;
2584
+ return totals.outputTokens;
2110
2585
  case "reasoning":
2111
- return agent.reasoningTokens;
2586
+ return totals.reasoningTokens;
2112
2587
  case "cacheRead":
2113
- return agent.cacheReadInputTokens;
2588
+ return totals.cacheReadInputTokens;
2114
2589
  case "cacheWrite":
2115
- return agent.cacheCreationInputTokens;
2590
+ return totals.cacheCreationInputTokens;
2116
2591
  case "total":
2117
2592
  default:
2118
- return agent.totalTokens;
2593
+ return totals.totalTokens;
2119
2594
  }
2120
2595
  }
2121
- function getActivityUsageValue(point, metricKind, dimension) {
2122
- if (metricKind === "cost") {
2123
- switch (dimension) {
2124
- case "input":
2125
- return point.inputCostUsd;
2126
- case "output":
2127
- return point.outputCostUsd;
2128
- case "reasoning":
2129
- return point.reasoningCostUsd;
2130
- case "cacheRead":
2131
- return point.cacheReadInputCostUsd;
2132
- case "cacheWrite":
2133
- return point.cacheCreationInputCostUsd;
2134
- case "total":
2135
- default:
2136
- return point.totalCostUsd;
2137
- }
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
+ });
2138
2606
  }
2139
- switch (dimension) {
2140
- case "input":
2141
- return point.inputTokens;
2142
- case "output":
2143
- return point.outputTokens;
2144
- case "reasoning":
2145
- return point.reasoningTokens;
2146
- case "cacheRead":
2147
- return point.cacheReadInputTokens;
2148
- case "cacheWrite":
2149
- return point.cacheCreationInputTokens;
2150
- case "total":
2151
- default:
2152
- return point.totalTokens;
2607
+ if (interval === "month") {
2608
+ return date.toLocaleDateString(void 0, {
2609
+ month: "short",
2610
+ year: "numeric"
2611
+ });
2153
2612
  }
2613
+ return date.toLocaleDateString(void 0, {
2614
+ month: "short",
2615
+ day: "numeric"
2616
+ });
2617
+ }
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);
2154
2640
  }
2155
2641
  function formatMetricValue(value, metricKind) {
2156
2642
  if (metricKind === "cost") {
@@ -2165,10 +2651,26 @@ function formatMetricValue(value, metricKind) {
2165
2651
  }
2166
2652
  return formatNumber(value);
2167
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
+ }
2168
2670
 
2169
2671
  // src/components/views/ThreadsView.tsx
2170
- var import_lucide_react6 = require("lucide-react");
2171
- var import_jsx_runtime13 = require("react/jsx-runtime");
2672
+ var import_lucide_react7 = require("lucide-react");
2673
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2172
2674
  var ThreadsView = ({
2173
2675
  config,
2174
2676
  threads,
@@ -2176,10 +2678,10 @@ var ThreadsView = ({
2176
2678
  onSearchChange,
2177
2679
  onThreadClick
2178
2680
  }) => {
2179
- return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "space-y-4", children: [
2180
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative max-w-sm", children: [
2181
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2182
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
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)(
2183
2685
  Input,
2184
2686
  {
2185
2687
  className: "pl-9",
@@ -2189,19 +2691,19 @@ var ThreadsView = ({
2189
2691
  }
2190
2692
  )
2191
2693
  ] }),
2192
- threads.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2193
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react6.MessageSquare, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2194
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2195
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
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)(
2196
2698
  "div",
2197
2699
  {
2198
2700
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
2199
2701
  onClick: () => onThreadClick?.(thread.threadId),
2200
2702
  children: [
2201
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex-1 min-w-0", children: [
2202
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-2", children: [
2203
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "font-medium truncate", children: thread.name }),
2204
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
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)(
2205
2707
  Badge,
2206
2708
  {
2207
2709
  variant: thread.status === "archived" ? "secondary" : "default",
@@ -2210,18 +2712,18 @@ var ThreadsView = ({
2210
2712
  }
2211
2713
  )
2212
2714
  ] }),
2213
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
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" })
2214
2716
  ] }),
2215
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
2216
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { children: [
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: [
2217
2719
  formatNumber2(thread.messageCount),
2218
2720
  " messages"
2219
2721
  ] }),
2220
- /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("p", { children: [
2722
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("p", { children: [
2221
2723
  thread.participantIds.length,
2222
2724
  " participants"
2223
2725
  ] }),
2224
- /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { children: formatDate2(thread.lastActivityAt) })
2726
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: formatDate(thread.lastActivityAt) })
2225
2727
  ] })
2226
2728
  ]
2227
2729
  },
@@ -2229,7 +2731,7 @@ var ThreadsView = ({
2229
2731
  )) })
2230
2732
  ] });
2231
2733
  };
2232
- function formatDate2(value) {
2734
+ function formatDate(value) {
2233
2735
  if (!value) return "No activity";
2234
2736
  const date = new Date(value);
2235
2737
  if (Number.isNaN(date.getTime())) return value;
@@ -2246,8 +2748,8 @@ function formatNumber2(value) {
2246
2748
 
2247
2749
  // src/components/views/ThreadDetailView.tsx
2248
2750
  var import_react3 = require("react");
2249
- var import_lucide_react7 = require("lucide-react");
2250
- var import_jsx_runtime14 = require("react/jsx-runtime");
2751
+ var import_lucide_react8 = require("lucide-react");
2752
+ var import_jsx_runtime15 = require("react/jsx-runtime");
2251
2753
  var MESSAGES_PAGE_SIZE = 50;
2252
2754
  var ThreadDetailView = ({
2253
2755
  threadId,
@@ -2305,36 +2807,36 @@ var ThreadDetailView = ({
2305
2807
  }
2306
2808
  }, [threadId, pageInfo, isLoadingMore, config.baseUrl, config.getRequestHeaders]);
2307
2809
  if (isLoading) {
2308
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
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" }) });
2309
2811
  }
2310
2812
  if (error) {
2311
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
2312
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "text-destructive font-medium", children: error.message }),
2313
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex justify-center gap-2", children: [
2314
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
2315
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ArrowLeft, { className: "mr-2 h-4 w-4" }),
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" }),
2316
2818
  "Back"
2317
2819
  ] }),
2318
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
2820
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
2319
2821
  ] })
2320
2822
  ] });
2321
2823
  }
2322
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-6", children: [
2323
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start gap-4", children: [
2324
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
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)(
2325
2827
  Button,
2326
2828
  {
2327
2829
  variant: "ghost",
2328
2830
  size: "icon",
2329
2831
  className: "mt-1 shrink-0",
2330
2832
  onClick: onBack,
2331
- children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ArrowLeft, { className: "h-4 w-4" })
2833
+ children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.ArrowLeft, { className: "h-4 w-4" })
2332
2834
  }
2333
2835
  ),
2334
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0", children: [
2335
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2", children: [
2336
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
2337
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
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)(
2338
2840
  Badge,
2339
2841
  {
2340
2842
  variant: thread?.status === "archived" ? "secondary" : "default",
@@ -2342,31 +2844,31 @@ var ThreadDetailView = ({
2342
2844
  }
2343
2845
  )
2344
2846
  ] }),
2345
- thread?.summary && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
2346
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
2347
- thread?.createdAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
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: [
2348
2850
  "Created ",
2349
- formatDate3(thread.createdAt)
2851
+ formatDate2(thread.createdAt)
2350
2852
  ] }),
2351
- thread?.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
2853
+ thread?.updatedAt && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { children: [
2352
2854
  "Updated ",
2353
- formatDate3(thread.updatedAt)
2855
+ formatDate2(thread.updatedAt)
2354
2856
  ] }),
2355
- thread?.participants && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { children: [
2857
+ thread?.participants && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { children: [
2356
2858
  thread.participants.length,
2357
2859
  " participants"
2358
2860
  ] })
2359
2861
  ] })
2360
2862
  ] })
2361
2863
  ] }),
2362
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "space-y-1", children: [
2363
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("h3", { className: "text-sm font-medium text-muted-foreground", children: [
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: [
2364
2866
  "Messages (",
2365
2867
  messages.length,
2366
2868
  pageInfo?.hasMoreBefore ? "+" : "",
2367
2869
  ")"
2368
2870
  ] }) }),
2369
- pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2871
+ pageInfo?.hasMoreBefore && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2370
2872
  Button,
2371
2873
  {
2372
2874
  variant: "ghost",
@@ -2374,12 +2876,12 @@ var ThreadDetailView = ({
2374
2876
  onClick: () => void loadMore(),
2375
2877
  disabled: isLoadingMore,
2376
2878
  children: [
2377
- isLoadingMore ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.ChevronUp, { className: "mr-2 h-3 w-3" }),
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" }),
2378
2880
  "Load older messages"
2379
2881
  ]
2380
2882
  }
2381
2883
  ) }),
2382
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(MessageRow, { message }, message.id)) }) })
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)) }) })
2383
2885
  ] })
2384
2886
  ] });
2385
2887
  };
@@ -2387,43 +2889,43 @@ function MessageRow({ message }) {
2387
2889
  const [expanded, setExpanded] = (0, import_react3.useState)(false);
2388
2890
  const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
2389
2891
  const hasReasoning = !!message.reasoning;
2390
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "px-4 py-3", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-start gap-3", children: [
2391
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(SenderIcon, { senderType: message.senderType }),
2392
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex-1 min-w-0", children: [
2393
- /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex items-center gap-2 text-xs", children: [
2394
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
2395
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
2396
- message.createdAt && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
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) })
2397
2899
  ] }),
2398
- message.content && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
2399
- (hasToolCalls || hasReasoning) && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "mt-2 space-y-2", children: [
2400
- hasToolCalls && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
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)(
2401
2903
  "button",
2402
2904
  {
2403
2905
  type: "button",
2404
2906
  onClick: () => setExpanded(!expanded),
2405
2907
  className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
2406
2908
  children: [
2407
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Wrench, { className: "h-3 w-3" }),
2909
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Wrench, { className: "h-3 w-3" }),
2408
2910
  message.toolCalls.length,
2409
2911
  " tool call",
2410
2912
  message.toolCalls.length > 1 ? "s" : ""
2411
2913
  ]
2412
2914
  }
2413
2915
  ),
2414
- hasReasoning && /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2916
+ hasReasoning && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
2415
2917
  "button",
2416
2918
  {
2417
2919
  type: "button",
2418
2920
  onClick: () => setExpanded(!expanded),
2419
2921
  className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
2420
2922
  children: [
2421
- /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Cpu, { className: "h-3 w-3" }),
2923
+ /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Cpu, { className: "h-3 w-3" }),
2422
2924
  "Reasoning"
2423
2925
  ]
2424
2926
  }
2425
2927
  ),
2426
- expanded && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
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(
2427
2929
  {
2428
2930
  ...hasToolCalls ? { toolCalls: message.toolCalls } : {},
2429
2931
  ...hasReasoning ? { reasoning: message.reasoning } : {}
@@ -2439,16 +2941,16 @@ function SenderIcon({ senderType }) {
2439
2941
  const base = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full";
2440
2942
  switch (senderType) {
2441
2943
  case "agent":
2442
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Bot, { className: "h-3.5 w-3.5" }) });
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" }) });
2443
2945
  case "user":
2444
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.User, { className: "h-3.5 w-3.5" }) });
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" }) });
2445
2947
  case "tool":
2446
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Wrench, { className: "h-3.5 w-3.5" }) });
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" }) });
2447
2949
  default:
2448
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react7.Cpu, { className: "h-3.5 w-3.5" }) });
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" }) });
2449
2951
  }
2450
2952
  }
2451
- function formatDate3(value) {
2953
+ function formatDate2(value) {
2452
2954
  const date = new Date(value);
2453
2955
  if (Number.isNaN(date.getTime())) return value;
2454
2956
  return date.toLocaleDateString(void 0, {
@@ -2470,8 +2972,8 @@ function formatTimestamp(value) {
2470
2972
  }
2471
2973
 
2472
2974
  // src/components/views/ParticipantsView.tsx
2473
- var import_lucide_react8 = require("lucide-react");
2474
- var import_jsx_runtime15 = require("react/jsx-runtime");
2975
+ var import_lucide_react9 = require("lucide-react");
2976
+ var import_jsx_runtime16 = require("react/jsx-runtime");
2475
2977
  var ParticipantsView = ({
2476
2978
  config,
2477
2979
  participants,
@@ -2479,10 +2981,10 @@ var ParticipantsView = ({
2479
2981
  onSearchChange,
2480
2982
  onParticipantClick
2481
2983
  }) => {
2482
- return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-4", children: [
2483
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "relative max-w-sm", children: [
2484
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2485
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
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)(
2486
2988
  Input,
2487
2989
  {
2488
2990
  className: "pl-9",
@@ -2492,33 +2994,33 @@ var ParticipantsView = ({
2492
2994
  }
2493
2995
  )
2494
2996
  ] }),
2495
- participants.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2496
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react8.Users, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2497
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2498
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "space-y-2", children: participants.map((p) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
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)(
2499
3001
  "div",
2500
3002
  {
2501
3003
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
2502
3004
  onClick: () => onParticipantClick?.(p.externalId),
2503
3005
  children: [
2504
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex-1 min-w-0", children: [
2505
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2", children: [
2506
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "font-medium truncate", children: p.displayName }),
2507
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Badge, { variant: "outline", className: "shrink-0 text-xs", children: p.participantType }),
2508
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(Badge, { variant: p.isGlobal ? "default" : "secondary", className: "shrink-0 text-xs", children: p.isGlobal ? config.labels.scopeGlobal : config.labels.scopeScoped })
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 })
2509
3011
  ] }),
2510
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
3012
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
2511
3013
  ] }),
2512
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
2513
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { children: [
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: [
2514
3016
  formatNumber3(p.messageCount),
2515
3017
  " messages"
2516
3018
  ] }),
2517
- /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("p", { children: [
3019
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("p", { children: [
2518
3020
  formatNumber3(p.threadCount),
2519
3021
  " threads"
2520
3022
  ] }),
2521
- /* @__PURE__ */ (0, import_jsx_runtime15.jsx)("p", { children: formatDate4(p.lastActivityAt) })
3023
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { children: formatDate3(p.lastActivityAt) })
2522
3024
  ] })
2523
3025
  ]
2524
3026
  },
@@ -2526,7 +3028,7 @@ var ParticipantsView = ({
2526
3028
  )) })
2527
3029
  ] });
2528
3030
  };
2529
- function formatDate4(value) {
3031
+ function formatDate3(value) {
2530
3032
  if (!value) return "No activity";
2531
3033
  const date = new Date(value);
2532
3034
  if (Number.isNaN(date.getTime())) return value;
@@ -2538,8 +3040,8 @@ function formatNumber3(value) {
2538
3040
 
2539
3041
  // src/components/views/ParticipantDetailView.tsx
2540
3042
  var import_react4 = require("react");
2541
- var import_lucide_react9 = require("lucide-react");
2542
- var import_jsx_runtime16 = require("react/jsx-runtime");
3043
+ var import_lucide_react10 = require("lucide-react");
3044
+ var import_jsx_runtime17 = require("react/jsx-runtime");
2543
3045
  var ParticipantDetailView = ({
2544
3046
  participantId,
2545
3047
  config,
@@ -2589,25 +3091,25 @@ var ParticipantDetailView = ({
2589
3091
  }
2590
3092
  };
2591
3093
  if (isLoading) {
2592
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
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" }) });
2593
3095
  }
2594
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "space-y-6", children: [
2595
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-4", children: [
2596
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.ArrowLeft, { className: "h-4 w-4" }) }),
2597
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex-1 min-w-0", children: [
2598
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("h2", { className: "text-xl font-semibold truncate", children: participantId }),
2599
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("p", { className: "text-sm text-muted-foreground", children: "Participant Detail" })
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" })
2600
3102
  ] }),
2601
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "flex items-center gap-2", children: [
2602
- saveMessage && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
2603
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
2604
- isSaving ? /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_lucide_react9.Save, { className: "mr-2 h-3 w-3" }),
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" }),
2605
3107
  "Save"
2606
3108
  ] })
2607
3109
  ] })
2608
3110
  ] }),
2609
- error && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
2610
- /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
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)(
2611
3113
  "textarea",
2612
3114
  {
2613
3115
  className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
@@ -2620,8 +3122,8 @@ var ParticipantDetailView = ({
2620
3122
  };
2621
3123
 
2622
3124
  // src/components/views/AgentsView.tsx
2623
- var import_lucide_react10 = require("lucide-react");
2624
- var import_jsx_runtime17 = require("react/jsx-runtime");
3125
+ var import_lucide_react11 = require("lucide-react");
3126
+ var import_jsx_runtime18 = require("react/jsx-runtime");
2625
3127
  var AgentsView = ({
2626
3128
  config,
2627
3129
  agents,
@@ -2629,10 +3131,10 @@ var AgentsView = ({
2629
3131
  onSearchChange,
2630
3132
  onAgentClick
2631
3133
  }) => {
2632
- return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "space-y-4", children: [
2633
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "relative max-w-sm", children: [
2634
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2635
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
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)(
2636
3138
  Input,
2637
3139
  {
2638
3140
  className: "pl-9",
@@ -2642,48 +3144,48 @@ var AgentsView = ({
2642
3144
  }
2643
3145
  )
2644
3146
  ] }),
2645
- agents.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2646
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(import_lucide_react10.Bot, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2647
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2648
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
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)(
2649
3151
  "div",
2650
3152
  {
2651
3153
  className: "rounded-lg border bg-card p-5 transition-colors hover:bg-muted/50 cursor-pointer",
2652
3154
  onClick: () => onAgentClick?.(agent.agentId),
2653
3155
  children: [
2654
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
2655
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "min-w-0", children: [
2656
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "font-medium truncate", children: agent.displayName }),
2657
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
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 })
2658
3160
  ] }),
2659
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
3161
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
2660
3162
  ] }),
2661
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
2662
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
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: [
2663
3165
  formatNumber4(agent.messageCount),
2664
3166
  " messages"
2665
3167
  ] }),
2666
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
3168
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
2667
3169
  formatNumber4(agent.llmCallCount),
2668
3170
  " LLM calls"
2669
3171
  ] }),
2670
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
3172
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
2671
3173
  formatNumber4(agent.toolCallMessageCount),
2672
3174
  " tool calls"
2673
3175
  ] }),
2674
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { children: [
3176
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
2675
3177
  formatNumber4(agent.totalTokens),
2676
3178
  " tokens"
2677
3179
  ] })
2678
3180
  ] }),
2679
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate5(agent.lastActivityAt) })
3181
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate4(agent.lastActivityAt) })
2680
3182
  ]
2681
3183
  },
2682
3184
  `${agent.namespace}:${agent.agentId}`
2683
3185
  )) })
2684
3186
  ] });
2685
3187
  };
2686
- function formatDate5(value) {
3188
+ function formatDate4(value) {
2687
3189
  if (!value) return "No activity";
2688
3190
  const date = new Date(value);
2689
3191
  if (Number.isNaN(date.getTime())) return value;
@@ -2694,8 +3196,8 @@ function formatNumber4(value) {
2694
3196
  }
2695
3197
 
2696
3198
  // src/components/views/AgentDetailView.tsx
2697
- var import_lucide_react11 = require("lucide-react");
2698
- var import_jsx_runtime18 = require("react/jsx-runtime");
3199
+ var import_lucide_react12 = require("lucide-react");
3200
+ var import_jsx_runtime19 = require("react/jsx-runtime");
2699
3201
  var AgentDetailView = ({
2700
3202
  agentId,
2701
3203
  config,
@@ -2704,13 +3206,13 @@ var AgentDetailView = ({
2704
3206
  }) => {
2705
3207
  const agent = agents.find((a) => a.agentId === agentId);
2706
3208
  if (!agent) {
2707
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-4 py-10 text-center", children: [
2708
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("p", { className: "text-muted-foreground", children: [
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: [
2709
3211
  "Agent not found: ",
2710
3212
  agentId
2711
3213
  ] }),
2712
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Button, { variant: "outline", onClick: onBack, children: [
2713
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.ArrowLeft, { className: "mr-2 h-4 w-4" }),
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" }),
2714
3216
  " Back"
2715
3217
  ] })
2716
3218
  ] });
@@ -2726,43 +3228,43 @@ var AgentDetailView = ({
2726
3228
  { label: "Cache Created", value: agent.cacheCreationInputTokens },
2727
3229
  { label: "Total Tokens", value: agent.totalTokens }
2728
3230
  ];
2729
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-6", children: [
2730
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-start gap-4", children: [
2731
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Button, { variant: "ghost", size: "icon", className: "mt-1 shrink-0", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react11.ArrowLeft, { className: "h-4 w-4" }) }),
2732
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex-1 min-w-0", children: [
2733
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-3", children: [
2734
- /* @__PURE__ */ (0, import_jsx_runtime18.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_runtime18.jsx)(import_lucide_react11.Bot, { className: "h-5 w-5" }) }),
2735
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { children: [
2736
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex items-center gap-2", children: [
2737
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("h2", { className: "text-xl font-semibold", children: agent.displayName }),
2738
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
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 })
2739
3241
  ] }),
2740
- agent.description && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm text-muted-foreground", children: agent.description })
3242
+ agent.description && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "text-sm text-muted-foreground", children: agent.description })
2741
3243
  ] })
2742
3244
  ] }),
2743
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
2744
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
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: [
2745
3247
  "ID: ",
2746
3248
  agent.agentId
2747
3249
  ] }),
2748
- /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
2749
3251
  "Namespace: ",
2750
3252
  agent.namespace
2751
3253
  ] }),
2752
- agent.lastActivityAt && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { children: [
3254
+ agent.lastActivityAt && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { children: [
2753
3255
  "Last active: ",
2754
- formatDate6(agent.lastActivityAt)
3256
+ formatDate5(agent.lastActivityAt)
2755
3257
  ] })
2756
3258
  ] })
2757
3259
  ] })
2758
3260
  ] }),
2759
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "grid gap-4 sm:grid-cols-3 lg:grid-cols-3", children: stats.map((stat) => /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
2760
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
2761
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { className: "mt-2 text-2xl font-semibold tracking-tight", children: new Intl.NumberFormat().format(stat.value) })
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) })
2762
3264
  ] }, stat.label)) })
2763
3265
  ] });
2764
3266
  };
2765
- function formatDate6(value) {
3267
+ function formatDate5(value) {
2766
3268
  const date = new Date(value);
2767
3269
  if (Number.isNaN(date.getTime())) return value;
2768
3270
  return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
@@ -2770,8 +3272,8 @@ function formatDate6(value) {
2770
3272
 
2771
3273
  // src/components/views/CollectionItemsView.tsx
2772
3274
  var import_react5 = require("react");
2773
- var import_lucide_react12 = require("lucide-react");
2774
- var import_jsx_runtime19 = require("react/jsx-runtime");
3275
+ var import_lucide_react13 = require("lucide-react");
3276
+ var import_jsx_runtime20 = require("react/jsx-runtime");
2775
3277
  var CollectionItemsView = ({
2776
3278
  collection,
2777
3279
  config,
@@ -2817,17 +3319,17 @@ var CollectionItemsView = ({
2817
3319
  if (keys.length === 0) return "(empty)";
2818
3320
  return keys.slice(0, 3).map((k) => `${k}: ${JSON.stringify(rest[k])?.slice(0, 30)}`).join(", ");
2819
3321
  };
2820
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "space-y-4", children: [
2821
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex items-center justify-between gap-4", children: [
2822
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("h2", { className: "text-lg font-semibold capitalize", children: collection }),
2823
- onCreateNew && /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Button, { size: "sm", onClick: onCreateNew, children: [
2824
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Plus, { className: "mr-2 h-3 w-3" }),
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" }),
2825
3327
  " New"
2826
3328
  ] })
2827
3329
  ] }),
2828
- /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "relative max-w-sm", children: [
2829
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2830
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
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)(
2831
3333
  Input,
2832
3334
  {
2833
3335
  className: "pl-9",
@@ -2837,20 +3339,20 @@ var CollectionItemsView = ({
2837
3339
  }
2838
3340
  )
2839
3341
  ] }),
2840
- error && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
2841
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2842
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react12.Database, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2843
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: search ? config.labels.noResults : `No items in ${collection}` })
2844
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("div", { className: "space-y-2", children: items.map((item, idx) => {
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) => {
2845
3347
  const itemId = getItemId(item);
2846
- return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
3348
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
2847
3349
  "div",
2848
3350
  {
2849
3351
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
2850
3352
  onClick: () => onItemClick?.(itemId),
2851
- children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex-1 min-w-0", children: [
2852
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "font-medium font-mono text-sm truncate", children: itemId }),
2853
- /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { className: "mt-1 text-xs text-muted-foreground truncate", children: getItemPreview(item) })
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) })
2854
3356
  ] })
2855
3357
  },
2856
3358
  itemId + idx
@@ -2861,8 +3363,8 @@ var CollectionItemsView = ({
2861
3363
 
2862
3364
  // src/components/views/CollectionItemDetailView.tsx
2863
3365
  var import_react6 = require("react");
2864
- var import_lucide_react13 = require("lucide-react");
2865
- var import_jsx_runtime20 = require("react/jsx-runtime");
3366
+ var import_lucide_react14 = require("lucide-react");
3367
+ var import_jsx_runtime21 = require("react/jsx-runtime");
2866
3368
  var CollectionItemDetailView = ({
2867
3369
  collection,
2868
3370
  itemId,
@@ -2936,15 +3438,15 @@ var CollectionItemDetailView = ({
2936
3438
  }
2937
3439
  };
2938
3440
  if (isLoading) {
2939
- return /* @__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" }) });
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" }) });
2940
3442
  }
2941
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "space-y-6", children: [
2942
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-4", children: [
2943
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.ArrowLeft, { className: "h-4 w-4" }) }),
2944
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h2", { className: "text-xl font-semibold truncate capitalize", children: isNew ? `New ${collection} item` : `${collection} / ${itemId}` }) }),
2945
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "flex items-center gap-2", children: [
2946
- saveMessage && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "text-xs text-emerald-600", children: saveMessage }),
2947
- !isNew && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
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)(
2948
3450
  Button,
2949
3451
  {
2950
3452
  variant: "destructive",
@@ -2952,19 +3454,19 @@ var CollectionItemDetailView = ({
2952
3454
  onClick: () => void handleDelete(),
2953
3455
  disabled: isDeleting,
2954
3456
  children: [
2955
- isDeleting ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Trash2, { className: "mr-2 h-3 w-3" }),
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" }),
2956
3458
  "Delete"
2957
3459
  ]
2958
3460
  }
2959
3461
  ),
2960
- /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
2961
- isSaving ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react13.Save, { className: "mr-2 h-3 w-3" }),
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" }),
2962
3464
  isNew ? "Create" : "Save"
2963
3465
  ] })
2964
3466
  ] })
2965
3467
  ] }),
2966
- 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 }),
2967
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
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)(
2968
3470
  "textarea",
2969
3471
  {
2970
3472
  className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
@@ -2978,8 +3480,8 @@ var CollectionItemDetailView = ({
2978
3480
 
2979
3481
  // src/components/views/EventsView.tsx
2980
3482
  var import_react7 = require("react");
2981
- var import_lucide_react14 = require("lucide-react");
2982
- var import_jsx_runtime21 = require("react/jsx-runtime");
3483
+ var import_lucide_react15 = require("lucide-react");
3484
+ var import_jsx_runtime22 = require("react/jsx-runtime");
2983
3485
  var STATUS_VARIANTS = {
2984
3486
  pending: "outline",
2985
3487
  processing: "default",
@@ -3012,13 +3514,13 @@ var EventsView = ({ config }) => {
3012
3514
  setIsLoading(false);
3013
3515
  }
3014
3516
  }, [threadId, config.baseUrl, config.getRequestHeaders]);
3015
- return /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "space-y-6", children: [
3016
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-end gap-3 max-w-lg", children: [
3017
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex-1", children: [
3018
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("label", { className: "text-sm font-medium mb-1 block", children: "Thread ID" }),
3019
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "relative", children: [
3020
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3021
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
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)(
3022
3524
  Input,
3023
3525
  {
3024
3526
  className: "pl-9",
@@ -3030,55 +3532,55 @@ var EventsView = ({ config }) => {
3030
3532
  )
3031
3533
  ] })
3032
3534
  ] }),
3033
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(Button, { onClick: () => void handleSearch(), disabled: isLoading || !threadId.trim(), children: [
3034
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
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,
3035
3537
  "Inspect"
3036
3538
  ] })
3037
3539
  ] }),
3038
- 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 }),
3039
- !hasSearched ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3040
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3041
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "Enter a thread ID to inspect its next pending queue event." })
3042
- ] }) : isLoading ? /* @__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" }) }) : !event ? /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3043
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react14.Activity, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3044
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "mt-3 text-sm text-muted-foreground", children: "No pending events found for this thread." })
3045
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
3046
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
3047
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3048
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "font-medium", children: event.eventType }),
3049
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs text-muted-foreground font-mono mt-1", children: event.id })
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 })
3050
3552
  ] }),
3051
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
3553
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
3052
3554
  ] }),
3053
- /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2 text-sm", children: [
3054
- event.traceId && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3055
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Trace:" }),
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:" }),
3056
3558
  " ",
3057
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-mono text-xs", children: event.traceId })
3559
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "font-mono text-xs", children: event.traceId })
3058
3560
  ] }),
3059
- event.parentEventId && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3060
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Parent:" }),
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:" }),
3061
3563
  " ",
3062
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "font-mono text-xs", children: event.parentEventId })
3564
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { className: "font-mono text-xs", children: event.parentEventId })
3063
3565
  ] }),
3064
- event.priority != null && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3065
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Priority:" }),
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:" }),
3066
3568
  " ",
3067
3569
  event.priority
3068
3570
  ] }),
3069
- event.createdAt && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3070
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "text-muted-foreground", children: "Created:" }),
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:" }),
3071
3573
  " ",
3072
3574
  formatTimestamp2(event.createdAt)
3073
3575
  ] })
3074
3576
  ] }),
3075
- event.payload != null && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3076
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Payload" }),
3077
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(event.payload, null, 2) })
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) })
3078
3580
  ] }),
3079
- event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)("div", { children: [
3080
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
3081
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-40", children: JSON.stringify(event.metadata, null, 2) })
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) })
3082
3584
  ] })
3083
3585
  ] })
3084
3586
  ] });
@@ -3096,7 +3598,7 @@ function formatTimestamp2(value) {
3096
3598
  }
3097
3599
 
3098
3600
  // src/CopilotzAdmin.tsx
3099
- var import_jsx_runtime22 = require("react/jsx-runtime");
3601
+ var import_jsx_runtime23 = require("react/jsx-runtime");
3100
3602
  var CopilotzAdmin = ({
3101
3603
  config: userConfig,
3102
3604
  className
@@ -3188,18 +3690,18 @@ var CopilotzAdmin = ({
3188
3690
  }
3189
3691
  })();
3190
3692
  if (admin.isLoading && !admin.overview) {
3191
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: cn("border-border", className), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
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 }) });
3192
3694
  }
3193
3695
  if (admin.error && !admin.overview) {
3194
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Card, { className: cn("border-destructive/50 bg-destructive/10", className), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(CardContent, { className: "space-y-4", children: [
3195
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
3196
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { variant: "destructive", onClick: () => void admin.refresh(), children: config.labels.retry })
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 })
3197
3699
  ] }) });
3198
3700
  }
3199
3701
  const renderCurrentView = () => {
3200
3702
  switch (route.page) {
3201
3703
  case "dashboard":
3202
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3704
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3203
3705
  DashboardView,
3204
3706
  {
3205
3707
  config,
@@ -3209,6 +3711,7 @@ var CopilotzAdmin = ({
3209
3711
  participants: admin.participants,
3210
3712
  agents: admin.agents,
3211
3713
  interval: admin.filters.interval,
3714
+ namespace,
3212
3715
  threadSearch,
3213
3716
  participantSearch,
3214
3717
  agentSearch,
@@ -3219,7 +3722,7 @@ var CopilotzAdmin = ({
3219
3722
  }
3220
3723
  );
3221
3724
  case "threads":
3222
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3725
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3223
3726
  ThreadsView,
3224
3727
  {
3225
3728
  config,
@@ -3230,9 +3733,9 @@ var CopilotzAdmin = ({
3230
3733
  }
3231
3734
  );
3232
3735
  case "thread-detail":
3233
- return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
3736
+ return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
3234
3737
  case "participants":
3235
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3738
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3236
3739
  ParticipantsView,
3237
3740
  {
3238
3741
  config,
@@ -3243,9 +3746,9 @@ var CopilotzAdmin = ({
3243
3746
  }
3244
3747
  );
3245
3748
  case "participant-detail":
3246
- return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
3749
+ return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
3247
3750
  case "agents":
3248
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3751
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3249
3752
  AgentsView,
3250
3753
  {
3251
3754
  config,
@@ -3256,9 +3759,9 @@ var CopilotzAdmin = ({
3256
3759
  }
3257
3760
  );
3258
3761
  case "agent-detail":
3259
- return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
3762
+ return route.resourceId ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
3260
3763
  case "collection-items":
3261
- return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3764
+ return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3262
3765
  CollectionItemsView,
3263
3766
  {
3264
3767
  collection: route.collection,
@@ -3269,7 +3772,7 @@ var CopilotzAdmin = ({
3269
3772
  }
3270
3773
  ) : null;
3271
3774
  case "collection-item-detail":
3272
- return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3775
+ return route.collection ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3273
3776
  CollectionItemDetailView,
3274
3777
  {
3275
3778
  collection: route.collection,
@@ -3280,12 +3783,12 @@ var CopilotzAdmin = ({
3280
3783
  }
3281
3784
  ) : null;
3282
3785
  case "events":
3283
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EventsView, { config });
3786
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(EventsView, { config });
3284
3787
  default:
3285
3788
  return null;
3286
3789
  }
3287
3790
  };
3288
- return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
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)(
3289
3792
  "div",
3290
3793
  {
3291
3794
  className: cn(
@@ -3293,7 +3796,7 @@ var CopilotzAdmin = ({
3293
3796
  className
3294
3797
  ),
3295
3798
  children: [
3296
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
3799
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
3297
3800
  AdminSidebar,
3298
3801
  {
3299
3802
  config,
@@ -3306,8 +3809,8 @@ var CopilotzAdmin = ({
3306
3809
  onNamespaceChange: setNamespace
3307
3810
  }
3308
3811
  ),
3309
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SidebarInset, { children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex flex-col h-full min-h-0", children: [
3310
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
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)(
3311
3814
  AdminHeader,
3312
3815
  {
3313
3816
  config,
@@ -3320,7 +3823,7 @@ var CopilotzAdmin = ({
3320
3823
  isLoading: admin.isLoading
3321
3824
  }
3322
3825
  ),
3323
- /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
3826
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
3324
3827
  ] }) })
3325
3828
  ]
3326
3829
  }
@@ -3337,6 +3840,7 @@ var CopilotzAdmin = ({
3337
3840
  fetchAdminOverview,
3338
3841
  fetchAdminParticipants,
3339
3842
  fetchAdminThreads,
3843
+ fetchAdminUsage,
3340
3844
  fetchCollectionItem,
3341
3845
  fetchCollectionItems,
3342
3846
  fetchCollectionNames,