@copilotz/admin 0.9.27 → 0.9.29

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
@@ -536,16 +536,6 @@ function CardHeader({ className, ...props }) {
536
536
  }
537
537
  );
538
538
  }
539
- function CardTitle({ className, ...props }) {
540
- return /* @__PURE__ */ jsx(
541
- "div",
542
- {
543
- "data-slot": "card-title",
544
- className: cn("leading-none font-semibold", className),
545
- ...props
546
- }
547
- );
548
- }
549
539
  function CardContent({ className, ...props }) {
550
540
  return /* @__PURE__ */ jsx(
551
541
  "div",
@@ -1431,7 +1421,7 @@ var AdminSidebar = ({
1431
1421
 
1432
1422
  // src/components/layout/AdminHeader.tsx
1433
1423
  import { RefreshCw } from "lucide-react";
1434
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1424
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1435
1425
  var PAGE_TITLES = {
1436
1426
  dashboard: "Dashboard",
1437
1427
  threads: "Threads",
@@ -1447,73 +1437,24 @@ var PAGE_TITLES = {
1447
1437
  var AdminHeader = ({
1448
1438
  config,
1449
1439
  currentRoute,
1450
- range,
1451
- interval,
1452
- onRangeChange,
1453
- onIntervalChange,
1454
1440
  onRefresh,
1455
- isLoading
1441
+ isLoading,
1442
+ controls
1456
1443
  }) => {
1457
1444
  let pageTitle = config.labels[`${currentRoute.page}Title`] || PAGE_TITLES[currentRoute.page] || currentRoute.page;
1458
1445
  if (currentRoute.page === "collection-items" && currentRoute.collection) {
1459
1446
  pageTitle = currentRoute.collection.charAt(0).toUpperCase() + currentRoute.collection.slice(1);
1460
1447
  }
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: [
1448
+ 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: [
1449
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-1", children: [
1463
1450
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1464
1451
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(SidebarTrigger, { className: "-ml-1" }) }),
1465
1452
  /* @__PURE__ */ jsx10(TooltipContent, { children: "Toggle Sidebar" })
1466
1453
  ] }),
1467
- /* @__PURE__ */ jsx10("h1", { className: "text-sm font-medium ml-2", children: pageTitle })
1454
+ /* @__PURE__ */ jsx10("h1", { className: "ml-2 whitespace-nowrap text-sm font-medium", children: pageTitle })
1468
1455
  ] }),
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
- ] }),
1456
+ controls && /* @__PURE__ */ jsx10("div", { className: "flex min-w-[240px] flex-1 items-center justify-end gap-2 overflow-x-auto", children: controls }),
1457
+ /* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-1", children: [
1517
1458
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1518
1459
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
1519
1460
  Button,
@@ -1545,7 +1486,6 @@ import {
1545
1486
  BarChart,
1546
1487
  CartesianGrid,
1547
1488
  Legend,
1548
- Tooltip as Tooltip2,
1549
1489
  XAxis,
1550
1490
  YAxis
1551
1491
  } from "recharts";
@@ -1553,7 +1493,6 @@ import {
1553
1493
  Activity as Activity2,
1554
1494
  Database as Database2,
1555
1495
  Filter,
1556
- RefreshCw as RefreshCw2,
1557
1496
  Search,
1558
1497
  Sparkles,
1559
1498
  Users as Users2,
@@ -1714,7 +1653,7 @@ function ChartLegendContent({
1714
1653
  }
1715
1654
 
1716
1655
  // src/components/views/DashboardView.tsx
1717
- import { Fragment as Fragment3, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1656
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1718
1657
  var DashboardView = ({
1719
1658
  config,
1720
1659
  overview,
@@ -1730,7 +1669,9 @@ var DashboardView = ({
1730
1669
  onParticipantSearchChange,
1731
1670
  onAgentSearchChange,
1732
1671
  onThreadClick,
1733
- namespace
1672
+ namespace,
1673
+ setHeaderControls,
1674
+ setHeaderRefresh
1734
1675
  }) => {
1735
1676
  void overview;
1736
1677
  void activity;
@@ -1758,13 +1699,17 @@ var DashboardView = ({
1758
1699
  UsageDashboard,
1759
1700
  {
1760
1701
  config,
1761
- namespace
1702
+ namespace,
1703
+ setHeaderControls,
1704
+ setHeaderRefresh
1762
1705
  }
1763
1706
  );
1764
1707
  };
1765
1708
  function UsageDashboard({
1766
1709
  config,
1767
- namespace
1710
+ namespace,
1711
+ setHeaderControls,
1712
+ setHeaderRefresh
1768
1713
  }) {
1769
1714
  const [period, setPeriod] = React6.useState("7d");
1770
1715
  const [bucket, setBucket] = React6.useState("day");
@@ -1862,256 +1807,107 @@ function UsageDashboard({
1862
1807
  period === "custom" ? customFrom : "",
1863
1808
  period === "custom" ? customTo : ""
1864
1809
  ].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
- ),
1810
+ const clearFilters = React6.useCallback(() => {
1811
+ setParticipantType("all");
1812
+ setThreadId("");
1813
+ setParticipantId("");
1814
+ setProvider("");
1815
+ setModel("");
1816
+ setCustomFrom("");
1817
+ setCustomTo("");
1818
+ }, []);
1819
+ const headerControls = React6.useMemo(() => /* @__PURE__ */ jsx13(
1820
+ DashboardHeaderControls,
1821
+ {
1822
+ attribution,
1823
+ bucket,
1824
+ config,
1825
+ dimension,
1826
+ groupBy,
1827
+ metricKind,
1828
+ period,
1829
+ setAttribution,
1830
+ setBucket,
1831
+ setDimension,
1832
+ setGroupBy,
1833
+ setMetricKind,
1834
+ setPeriod
1835
+ }
1836
+ ), [
1837
+ attribution,
1838
+ bucket,
1839
+ config,
1840
+ dimension,
1841
+ groupBy,
1842
+ metricKind,
1843
+ period
1844
+ ]);
1845
+ React6.useEffect(() => {
1846
+ setHeaderControls?.(headerControls);
1847
+ return () => setHeaderControls?.(null);
1848
+ }, [headerControls, setHeaderControls]);
1849
+ React6.useEffect(() => {
1850
+ setHeaderRefresh?.(() => () => {
1851
+ void loadUsage();
1852
+ });
1853
+ return () => setHeaderRefresh?.(null);
1854
+ }, [loadUsage, setHeaderRefresh]);
1855
+ return /* @__PURE__ */ jsxs8("div", { className: "grid h-full min-h-0 grid-rows-[auto_minmax(0,4fr)_minmax(0,5fr)] gap-3", children: [
1856
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-3", children: [
1857
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-3 xl:flex-row xl:items-start xl:justify-between", children: [
1858
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1859
+ /* @__PURE__ */ jsx13("h2", { className: "text-xl font-semibold tracking-tight", children: config.labels.llmUsageTitle }),
1860
+ /* @__PURE__ */ jsxs8("div", { className: "mt-1 flex flex-wrap items-center gap-2", children: [
1861
+ /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: formatUsageRangeLabel(period, range) }),
1862
+ /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: getGroupByLabel(groupBy) }),
1863
+ groupBy === "participant" && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: attribution === "initiatedBy" ? "Initiated by sender" : "Generated by caller" }),
1864
+ isLoading && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: config.labels.loading })
1865
+ ] })
1866
+ ] }),
1970
1867
  /* @__PURE__ */ jsx13(
1971
- UsageSelect,
1868
+ InlineFilters,
1972
1869
  {
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
1870
+ activeFilterCount,
1871
+ clearFilters,
1872
+ customFrom,
1873
+ customTo,
1874
+ model,
1875
+ participantId,
1876
+ participantType,
1877
+ period,
1878
+ provider,
1879
+ setCustomFrom,
1880
+ setCustomTo,
1881
+ setModel,
1882
+ setParticipantId,
1883
+ setParticipantType,
1884
+ setProvider,
1885
+ setThreadId,
1886
+ threadId
1980
1887
  }
1981
1888
  )
