@copilotz/admin 0.9.27 → 0.9.28

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.js CHANGED
@@ -1431,7 +1431,7 @@ var AdminSidebar = ({
1431
1431
 
1432
1432
  // src/components/layout/AdminHeader.tsx
1433
1433
  import { RefreshCw } from "lucide-react";
1434
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1434
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1435
1435
  var PAGE_TITLES = {
1436
1436
  dashboard: "Dashboard",
1437
1437
  threads: "Threads",
@@ -1447,73 +1447,24 @@ var PAGE_TITLES = {
1447
1447
  var AdminHeader = ({
1448
1448
  config,
1449
1449
  currentRoute,
1450
- range,
1451
- interval,
1452
- onRangeChange,
1453
- onIntervalChange,
1454
1450
  onRefresh,
1455
- isLoading
1451
+ isLoading,
1452
+ controls
1456
1453
  }) => {
1457
1454
  let pageTitle = config.labels[`${currentRoute.page}Title`] || PAGE_TITLES[currentRoute.page] || currentRoute.page;
1458
1455
  if (currentRoute.page === "collection-items" && currentRoute.collection) {
1459
1456
  pageTitle = currentRoute.collection.charAt(0).toUpperCase() + currentRoute.collection.slice(1);
1460
1457
  }
1461
- return /* @__PURE__ */ jsx10(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80", children: /* @__PURE__ */ jsx10(CardHeader, { className: "p-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
1462
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
1458
+ return /* @__PURE__ */ jsx10(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 shadow-none", children: /* @__PURE__ */ jsx10(CardHeader, { className: "px-3 py-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex min-h-10 flex-wrap items-center gap-2", children: [
1459
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-1", children: [
1463
1460
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1464
1461
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(SidebarTrigger, { className: "-ml-1" }) }),
1465
1462
  /* @__PURE__ */ jsx10(TooltipContent, { children: "Toggle Sidebar" })
1466
1463
  ] }),
1467
- /* @__PURE__ */ jsx10("h1", { className: "text-sm font-medium ml-2", children: pageTitle })
1464
+ /* @__PURE__ */ jsx10("h1", { className: "ml-2 whitespace-nowrap text-sm font-medium", children: pageTitle })
1468
1465
  ] }),
