@copilotz/admin 0.9.25 → 0.9.27

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