1982
1889
  ] }),
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
- }
2071
- ),
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
- )
2081
- ] })
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(
2102
- EmptyDashboard,
2103
- {
2104
- description: config.labels.noResults,
2105
- title: "No usage"
2106
- }
2107
- ) : /* @__PURE__ */ jsx13(
2108
- UsageChart,
1890
+ /* @__PURE__ */ jsx13(
1891
+ UsageSummary,
2109
1892
  {
2110
- chartState,
2111
- metricKind
1893
+ labels: config.labels,
1894
+ totals
2112
1895
  }
2113
- ) })
1896
+ )
2114
1897
  ] }),
1898
+ /* @__PURE__ */ jsx13(Card, { className: "min-h-0 gap-0 overflow-hidden py-2", children: /* @__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(
1899
+ EmptyDashboard,
1900
+ {
1901
+ description: config.labels.noResults,
1902
+ title: "No usage"
1903
+ }
1904
+ ) : /* @__PURE__ */ jsx13(
1905
+ UsageChart,
1906
+ {
1907
+ chartState,
1908
+ metricKind
1909
+ }
1910
+ ) }) }),
2115
1911
  /* @__PURE__ */ jsx13(
2116
1912
  UsageTable,
2117
1913
  {
@@ -2132,9 +1928,7 @@ function UsageDashboard({
2132
1928
  ] });
2133
1929
  }