1469
- /* @__PURE__ */ jsx10("div", { className: "flex-1" }),
1470
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
1471
- currentRoute.page === "dashboard" && /* @__PURE__ */ jsxs6(Fragment2, { children: [
1472
- /* @__PURE__ */ jsx10(
1473
- Button,
1474
- {
1475
- variant: range === "24h" ? "default" : "ghost",
1476
- size: "sm",
1477
- className: "h-7 text-xs",
1478
- onClick: () => onRangeChange("24h"),
1479
- children: config.labels.range24h
1480
- }
1481
- ),
1482
- /* @__PURE__ */ jsx10(
1483
- Button,
1484
- {
1485
- variant: range === "7d" ? "default" : "ghost",
1486
- size: "sm",
1487
- className: "h-7 text-xs",
1488
- onClick: () => onRangeChange("7d"),
1489
- children: config.labels.range7d
1490
- }
1491
- ),
1492
- /* @__PURE__ */ jsx10(
1493
- Button,
1494
- {
1495
- variant: range === "30d" ? "default" : "ghost",
1496
- size: "sm",
1497
- className: "h-7 text-xs",
1498
- onClick: () => onRangeChange("30d"),
1499
- children: config.labels.range30d
1500
- }
1501
- ),
1502
- /* @__PURE__ */ jsxs6(
1503
- Select,
1504
- {
1505
- value: interval,
1506
- onValueChange: (v) => onIntervalChange(v),
1507
- children: [
1508
- /* @__PURE__ */ jsx10(SelectTrigger, { className: "h-7 w-[90px] text-xs", children: /* @__PURE__ */ jsx10(SelectValue, {}) }),
1509
- /* @__PURE__ */ jsxs6(SelectContent, { children: [
1510
- /* @__PURE__ */ jsx10(SelectItem, { value: "hour", children: config.labels.intervalHour }),
1511
- /* @__PURE__ */ jsx10(SelectItem, { value: "day", children: config.labels.intervalDay })
1512
- ] })
1513
- ]
1514
- }
1515
- )
1516
- ] }),
1466
+ controls && /* @__PURE__ */ jsx10("div", { className: "flex min-w-[240px] flex-1 items-center justify-end gap-2 overflow-x-auto", children: controls }),
1467
+ /* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-1", children: [
1517
1468
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1518
1469
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
1519
1470
  Button,
@@ -1553,7 +1504,6 @@ import {
1553
1504
  Activity as Activity2,
1554
1505
  Database as Database2,
1555
1506
  Filter,
1556
- RefreshCw as RefreshCw2,
1557
1507
  Search,
1558
1508
  Sparkles,
1559
1509
  Users as Users2,
@@ -1714,7 +1664,7 @@ function ChartLegendContent({
1714
1664
  }
1715
1665
 
1716
1666
  // src/components/views/DashboardView.tsx
1717
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1667
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1718
1668
  var DashboardView = ({
1719
1669
  config,
1720
1670
  overview,
@@ -1730,7 +1680,9 @@ var DashboardView = ({
1730
1680
  onParticipantSearchChange,
1731
1681
  onAgentSearchChange,
1732
1682
  onThreadClick,
1733
- namespace
1683
+ namespace,
1684
+ setHeaderControls,
1685
+ setHeaderRefresh
1734
1686
  }) => {
1735
1687
  void overview;
1736
1688
  void activity;
@@ -1758,13 +1710,17 @@ var DashboardView = ({
1758
1710
  UsageDashboard,
1759
1711
  {
1760
1712
  config,
1761
- namespace
1713
+ namespace,
1714
+ setHeaderControls,
1715
+ setHeaderRefresh
1762
1716
  }
1763
1717
  );
1764
1718
  };
1765
1719
  function UsageDashboard({
1766
1720
  config,
1767
- namespace
1721
+ namespace,
1722
+ setHeaderControls,
1723
+ setHeaderRefresh
1768
1724
  }) {
1769
1725
  const [period, setPeriod] = React6.useState("7d");
1770
1726
  const [bucket, setBucket] = React6.useState("day");
@@ -1862,243 +1818,109 @@ function UsageDashboard({
1862
1818
  period === "custom" ? customFrom : "",
1863
1819
  period === "custom" ? customTo : ""
1864
1820
  ].filter((value) => value.trim().length > 0).length;
1865
- return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
1866
- /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between", children: [
1867
- /* @__PURE__ */ jsxs8("div", { children: [
1868
- /* @__PURE__ */ jsx13("h2", { className: "text-2xl font-semibold tracking-tight", children: config.labels.llmUsageTitle }),
1869
- /* @__PURE__ */ jsxs8("div", { className: "mt-2 flex flex-wrap items-center gap-2", children: [
1870
- /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: formatUsageRangeLabel(period, range) }),
1871
- /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: getGroupByLabel(groupBy) }),
1872
- groupBy === "participant" && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: attribution === "initiatedBy" ? "Initiated by sender" : "Generated by caller" })
1873
- ] })
1874
- ] }),
1875
- /* @__PURE__ */ jsxs8(
1876
- Button,
1877
- {
1878
- className: "w-full sm:w-auto",
1879
- disabled: isLoading,
1880
- onClick: () => void loadUsage(),
1881
- size: "sm",
1882
- variant: "outline",
1883
- children: [
1884
- /* @__PURE__ */ jsx13(RefreshCw2, { className: cn("size-4", isLoading && "animate-spin") }),
1885
- config.labels.refresh
1886
- ]
1887
- }
1888
- )
1889
- ] }),
1890
- /* @__PURE__ */ jsx13(
1891
- UsageSummary,
1892
- {
1893
- dimension,
1894
- labels: config.labels,
1895
- metricKind,
1896
- totals
1897
- }
1898
- ),
1899
- /* @__PURE__ */ jsx13(Card, { className: "gap-4 overflow-hidden py-4", children: /* @__PURE__ */ jsxs8(CardContent, { className: "space-y-4 px-4 lg:px-5", children: [
1900
- /* @__PURE__ */ jsxs8("div", { className: "grid gap-2 md:grid-cols-2 xl:grid-cols-6", children: [
1901
- /* @__PURE__ */ jsx13(
1902
- UsageSelect,
1903
- {
1904
- label: "Period",
1905
- onValueChange: (value) => setPeriod(value),
1906
- options: [
1907
- ["24h", config.labels.range24h],
1908
- ["7d", config.labels.range7d],
1909
- ["30d", config.labels.range30d],
1910
- ["custom", "Custom"]
1911
- ],
1912
- value: period
1913
- }
1914
- ),
1915
- /* @__PURE__ */ jsx13(
1916
- UsageSelect,
1917
- {
1918
- label: "Bucket",
1919
- onValueChange: (value) => setBucket(value),
1920
- options: [
1921
- ["minute", "Minute"],
1922
- ["hour", "Hour"],
1923
- ["day", "Day"],
1924
- ["week", "Week"],
1925
- ["month", "Month"]
1926
- ],
1927
- value: bucket
1928
- }
1929
- ),
1930
- /* @__PURE__ */ jsx13(
1931
- UsageSelect,
1932
- {
1933
- label: config.labels.usageMetricLabel,
1934
- onValueChange: (value) => setMetricKind(value),
1935
- options: [
1936
- ["cost", config.labels.usageMetricCost],
1937
- ["tokens", config.labels.usageMetricTokens],
1938
- ["calls", "Calls"]
1939
- ],
1940
- value: metricKind
1941
- }
1942
- ),
1943
- /* @__PURE__ */ jsx13(
1944
- UsageSelect,
1945
- {
1946
- label: "Group",
1947
- onValueChange: (value) => setGroupBy(value),
1948
- options: [
1949
- ["participant", "Participant"],
1950
- ["thread", "Thread"],
1951
- ["namespace", "Namespace"],
1952
- ["provider", "Provider"],
1953
- ["model", "Model"]
1954
- ],
1955
- value: groupBy
1956
- }
1957
- ),
1958
- /* @__PURE__ */ jsx13(
1959
- UsageSelect,
1960
- {
1961
- label: "Attribution",
1962
- onValueChange: (value) => setAttribution(value),
1963
- options: [
1964
- ["initiatedBy", "Initiated by"],
1965
- ["generatedBy", "Generated by"]
1966
- ],
1967
- value: attribution
1968
- }
1969
- ),
1821
+ const clearFilters = React6.useCallback(() => {
1822
+ setParticipantType("all");
1823
+ setThreadId("");
1824
+ setParticipantId("");
1825
+ setProvider("");
1826
+ setModel("");
1827
+ setCustomFrom("");
1828
+ setCustomTo("");
1829
+ }, []);
1830
+ const headerControls = React6.useMemo(() => /* @__PURE__ */ jsx13(
1831
+ DashboardHeaderControls,
1832
+ {
1833
+ attribution,
1834
+ bucket,
1835
+ config,
1836
+ dimension,
1837
+ groupBy,
1838
+ metricKind,
1839
+ period,
1840
+ setAttribution,
1841
+ setBucket,
1842
+ setDimension,
1843
+ setGroupBy,
1844
+ setMetricKind,
1845
+ setPeriod
1846
+ }
1847
+ ), [
1848
+ attribution,
1849
+ bucket,
1850
+ config,
1851
+ dimension,
1852
+ groupBy,
1853
+ metricKind,
1854
+ period
1855
+ ]);
1856
+ React6.useEffect(() => {
1857
+ setHeaderControls?.(headerControls);
1858
+ return () => setHeaderControls?.(null);
1859
+ }, [headerControls, setHeaderControls]);
1860
+ React6.useEffect(() => {
1861
+ setHeaderRefresh?.(() => () => {
1862
+ void loadUsage();
1863
+ });
1864
+ return () => setHeaderRefresh?.(null);
1865
+ }, [loadUsage, setHeaderRefresh]);
1866
+ return /* @__PURE__ */ jsxs8("div", { className: "grid h-full min-h-0 grid-rows-[auto_minmax(0,4fr)_minmax(0,5fr)] gap-3", children: [
1867
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-3", children: [
1868
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-3 xl:flex-row xl:items-end xl:justify-between", children: [
1869
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1870
+ /* @__PURE__ */ jsx13("h2", { className: "text-xl font-semibold tracking-tight", children: config.labels.llmUsageTitle }),
1871
+ /* @__PURE__ */ jsxs8("div", { className: "mt-1 flex flex-wrap items-center gap-2", children: [
1872
+ /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: formatUsageRangeLabel(period, range) }),
1873
+ /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: getGroupByLabel(groupBy) }),
1874
+ groupBy === "participant" && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: attribution === "initiatedBy" ? "Initiated by sender" : "Generated by caller" }),
1875
+ isLoading && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: config.labels.loading })
1876
+ ] })
1877
+ ] }),
1970
1878
  /* @__PURE__ */ jsx13(
1971
- UsageSelect,
1879
+ InlineFilters,
1972
1880
  {
1973
- label: config.labels.usageDimensionLabel,
1974
- onValueChange: (value) => setDimension(value),
1975
- options: USAGE_DIMENSIONS.map((nextDimension) => [
1976
- nextDimension,
1977
- getUsageDimensionLabel(config.labels, nextDimension)
1978
- ]),
1979
- value: dimension
1881
+ activeFilterCount,
1882
+ clearFilters,
1883
+ customFrom,
1884
+ customTo,
1885
+ model,
1886
+ participantId,
1887
+ participantType,
1888
+ period,
1889
+ provider,
1890
+ setCustomFrom,
1891
+ setCustomTo,
1892
+ setModel,
1893
+ setParticipantId,
1894
+ setParticipantType,
1895
+ setProvider,
1896
+ setThreadId,
1897
+ threadId
1980
1898
  }
1981
1899
  )