2134
1930
  function UsageSummary({
2135
- dimension,
2136
1931
  labels,
2137
- metricKind,
2138
1932
  totals
2139
1933
  }) {
2140
1934
  const summary = [
@@ -2151,28 +1945,19 @@ function UsageSummary({
2151
1945
  icon: Activity2
2152
1946
  },
2153
1947
  {
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,
1948
+ label: "Calls",
1949
+ value: formatMetricValue(totals.totalCalls, "calls"),
1950
+ detail: totals.totalCalls > 0 ? `${formatMetricValue(totals.totalCostUsd / totals.totalCalls, "cost")} avg` : "No calls",
2166
1951
  icon: Sparkles
2167
1952
  }
2168
1953
  ];
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: [
1954
+ 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
1955
  /* @__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 })
1956
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-xs text-muted-foreground", children: item.label }),
1957
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-lg font-semibold tracking-tight", children: item.value }),
1958
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-[11px] text-muted-foreground", children: item.detail })
2174
1959
  ] }),
2175
- /* @__PURE__ */ jsx13("div", { className: "rounded-md border bg-muted/50 p-2 text-muted-foreground", children: /* @__PURE__ */ jsx13(item.icon, { className: "size-4" }) })
1960
+ /* @__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
1961
  ] }) }) }, item.label)) });
2177
1962
  }
2178
1963
  function UsageChart({
@@ -2182,7 +1967,7 @@ function UsageChart({
2182
1967
  return /* @__PURE__ */ jsx13(
2183
1968
  ChartContainer,
2184
1969
  {
2185
- className: "h-[320px] w-full",
1970
+ className: "h-full min-h-[220px] w-full",
2186
1971
  config: chartState.config,
2187
1972
  children: /* @__PURE__ */ jsxs8(
2188
1973
  BarChart,
@@ -2211,7 +1996,7 @@ function UsageChart({
2211
1996
  }
2212
1997
  ),
2213
1998
  /* @__PURE__ */ jsx13(
2214
- Tooltip2,
1999
+ Tooltip,
2215
2000
  {
2216
2001
  content: /* @__PURE__ */ jsx13(
2217
2002
  ChartTooltipContent,
@@ -2256,97 +2041,343 @@ function UsageTable({
2256
2041
  }) {
2257
2042
  const totalValue = getUsageTotalValue(totals, metricKind, dimension);
2258
2043
  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: [
2261
- /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: "Usage detail" }),
2262
- /* @__PURE__ */ jsxs8(Badge, { variant: "outline", children: [
2263
- formatNumber(rows.length),
2264
- " ",
2265
- getGroupByLabel(groupBy).toLowerCase()
2266
- ] })
2044
+ return /* @__PURE__ */ jsx13(Card, { className: "min-h-0 gap-0 overflow-hidden py-0", children: /* @__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: [
2045
+ /* @__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: [
2046
+ /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 font-medium", children: getGroupByLabel(groupBy) }),
2047
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: getUsageSummaryLabel(labels, metricKind, dimension) }),
2048
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Share" }),
2049
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Calls" }),
2050
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Input" }),
2051
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Output" }),
2052
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Reasoning" }),
2053
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Cache read" }),
2054
+ /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 text-right font-medium", children: "Avg/call" })
2267
2055
  ] }) }),
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: [
2270
- /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 font-medium", children: getGroupByLabel(groupBy) }),
2271
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: getUsageSummaryLabel(labels, metricKind, dimension) }),
2272
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Share" }),
2273
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Calls" }),
2274
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Input" }),
2275
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Output" }),
2276
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Reasoning" }),
2277
- /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Cache read" }),
2278
- /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 text-right font-medium", children: "Avg/call" })
2279
- ] }) }),
2280
- /* @__PURE__ */ jsx13("tbody", { children: rows.slice(0, 60).map((row) => {
2281
- const share = totalValue > 0 ? row.value / totalValue : 0;
2282
- return /* @__PURE__ */ jsxs8(
2283
- "tr",
2284
- {
2285
- className: cn(
2286
- "border-b last:border-0",
2287
- filterable && "cursor-pointer transition-colors hover:bg-muted/50"
2288
- ),
2289
- onClick: () => filterable && onRowFilter(row),
2290
- children: [
2291
- /* @__PURE__ */ jsxs8("td", { className: "px-5 py-3", children: [
2292
- /* @__PURE__ */ jsx13("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
2293
- row.groupKey !== row.groupLabel && /* @__PURE__ */ jsx13("div", { className: "mt-0.5 max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
2294
- ] }),
2295
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right font-medium", children: formatMetricValue(row.value, metricKind) }),
2296
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatPercent(share) }),
2297
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatNumber(row.totalCalls) }),
2298
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2299
- getUsageTotalValue(row, metricKind, "input"),
2300
- metricKind
2301
- ) }),
2302
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2303
- getUsageTotalValue(row, metricKind, "output"),
2304
- metricKind
2305
- ) }),
2306
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2307
- getUsageTotalValue(row, metricKind, "reasoning"),
2308
- metricKind
2309
- ) }),
2310
- /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2311
- getUsageTotalValue(row, metricKind, "cacheRead"),
2312
- metricKind
2313
- ) }),
2314
- /* @__PURE__ */ jsx13("td", { className: "px-5 py-3 text-right", children: formatMetricValue(
2315
- row.totalCalls > 0 ? row.value / row.totalCalls : 0,
2316
- metricKind
2317
- ) })
2318
- ]
2319
- },
2320
- row.groupKey
2321
- );
2322
- }) })
2323
- ] }) }) })
2324
- ] });
2056
+ /* @__PURE__ */ jsx13("tbody", { children: rows.slice(0, 60).map((row) => {
2057
+ const share = totalValue > 0 ? row.value / totalValue : 0;
2058
+ return /* @__PURE__ */ jsxs8(
2059
+ "tr",
2060
+ {
2061
+ className: cn(
2062
+ "border-b last:border-0",
2063
+ filterable && "cursor-pointer transition-colors hover:bg-muted/50"
2064
+ ),
2065
+ onClick: () => filterable && onRowFilter(row),
2066
+ children: [
2067
+ /* @__PURE__ */ jsxs8("td", { className: "px-5 py-3", children: [
2068
+ /* @__PURE__ */ jsx13("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
2069
+ row.groupKey !== row.groupLabel && /* @__PURE__ */ jsx13("div", { className: "mt-0.5 max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
2070
+ ] }),
2071
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right font-medium", children: formatMetricValue(row.value, metricKind) }),
2072
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatPercent(share) }),
2073
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatNumber(row.totalCalls) }),
2074
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2075
+ getUsageTotalValue(row, metricKind, "input"),
2076
+ metricKind
2077
+ ) }),
2078
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2079
+ getUsageTotalValue(row, metricKind, "output"),
2080
+ metricKind
2081
+ ) }),
2082
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2083
+ getUsageTotalValue(row, metricKind, "reasoning"),
2084
+ metricKind
2085
+ ) }),
2086
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2087
+ getUsageTotalValue(row, metricKind, "cacheRead"),
2088
+ metricKind
2089
+ ) }),
2090
+ /* @__PURE__ */ jsx13("td", { className: "px-5 py-3 text-right", children: formatMetricValue(
2091
+ row.totalCalls > 0 ? row.value / row.totalCalls : 0,
2092
+ metricKind
2093
+ ) })
2094
+ ]
2095
+ },
2096
+ row.groupKey
2097
+ );
2098
+ }) })
2099
+ ] }) }) }) });
2325
2100
  }
2326
- 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 }),
2329
- /* @__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, {}) }),
2331
- /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2332
- ] })
2101
+ function DashboardHeaderControls({
2102
+ attribution,
2103
+ bucket,
2104
+ config,
2105
+ dimension,
2106
+ groupBy,
2107
+ metricKind,
2108
+ period,
2109
+ setAttribution,
2110
+ setBucket,
2111
+ setDimension,
2112
+ setGroupBy,
2113
+ setMetricKind,
2114
+ setPeriod
2115
+ }) {
2116
+ return /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
2117
+ /* @__PURE__ */ jsx13(
2118
+ HeaderSelect,
2119
+ {
2120
+ label: "Period",
2121
+ onValueChange: (value) => setPeriod(value),
2122
+ options: [
2123
+ ["24h", config.labels.range24h],
2124
+ ["7d", config.labels.range7d],
2125
+ ["30d", config.labels.range30d],
2126
+ ["custom", "Custom"]
2127
+ ],
2128
+ value: period,
2129
+ width: "w-[86px]"
2130
+ }
2131
+ ),
2132
+ /* @__PURE__ */ jsx13(
2133
+ HeaderSelect,
2134
+ {
2135
+ label: "Bucket",
2136
+ onValueChange: (value) => setBucket(value),
2137
+ options: [
2138
+ ["minute", "Minute"],
2139
+ ["hour", "Hour"],
2140
+ ["day", "Day"],
2141
+ ["week", "Week"],
2142
+ ["month", "Month"]
2143
+ ],
2144
+ value: bucket,
2145
+ width: "w-[92px]"
2146
+ }
2147
+ ),
2148
+ /* @__PURE__ */ jsx13(
2149
+ HeaderSelect,
2150
+ {
2151
+ label: config.labels.usageMetricLabel,
2152
+ onValueChange: (value) => setMetricKind(value),
2153
+ options: [
2154
+ ["cost", config.labels.usageMetricCost],
2155
+ ["tokens", config.labels.usageMetricTokens],
2156
+ ["calls", "Calls"]
2157
+ ],
2158
+ value: metricKind,
2159
+ width: "w-[94px]"
2160
+ }
2161
+ ),
2162
+ /* @__PURE__ */ jsx13(
2163
+ HeaderSelect,
2164
+ {
2165
+ label: "Group",
2166
+ onValueChange: (value) => setGroupBy(value),
2167
+ options: [
2168
+ ["participant", "Participant"],
2169
+ ["thread", "Thread"],
2170
+ ["namespace", "Namespace"],
2171
+ ["provider", "Provider"],
2172
+ ["model", "Model"]
2173
+ ],
2174
+ value: groupBy,
2175
+ width: "w-[128px]"
2176
+ }
2177
+ ),
2178
+ /* @__PURE__ */ jsx13(
2179
+ HeaderSelect,
2180
+ {
2181
+ label: "Attribution",
2182
+ onValueChange: (value) => setAttribution(value),
2183
+ options: [
2184
+ ["initiatedBy", "Initiated by"],
2185
+ ["generatedBy", "Generated by"]
2186
+ ],
2187
+ value: attribution,
2188
+ width: "w-[132px]"
2189
+ }
2190
+ ),
2191
+ /* @__PURE__ */ jsx13(
2192
+ HeaderSelect,
2193
+ {
2194
+ label: config.labels.usageDimensionLabel,
2195
+ onValueChange: (value) => setDimension(value),
2196
+ options: USAGE_DIMENSIONS.map((nextDimension) => [
2197
+ nextDimension,
2198
+ getUsageDimensionLabel(config.labels, nextDimension)
2199
+ ]),
2200
+ value: dimension,
2201
+ width: "w-[116px]"
2202
+ }
2203
+ )
2333
2204
  ] });