1982
1900
  ] }),
1983
- /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border bg-muted/30 p-3", children: [
1984
- /* @__PURE__ */ jsxs8("div", { className: "mb-3 flex items-center justify-between gap-3", children: [
1985
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 text-sm font-medium", children: [
1986
- /* @__PURE__ */ jsx13(Filter, { className: "size-4" }),
1987
- /* @__PURE__ */ jsx13("span", { children: "Filters" }),
1988
- activeFilterCount > 0 && /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: activeFilterCount })
1989
- ] }),
1990
- activeFilterCount > 0 && /* @__PURE__ */ jsx13(
1991
- Button,
1992
- {
1993
- onClick: () => {
1994
- setParticipantType("all");
1995
- setThreadId("");
1996
- setParticipantId("");
1997
- setProvider("");
1998
- setModel("");
1999
- setCustomFrom("");
2000
- setCustomTo("");
2001
- },
2002
- size: "sm",
2003
- variant: "ghost",
2004
- children: "Clear"
2005
- }
2006
- )
2007
- ] }),
2008
- /* @__PURE__ */ jsxs8("div", { className: "grid gap-2 md:grid-cols-2 xl:grid-cols-6", children: [
2009
- period === "custom" && /* @__PURE__ */ jsxs8(Fragment3, { children: [
2010
- /* @__PURE__ */ jsx13(
2011
- FilterInput,
2012
- {
2013
- label: "From",
2014
- onChange: setCustomFrom,
2015
- type: "datetime-local",
2016
- value: customFrom
2017
- }
2018
- ),
2019
- /* @__PURE__ */ jsx13(
2020
- FilterInput,
2021
- {
2022
- label: "To",
2023
- onChange: setCustomTo,
2024
- type: "datetime-local",
2025
- value: customTo
2026
- }
2027
- )
2028
- ] }),
2029
- /* @__PURE__ */ jsx13(
2030
- UsageSelect,
2031
- {
2032
- label: "Type",
2033
- onValueChange: (value) => setParticipantType(
2034
- value
2035
- ),
2036
- options: [
2037
- ["all", "All"],
2038
- ["human", "Human"],
2039
- ["agent", "Agent"],
2040
- ["job", "Job"]
2041
- ],
2042
- value: participantType
2043
- }
2044
- ),
2045
- /* @__PURE__ */ jsx13(
2046
- FilterInput,
2047
- {
2048
- icon: /* @__PURE__ */ jsx13(Search, { className: "size-3.5" }),
2049
- label: "Thread",
2050
- onChange: setThreadId,
2051
- value: threadId
2052
- }
2053
- ),
2054
- /* @__PURE__ */ jsx13(
2055
- FilterInput,
2056
- {
2057
- icon: /* @__PURE__ */ jsx13(Users2, { className: "size-3.5" }),
2058
- label: "Participant",
2059
- onChange: setParticipantId,
2060
- value: participantId
2061
- }
2062
- ),
2063
- /* @__PURE__ */ jsx13(
2064
- FilterInput,
2065
- {
2066
- icon: /* @__PURE__ */ jsx13(Database2, { className: "size-3.5" }),
2067
- label: "Provider",
2068
- onChange: setProvider,
2069
- value: provider
2070
- }
1901
+ /* @__PURE__ */ jsx13(
1902
+ UsageSummary,
1903
+ {
1904
+ labels: config.labels,
1905
+ totals
1906
+ }
1907
+ )
1908
+ ] }),
1909
+ /* @__PURE__ */ jsxs8(Card, { className: "min-h-0 gap-2 overflow-hidden py-3", children: [
1910
+ /* @__PURE__ */ jsx13(CardHeader, { className: "px-4", children: /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-2 md:flex-row md:items-start md:justify-between", children: /* @__PURE__ */ jsxs8("div", { children: [
1911
+ /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: getUsageSummaryLabel(config.labels, metricKind, dimension) }),
1912
+ /* @__PURE__ */ jsxs8("p", { className: "mt-1 text-sm text-muted-foreground", children: [
1913
+ formatMetricValue(
1914
+ getUsageTotalValue(totals, metricKind, dimension),
1915
+ metricKind
2071
1916
  ),
2072
- /* @__PURE__ */ jsx13(
2073
- FilterInput,
2074
- {
2075
- icon: /* @__PURE__ */ jsx13(Sparkles, { className: "size-3.5" }),
2076
- label: "Model",
2077
- onChange: setModel,
2078
- value: model
2079
- }
2080
- )
1917
+ " ",
1918
+ "across ",
1919
+ formatNumber(totals.totalCalls),
1920
+ " calls"
2081
1921
  ] })
2082
- ] })
2083
- ] }) }),
2084
- /* @__PURE__ */ jsxs8(Card, { className: "gap-3 overflow-hidden py-4", children: [
2085
- /* @__PURE__ */ jsx13(CardHeader, { className: "px-4 lg:px-5", children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2 md:flex-row md:items-start md:justify-between", children: [
2086
- /* @__PURE__ */ jsxs8("div", { children: [
2087
- /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: getUsageSummaryLabel(config.labels, metricKind, dimension) }),
2088
- /* @__PURE__ */ jsxs8("p", { className: "mt-1 text-sm text-muted-foreground", children: [
2089
- formatMetricValue(
2090
- getUsageTotalValue(totals, metricKind, dimension),
2091
- metricKind
2092
- ),
2093
- " ",
2094
- "across ",
2095
- formatNumber(totals.totalCalls),
2096
- " calls"
2097
- ] })
2098
- ] }),
2099
- isLoading && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: config.labels.loading })
2100
- ] }) }),
2101
- /* @__PURE__ */ jsx13(CardContent, { className: "px-2 lg:px-4", children: error ? /* @__PURE__ */ jsx13("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive", children: error }) : chartState.data.length === 0 ? /* @__PURE__ */ jsx13(
1922
+ ] }) }) }),
1923
+ /* @__PURE__ */ jsx13(CardContent, { className: "min-h-0 flex-1 px-2 lg:px-4", children: error ? /* @__PURE__ */ jsx13("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive", children: error }) : chartState.data.length === 0 ? /* @__PURE__ */ jsx13(
2102
1924
  EmptyDashboard,
2103
1925
  {
2104
1926
  description: config.labels.noResults,
@@ -2132,9 +1954,7 @@ function UsageDashboard({
2132
1954
  ] });
2133
1955
  }
2134
1956
  function UsageSummary({
2135
- dimension,
2136
1957
  labels,
2137
- metricKind,
2138
1958
  totals
2139
1959
  }) {
2140
1960
  const summary = [
@@ -2151,28 +1971,19 @@ function UsageSummary({
2151
1971
  icon: Activity2
2152
1972
  },
2153
1973
  {
2154
- label: labels.usageCacheRead,
2155
- value: formatMetricValue(totals.cacheReadInputCostUsd, "cost"),
2156
- detail: `${formatMetricValue(totals.cacheReadInputTokens, "tokens")} tokens`,
2157
- icon: Database2
2158
- },
2159
- {
2160
- label: getUsageSummaryLabel(labels, metricKind, dimension),
2161
- value: formatMetricValue(
2162
- getUsageTotalValue(totals, metricKind, dimension),
2163
- metricKind
2164
- ),
2165
- detail: labels.usageTotal,
1974
+ label: "Calls",
1975
+ value: formatMetricValue(totals.totalCalls, "calls"),
1976
+ detail: totals.totalCalls > 0 ? `${formatMetricValue(totals.totalCostUsd / totals.totalCalls, "cost")} avg` : "No calls",
2166
1977
  icon: Sparkles
2167
1978
  }
2168
1979
  ];
2169
- return /* @__PURE__ */ jsx13("div", { className: "grid gap-3 sm:grid-cols-2 xl:grid-cols-4", children: summary.map((item) => /* @__PURE__ */ jsx13(Card, { className: "gap-3 py-4", children: /* @__PURE__ */ jsx13(CardContent, { className: "px-4", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between gap-3", children: [
1980
+ return /* @__PURE__ */ jsx13("div", { className: "grid gap-2 md:grid-cols-3", children: summary.map((item) => /* @__PURE__ */ jsx13(Card, { className: "gap-0 rounded-lg py-2 shadow-xs", children: /* @__PURE__ */ jsx13(CardContent, { className: "px-3", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
2170
1981
  /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
2171
- /* @__PURE__ */ jsx13("p", { className: "truncate text-sm text-muted-foreground", children: item.label }),
2172
- /* @__PURE__ */ jsx13("p", { className: "mt-1 truncate text-2xl font-semibold tracking-tight", children: item.value }),
2173
- /* @__PURE__ */ jsx13("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: item.detail })
1982
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-xs text-muted-foreground", children: item.label }),
1983
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-lg font-semibold tracking-tight", children: item.value }),
1984
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-[11px] text-muted-foreground", children: item.detail })
2174
1985
  ] }),
2175
- /* @__PURE__ */ jsx13("div", { className: "rounded-md border bg-muted/50 p-2 text-muted-foreground", children: /* @__PURE__ */ jsx13(item.icon, { className: "size-4" }) })
1986
+ /* @__PURE__ */ jsx13("div", { className: "rounded-md border bg-muted/50 p-1.5 text-muted-foreground", children: /* @__PURE__ */ jsx13(item.icon, { className: "size-4" }) })
2176
1987
  ] }) }) }, item.label)) });
2177
1988
  }
2178
1989
  function UsageChart({
@@ -2182,7 +1993,7 @@ function UsageChart({
2182
1993
  return /* @__PURE__ */ jsx13(
2183
1994
  ChartContainer,
2184
1995
  {
2185
- className: "h-[320px] w-full",
1996
+ className: "h-full min-h-[220px] w-full",
2186
1997
  config: chartState.config,
2187
1998
  children: /* @__PURE__ */ jsxs8(
2188
1999
  BarChart,
@@ -2256,8 +2067,8 @@ function UsageTable({
2256
2067
  }) {
2257
2068
  const totalValue = getUsageTotalValue(totals, metricKind, dimension);
2258
2069
  const filterable = groupBy !== "namespace";
2259
- return /* @__PURE__ */ jsxs8(Card, { className: "gap-3 py-4", children: [
2260
- /* @__PURE__ */ jsx13(CardHeader, { className: "px-4 lg:px-5", children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
2070
+ return /* @__PURE__ */ jsxs8(Card, { className: "min-h-0 gap-2 overflow-hidden py-3", children: [
2071
+ /* @__PURE__ */ jsx13(CardHeader, { className: "px-4", children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
2261
2072
  /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: "Usage detail" }),
2262
2073
  /* @__PURE__ */ jsxs8(Badge, { variant: "outline", children: [
2263
2074
  formatNumber(rows.length),
@@ -2265,8 +2076,8 @@ function UsageTable({
2265
2076
  getGroupByLabel(groupBy).toLowerCase()
2266
2077
  ] })
2267
2078
  ] }) }),
2268
- /* @__PURE__ */ jsx13(CardContent, { className: "px-0", children: rows.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "px-5 py-4 text-sm text-muted-foreground", children: labels.noResults }) : /* @__PURE__ */ jsx13("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs8("table", { className: "w-full min-w-[940px] text-sm", children: [
2269
- /* @__PURE__ */ jsx13("thead", { children: /* @__PURE__ */ jsxs8("tr", { className: "border-b text-left text-xs uppercase tracking-[0.12em] text-muted-foreground", children: [
2079
+ /* @__PURE__ */ jsx13(CardContent, { className: "min-h-0 flex-1 overflow-hidden px-0", children: rows.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "px-5 py-4 text-sm text-muted-foreground", children: labels.noResults }) : /* @__PURE__ */ jsx13("div", { className: "h-full overflow-auto", children: /* @__PURE__ */ jsxs8("table", { className: "w-full min-w-[940px] text-sm", children: [
2080
+ /* @__PURE__ */ jsx13("thead", { className: "sticky top-0 z-10 bg-card", children: /* @__PURE__ */ jsxs8("tr", { className: "border-b text-left text-xs uppercase tracking-[0.12em] text-muted-foreground", children: [
2270
2081
  /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 font-medium", children: getGroupByLabel(groupBy) }),
2271
2082
  /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: getUsageSummaryLabel(labels, metricKind, dimension) }),
2272
2083
  /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Share" }),
@@ -2323,24 +2134,271 @@ function UsageTable({
2323
2134
  ] }) }) })
2324
2135
  ] });
2325
2136
  }
2137
+ function DashboardHeaderControls({
2138
+ attribution,
2139
+ bucket,
2140
+ config,
2141
+ dimension,
2142
+ groupBy,
2143
+ metricKind,
2144
+ period,
2145
+ setAttribution,
2146
+ setBucket,
2147
+ setDimension,
2148
+ setGroupBy,
2149
+ setMetricKind,
2150
+ setPeriod
2151
+ }) {
2152
+ return /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
2153
+ /* @__PURE__ */ jsx13(
2154
+ HeaderSelect,
2155
+ {
2156
+ label: "Period",
2157
+ onValueChange: (value) => setPeriod(value),
2158
+ options: [
2159
+ ["24h", config.labels.range24h],
2160
+ ["7d", config.labels.range7d],
2161
+ ["30d", config.labels.range30d],
2162
+ ["custom", "Custom"]
2163
+ ],
2164
+ value: period,
2165
+ width: "w-[86px]"
2166
+ }
2167
+ ),
2168
+ /* @__PURE__ */ jsx13(
2169
+ HeaderSelect,
2170
+ {
2171
+ label: "Bucket",
2172
+ onValueChange: (value) => setBucket(value),
2173
+ options: [
2174
+ ["minute", "Minute"],
2175
+ ["hour", "Hour"],
2176
+ ["day", "Day"],
2177
+ ["week", "Week"],
2178
+ ["month", "Month"]
2179
+ ],
2180
+ value: bucket,
2181
+ width: "w-[92px]"
2182
+ }
2183
+ ),
2184
+ /* @__PURE__ */ jsx13(
2185
+ HeaderSelect,
2186
+ {
2187
+ label: config.labels.usageMetricLabel,
2188
+ onValueChange: (value) => setMetricKind(value),
2189
+ options: [
2190
+ ["cost", config.labels.usageMetricCost],
2191
+ ["tokens", config.labels.usageMetricTokens],
2192
+ ["calls", "Calls"]
2193
+ ],
2194
+ value: metricKind,
2195
+ width: "w-[94px]"
2196
+ }
2197
+ ),
2198
+ /* @__PURE__ */ jsx13(
2199
+ HeaderSelect,
2200
+ {
2201
+ label: "Group",
2202
+ onValueChange: (value) => setGroupBy(value),
2203
+ options: [
2204
+ ["participant", "Participant"],
2205
+ ["thread", "Thread"],
2206
+ ["namespace", "Namespace"],
2207
+ ["provider", "Provider"],
2208
+ ["model", "Model"]
2209
+ ],
2210
+ value: groupBy,
2211
+ width: "w-[128px]"
2212
+ }
2213
+ ),
2214
+ /* @__PURE__ */ jsx13(
2215
+ HeaderSelect,
2216
+ {
2217
+ label: "Attribution",
2218
+ onValueChange: (value) => setAttribution(value),
2219
+ options: [
2220
+ ["initiatedBy", "Initiated by"],
2221
+ ["generatedBy", "Generated by"]
2222
+ ],
2223
+ value: attribution,
2224
+ width: "w-[132px]"
2225
+ }
2226
+ ),
2227
+ /* @__PURE__ */ jsx13(
2228
+ HeaderSelect,
2229
+ {
2230
+ label: config.labels.usageDimensionLabel,
2231
+ onValueChange: (value) => setDimension(value),
2232
+ options: USAGE_DIMENSIONS.map((nextDimension) => [
2233
+ nextDimension,
2234
+ getUsageDimensionLabel(config.labels, nextDimension)
2235
+ ]),
2236
+ value: dimension,
2237
+ width: "w-[116px]"
2238
+ }
2239
+ )
2240
+ ] });
2241
+ }
2242
+ function InlineFilters({
2243
+ activeFilterCount,
2244
+ clearFilters,
2245
+ customFrom,
2246
+ customTo,
2247
+ model,
2248
+ participantId,
2249
+ participantType,
2250
+ period,
2251
+ provider,
2252
+ setCustomFrom,
2253
+ setCustomTo,
2254
+ setModel,
2255
+ setParticipantId,
2256
+ setParticipantType,
2257
+ setProvider,
2258
+ setThreadId,
2259
+ threadId
2260
+ }) {
2261
+ return /* @__PURE__ */ jsxs8("div", { className: "flex max-w-full flex-wrap items-end justify-end gap-2", children: [
2262
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 pb-1 text-xs font-medium text-muted-foreground", children: [
2263
+ /* @__PURE__ */ jsx13(Filter, { className: "size-3.5" }),
2264
+ /* @__PURE__ */ jsx13("span", { children: "Filters" }),
2265
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: activeFilterCount })
2266
+ ] }),
2267
+ period === "custom" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
2268
+ /* @__PURE__ */ jsx13(
2269
+ FilterInput,
2270
+ {
2271
+ compact: true,
2272
+ label: "From",
2273
+ onChange: setCustomFrom,
2274
+ type: "datetime-local",
2275
+ value: customFrom
2276
+ }
2277
+ ),
2278
+ /* @__PURE__ */ jsx13(
2279
+ FilterInput,
2280
+ {
2281
+ compact: true,
2282
+ label: "To",
2283
+ onChange: setCustomTo,
2284
+ type: "datetime-local",
2285
+ value: customTo
2286
+ }
2287
+ )
2288
+ ] }),
2289
+ /* @__PURE__ */ jsx13(
2290
+ UsageSelect,
2291
+ {
2292
+ compact: true,
2293
+ label: "Type",
2294
+ onValueChange: (value) => setParticipantType(value),
2295
+ options: [
2296
+ ["all", "All"],
2297
+ ["human", "Human"],
2298
+ ["agent", "Agent"],
2299
+ ["job", "Job"]
2300
+ ],
2301
+ value: participantType
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsx13(
2305
+ FilterInput,
2306
+ {
2307
+ compact: true,
2308
+ icon: /* @__PURE__ */ jsx13(Search, { className: "size-3.5" }),
2309
+ label: "Thread",
2310
+ onChange: setThreadId,
2311
+ value: threadId
2312
+ }
2313
+ ),
2314
+ /* @__PURE__ */ jsx13(
2315
+ FilterInput,
2316
+ {
2317
+ compact: true,
2318
+ icon: /* @__PURE__ */ jsx13(Users2, { className: "size-3.5" }),
2319
+ label: "Participant",
2320
+ onChange: setParticipantId,
2321
+ value: participantId
2322
+ }
2323
+ ),
2324
+ /* @__PURE__ */ jsx13(
2325
+ FilterInput,
2326
+ {
2327
+ compact: true,
2328
+ icon: /* @__PURE__ */ jsx13(Database2, { className: "size-3.5" }),
2329
+ label: "Provider",
2330
+ onChange: setProvider,
2331
+ value: provider
2332
+ }
2333
+ ),
2334
+ /* @__PURE__ */ jsx13(
2335
+ FilterInput,
2336
+ {
2337
+ compact: true,
2338
+ icon: /* @__PURE__ */ jsx13(Sparkles, { className: "size-3.5" }),
2339
+ label: "Model",
2340
+ onChange: setModel,
2341
+ value: model
2342
+ }
2343
+ ),
2344
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(
2345
+ Button,
2346
+ {
2347
+ className: "h-8",
2348
+ onClick: clearFilters,
2349
+ size: "sm",
2350
+ variant: "ghost",
2351
+ children: "Clear"
2352
+ }
2353
+ )
2354
+ ] });
2355
+ }
2356
+ function HeaderSelect(props) {
2357
+ return /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2358
+ /* @__PURE__ */ jsx13(
2359
+ SelectTrigger,
2360
+ {
2361
+ "aria-label": props.label,
2362
+ className: cn("h-8 bg-background text-xs", props.width),
2363
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2364
+ }
2365
+ ),
2366
+ /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2367
+ ] });
2368
+ }
2326
2369
  function UsageSelect(props) {
2327
- return /* @__PURE__ */ jsxs8("label", { className: "space-y-1", children: [
2328
- /* @__PURE__ */ jsx13("span", { className: "text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground", children: props.label }),
2370
+ return /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[116px]"), children: [
2371
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2329
2372
  /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2330
- /* @__PURE__ */ jsx13(SelectTrigger, { className: "h-9 w-full min-w-0 bg-background", children: /* @__PURE__ */ jsx13(SelectValue, {}) }),
2373
+ /* @__PURE__ */ jsx13(
2374
+ SelectTrigger,
2375
+ {
2376
+ "aria-label": props.label,
2377
+ className: cn(
2378
+ "w-full min-w-0 bg-background",
2379
+ props.compact ? "h-8 text-xs" : "h-9"
2380
+ ),
2381
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2382
+ }
2383
+ ),
2331
2384
  /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2332
2385
  ] })
2333
2386
  ] });
2334
2387
  }
2335
2388
  function FilterInput(props) {
2336
- return /* @__PURE__ */ jsxs8("label", { className: "space-y-1", children: [
2337
- /* @__PURE__ */ jsx13("span", { className: "text-[11px] font-medium uppercase tracking-[0.16em] text-muted-foreground", children: props.label }),
2389
+ return /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[150px]"), children: [
2390
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2338
2391
  /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2339
2392
  props.icon && /* @__PURE__ */ jsx13("span", { className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground", children: props.icon }),
2340
2393
  /* @__PURE__ */ jsx13(
2341
2394
  Input,
2342
2395
  {
2343
- className: cn("h-9 bg-background", props.icon && "pl-8"),
2396
+ "aria-label": props.label,
2397
+ className: cn(
2398
+ "bg-background",
2399
+ props.compact ? "h-8 text-xs" : "h-9",
2400
+ props.icon && "pl-8"
2401
+ ),
2344
2402
  onChange: (event) => props.onChange(event.target.value),
2345
2403
  type: props.type ?? "text",
2346
2404
  value: props.value
@@ -3599,6 +3657,8 @@ var CopilotzAdmin = ({
3599
3657
  const [route, setRoute] = useState9({ page: config.defaultPage });
3600
3658
  const [namespace, setNamespace] = useState9(config.namespace);
3601
3659
  const [collections, setCollections] = useState9([]);
3660
+ const [headerControls, setHeaderControls] = useState9(null);
3661
+ const [headerRefresh, setHeaderRefresh] = useState9(null);
3602
3662
  const [threadSearch, setThreadSearch] = useState9("");
3603
3663
  const [participantSearch, setParticipantSearch] = useState9("");
3604
3664
  const [agentSearch, setAgentSearch] = useState9("");
@@ -3707,7 +3767,9 @@ var CopilotzAdmin = ({
3707
3767
  onThreadSearchChange: setThreadSearch,
3708
3768
  onParticipantSearchChange: setParticipantSearch,
3709
3769
  onAgentSearchChange: setAgentSearch,
3710
- onThreadClick: handleThreadClick
3770
+ onThreadClick: handleThreadClick,
3771
+ setHeaderControls,
3772
+ setHeaderRefresh
3711
3773
  }
3712
3774
  );
3713
3775
  case "threads":
@@ -3804,15 +3866,18 @@ var CopilotzAdmin = ({
3804
3866
  {
3805
3867
  config,
3806
3868
  currentRoute: route,
3807
- range: admin.filters.range,
3808
- interval: admin.filters.interval,
3809
- onRangeChange: admin.setRange,
3810
- onIntervalChange: admin.setInterval,
3811
- onRefresh: () => void admin.refresh(),
3812
- isLoading: admin.isLoading
3869
+ onRefresh: () => {
3870
+ if (route.page === "dashboard" && headerRefresh) {
3871
+ headerRefresh();
3872
+ return;
3873
+ }
3874
+ void admin.refresh();
3875
+ },
3876
+ isLoading: admin.isLoading,
3877
+ controls: route.page === "dashboard" ? headerControls : null
3813
3878
  }
3814
3879
  ),
3815
- /* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
3880
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-auto p-4", children: renderCurrentView() })
3816
3881
  ] }) })
3817
3882
  ]
3818
3883
  }