2334
2205
  }
2335
- 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 }),
2338
- /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2339
- 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 }),
2206
+ function InlineFilters({
2207
+ activeFilterCount,
2208
+ clearFilters,
2209
+ customFrom,
2210
+ customTo,
2211
+ model,
2212
+ participantId,
2213
+ participantType,
2214
+ period,
2215
+ provider,
2216
+ setCustomFrom,
2217
+ setCustomTo,
2218
+ setModel,
2219
+ setParticipantId,
2220
+ setParticipantType,
2221
+ setProvider,
2222
+ setThreadId,
2223
+ threadId
2224
+ }) {
2225
+ return /* @__PURE__ */ jsxs8("div", { className: "flex max-w-full flex-wrap items-end justify-end gap-2", children: [
2226
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 pb-1 text-xs font-medium text-muted-foreground", children: [
2227
+ /* @__PURE__ */ jsx13(Filter, { className: "size-3.5" }),
2228
+ /* @__PURE__ */ jsx13("span", { children: "Filters" }),
2229
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: activeFilterCount })
2230
+ ] }),
2231
+ period === "custom" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
2340
2232
  /* @__PURE__ */ jsx13(
2341
- Input,
2233
+ FilterInput,
2234
+ {
2235
+ compact: true,
2236
+ label: "From",
2237
+ onChange: setCustomFrom,
2238
+ type: "datetime-local",
2239
+ value: customFrom
2240
+ }
2241
+ ),
2242
+ /* @__PURE__ */ jsx13(
2243
+ FilterInput,
2342
2244
  {
2343
- className: cn("h-9 bg-background", props.icon && "pl-8"),
2344
- onChange: (event) => props.onChange(event.target.value),
2345
- type: props.type ?? "text",
2346
- value: props.value
2245
+ compact: true,
2246
+ label: "To",
2247
+ onChange: setCustomTo,
2248
+ type: "datetime-local",
2249
+ value: customTo
2347
2250
  }
2348
2251
  )
2349
- ] })
2252
+ ] }),
2253
+ /* @__PURE__ */ jsx13(
2254
+ UsageSelect,
2255
+ {
2256
+ compact: true,
2257
+ label: "Type",
2258
+ onValueChange: (value) => setParticipantType(value),
2259
+ options: [
2260
+ ["all", "All"],
2261
+ ["human", "Human"],
2262
+ ["agent", "Agent"],
2263
+ ["job", "Job"]
2264
+ ],
2265
+ value: participantType
2266
+ }
2267
+ ),
2268
+ /* @__PURE__ */ jsx13(
2269
+ FilterInput,
2270
+ {
2271
+ compact: true,
2272
+ icon: /* @__PURE__ */ jsx13(Search, { className: "size-3.5" }),
2273
+ label: "Thread",
2274
+ onChange: setThreadId,
2275
+ value: threadId
2276
+ }
2277
+ ),
2278
+ /* @__PURE__ */ jsx13(
2279
+ FilterInput,
2280
+ {
2281
+ compact: true,
2282
+ icon: /* @__PURE__ */ jsx13(Users2, { className: "size-3.5" }),
2283
+ label: "Participant",
2284
+ onChange: setParticipantId,
2285
+ value: participantId
2286
+ }
2287
+ ),
2288
+ /* @__PURE__ */ jsx13(
2289
+ FilterInput,
2290
+ {
2291
+ compact: true,
2292
+ icon: /* @__PURE__ */ jsx13(Database2, { className: "size-3.5" }),
2293
+ label: "Provider",
2294
+ onChange: setProvider,
2295
+ value: provider
2296
+ }
2297
+ ),
2298
+ /* @__PURE__ */ jsx13(
2299
+ FilterInput,
2300
+ {
2301
+ compact: true,
2302
+ icon: /* @__PURE__ */ jsx13(Sparkles, { className: "size-3.5" }),
2303
+ label: "Model",
2304
+ onChange: setModel,
2305
+ value: model
2306
+ }
2307
+ ),
2308
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(
2309
+ Button,
2310
+ {
2311
+ className: "h-8",
2312
+ onClick: clearFilters,
2313
+ size: "sm",
2314
+ variant: "ghost",
2315
+ children: "Clear"
2316
+ }
2317
+ )
2318
+ ] });
2319
+ }
2320
+ function HeaderSelect(props) {
2321
+ return /* @__PURE__ */ jsxs8(Tooltip, { children: [
2322
+ /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2323
+ /* @__PURE__ */ jsx13(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx13(
2324
+ SelectTrigger,
2325
+ {
2326
+ "aria-label": props.label,
2327
+ className: cn("h-8 bg-background text-xs", props.width),
2328
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2329
+ }
2330
+ ) }),
2331
+ /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2332
+ ] }),
2333
+ /* @__PURE__ */ jsx13(TooltipContent, { children: props.label })
2334
+ ] });
2335
+ }
2336
+ function UsageSelect(props) {
2337
+ return /* @__PURE__ */ jsxs8(Tooltip, { children: [
2338
+ /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[116px]"), children: [
2339
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2340
+ /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2341
+ /* @__PURE__ */ jsx13(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx13(
2342
+ SelectTrigger,
2343
+ {
2344
+ "aria-label": props.label,
2345
+ className: cn(
2346
+ "w-full min-w-0 bg-background",
2347
+ props.compact ? "h-8 text-xs" : "h-9"
2348
+ ),
2349
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2350
+ }
2351
+ ) }),
2352
+ /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2353
+ ] })
2354
+ ] }),
2355
+ /* @__PURE__ */ jsx13(TooltipContent, { children: props.label })
2356
+ ] });
2357
+ }
2358
+ function FilterInput(props) {
2359
+ return /* @__PURE__ */ jsxs8(Tooltip, { children: [
2360
+ /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[150px]"), children: [
2361
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2362
+ /* @__PURE__ */ jsx13(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2363
+ 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 }),
2364
+ /* @__PURE__ */ jsx13(
2365
+ Input,
2366
+ {
2367
+ "aria-label": props.label,
2368
+ className: cn(
2369
+ "bg-background",
2370
+ props.compact ? "h-8 text-xs" : "h-9",
2371
+ props.icon && "pl-8"
2372
+ ),
2373
+ onChange: (event) => props.onChange(event.target.value),
2374
+ type: props.type ?? "text",
2375
+ value: props.value
2376
+ }
2377
+ )
2378
+ ] }) })
2379
+ ] }),
2380
+ /* @__PURE__ */ jsx13(TooltipContent, { children: props.label })
2350
2381
  ] });
2351
2382
  }
2352
2383
  function EmptyDashboard({
@@ -3599,6 +3630,8 @@ var CopilotzAdmin = ({
3599
3630
  const [route, setRoute] = useState9({ page: config.defaultPage });
3600
3631
  const [namespace, setNamespace] = useState9(config.namespace);
3601
3632
  const [collections, setCollections] = useState9([]);
3633
+ const [headerControls, setHeaderControls] = useState9(null);
3634
+ const [headerRefresh, setHeaderRefresh] = useState9(null);
3602
3635
  const [threadSearch, setThreadSearch] = useState9("");
3603
3636
  const [participantSearch, setParticipantSearch] = useState9("");
3604
3637
  const [agentSearch, setAgentSearch] = useState9("");
@@ -3707,7 +3740,9 @@ var CopilotzAdmin = ({
3707
3740
  onThreadSearchChange: setThreadSearch,
3708
3741
  onParticipantSearchChange: setParticipantSearch,
3709
3742
  onAgentSearchChange: setAgentSearch,
3710
- onThreadClick: handleThreadClick
3743
+ onThreadClick: handleThreadClick,
3744
+ setHeaderControls,
3745
+ setHeaderRefresh
3711
3746
  }
3712
3747
  );
3713
3748
  case "threads":
@@ -3804,15 +3839,18 @@ var CopilotzAdmin = ({
3804
3839
  {
3805
3840
  config,
3806
3841
  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
3842
+ onRefresh: () => {
3843
+ if (route.page === "dashboard" && headerRefresh) {
3844
+ headerRefresh();
3845
+ return;
3846
+ }
3847
+ void admin.refresh();
3848
+ },
3849
+ isLoading: admin.isLoading,
3850
+ controls: route.page === "dashboard" ? headerControls : null
3813
3851
  }
3814
3852
  ),
3815
- /* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
3853
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-auto p-4", children: renderCurrentView() })
3816
3854
  ] }) })
3817
3855
  ]
3818
3856
  }