@copilotz/admin 0.9.25 → 0.9.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -263,6 +263,7 @@ async function fetchAdminUsage(filters, options) {
263
263
  interval: filters.interval,
264
264
  metric: filters.metric,
265
265
  groupBy: filters.groupBy,
266
+ attribution: filters.attribution,
266
267
  threadId: filters.threadId,
267
268
  participantId: filters.participantId,
268
269
  participantType: filters.participantType,
@@ -535,6 +536,16 @@ function CardHeader({ className, ...props }) {
535
536
  }
536
537
  );
537
538
  }
539
+ function CardTitle({ className, ...props }) {
540
+ return /* @__PURE__ */ jsx(
541
+ "div",
542
+ {
543
+ "data-slot": "card-title",
544
+ className: cn("leading-none font-semibold", className),
545
+ ...props
546
+ }
547
+ );
548
+ }
538
549
  function CardContent({ className, ...props }) {
539
550
  return /* @__PURE__ */ jsx(
540
551
  "div",
@@ -1420,7 +1431,7 @@ var AdminSidebar = ({
1420
1431
 
1421
1432
  // src/components/layout/AdminHeader.tsx
1422
1433
  import { RefreshCw } from "lucide-react";
1423
- import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1434
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
1424
1435
  var PAGE_TITLES = {
1425
1436
  dashboard: "Dashboard",
1426
1437
  threads: "Threads",
@@ -1436,73 +1447,24 @@ var PAGE_TITLES = {
1436
1447
  var AdminHeader = ({
1437
1448
  config,
1438
1449
  currentRoute,
1439
- range,
1440
- interval,
1441
- onRangeChange,
1442
- onIntervalChange,
1443
1450
  onRefresh,
1444
- isLoading
1451
+ isLoading,
1452
+ controls
1445
1453
  }) => {
1446
1454
  let pageTitle = config.labels[`${currentRoute.page}Title`] || PAGE_TITLES[currentRoute.page] || currentRoute.page;
1447
1455
  if (currentRoute.page === "collection-items" && currentRoute.collection) {
1448
1456
  pageTitle = currentRoute.collection.charAt(0).toUpperCase() + currentRoute.collection.slice(1);
1449
1457
  }
1450
- return /* @__PURE__ */ jsx10(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80", children: /* @__PURE__ */ jsx10(CardHeader, { className: "p-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between gap-2", children: [
1451
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
1458
+ return /* @__PURE__ */ jsx10(Card, { className: "py-0 border-b rounded-none relative z-10 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/80 shadow-none", children: /* @__PURE__ */ jsx10(CardHeader, { className: "px-3 py-2", children: /* @__PURE__ */ jsxs6("div", { className: "flex min-h-10 flex-wrap items-center gap-2", children: [
1459
+ /* @__PURE__ */ jsxs6("div", { className: "flex min-w-0 items-center gap-1", children: [
1452
1460
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1453
1461
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(SidebarTrigger, { className: "-ml-1" }) }),
1454
1462
  /* @__PURE__ */ jsx10(TooltipContent, { children: "Toggle Sidebar" })
1455
1463
  ] }),
1456
- /* @__PURE__ */ jsx10("h1", { className: "text-sm font-medium ml-2", children: pageTitle })
1464
+ /* @__PURE__ */ jsx10("h1", { className: "ml-2 whitespace-nowrap text-sm font-medium", children: pageTitle })
1457
1465
  ] }),
1458
- /* @__PURE__ */ jsx10("div", { className: "flex-1" }),
1459
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1", children: [
1460
- currentRoute.page === "dashboard" && /* @__PURE__ */ jsxs6(Fragment2, { children: [
1461
- /* @__PURE__ */ jsx10(
1462
- Button,
1463
- {
1464
- variant: range === "24h" ? "default" : "ghost",
1465
- size: "sm",
1466
- className: "h-7 text-xs",
1467
- onClick: () => onRangeChange("24h"),
1468
- children: config.labels.range24h
1469
- }
1470
- ),
1471
- /* @__PURE__ */ jsx10(
1472
- Button,
1473
- {
1474
- variant: range === "7d" ? "default" : "ghost",
1475
- size: "sm",
1476
- className: "h-7 text-xs",
1477
- onClick: () => onRangeChange("7d"),
1478
- children: config.labels.range7d
1479
- }
1480
- ),
1481
- /* @__PURE__ */ jsx10(
1482
- Button,
1483
- {
1484
- variant: range === "30d" ? "default" : "ghost",
1485
- size: "sm",
1486
- className: "h-7 text-xs",
1487
- onClick: () => onRangeChange("30d"),
1488
- children: config.labels.range30d
1489
- }
1490
- ),
1491
- /* @__PURE__ */ jsxs6(
1492
- Select,
1493
- {
1494
- value: interval,
1495
- onValueChange: (v) => onIntervalChange(v),
1496
- children: [
1497
- /* @__PURE__ */ jsx10(SelectTrigger, { className: "h-7 w-[90px] text-xs", children: /* @__PURE__ */ jsx10(SelectValue, {}) }),
1498
- /* @__PURE__ */ jsxs6(SelectContent, { children: [
1499
- /* @__PURE__ */ jsx10(SelectItem, { value: "hour", children: config.labels.intervalHour }),
1500
- /* @__PURE__ */ jsx10(SelectItem, { value: "day", children: config.labels.intervalDay })
1501
- ] })
1502
- ]
1503
- }
1504
- )
1505
- ] }),
1466
+ controls && /* @__PURE__ */ jsx10("div", { className: "flex min-w-[240px] flex-1 items-center justify-end gap-2 overflow-x-auto", children: controls }),
1467
+ /* @__PURE__ */ jsxs6("div", { className: "ml-auto flex items-center gap-1", children: [
1506
1468
  /* @__PURE__ */ jsxs6(Tooltip, { children: [
1507
1469
  /* @__PURE__ */ jsx10(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx10(
1508
1470
  Button,
@@ -1528,7 +1490,25 @@ var AdminHeader = ({
1528
1490
  };
1529
1491
 
1530
1492
  // src/components/views/DashboardView.tsx
1531
- import React5 from "react";
1493
+ import React6 from "react";
1494
+ import {
1495
+ Bar,
1496
+ BarChart,
1497
+ CartesianGrid,
1498
+ Legend,
1499
+ Tooltip as Tooltip2,
1500
+ XAxis,
1501
+ YAxis
1502
+ } from "recharts";
1503
+ import {
1504
+ Activity as Activity2,
1505
+ Database as Database2,
1506
+ Filter,
1507
+ Search,
1508
+ Sparkles,
1509
+ Users as Users2,
1510
+ Wallet
1511
+ } from "lucide-react";
1532
1512
 
1533
1513
  // src/components/ui/badge.tsx
1534
1514
  import { Slot as Slot3 } from "@radix-ui/react-slot";
@@ -1567,8 +1547,124 @@ function Badge({
1567
1547
  );
1568
1548
  }
1569
1549
 
1550
+ // src/components/ui/chart.tsx
1551
+ import * as React5 from "react";
1552
+ import * as RechartsPrimitive from "recharts";
1553
+ import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1554
+ var ChartContext = React5.createContext(null);
1555
+ function useChart() {
1556
+ const context = React5.useContext(ChartContext);
1557
+ if (!context) {
1558
+ throw new Error("useChart must be used within a ChartContainer");
1559
+ }
1560
+ return context;
1561
+ }
1562
+ function ChartContainer({
1563
+ id,
1564
+ className,
1565
+ config,
1566
+ children,
1567
+ ...props
1568
+ }) {
1569
+ const uniqueId = React5.useId();
1570
+ const chartId = `chart-${id ?? uniqueId.replace(/:/g, "")}`;
1571
+ return /* @__PURE__ */ jsx12(ChartContext.Provider, { value: config, children: /* @__PURE__ */ jsxs7(
1572
+ "div",
1573
+ {
1574
+ "data-chart": chartId,
1575
+ className: cn(
1576
+ "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",
1577
+ className
1578
+ ),
1579
+ ...props,
1580
+ children: [
1581
+ /* @__PURE__ */ jsx12("style", { children: Object.entries(config).map(([key, item]) => {
1582
+ return `[data-chart=${chartId}] { --color-${key}: ${item.color}; }`;
1583
+ }).join("\n") }),
1584
+ /* @__PURE__ */ jsx12(RechartsPrimitive.ResponsiveContainer, { children })
1585
+ ]
1586
+ }
1587
+ ) });
1588
+ }
1589
+ function ChartTooltipContent({
1590
+ active,
1591
+ payload,
1592
+ label,
1593
+ className,
1594
+ formatter,
1595
+ labelFormatter
1596
+ }) {
1597
+ const config = useChart();
1598
+ if (!active || !payload?.length) return null;
1599
+ const total = payload.reduce((sum, item) => {
1600
+ const value = typeof item.value === "number" ? item.value : Number(item.value ?? 0);
1601
+ return sum + (Number.isFinite(value) ? value : 0);
1602
+ }, 0);
1603
+ return /* @__PURE__ */ jsxs7(
1604
+ "div",
1605
+ {
1606
+ className: cn(
1607
+ "min-w-44 rounded-lg border bg-popover px-3 py-2 text-popover-foreground shadow-md",
1608
+ className
1609
+ ),
1610
+ children: [
1611
+ /* @__PURE__ */ jsxs7("div", { className: "mb-2 flex items-center justify-between gap-4 border-b pb-2", children: [
1612
+ /* @__PURE__ */ jsx12("p", { className: "text-xs font-medium text-muted-foreground", children: labelFormatter ? labelFormatter(label) : label }),
1613
+ /* @__PURE__ */ jsx12("p", { className: "text-xs font-semibold text-foreground", children: formatter ? formatter(total) : total })
1614
+ ] }),
1615
+ /* @__PURE__ */ jsx12("div", { className: "space-y-1.5", children: payload.filter((item) => Number(item.value ?? 0) > 0).map((item) => {
1616
+ const key = String(item.dataKey ?? item.name ?? "");
1617
+ const itemConfig = config[key];
1618
+ const color = item.color ?? itemConfig?.color ?? "currentColor";
1619
+ return /* @__PURE__ */ jsxs7(
1620
+ "div",
1621
+ {
1622
+ className: "grid grid-cols-[0.6rem_1fr_auto] items-center gap-2",
1623
+ children: [
1624
+ /* @__PURE__ */ jsx12(
1625
+ "span",
1626
+ {
1627
+ className: "size-2 rounded-[2px]",
1628
+ style: { backgroundColor: color }
1629
+ }
1630
+ ),
1631
+ /* @__PURE__ */ jsx12("span", { className: "max-w-48 truncate text-muted-foreground", children: itemConfig?.label ?? item.name ?? key }),
1632
+ /* @__PURE__ */ jsx12("span", { className: "font-medium text-foreground", children: formatter ? formatter(item.value ?? 0) : item.value })
1633
+ ]
1634
+ },
1635
+ key
1636
+ );
1637
+ }) })
1638
+ ]
1639
+ }
1640
+ );
1641
+ }
1642
+ function ChartLegendContent({
1643
+ payload,
1644
+ className
1645
+ }) {
1646
+ const config = useChart();
1647
+ if (!payload?.length) return null;
1648
+ return /* @__PURE__ */ jsx12("div", { className: cn("flex flex-wrap items-center gap-x-4 gap-y-2", className), children: payload.map((item) => {
1649
+ const key = String(item.dataKey ?? item.value ?? "");
1650
+ const itemConfig = config[key];
1651
+ return /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
1652
+ /* @__PURE__ */ jsx12(
1653
+ "span",
1654
+ {
1655
+ className: "size-2 rounded-[2px]",
1656
+ style: {
1657
+ backgroundColor: item.color ?? itemConfig?.color ?? "currentColor"
1658
+ }
1659
+ }
1660
+ ),
1661
+ /* @__PURE__ */ jsx12("span", { className: "max-w-52 truncate text-xs text-muted-foreground", children: itemConfig?.label ?? item.value ?? key })
1662
+ ] }, key);
1663
+ }) });
1664
+ }
1665
+
1570
1666
  // src/components/views/DashboardView.tsx
1571
- import { Fragment as Fragment3, jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
1667
+ import { Fragment as Fragment2, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
1572
1668
  var DashboardView = ({
1573
1669
  config,
1574
1670
  overview,
@@ -1584,172 +1680,76 @@ var DashboardView = ({
1584
1680
  onParticipantSearchChange,
1585
1681
  onAgentSearchChange,
1586
1682
  onThreadClick,
1587
- namespace
1683
+ namespace,
1684
+ setHeaderControls,
1685
+ setHeaderRefresh
1588
1686
  }) => {
1589
- const [usageMetricKind, setUsageMetricKind] = React5.useState(
1687
+ void overview;
1688
+ void activity;
1689
+ void threads;
1690
+ void participants;
1691
+ void agents;
1692
+ void interval;
1693
+ void threadSearch;
1694
+ void participantSearch;
1695
+ void agentSearch;
1696
+ void onThreadSearchChange;
1697
+ void onParticipantSearchChange;
1698
+ void onAgentSearchChange;
1699
+ void onThreadClick;
1700
+ if (!config.features.showOverview) {
1701
+ return /* @__PURE__ */ jsx13(
1702
+ EmptyDashboard,
1703
+ {
1704
+ description: config.labels.emptyDescription,
1705
+ title: config.labels.emptyTitle
1706
+ }
1707
+ );
1708
+ }
1709
+ return /* @__PURE__ */ jsx13(
1710
+ UsageDashboard,
1711
+ {
1712
+ config,
1713
+ namespace,
1714
+ setHeaderControls,
1715
+ setHeaderRefresh
1716
+ }
1717
+ );
1718
+ };
1719
+ function UsageDashboard({
1720
+ config,
1721
+ namespace,
1722
+ setHeaderControls,
1723
+ setHeaderRefresh
1724
+ }) {
1725
+ const [period, setPeriod] = React6.useState("7d");
1726
+ const [bucket, setBucket] = React6.useState("day");
1727
+ const [metricKind, setMetricKind] = React6.useState(
1590
1728
  "cost"
1591
1729
  );
1592
- const [usageDimension, setUsageDimension] = React5.useState(
1593
- "total"
1730
+ const [dimension, setDimension] = React6.useState("total");
1731
+ const [groupBy, setGroupBy] = React6.useState(
1732
+ "participant"
1594
1733
  );
1595
- const llmSummaryValue = overview ? getOverviewUsageValue(overview, usageMetricKind, usageDimension) : 0;
1596
- const llmSummaryLabel = getUsageSummaryLabel(
1597
- config.labels,
1598
- usageMetricKind,
1599
- usageDimension
1734
+ const [attribution, setAttribution] = React6.useState(
1735
+ "initiatedBy"
1600
1736
  );
1601
- const cards = [
1602
- {
1603
- label: config.labels.messagesCard,
1604
- value: overview?.messageTotals.total ?? 0,
1605
- detail: `${overview?.messageTotals.toolCallMessages ?? 0} tool-call messages`
1606
- },
1607
- {
1608
- label: config.labels.activeThreadsCard,
1609
- value: overview?.threadTotals.active ?? 0,
1610
- detail: `${overview?.threadTotals.total ?? 0} total threads`
1611
- },
1612
- {
1613
- label: config.labels.participantsCard,
1614
- value: overview?.participantTotals.total ?? 0,
1615
- detail: `${overview?.participantTotals.agents ?? 0} agents, ${overview?.participantTotals.jobs ?? 0} jobs`
1616
- },
1617
- {
1618
- label: llmSummaryLabel,
1619
- value: llmSummaryValue,
1620
- detail: `${overview?.llmTotals.totalCalls ?? 0} ${config.labels.usageCallsDetail}`,
1621
- metricKind: usageMetricKind
1622
- },
1623
- {
1624
- label: config.labels.queueCard,
1625
- value: overview?.queueTotals.pending ?? 0,
1626
- detail: `${overview?.queueTotals.failed ?? 0} failed`
1627
- }
1628
- ];
1629
- const isEmpty = cards.every((card) => card.value === 0) && activity.length === 0 && threads.length === 0 && participants.length === 0 && agents.length === 0;
1630
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-6", children: [
1631
- isEmpty && /* @__PURE__ */ jsxs7("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
1632
- /* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold", children: config.labels.emptyTitle }),
1633
- /* @__PURE__ */ jsx12("p", { className: "mt-2 text-sm text-muted-foreground", children: config.labels.emptyDescription })
1634
- ] }),
1635
- config.features.showOverview && /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
1636
- /* @__PURE__ */ jsx12(SectionHeading, { title: config.labels.overviewTitle }),
1637
- /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3 lg:grid-cols-5", children: cards.map((card) => /* @__PURE__ */ jsxs7(
1638
- "div",
1639
- {
1640
- className: "rounded-xl border bg-card p-5 shadow-sm",
1641
- children: [
1642
- /* @__PURE__ */ jsx12("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
1643
- /* @__PURE__ */ jsx12("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatMetricValue(
1644
- card.value,
1645
- card.metricKind ?? "tokens"
1646
- ) }),
1647
- /* @__PURE__ */ jsx12("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
1648
- ]
1649
- },
1650
- card.label
1651
- )) })
1652
- ] }),
1653
- config.features.showOverview && /* @__PURE__ */ jsx12(
1654
- UsageExplorer,
1655
- {
1656
- config,
1657
- metricKind: usageMetricKind,
1658
- namespace,
1659
- onDimensionChange: setUsageDimension,
1660
- onMetricKindChange: setUsageMetricKind,
1661
- selectedDimension: usageDimension
1662
- }
1663
- ),
1664
- config.features.showActivity && /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
1665
- /* @__PURE__ */ jsx12(SectionHeading, { title: config.labels.activityTitle }),
1666
- /* @__PURE__ */ jsx12(
1667
- ActivityChart,
1668
- {
1669
- interval,
1670
- labels: config.labels,
1671
- maxBars: config.ui.maxActivityBars,
1672
- points: activity,
1673
- usageDimension,
1674
- usageMetricKind
1675
- }
1676
- )
1677
- ] }),
1678
- /* @__PURE__ */ jsxs7("div", { className: "grid gap-6 lg:grid-cols-3", children: [
1679
- config.features.showThreads && /* @__PURE__ */ jsx12(
1680
- DataTable,
1681
- {
1682
- rows: threads,
1683
- searchPlaceholder: config.labels.threadSearchPlaceholder,
1684
- searchValue: threadSearch,
1685
- setSearchValue: onThreadSearchChange,
1686
- title: config.labels.threadsTitle,
1687
- children: /* @__PURE__ */ jsx12(
1688
- ThreadsTable,
1689
- {
1690
- rows: threads,
1691
- labels: config.labels,
1692
- onThreadClick
1693
- }
1694
- )
1695
- }
1696
- ),
1697
- config.features.showParticipants && /* @__PURE__ */ jsx12(
1698
- DataTable,
1699
- {
1700
- rows: participants,
1701
- searchPlaceholder: config.labels.participantSearchPlaceholder,
1702
- searchValue: participantSearch,
1703
- setSearchValue: onParticipantSearchChange,
1704
- title: config.labels.participantsTitle,
1705
- children: /* @__PURE__ */ jsx12(ParticipantsTable, { rows: participants, labels: config.labels })
1706
- }
1707
- ),
1708
- config.features.showAgents && /* @__PURE__ */ jsx12(
1709
- DataTable,
1710
- {
1711
- rows: agents,
1712
- searchPlaceholder: config.labels.agentSearchPlaceholder,
1713
- searchValue: agentSearch,
1714
- setSearchValue: onAgentSearchChange,
1715
- title: config.labels.agentsTitle,
1716
- children: /* @__PURE__ */ jsx12(
1717
- AgentsTable,
1718
- {
1719
- rows: agents,
1720
- labels: config.labels,
1721
- usageMetricKind,
1722
- usageDimension
1723
- }
1724
- )
1725
- }
1726
- )
1727
- ] })
1728
- ] });
1729
- };
1730
- function SectionHeading({ title }) {
1731
- return /* @__PURE__ */ jsx12("h3", { className: "text-lg font-semibold tracking-tight", children: title });
1732
- }
1733
- function UsageExplorer(props) {
1734
- const [period, setPeriod] = React5.useState("7d");
1735
- const [bucket, setBucket] = React5.useState("day");
1736
- const [groupBy, setGroupBy] = React5.useState("participant");
1737
- const [participantType, setParticipantType] = React5.useState("all");
1738
- const [threadId, setThreadId] = React5.useState("");
1739
- const [participantId, setParticipantId] = React5.useState("");
1740
- const [provider, setProvider] = React5.useState("");
1741
- const [model, setModel] = React5.useState("");
1742
- const [customFrom, setCustomFrom] = React5.useState("");
1743
- const [customTo, setCustomTo] = React5.useState("");
1744
- const [usage, setUsage] = React5.useState(null);
1745
- const [isLoading, setIsLoading] = React5.useState(false);
1746
- const [error, setError] = React5.useState(null);
1747
- const range = React5.useMemo(() => getUsageRange(period, customFrom, customTo), [
1737
+ const [participantType, setParticipantType] = React6.useState("all");
1738
+ const [threadId, setThreadId] = React6.useState("");
1739
+ const [participantId, setParticipantId] = React6.useState("");
1740
+ const [provider, setProvider] = React6.useState("");
1741
+ const [model, setModel] = React6.useState("");
1742
+ const [customFrom, setCustomFrom] = React6.useState("");
1743
+ const [customTo, setCustomTo] = React6.useState("");
1744
+ const [usage, setUsage] = React6.useState(null);
1745
+ const [isLoading, setIsLoading] = React6.useState(false);
1746
+ const [error, setError] = React6.useState(null);
1747
+ const range = React6.useMemo(() => getUsageRange(period, customFrom, customTo), [
1748
1748
  customFrom,
1749
1749
  customTo,
1750
1750
  period
1751
1751
  ]);
1752
- const loadUsage = React5.useCallback(async () => {
1752
+ const loadUsage = React6.useCallback(async () => {
1753
1753
  setIsLoading(true);
1754
1754
  setError(null);
1755
1755
  try {
@@ -1757,17 +1757,18 @@ function UsageExplorer(props) {
1757
1757
  from: range.from,
1758
1758
  to: range.to,
1759
1759
  interval: bucket,
1760
- metric: props.metricKind,
1760
+ metric: metricKind,
1761
1761
  groupBy,
1762
- namespace: props.namespace || void 0,
1762
+ attribution,
1763
+ namespace: namespace || void 0,
1763
1764
  participantType,
1764
1765
  threadId: emptyToUndefined(threadId),
1765
1766
  participantId: emptyToUndefined(participantId),
1766
1767
  provider: emptyToUndefined(provider),
1767
1768
  model: emptyToUndefined(model)
1768
1769
  }, {
1769
- baseUrl: props.config.baseUrl,
1770
- getRequestHeaders: props.config.getRequestHeaders
1770
+ baseUrl: config.baseUrl,
1771
+ getRequestHeaders: config.getRequestHeaders
1771
1772
  });
1772
1773
  setUsage(next);
1773
1774
  } catch (err) {
@@ -1777,505 +1778,659 @@ function UsageExplorer(props) {
1777
1778
  setIsLoading(false);
1778
1779
  }
1779
1780
  }, [
1781
+ attribution,
1780
1782
  bucket,
1783
+ config.baseUrl,
1784
+ config.getRequestHeaders,
1781
1785
  groupBy,
1786
+ metricKind,
1782
1787
  model,
1788
+ namespace,
1783
1789
  participantId,
1784
1790
  participantType,
1785
- props.config.baseUrl,
1786
- props.config.getRequestHeaders,
1787
- props.metricKind,
1788
- props.namespace,
1789
1791
  provider,
1790
1792
  range.from,
1791
1793
  range.to,
1792
1794
  threadId
1793
1795
  ]);
1794
- React5.useEffect(() => {
1796
+ React6.useEffect(() => {
1795
1797
  void loadUsage();
1796
1798
  }, [loadUsage]);
1797
- return /* @__PURE__ */ jsxs7("section", { className: "space-y-4", children: [
1798
- /* @__PURE__ */ jsxs7("div", { className: "flex flex-col gap-3 lg:flex-row lg:items-end lg:justify-between", children: [
1799
- /* @__PURE__ */ jsx12(SectionHeading, { title: props.config.labels.llmUsageTitle }),
1800
- /* @__PURE__ */ jsxs7("div", { className: "grid gap-3 sm:grid-cols-2 lg:grid-cols-5", children: [
1801
- /* @__PURE__ */ jsx12(
1802
- UsageSelect,
1803
- {
1804
- label: "Period",
1805
- value: period,
1806
- onValueChange: (value) => setPeriod(value),
1807
- options: [
1808
- ["24h", props.config.labels.range24h],
1809
- ["7d", props.config.labels.range7d],
1810
- ["30d", props.config.labels.range30d],
1811
- ["custom", "Custom"]
1812
- ]
1813
- }
1814
- ),
1815
- /* @__PURE__ */ jsx12(
1816
- UsageSelect,
1817
- {
1818
- label: "Bucket",
1819
- value: bucket,
1820
- onValueChange: (value) => setBucket(value),
1821
- options: [
1822
- ["minute", "Minute"],
1823
- ["hour", "Hour"],
1824
- ["day", "Day"],
1825
- ["week", "Week"],
1826
- ["month", "Month"]
1827
- ]
1828
- }
1829
- ),
1830
- /* @__PURE__ */ jsx12(
1831
- UsageSelect,
1832
- {
1833
- label: props.config.labels.usageMetricLabel,
1834
- value: props.metricKind,
1835
- onValueChange: (value) => props.onMetricKindChange(value),
1836
- options: [
1837
- ["cost", props.config.labels.usageMetricCost],
1838
- ["tokens", props.config.labels.usageMetricTokens],
1839
- ["calls", "Calls"]
1840
- ]
1841
- }
1842
- ),
1843
- /* @__PURE__ */ jsx12(
1844
- UsageSelect,
1845
- {
1846
- label: "Group by",
1847
- value: groupBy,
1848
- onValueChange: (value) => setGroupBy(value),
1849
- options: [
1850
- ["participant", "Participant"],
1851
- ["thread", "Thread"],
1852
- ["namespace", "Namespace"],
1853
- ["provider", "Provider"],
1854
- ["model", "Model"]
1855
- ]
1856
- }
1857
- ),
1858
- /* @__PURE__ */ jsx12(
1859
- UsageSelect,
1799
+ const points = usage?.points ?? [];
1800
+ const totals = usage?.totals ?? EMPTY_TOTALS;
1801
+ const chartState = React6.useMemo(() => buildChartState(points, metricKind, dimension, bucket), [
1802
+ bucket,
1803
+ dimension,
1804
+ metricKind,
1805
+ points
1806
+ ]);
1807
+ const groupedRows = React6.useMemo(() => aggregateUsageRows(points, metricKind, dimension), [
1808
+ dimension,
1809
+ metricKind,
1810
+ points
1811
+ ]);
1812
+ const activeFilterCount = [
1813
+ participantType !== "all" ? participantType : "",
1814
+ threadId,
1815
+ participantId,
1816
+ provider,
1817
+ model,
1818
+ period === "custom" ? customFrom : "",
1819
+ period === "custom" ? customTo : ""
1820
+ ].filter((value) => value.trim().length > 0).length;
1821
+ const clearFilters = React6.useCallback(() => {
1822
+ setParticipantType("all");
1823
+ setThreadId("");
1824
+ setParticipantId("");
1825
+ setProvider("");
1826
+ setModel("");
1827
+ setCustomFrom("");
1828
+ setCustomTo("");
1829
+ }, []);
1830
+ const headerControls = React6.useMemo(() => /* @__PURE__ */ jsx13(
1831
+ DashboardHeaderControls,
1832
+ {
1833
+ attribution,
1834
+ bucket,
1835
+ config,
1836
+ dimension,
1837
+ groupBy,
1838
+ metricKind,
1839
+ period,
1840
+ setAttribution,
1841
+ setBucket,
1842
+ setDimension,
1843
+ setGroupBy,
1844
+ setMetricKind,
1845
+ setPeriod
1846
+ }
1847
+ ), [
1848
+ attribution,
1849
+ bucket,
1850
+ config,
1851
+ dimension,
1852
+ groupBy,
1853
+ metricKind,
1854
+ period
1855
+ ]);
1856
+ React6.useEffect(() => {
1857
+ setHeaderControls?.(headerControls);
1858
+ return () => setHeaderControls?.(null);
1859
+ }, [headerControls, setHeaderControls]);
1860
+ React6.useEffect(() => {
1861
+ setHeaderRefresh?.(() => () => {
1862
+ void loadUsage();
1863
+ });
1864
+ return () => setHeaderRefresh?.(null);
1865
+ }, [loadUsage, setHeaderRefresh]);
1866
+ return /* @__PURE__ */ jsxs8("div", { className: "grid h-full min-h-0 grid-rows-[auto_minmax(0,4fr)_minmax(0,5fr)] gap-3", children: [
1867
+ /* @__PURE__ */ jsxs8("div", { className: "space-y-3", children: [
1868
+ /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-3 xl:flex-row xl:items-end xl:justify-between", children: [
1869
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1870
+ /* @__PURE__ */ jsx13("h2", { className: "text-xl font-semibold tracking-tight", children: config.labels.llmUsageTitle }),
1871
+ /* @__PURE__ */ jsxs8("div", { className: "mt-1 flex flex-wrap items-center gap-2", children: [
1872
+ /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: formatUsageRangeLabel(period, range) }),
1873
+ /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: getGroupByLabel(groupBy) }),
1874
+ groupBy === "participant" && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: attribution === "initiatedBy" ? "Initiated by sender" : "Generated by caller" }),
1875
+ isLoading && /* @__PURE__ */ jsx13(Badge, { variant: "outline", children: config.labels.loading })
1876
+ ] })
1877
+ ] }),
1878
+ /* @__PURE__ */ jsx13(
1879
+ InlineFilters,
1860
1880
  {
1861
- label: props.config.labels.usageDimensionLabel,
1862
- value: props.selectedDimension,
1863
- onValueChange: (value) => props.onDimensionChange(value),
1864
- options: USAGE_DIMENSIONS.map((dimension) => [
1865
- dimension,
1866
- getUsageDimensionLabel(props.config.labels, dimension)
1867
- ])
1881
+ activeFilterCount,
1882
+ clearFilters,
1883
+ customFrom,
1884
+ customTo,
1885
+ model,
1886
+ participantId,
1887
+ participantType,
1888
+ period,
1889
+ provider,
1890
+ setCustomFrom,
1891
+ setCustomTo,
1892
+ setModel,
1893
+ setParticipantId,
1894
+ setParticipantType,
1895
+ setProvider,
1896
+ setThreadId,
1897
+ threadId
1868
1898
  }
1869
1899
  )
1870
- ] })
1871
- ] }),
1872
- /* @__PURE__ */ jsx12("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: /* @__PURE__ */ jsxs7("div", { className: "grid gap-3 md:grid-cols-2 xl:grid-cols-6", children: [
1873
- period === "custom" && /* @__PURE__ */ jsxs7(Fragment3, { children: [
1874
- /* @__PURE__ */ jsx12(FilterInput, { label: "From", type: "datetime-local", value: customFrom, onChange: setCustomFrom }),
1875
- /* @__PURE__ */ jsx12(FilterInput, { label: "To", type: "datetime-local", value: customTo, onChange: setCustomTo })
1876
1900
  ] }),
1877
- /* @__PURE__ */ jsx12(
1878
- UsageSelect,
1901
+ /* @__PURE__ */ jsx13(
1902
+ UsageSummary,
1879
1903
  {
1880
- label: "Participant type",
1881
- value: participantType,
1882
- onValueChange: (value) => setParticipantType(value),
1883
- options: [
1884
- ["all", "All"],
1885
- ["human", "Human"],
1886
- ["agent", "Agent"],
1887
- ["job", "Job"]
1888
- ]
1904
+ labels: config.labels,
1905
+ totals
1889
1906
  }
1890
- ),
1891
- /* @__PURE__ */ jsx12(FilterInput, { label: "Thread", value: threadId, onChange: setThreadId }),
1892
- /* @__PURE__ */ jsx12(FilterInput, { label: "Participant", value: participantId, onChange: setParticipantId }),
1893
- /* @__PURE__ */ jsx12(FilterInput, { label: "Provider", value: provider, onChange: setProvider }),
1894
- /* @__PURE__ */ jsx12(FilterInput, { label: "Model", value: model, onChange: setModel }),
1895
- /* @__PURE__ */ jsx12("div", { className: "flex items-end", children: /* @__PURE__ */ jsx12(
1896
- Button,
1907
+ )
1908
+ ] }),
1909
+ /* @__PURE__ */ jsxs8(Card, { className: "min-h-0 gap-2 overflow-hidden py-3", children: [
1910
+ /* @__PURE__ */ jsx13(CardHeader, { className: "px-4", children: /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-2 md:flex-row md:items-start md:justify-between", children: /* @__PURE__ */ jsxs8("div", { children: [
1911
+ /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: getUsageSummaryLabel(config.labels, metricKind, dimension) }),
1912
+ /* @__PURE__ */ jsxs8("p", { className: "mt-1 text-sm text-muted-foreground", children: [
1913
+ formatMetricValue(
1914
+ getUsageTotalValue(totals, metricKind, dimension),
1915
+ metricKind
1916
+ ),
1917
+ " ",
1918
+ "across ",
1919
+ formatNumber(totals.totalCalls),
1920
+ " calls"
1921
+ ] })
1922
+ ] }) }) }),
1923
+ /* @__PURE__ */ jsx13(CardContent, { className: "min-h-0 flex-1 px-2 lg:px-4", children: error ? /* @__PURE__ */ jsx13("div", { className: "rounded-lg border border-destructive/30 bg-destructive/10 p-4 text-sm text-destructive", children: error }) : chartState.data.length === 0 ? /* @__PURE__ */ jsx13(
1924
+ EmptyDashboard,
1925
+ {
1926
+ description: config.labels.noResults,
1927
+ title: "No usage"
1928
+ }
1929
+ ) : /* @__PURE__ */ jsx13(
1930
+ UsageChart,
1897
1931
  {
1898
- className: "h-9 w-full",
1899
- onClick: () => void loadUsage(),
1900
- disabled: isLoading,
1901
- variant: "outline",
1902
- children: props.config.labels.refresh
1932
+ chartState,
1933
+ metricKind
1903
1934
  }
1904
1935
  ) })
1905
- ] }) }),
1906
- /* @__PURE__ */ jsx12(
1907
- UsageChart,
1908
- {
1909
- labels: props.config.labels,
1910
- metricKind: props.metricKind,
1911
- dimension: props.selectedDimension,
1912
- points: usage?.points ?? [],
1913
- bucket,
1914
- isLoading,
1915
- error
1916
- }
1917
- ),
1918
- /* @__PURE__ */ jsx12(
1936
+ ] }),
1937
+ /* @__PURE__ */ jsx13(
1919
1938
  UsageTable,
1920
1939
  {
1921
- labels: props.config.labels,
1922
- metricKind: props.metricKind,
1923
- dimension: props.selectedDimension,
1924
- rows: usage?.rows ?? [],
1925
- isLoading
1940
+ dimension,
1941
+ groupBy,
1942
+ labels: config.labels,
1943
+ metricKind,
1944
+ onRowFilter: (row) => {
1945
+ if (groupBy === "thread") setThreadId(row.groupKey);
1946
+ if (groupBy === "participant") setParticipantId(row.groupKey);
1947
+ if (groupBy === "provider") setProvider(row.groupKey);
1948
+ if (groupBy === "model") setModel(row.groupKey);
1949
+ },
1950
+ rows: groupedRows,
1951
+ totals
1926
1952
  }
1927
1953
  )
1928
1954
  ] });
1929
1955
  }
1930
- function UsageSelect(props) {
1931
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-1", children: [
1932
- /* @__PURE__ */ jsx12("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: props.label }),
1933
- /* @__PURE__ */ jsxs7(Select, { value: props.value, onValueChange: props.onValueChange, children: [
1934
- /* @__PURE__ */ jsx12(SelectTrigger, { className: "h-9 w-full min-w-[140px]", children: /* @__PURE__ */ jsx12(SelectValue, {}) }),
1935
- /* @__PURE__ */ jsx12(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx12(SelectItem, { value, children: label }, value)) })
1936
- ] })
1937
- ] });
1938
- }
1939
- function FilterInput(props) {
1940
- return /* @__PURE__ */ jsxs7("div", { className: "space-y-1", children: [
1941
- /* @__PURE__ */ jsx12("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: props.label }),
1942
- /* @__PURE__ */ jsx12(
1943
- Input,
1944
- {
1945
- className: "h-9",
1946
- type: props.type ?? "text",
1947
- value: props.value,
1948
- onChange: (event) => props.onChange(event.target.value)
1949
- }
1950
- )
1951
- ] });
1956
+ function UsageSummary({
1957
+ labels,
1958
+ totals
1959
+ }) {
1960
+ const summary = [
1961
+ {
1962
+ label: labels.usageMetricCost,
1963
+ value: formatMetricValue(totals.totalCostUsd, "cost"),
1964
+ detail: `${formatNumber(totals.totalCalls)} ${labels.usageCallsDetail}`,
1965
+ icon: Wallet
1966
+ },
1967
+ {
1968
+ label: labels.usageMetricTokens,
1969
+ value: formatMetricValue(totals.totalTokens, "tokens"),
1970
+ detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
1971
+ icon: Activity2
1972
+ },
1973
+ {
1974
+ label: "Calls",
1975
+ value: formatMetricValue(totals.totalCalls, "calls"),
1976
+ detail: totals.totalCalls > 0 ? `${formatMetricValue(totals.totalCostUsd / totals.totalCalls, "cost")} avg` : "No calls",
1977
+ icon: Sparkles
1978
+ }
1979
+ ];
1980
+ return /* @__PURE__ */ jsx13("div", { className: "grid gap-2 md:grid-cols-3", children: summary.map((item) => /* @__PURE__ */ jsx13(Card, { className: "gap-0 rounded-lg py-2 shadow-xs", children: /* @__PURE__ */ jsx13(CardContent, { className: "px-3", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center justify-between gap-3", children: [
1981
+ /* @__PURE__ */ jsxs8("div", { className: "min-w-0", children: [
1982
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-xs text-muted-foreground", children: item.label }),
1983
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-lg font-semibold tracking-tight", children: item.value }),
1984
+ /* @__PURE__ */ jsx13("p", { className: "truncate text-[11px] text-muted-foreground", children: item.detail })
1985
+ ] }),
1986
+ /* @__PURE__ */ jsx13("div", { className: "rounded-md border bg-muted/50 p-1.5 text-muted-foreground", children: /* @__PURE__ */ jsx13(item.icon, { className: "size-4" }) })
1987
+ ] }) }) }, item.label)) });
1952
1988
  }
1953
- function UsageChart(props) {
1954
- const buckets = React5.useMemo(() => buildUsageBuckets(props.points), [props.points]);
1955
- const visibleBuckets = buckets.slice(-18);
1956
- const groups = React5.useMemo(() => topUsageGroups(props.points, props.metricKind, props.dimension), [
1957
- props.dimension,
1958
- props.metricKind,
1959
- props.points
1960
- ]);
1961
- const maxBucketValue = Math.max(
1962
- ...visibleBuckets.map(
1963
- (bucket) => bucket.points.reduce((sum, point) => sum + getUsagePointValue(point, props.metricKind, props.dimension), 0)
1964
- ),
1965
- 1
1966
- );
1967
- return /* @__PURE__ */ jsx12("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: props.error ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-destructive", children: props.error }) : props.isLoading && props.points.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: props.labels.loading }) : visibleBuckets.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ jsxs7("div", { className: "space-y-4", children: [
1968
- /* @__PURE__ */ jsx12("div", { className: "flex min-h-56 items-end gap-2", children: visibleBuckets.map((bucket) => {
1969
- const bucketTotal = bucket.points.reduce((sum, point) => sum + getUsagePointValue(point, props.metricKind, props.dimension), 0);
1970
- return /* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 flex-col items-center gap-2", children: [
1971
- /* @__PURE__ */ jsx12("div", { className: "flex h-40 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ jsx12(
1972
- "div",
1973
- {
1974
- className: "flex w-full flex-col-reverse overflow-hidden rounded-md",
1975
- style: {
1976
- height: `${Math.max(bucketTotal / maxBucketValue * 100, 6)}%`
1977
- },
1978
- children: groups.map((group, index) => {
1979
- const point = bucket.points.find((item) => item.groupKey === group.key);
1980
- const value = point ? getUsagePointValue(point, props.metricKind, props.dimension) : 0;
1981
- if (value <= 0 || bucketTotal <= 0) return null;
1982
- return /* @__PURE__ */ jsx12(
1983
- "div",
1984
- {
1985
- title: `${group.label}: ${formatMetricValue(value, props.metricKind)}`,
1986
- style: {
1987
- height: `${value / bucketTotal * 100}%`,
1988
- backgroundColor: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length]
1989
- }
1990
- },
1991
- group.key
1992
- );
1993
- })
1994
- }
1995
- ) }),
1996
- /* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
1997
- /* @__PURE__ */ jsx12("p", { className: "text-xs font-medium", children: formatUsageBucket(bucket.bucket, props.bucket) }),
1998
- /* @__PURE__ */ jsx12("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(bucketTotal, props.metricKind) })
1999
- ] })
2000
- ] }, bucket.bucket);
2001
- }) }),
2002
- /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-3", children: groups.map((group, index) => /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2 text-xs", children: [
2003
- /* @__PURE__ */ jsx12(
2004
- "span",
1989
+ function UsageChart({
1990
+ chartState,
1991
+ metricKind
1992
+ }) {
1993
+ return /* @__PURE__ */ jsx13(
1994
+ ChartContainer,
1995
+ {
1996
+ className: "h-full min-h-[220px] w-full",
1997
+ config: chartState.config,
1998
+ children: /* @__PURE__ */ jsxs8(
1999
+ BarChart,
2005
2000
  {
2006
- className: "size-2 rounded-sm",
2007
- style: { backgroundColor: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length] }
2001
+ accessibilityLayer: true,
2002
+ data: chartState.data,
2003
+ margin: { left: 8, right: 8, top: 12 },
2004
+ children: [
2005
+ /* @__PURE__ */ jsx13(CartesianGrid, { vertical: false }),
2006
+ /* @__PURE__ */ jsx13(
2007
+ XAxis,
2008
+ {
2009
+ axisLine: false,
2010
+ dataKey: "label",
2011
+ tickLine: false,
2012
+ tickMargin: 10
2013
+ }
2014
+ ),
2015
+ /* @__PURE__ */ jsx13(
2016
+ YAxis,
2017
+ {
2018
+ axisLine: false,
2019
+ tickFormatter: (value) => formatCompactMetric(value, metricKind),
2020
+ tickLine: false,
2021
+ width: 60
2022
+ }
2023
+ ),
2024
+ /* @__PURE__ */ jsx13(
2025
+ Tooltip2,
2026
+ {
2027
+ content: /* @__PURE__ */ jsx13(
2028
+ ChartTooltipContent,
2029
+ {
2030
+ formatter: (value) => formatMetricValue(Number(value), metricKind),
2031
+ labelFormatter: (value) => String(value ?? "")
2032
+ }
2033
+ ),
2034
+ cursor: false
2035
+ }
2036
+ ),
2037
+ /* @__PURE__ */ jsx13(
2038
+ Legend,
2039
+ {
2040
+ content: /* @__PURE__ */ jsx13(ChartLegendContent, { className: "justify-center pt-3" })
2041
+ }
2042
+ ),
2043
+ chartState.series.map((series) => /* @__PURE__ */ jsx13(
2044
+ Bar,
2045
+ {
2046
+ dataKey: series.id,
2047
+ fill: `var(--color-${series.id})`,
2048
+ radius: [4, 4, 0, 0],
2049
+ stackId: "usage"
2050
+ },
2051
+ series.id
2052
+ ))
2053
+ ]
2008
2054
  }
2009
- ),
2010
- /* @__PURE__ */ jsx12("span", { className: "max-w-48 truncate text-muted-foreground", children: group.label })
2011
- ] }, group.key)) })
2012
- ] }) });
2013
- }
2014
- function UsageTable(props) {
2015
- const rows = props.rows.slice(0, 40);
2016
- return /* @__PURE__ */ jsxs7("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
2017
- /* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
2018
- /* @__PURE__ */ jsx12(SectionHeading, { title: "Usage detail" }),
2019
- props.isLoading && /* @__PURE__ */ jsx12(Badge, { variant: "outline", children: props.labels.loading })
2020
- ] }),
2021
- rows.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ jsx12("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs7("table", { className: "w-full min-w-[720px] text-sm", children: [
2022
- /* @__PURE__ */ jsx12("thead", { children: /* @__PURE__ */ jsxs7("tr", { className: "border-b text-left text-xs uppercase tracking-[0.14em] text-muted-foreground", children: [
2023
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 font-medium", children: "Interval" }),
2024
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 font-medium", children: "Group" }),
2025
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 text-right font-medium", children: "Input" }),
2026
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 text-right font-medium", children: "Output" }),
2027
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 text-right font-medium", children: "Reasoning" }),
2028
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 text-right font-medium", children: "Cache read" }),
2029
- /* @__PURE__ */ jsx12("th", { className: "py-2 pr-4 text-right font-medium", children: "Cache write" }),
2030
- /* @__PURE__ */ jsx12("th", { className: "py-2 text-right font-medium", children: getUsageSummaryLabel(props.labels, props.metricKind, props.dimension) })
2031
- ] }) }),
2032
- /* @__PURE__ */ jsx12("tbody", { children: rows.map((row) => /* @__PURE__ */ jsxs7("tr", { className: "border-b last:border-0", children: [
2033
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-muted-foreground", children: formatDate(row.bucket) }),
2034
- /* @__PURE__ */ jsx12("td", { className: "max-w-72 truncate py-2 pr-4 font-medium", children: row.groupLabel }),
2035
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "input"), props.metricKind) }),
2036
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "output"), props.metricKind) }),
2037
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "reasoning"), props.metricKind) }),
2038
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "cacheRead"), props.metricKind) }),
2039
- /* @__PURE__ */ jsx12("td", { className: "py-2 pr-4 text-right", children: formatMetricValue(getUsagePointValue(row, props.metricKind, "cacheWrite"), props.metricKind) }),
2040
- /* @__PURE__ */ jsx12("td", { className: "py-2 text-right font-medium", children: formatMetricValue(getUsagePointValue(row, props.metricKind, props.dimension), props.metricKind) })
2041
- ] }, `${row.bucket}:${row.groupKey}`)) })
2042
- ] }) })
2043
- ] });
2044
- }
2045
- function ActivityChart(props) {
2046
- const trimmedPoints = props.points.slice(-props.maxBars);
2047
- const maxUsageValue = Math.max(
2048
- ...trimmedPoints.map(
2049
- (point) => getActivityUsageValue(
2050
- point,
2051
- props.usageMetricKind,
2052
- props.usageDimension
2053
2055
  )
2054
- ),
2055
- 1
2056
+ }
2056
2057
  );
2057
- return /* @__PURE__ */ jsx12("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: trimmedPoints.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: props.labels.noResults }) : /* @__PURE__ */ jsx12("div", { className: "flex min-h-48 items-end gap-2", children: trimmedPoints.map((point) => {
2058
- const usageValue = getActivityUsageValue(
2059
- point,
2060
- props.usageMetricKind,
2061
- props.usageDimension
2062
- );
2063
- return /* @__PURE__ */ jsxs7(
2064
- "div",
2065
- {
2066
- className: "flex min-w-0 flex-1 flex-col items-center gap-2",
2067
- children: [
2068
- /* @__PURE__ */ jsx12("div", { className: "flex h-36 w-full items-end rounded-lg bg-muted px-1 pb-1", children: /* @__PURE__ */ jsx12(
2069
- "div",
2070
- {
2071
- className: "w-full rounded-md bg-primary transition-all",
2072
- style: {
2073
- height: `${Math.max(usageValue / maxUsageValue * 100, 8)}%`
2074
- }
2075
- }
2076
- ) }),
2077
- /* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
2078
- /* @__PURE__ */ jsx12("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
2079
- /* @__PURE__ */ jsx12("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(usageValue, props.usageMetricKind) }),
2080
- /* @__PURE__ */ jsxs7("p", { className: "text-[11px] text-muted-foreground", children: [
2081
- formatNumber(point.totalCalls),
2082
- " ",
2083
- props.labels.usageCallsDetail
2084
- ] })
2085
- ] })
2086
- ]
2087
- },
2088
- point.bucket
2089
- );
2090
- }) }) });
2091
2058
  }
2092
- function DataTable(props) {
2093
- return /* @__PURE__ */ jsxs7("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
2094
- /* @__PURE__ */ jsxs7("div", { className: "mb-4 flex items-center justify-between gap-3", children: [
2095
- /* @__PURE__ */ jsx12(SectionHeading, { title: props.title }),
2096
- /* @__PURE__ */ jsx12(
2097
- Input,
2098
- {
2099
- className: "h-8 w-full max-w-44",
2100
- onChange: (event) => props.setSearchValue(event.target.value),
2101
- placeholder: props.searchPlaceholder,
2102
- value: props.searchValue
2103
- }
2104
- )
2105
- ] }),
2106
- props.rows.length === 0 ? /* @__PURE__ */ jsx12("p", { className: "text-sm text-muted-foreground", children: "No results" }) : props.children
2107
- ] });
2108
- }
2109
- function ThreadsTable({
2110
- rows,
2059
+ function UsageTable({
2060
+ dimension,
2061
+ groupBy,
2111
2062
  labels,
2112
- onThreadClick
2063
+ metricKind,
2064
+ onRowFilter,
2065
+ rows,
2066
+ totals
2113
2067
  }) {
2114
- return /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: rows.map((thread) => /* @__PURE__ */ jsxs7(
2115
- "div",
2116
- {
2117
- className: cn(
2118
- "rounded-lg border bg-muted/50 p-4",
2119
- onThreadClick && "cursor-pointer hover:bg-muted transition-colors"
2120
- ),
2121
- onClick: () => onThreadClick?.(thread.threadId),
2122
- children: [
2123
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
2124
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
2125
- /* @__PURE__ */ jsx12("p", { className: "font-medium", children: thread.name }),
2126
- /* @__PURE__ */ jsx12("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
2127
- ] }),
2128
- /* @__PURE__ */ jsx12(
2129
- Badge,
2130
- {
2131
- variant: thread.status === "archived" ? "secondary" : "default",
2132
- children: thread.status === "archived" ? labels.statusArchived : labels.statusActive
2133
- }
2134
- )
2135
- ] }),
2136
- /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
2137
- /* @__PURE__ */ jsxs7("span", { children: [
2138
- formatNumber(thread.messageCount),
2139
- " messages"
2140
- ] }),
2141
- /* @__PURE__ */ jsxs7("span", { children: [
2142
- thread.participantIds.length,
2143
- " participants"
2144
- ] }),
2145
- /* @__PURE__ */ jsx12("span", { children: formatDate(thread.lastActivityAt) })
2146
- ] })
2147
- ]
2148
- },
2149
- thread.threadId
2150
- )) });
2068
+ const totalValue = getUsageTotalValue(totals, metricKind, dimension);
2069
+ const filterable = groupBy !== "namespace";
2070
+ return /* @__PURE__ */ jsxs8(Card, { className: "min-h-0 gap-2 overflow-hidden py-3", children: [
2071
+ /* @__PURE__ */ jsx13(CardHeader, { className: "px-4", children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between", children: [
2072
+ /* @__PURE__ */ jsx13(CardTitle, { className: "text-base", children: "Usage detail" }),
2073
+ /* @__PURE__ */ jsxs8(Badge, { variant: "outline", children: [
2074
+ formatNumber(rows.length),
2075
+ " ",
2076
+ getGroupByLabel(groupBy).toLowerCase()
2077
+ ] })
2078
+ ] }) }),
2079
+ /* @__PURE__ */ jsx13(CardContent, { className: "min-h-0 flex-1 overflow-hidden px-0", children: rows.length === 0 ? /* @__PURE__ */ jsx13("p", { className: "px-5 py-4 text-sm text-muted-foreground", children: labels.noResults }) : /* @__PURE__ */ jsx13("div", { className: "h-full overflow-auto", children: /* @__PURE__ */ jsxs8("table", { className: "w-full min-w-[940px] text-sm", children: [
2080
+ /* @__PURE__ */ jsx13("thead", { className: "sticky top-0 z-10 bg-card", children: /* @__PURE__ */ jsxs8("tr", { className: "border-b text-left text-xs uppercase tracking-[0.12em] text-muted-foreground", children: [
2081
+ /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 font-medium", children: getGroupByLabel(groupBy) }),
2082
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: getUsageSummaryLabel(labels, metricKind, dimension) }),
2083
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Share" }),
2084
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Calls" }),
2085
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Input" }),
2086
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Output" }),
2087
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Reasoning" }),
2088
+ /* @__PURE__ */ jsx13("th", { className: "px-3 py-2.5 text-right font-medium", children: "Cache read" }),
2089
+ /* @__PURE__ */ jsx13("th", { className: "px-5 py-2.5 text-right font-medium", children: "Avg/call" })
2090
+ ] }) }),
2091
+ /* @__PURE__ */ jsx13("tbody", { children: rows.slice(0, 60).map((row) => {
2092
+ const share = totalValue > 0 ? row.value / totalValue : 0;
2093
+ return /* @__PURE__ */ jsxs8(
2094
+ "tr",
2095
+ {
2096
+ className: cn(
2097
+ "border-b last:border-0",
2098
+ filterable && "cursor-pointer transition-colors hover:bg-muted/50"
2099
+ ),
2100
+ onClick: () => filterable && onRowFilter(row),
2101
+ children: [
2102
+ /* @__PURE__ */ jsxs8("td", { className: "px-5 py-3", children: [
2103
+ /* @__PURE__ */ jsx13("div", { className: "max-w-80 truncate font-medium", children: row.groupLabel }),
2104
+ row.groupKey !== row.groupLabel && /* @__PURE__ */ jsx13("div", { className: "mt-0.5 max-w-80 truncate text-xs text-muted-foreground", children: row.groupKey })
2105
+ ] }),
2106
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right font-medium", children: formatMetricValue(row.value, metricKind) }),
2107
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatPercent(share) }),
2108
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatNumber(row.totalCalls) }),
2109
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2110
+ getUsageTotalValue(row, metricKind, "input"),
2111
+ metricKind
2112
+ ) }),
2113
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2114
+ getUsageTotalValue(row, metricKind, "output"),
2115
+ metricKind
2116
+ ) }),
2117
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2118
+ getUsageTotalValue(row, metricKind, "reasoning"),
2119
+ metricKind
2120
+ ) }),
2121
+ /* @__PURE__ */ jsx13("td", { className: "px-3 py-3 text-right", children: formatMetricValue(
2122
+ getUsageTotalValue(row, metricKind, "cacheRead"),
2123
+ metricKind
2124
+ ) }),
2125
+ /* @__PURE__ */ jsx13("td", { className: "px-5 py-3 text-right", children: formatMetricValue(
2126
+ row.totalCalls > 0 ? row.value / row.totalCalls : 0,
2127
+ metricKind
2128
+ ) })
2129
+ ]
2130
+ },
2131
+ row.groupKey
2132
+ );
2133
+ }) })
2134
+ ] }) }) })
2135
+ ] });
2151
2136
  }
2152
- function ParticipantsTable({
2153
- rows,
2154
- labels
2137
+ function DashboardHeaderControls({
2138
+ attribution,
2139
+ bucket,
2140
+ config,
2141
+ dimension,
2142
+ groupBy,
2143
+ metricKind,
2144
+ period,
2145
+ setAttribution,
2146
+ setBucket,
2147
+ setDimension,
2148
+ setGroupBy,
2149
+ setMetricKind,
2150
+ setPeriod
2155
2151
  }) {
2156
- return /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: rows.map((participant) => /* @__PURE__ */ jsxs7(
2157
- "div",
2158
- {
2159
- className: "rounded-lg border bg-muted/50 p-4",
2160
- children: [
2161
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
2162
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
2163
- /* @__PURE__ */ jsx12("p", { className: "font-medium", children: participant.displayName }),
2164
- /* @__PURE__ */ jsx12("p", { className: "mt-1 text-xs uppercase tracking-[0.18em] text-muted-foreground", children: participant.participantType })
2165
- ] }),
2166
- /* @__PURE__ */ jsx12(Badge, { variant: "outline", children: participant.isGlobal ? labels.scopeGlobal : labels.scopeScoped })
2167
- ] }),
2168
- /* @__PURE__ */ jsxs7("div", { className: "mt-3 flex flex-wrap gap-3 text-xs text-muted-foreground", children: [
2169
- /* @__PURE__ */ jsxs7("span", { children: [
2170
- formatNumber(participant.messageCount),
2171
- " messages"
2172
- ] }),
2173
- /* @__PURE__ */ jsxs7("span", { children: [
2174
- formatNumber(participant.threadCount),
2175
- " threads"
2176
- ] }),
2177
- /* @__PURE__ */ jsx12("span", { children: formatDate(participant.lastActivityAt) })
2178
- ] })
2179
- ]
2180
- },
2181
- `${participant.namespace}:${participant.externalId}`
2182
- )) });
2152
+ return /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-1.5", children: [
2153
+ /* @__PURE__ */ jsx13(
2154
+ HeaderSelect,
2155
+ {
2156
+ label: "Period",
2157
+ onValueChange: (value) => setPeriod(value),
2158
+ options: [
2159
+ ["24h", config.labels.range24h],
2160
+ ["7d", config.labels.range7d],
2161
+ ["30d", config.labels.range30d],
2162
+ ["custom", "Custom"]
2163
+ ],
2164
+ value: period,
2165
+ width: "w-[86px]"
2166
+ }
2167
+ ),
2168
+ /* @__PURE__ */ jsx13(
2169
+ HeaderSelect,
2170
+ {
2171
+ label: "Bucket",
2172
+ onValueChange: (value) => setBucket(value),
2173
+ options: [
2174
+ ["minute", "Minute"],
2175
+ ["hour", "Hour"],
2176
+ ["day", "Day"],
2177
+ ["week", "Week"],
2178
+ ["month", "Month"]
2179
+ ],
2180
+ value: bucket,
2181
+ width: "w-[92px]"
2182
+ }
2183
+ ),
2184
+ /* @__PURE__ */ jsx13(
2185
+ HeaderSelect,
2186
+ {
2187
+ label: config.labels.usageMetricLabel,
2188
+ onValueChange: (value) => setMetricKind(value),
2189
+ options: [
2190
+ ["cost", config.labels.usageMetricCost],
2191
+ ["tokens", config.labels.usageMetricTokens],
2192
+ ["calls", "Calls"]
2193
+ ],
2194
+ value: metricKind,
2195
+ width: "w-[94px]"
2196
+ }
2197
+ ),
2198
+ /* @__PURE__ */ jsx13(
2199
+ HeaderSelect,
2200
+ {
2201
+ label: "Group",
2202
+ onValueChange: (value) => setGroupBy(value),
2203
+ options: [
2204
+ ["participant", "Participant"],
2205
+ ["thread", "Thread"],
2206
+ ["namespace", "Namespace"],
2207
+ ["provider", "Provider"],
2208
+ ["model", "Model"]
2209
+ ],
2210
+ value: groupBy,
2211
+ width: "w-[128px]"
2212
+ }
2213
+ ),
2214
+ /* @__PURE__ */ jsx13(
2215
+ HeaderSelect,
2216
+ {
2217
+ label: "Attribution",
2218
+ onValueChange: (value) => setAttribution(value),
2219
+ options: [
2220
+ ["initiatedBy", "Initiated by"],
2221
+ ["generatedBy", "Generated by"]
2222
+ ],
2223
+ value: attribution,
2224
+ width: "w-[132px]"
2225
+ }
2226
+ ),
2227
+ /* @__PURE__ */ jsx13(
2228
+ HeaderSelect,
2229
+ {
2230
+ label: config.labels.usageDimensionLabel,
2231
+ onValueChange: (value) => setDimension(value),
2232
+ options: USAGE_DIMENSIONS.map((nextDimension) => [
2233
+ nextDimension,
2234
+ getUsageDimensionLabel(config.labels, nextDimension)
2235
+ ]),
2236
+ value: dimension,
2237
+ width: "w-[116px]"
2238
+ }
2239
+ )
2240
+ ] });
2183
2241
  }
2184
- function AgentsTable({
2185
- rows,
2186
- labels,
2187
- usageMetricKind,
2188
- usageDimension
2242
+ function InlineFilters({
2243
+ activeFilterCount,
2244
+ clearFilters,
2245
+ customFrom,
2246
+ customTo,
2247
+ model,
2248
+ participantId,
2249
+ participantType,
2250
+ period,
2251
+ provider,
2252
+ setCustomFrom,
2253
+ setCustomTo,
2254
+ setModel,
2255
+ setParticipantId,
2256
+ setParticipantType,
2257
+ setProvider,
2258
+ setThreadId,
2259
+ threadId
2189
2260
  }) {
2190
- return /* @__PURE__ */ jsx12("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ jsxs7(
2191
- "div",
2192
- {
2193
- className: "rounded-lg border bg-muted/50 p-4",
2194
- children: [
2195
- /* @__PURE__ */ jsxs7("div", { className: "flex items-start justify-between gap-3", children: [
2196
- /* @__PURE__ */ jsxs7("div", { className: "min-w-0", children: [
2197
- /* @__PURE__ */ jsx12("p", { className: "font-medium", children: agent.displayName }),
2198
- /* @__PURE__ */ jsx12("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
2199
- ] }),
2200
- /* @__PURE__ */ jsx12(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
2201
- ] }),
2202
- /* @__PURE__ */ jsx12("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs", children: [
2203
- {
2204
- label: "Messages",
2205
- value: formatNumber(agent.messageCount)
2206
- },
2207
- {
2208
- label: "LLM calls",
2209
- value: formatNumber(agent.llmCallCount)
2210
- },
2211
- {
2212
- label: "Tool calls",
2213
- value: formatNumber(agent.toolCallMessageCount)
2214
- },
2215
- {
2216
- label: getUsageSummaryLabel(labels, usageMetricKind, usageDimension),
2217
- value: formatMetricValue(
2218
- getAgentUsageValue(agent, usageMetricKind, usageDimension),
2219
- usageMetricKind
2220
- )
2221
- }
2222
- ].map((item) => /* @__PURE__ */ jsxs7("div", { children: [
2223
- /* @__PURE__ */ jsx12("p", { className: "font-medium text-foreground", children: item.value }),
2224
- /* @__PURE__ */ jsx12("p", { className: "text-muted-foreground", children: item.label })
2225
- ] }, item.label)) })
2226
- ]
2227
- },
2228
- `${agent.namespace}:${agent.agentId}`
2229
- )) });
2261
+ return /* @__PURE__ */ jsxs8("div", { className: "flex max-w-full flex-wrap items-end justify-end gap-2", children: [
2262
+ /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2 pb-1 text-xs font-medium text-muted-foreground", children: [
2263
+ /* @__PURE__ */ jsx13(Filter, { className: "size-3.5" }),
2264
+ /* @__PURE__ */ jsx13("span", { children: "Filters" }),
2265
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(Badge, { variant: "secondary", children: activeFilterCount })
2266
+ ] }),
2267
+ period === "custom" && /* @__PURE__ */ jsxs8(Fragment2, { children: [
2268
+ /* @__PURE__ */ jsx13(
2269
+ FilterInput,
2270
+ {
2271
+ compact: true,
2272
+ label: "From",
2273
+ onChange: setCustomFrom,
2274
+ type: "datetime-local",
2275
+ value: customFrom
2276
+ }
2277
+ ),
2278
+ /* @__PURE__ */ jsx13(
2279
+ FilterInput,
2280
+ {
2281
+ compact: true,
2282
+ label: "To",
2283
+ onChange: setCustomTo,
2284
+ type: "datetime-local",
2285
+ value: customTo
2286
+ }
2287
+ )
2288
+ ] }),
2289
+ /* @__PURE__ */ jsx13(
2290
+ UsageSelect,
2291
+ {
2292
+ compact: true,
2293
+ label: "Type",
2294
+ onValueChange: (value) => setParticipantType(value),
2295
+ options: [
2296
+ ["all", "All"],
2297
+ ["human", "Human"],
2298
+ ["agent", "Agent"],
2299
+ ["job", "Job"]
2300
+ ],
2301
+ value: participantType
2302
+ }
2303
+ ),
2304
+ /* @__PURE__ */ jsx13(
2305
+ FilterInput,
2306
+ {
2307
+ compact: true,
2308
+ icon: /* @__PURE__ */ jsx13(Search, { className: "size-3.5" }),
2309
+ label: "Thread",
2310
+ onChange: setThreadId,
2311
+ value: threadId
2312
+ }
2313
+ ),
2314
+ /* @__PURE__ */ jsx13(
2315
+ FilterInput,
2316
+ {
2317
+ compact: true,
2318
+ icon: /* @__PURE__ */ jsx13(Users2, { className: "size-3.5" }),
2319
+ label: "Participant",
2320
+ onChange: setParticipantId,
2321
+ value: participantId
2322
+ }
2323
+ ),
2324
+ /* @__PURE__ */ jsx13(
2325
+ FilterInput,
2326
+ {
2327
+ compact: true,
2328
+ icon: /* @__PURE__ */ jsx13(Database2, { className: "size-3.5" }),
2329
+ label: "Provider",
2330
+ onChange: setProvider,
2331
+ value: provider
2332
+ }
2333
+ ),
2334
+ /* @__PURE__ */ jsx13(
2335
+ FilterInput,
2336
+ {
2337
+ compact: true,
2338
+ icon: /* @__PURE__ */ jsx13(Sparkles, { className: "size-3.5" }),
2339
+ label: "Model",
2340
+ onChange: setModel,
2341
+ value: model
2342
+ }
2343
+ ),
2344
+ activeFilterCount > 0 && /* @__PURE__ */ jsx13(
2345
+ Button,
2346
+ {
2347
+ className: "h-8",
2348
+ onClick: clearFilters,
2349
+ size: "sm",
2350
+ variant: "ghost",
2351
+ children: "Clear"
2352
+ }
2353
+ )
2354
+ ] });
2230
2355
  }
2231
- function formatBucket(bucket, interval) {
2232
- const date = new Date(bucket);
2233
- if (Number.isNaN(date.getTime())) return bucket;
2234
- return interval === "hour" ? date.toLocaleString(void 0, {
2235
- hour: "numeric",
2236
- month: "short",
2237
- day: "numeric"
2238
- }) : date.toLocaleDateString(void 0, {
2239
- month: "short",
2240
- day: "numeric"
2241
- });
2356
+ function HeaderSelect(props) {
2357
+ return /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2358
+ /* @__PURE__ */ jsx13(
2359
+ SelectTrigger,
2360
+ {
2361
+ "aria-label": props.label,
2362
+ className: cn("h-8 bg-background text-xs", props.width),
2363
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2364
+ }
2365
+ ),
2366
+ /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2367
+ ] });
2242
2368
  }
2243
- function formatUsageBucket(bucket, interval) {
2244
- const date = new Date(bucket);
2245
- if (Number.isNaN(date.getTime())) return bucket;
2246
- if (interval === "minute" || interval === "hour") {
2247
- return date.toLocaleString(void 0, {
2248
- month: "short",
2249
- day: "numeric",
2250
- hour: "numeric",
2251
- minute: interval === "minute" ? "2-digit" : void 0
2252
- });
2253
- }
2254
- if (interval === "month") {
2255
- return date.toLocaleDateString(void 0, {
2256
- month: "short",
2257
- year: "numeric"
2258
- });
2259
- }
2260
- return date.toLocaleDateString(void 0, {
2261
- month: "short",
2262
- day: "numeric"
2263
- });
2369
+ function UsageSelect(props) {
2370
+ return /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[116px]"), children: [
2371
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2372
+ /* @__PURE__ */ jsxs8(Select, { value: props.value, onValueChange: props.onValueChange, children: [
2373
+ /* @__PURE__ */ jsx13(
2374
+ SelectTrigger,
2375
+ {
2376
+ "aria-label": props.label,
2377
+ className: cn(
2378
+ "w-full min-w-0 bg-background",
2379
+ props.compact ? "h-8 text-xs" : "h-9"
2380
+ ),
2381
+ children: /* @__PURE__ */ jsx13(SelectValue, {})
2382
+ }
2383
+ ),
2384
+ /* @__PURE__ */ jsx13(SelectContent, { children: props.options.map(([value, label]) => /* @__PURE__ */ jsx13(SelectItem, { value, children: label }, value)) })
2385
+ ] })
2386
+ ] });
2264
2387
  }
2265
- function formatDate(value) {
2266
- if (!value) return "No activity";
2267
- const date = new Date(value);
2268
- if (Number.isNaN(date.getTime())) return value;
2269
- return date.toLocaleString(void 0, {
2270
- month: "short",
2271
- day: "numeric",
2272
- hour: "numeric",
2273
- minute: "2-digit"
2274
- });
2388
+ function FilterInput(props) {
2389
+ return /* @__PURE__ */ jsxs8("label", { className: cn("space-y-1", props.compact && "w-[150px]"), children: [
2390
+ /* @__PURE__ */ jsx13("span", { className: "sr-only", children: props.label }),
2391
+ /* @__PURE__ */ jsxs8("div", { className: "relative", children: [
2392
+ props.icon && /* @__PURE__ */ jsx13("span", { className: "pointer-events-none absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground", children: props.icon }),
2393
+ /* @__PURE__ */ jsx13(
2394
+ Input,
2395
+ {
2396
+ "aria-label": props.label,
2397
+ className: cn(
2398
+ "bg-background",
2399
+ props.compact ? "h-8 text-xs" : "h-9",
2400
+ props.icon && "pl-8"
2401
+ ),
2402
+ onChange: (event) => props.onChange(event.target.value),
2403
+ type: props.type ?? "text",
2404
+ value: props.value
2405
+ }
2406
+ )
2407
+ ] })
2408
+ ] });
2275
2409
  }
2276
- function formatNumber(value) {
2277
- return new Intl.NumberFormat().format(value);
2410
+ function EmptyDashboard({
2411
+ description,
2412
+ title
2413
+ }) {
2414
+ return /* @__PURE__ */ jsxs8("div", { className: "rounded-lg border border-dashed bg-muted/20 p-8 text-center", children: [
2415
+ /* @__PURE__ */ jsx13("h3", { className: "text-base font-semibold", children: title }),
2416
+ /* @__PURE__ */ jsx13("p", { className: "mt-2 text-sm text-muted-foreground", children: description })
2417
+ ] });
2278
2418
  }
2419
+ var EMPTY_TOTALS = {
2420
+ inputTokens: 0,
2421
+ outputTokens: 0,
2422
+ reasoningTokens: 0,
2423
+ cacheReadInputTokens: 0,
2424
+ cacheCreationInputTokens: 0,
2425
+ totalTokens: 0,
2426
+ inputCostUsd: 0,
2427
+ outputCostUsd: 0,
2428
+ reasoningCostUsd: 0,
2429
+ cacheReadInputCostUsd: 0,
2430
+ cacheCreationInputCostUsd: 0,
2431
+ totalCostUsd: 0,
2432
+ totalCalls: 0
2433
+ };
2279
2434
  var USAGE_DIMENSIONS = [
2280
2435
  "total",
2281
2436
  "input",
@@ -2292,27 +2447,43 @@ var USAGE_CHART_COLORS = [
2292
2447
  "hsl(var(--chart-5, 346 77% 49%))",
2293
2448
  "hsl(var(--muted-foreground))"
2294
2449
  ];
2295
- function emptyToUndefined(value) {
2296
- const trimmed = value.trim();
2297
- return trimmed.length > 0 ? trimmed : void 0;
2298
- }
2299
- function getUsageRange(period, customFrom, customTo) {
2300
- if (period === "custom") {
2301
- return {
2302
- from: customFrom ? new Date(customFrom).toISOString() : void 0,
2303
- to: customTo ? new Date(customTo).toISOString() : void 0
2450
+ function buildChartState(points, metricKind, dimension, interval) {
2451
+ const topGroups = topUsageGroups(points, metricKind, dimension);
2452
+ const groupIdByKey = new Map(topGroups.map((group, index) => [
2453
+ group.key,
2454
+ `series${index + 1}`
2455
+ ]));
2456
+ const series = topGroups.map((group, index) => ({
2457
+ color: USAGE_CHART_COLORS[index % USAGE_CHART_COLORS.length],
2458
+ id: groupIdByKey.get(group.key) ?? `series${index + 1}`,
2459
+ key: group.key,
2460
+ label: group.label
2461
+ }));
2462
+ const config = Object.fromEntries(
2463
+ series.map((item) => [item.id, {
2464
+ color: item.color,
2465
+ label: item.label
2466
+ }])
2467
+ );
2468
+ const buckets = buildUsageBuckets(points);
2469
+ const data = buckets.map((bucket) => {
2470
+ const row = {
2471
+ bucket: bucket.bucket,
2472
+ label: formatUsageBucket(bucket.bucket, interval)
2304
2473
  };
2305
- }
2306
- const to = /* @__PURE__ */ new Date();
2307
- const from = new Date(to);
2308
- if (period === "24h") {
2309
- from.setHours(from.getHours() - 24);
2310
- } else if (period === "30d") {
2311
- from.setDate(from.getDate() - 30);
2312
- } else {
2313
- from.setDate(from.getDate() - 7);
2314
- }
2315
- return { from: from.toISOString(), to: to.toISOString() };
2474
+ for (const item of series) row[item.id] = 0;
2475
+ for (const point of bucket.points) {
2476
+ const seriesId = groupIdByKey.get(point.groupKey);
2477
+ if (!seriesId) continue;
2478
+ row[seriesId] = Number(row[seriesId] ?? 0) + getUsageTotalValue(point, metricKind, dimension);
2479
+ }
2480
+ return row;
2481
+ });
2482
+ return {
2483
+ config,
2484
+ data,
2485
+ series
2486
+ };
2316
2487
  }
2317
2488
  function buildUsageBuckets(points) {
2318
2489
  const byBucket = /* @__PURE__ */ new Map();
@@ -2321,7 +2492,39 @@ function buildUsageBuckets(points) {
2321
2492
  rows.push(point);
2322
2493
  byBucket.set(point.bucket, rows);
2323
2494
  }
2324
- return Array.from(byBucket.entries()).map(([bucket, bucketPoints]) => ({ bucket, points: bucketPoints })).sort((a, b) => new Date(a.bucket).getTime() - new Date(b.bucket).getTime());
2495
+ return Array.from(byBucket.entries()).map(([bucket, bucketPoints]) => ({ bucket, points: bucketPoints })).sort(
2496
+ (a, b) => new Date(a.bucket).getTime() - new Date(b.bucket).getTime()
2497
+ );
2498
+ }
2499
+ function aggregateUsageRows(points, metricKind, dimension) {
2500
+ const totals = /* @__PURE__ */ new Map();
2501
+ for (const point of points) {
2502
+ const existing = totals.get(point.groupKey) ?? {
2503
+ ...EMPTY_TOTALS,
2504
+ groupKey: point.groupKey,
2505
+ groupLabel: point.groupLabel,
2506
+ value: 0
2507
+ };
2508
+ addUsageTotals(existing, point);
2509
+ existing.value = getUsageTotalValue(existing, metricKind, dimension);
2510
+ totals.set(point.groupKey, existing);
2511
+ }
2512
+ return Array.from(totals.values()).sort((a, b) => b.value - a.value);
2513
+ }
2514
+ function addUsageTotals(target, source) {
2515
+ target.inputTokens += source.inputTokens;
2516
+ target.outputTokens += source.outputTokens;
2517
+ target.reasoningTokens += source.reasoningTokens;
2518
+ target.cacheReadInputTokens += source.cacheReadInputTokens;
2519
+ target.cacheCreationInputTokens += source.cacheCreationInputTokens;
2520
+ target.totalTokens += source.totalTokens;
2521
+ target.inputCostUsd += source.inputCostUsd;
2522
+ target.outputCostUsd += source.outputCostUsd;
2523
+ target.reasoningCostUsd += source.reasoningCostUsd;
2524
+ target.cacheReadInputCostUsd += source.cacheReadInputCostUsd;
2525
+ target.cacheCreationInputCostUsd += source.cacheCreationInputCostUsd;
2526
+ target.totalCostUsd += source.totalCostUsd;
2527
+ target.totalCalls += source.totalCalls;
2325
2528
  }
2326
2529
  function topUsageGroups(points, metricKind, dimension) {
2327
2530
  const totals = /* @__PURE__ */ new Map();
@@ -2331,11 +2534,33 @@ function topUsageGroups(points, metricKind, dimension) {
2331
2534
  label: point.groupLabel,
2332
2535
  value: 0
2333
2536
  };
2334
- existing.value += getUsagePointValue(point, metricKind, dimension);
2537
+ existing.value += getUsageTotalValue(point, metricKind, dimension);
2335
2538
  totals.set(point.groupKey, existing);
2336
2539
  }
2337
2540
  return Array.from(totals.values()).sort((a, b) => b.value - a.value).slice(0, 6);
2338
2541
  }
2542
+ function getUsageRange(period, customFrom, customTo) {
2543
+ if (period === "custom") {
2544
+ return {
2545
+ from: customFrom ? new Date(customFrom).toISOString() : void 0,
2546
+ to: customTo ? new Date(customTo).toISOString() : void 0
2547
+ };
2548
+ }
2549
+ const to = /* @__PURE__ */ new Date();
2550
+ const from = new Date(to);
2551
+ if (period === "24h") {
2552
+ from.setHours(from.getHours() - 24);
2553
+ } else if (period === "30d") {
2554
+ from.setDate(from.getDate() - 30);
2555
+ } else {
2556
+ from.setDate(from.getDate() - 7);
2557
+ }
2558
+ return { from: from.toISOString(), to: to.toISOString() };
2559
+ }
2560
+ function emptyToUndefined(value) {
2561
+ const trimmed = value.trim();
2562
+ return trimmed.length > 0 ? trimmed : void 0;
2563
+ }
2339
2564
  function getUsageDimensionLabel(labels, dimension) {
2340
2565
  switch (dimension) {
2341
2566
  case "input":
@@ -2357,146 +2582,100 @@ function getUsageSummaryLabel(labels, metricKind, dimension) {
2357
2582
  const metricLabel = metricKind === "cost" ? labels.usageMetricCost : metricKind === "calls" ? "Calls" : labels.usageMetricTokens;
2358
2583
  return `${getUsageDimensionLabel(labels, dimension)} ${metricLabel}`;
2359
2584
  }
2360
- function getOverviewUsageValue(overview, metricKind, dimension) {
2361
- const llmTotals = overview.llmTotals;
2362
- if (metricKind === "calls") return llmTotals.totalCalls;
2363
- if (metricKind === "cost") {
2364
- switch (dimension) {
2365
- case "input":
2366
- return llmTotals.inputCostUsd;
2367
- case "output":
2368
- return llmTotals.outputCostUsd;
2369
- case "reasoning":
2370
- return llmTotals.reasoningCostUsd;
2371
- case "cacheRead":
2372
- return llmTotals.cacheReadInputCostUsd;
2373
- case "cacheWrite":
2374
- return llmTotals.cacheCreationInputCostUsd;
2375
- case "total":
2376
- default:
2377
- return llmTotals.totalCostUsd;
2378
- }
2379
- }
2380
- switch (dimension) {
2381
- case "input":
2382
- return llmTotals.inputTokens;
2383
- case "output":
2384
- return llmTotals.outputTokens;
2385
- case "reasoning":
2386
- return llmTotals.reasoningTokens;
2387
- case "cacheRead":
2388
- return llmTotals.cacheReadInputTokens;
2389
- case "cacheWrite":
2390
- return llmTotals.cacheCreationInputTokens;
2391
- case "total":
2585
+ function getGroupByLabel(groupBy) {
2586
+ switch (groupBy) {
2587
+ case "thread":
2588
+ return "Thread";
2589
+ case "namespace":
2590
+ return "Namespace";
2591
+ case "provider":
2592
+ return "Provider";
2593
+ case "model":
2594
+ return "Model";
2595
+ case "participant":
2392
2596
  default:
2393
- return llmTotals.totalTokens;
2597
+ return "Participant";
2394
2598
  }
2395
2599
  }
2396
- function getAgentUsageValue(agent, metricKind, dimension) {
2600
+ function getUsageTotalValue(totals, metricKind, dimension) {
2601
+ if (metricKind === "calls") return totals.totalCalls;
2397
2602
  if (metricKind === "cost") {
2398
2603
  switch (dimension) {
2399
2604
  case "input":
2400
- return agent.inputCostUsd;
2605
+ return totals.inputCostUsd;
2401
2606
  case "output":
2402
- return agent.outputCostUsd;
2607
+ return totals.outputCostUsd;
2403
2608
  case "reasoning":
2404
- return agent.reasoningCostUsd;
2609
+ return totals.reasoningCostUsd;
2405
2610
  case "cacheRead":
2406
- return agent.cacheReadInputCostUsd;
2611
+ return totals.cacheReadInputCostUsd;
2407
2612
  case "cacheWrite":
2408
- return agent.cacheCreationInputCostUsd;
2613
+ return totals.cacheCreationInputCostUsd;
2409
2614
  case "total":
2410
2615
  default:
2411
- return agent.totalCostUsd;
2616
+ return totals.totalCostUsd;
2412
2617
  }
2413
2618
  }
2414
- if (metricKind === "calls") return agent.llmCallCount;
2415
2619
  switch (dimension) {
2416
2620
  case "input":
2417
- return agent.inputTokens;
2621
+ return totals.inputTokens;
2418
2622
  case "output":
2419
- return agent.outputTokens;
2623
+ return totals.outputTokens;
2420
2624
  case "reasoning":
2421
- return agent.reasoningTokens;
2625
+ return totals.reasoningTokens;
2422
2626
  case "cacheRead":
2423
- return agent.cacheReadInputTokens;
2627
+ return totals.cacheReadInputTokens;
2424
2628
  case "cacheWrite":
2425
- return agent.cacheCreationInputTokens;
2629
+ return totals.cacheCreationInputTokens;
2426
2630
  case "total":
2427
2631
  default:
2428
- return agent.totalTokens;
2632
+ return totals.totalTokens;
2429
2633
  }
2430
2634
  }
2431
- function getActivityUsageValue(point, metricKind, dimension) {
2432
- if (metricKind === "cost") {
2433
- switch (dimension) {
2434
- case "input":
2435
- return point.inputCostUsd;
2436
- case "output":
2437
- return point.outputCostUsd;
2438
- case "reasoning":
2439
- return point.reasoningCostUsd;
2440
- case "cacheRead":
2441
- return point.cacheReadInputCostUsd;
2442
- case "cacheWrite":
2443
- return point.cacheCreationInputCostUsd;
2444
- case "total":
2445
- default:
2446
- return point.totalCostUsd;
2447
- }
2635
+ function formatUsageBucket(bucket, interval) {
2636
+ const date = new Date(bucket);
2637
+ if (Number.isNaN(date.getTime())) return bucket;
2638
+ if (interval === "minute" || interval === "hour") {
2639
+ return date.toLocaleString(void 0, {
2640
+ month: "short",
2641
+ day: "numeric",
2642
+ hour: "numeric",
2643
+ minute: interval === "minute" ? "2-digit" : void 0
2644
+ });
2448
2645
  }
2449
- if (metricKind === "calls") return point.llmCallCount;
2450
- switch (dimension) {
2451
- case "input":
2452
- return point.inputTokens;
2453
- case "output":
2454
- return point.outputTokens;
2455
- case "reasoning":
2456
- return point.reasoningTokens;
2457
- case "cacheRead":
2458
- return point.cacheReadInputTokens;
2459
- case "cacheWrite":
2460
- return point.cacheCreationInputTokens;
2461
- case "total":
2462
- default:
2463
- return point.totalTokens;
2646
+ if (interval === "month") {
2647
+ return date.toLocaleDateString(void 0, {
2648
+ month: "short",
2649
+ year: "numeric"
2650
+ });
2464
2651
  }
2652
+ return date.toLocaleDateString(void 0, {
2653
+ month: "short",
2654
+ day: "numeric"
2655
+ });
2465
2656
  }
2466
- function getUsagePointValue(point, metricKind, dimension) {
2467
- if (metricKind === "cost") {
2468
- switch (dimension) {
2469
- case "input":
2470
- return point.inputCostUsd;
2471
- case "output":
2472
- return point.outputCostUsd;
2473
- case "reasoning":
2474
- return point.reasoningCostUsd;
2475
- case "cacheRead":
2476
- return point.cacheReadInputCostUsd;
2477
- case "cacheWrite":
2478
- return point.cacheCreationInputCostUsd;
2479
- case "total":
2480
- default:
2481
- return point.totalCostUsd;
2482
- }
2483
- }
2484
- if (metricKind === "calls") return point.totalCalls;
2485
- switch (dimension) {
2486
- case "input":
2487
- return point.inputTokens;
2488
- case "output":
2489
- return point.outputTokens;
2490
- case "reasoning":
2491
- return point.reasoningTokens;
2492
- case "cacheRead":
2493
- return point.cacheReadInputTokens;
2494
- case "cacheWrite":
2495
- return point.cacheCreationInputTokens;
2496
- case "total":
2497
- default:
2498
- return point.totalTokens;
2499
- }
2657
+ function formatUsageRangeLabel(period, range) {
2658
+ if (period !== "custom") return period;
2659
+ if (!range.from && !range.to) return "Custom";
2660
+ return `${formatShortDate(range.from)} - ${formatShortDate(range.to)}`;
2661
+ }
2662
+ function formatShortDate(value) {
2663
+ if (!value) return "Open";
2664
+ const date = new Date(value);
2665
+ if (Number.isNaN(date.getTime())) return value;
2666
+ return date.toLocaleDateString(void 0, {
2667
+ month: "short",
2668
+ day: "numeric"
2669
+ });
2670
+ }
2671
+ function formatNumber(value) {
2672
+ return new Intl.NumberFormat().format(value);
2673
+ }
2674
+ function formatPercent(value) {
2675
+ return new Intl.NumberFormat(void 0, {
2676
+ maximumFractionDigits: 1,
2677
+ style: "percent"
2678
+ }).format(value);
2500
2679
  }
2501
2680
  function formatMetricValue(value, metricKind) {
2502
2681
  if (metricKind === "cost") {
@@ -2511,10 +2690,26 @@ function formatMetricValue(value, metricKind) {
2511
2690
  }
2512
2691
  return formatNumber(value);
2513
2692
  }
2693
+ function formatCompactMetric(value, metricKind) {
2694
+ if (metricKind === "cost") {
2695
+ return new Intl.NumberFormat(void 0, {
2696
+ compactDisplay: "short",
2697
+ currency: "USD",
2698
+ maximumFractionDigits: 1,
2699
+ notation: "compact",
2700
+ style: "currency"
2701
+ }).format(value);
2702
+ }
2703
+ return new Intl.NumberFormat(void 0, {
2704
+ compactDisplay: "short",
2705
+ maximumFractionDigits: 1,
2706
+ notation: "compact"
2707
+ }).format(value);
2708
+ }
2514
2709
 
2515
2710
  // src/components/views/ThreadsView.tsx
2516
- import { Search, MessageSquare as MessageSquare2 } from "lucide-react";
2517
- import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
2711
+ import { Search as Search2, MessageSquare as MessageSquare2 } from "lucide-react";
2712
+ import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2518
2713
  var ThreadsView = ({
2519
2714
  config,
2520
2715
  threads,
@@ -2522,10 +2717,10 @@ var ThreadsView = ({
2522
2717
  onSearchChange,
2523
2718
  onThreadClick
2524
2719
  }) => {
2525
- return /* @__PURE__ */ jsxs8("div", { className: "space-y-4", children: [
2526
- /* @__PURE__ */ jsxs8("div", { className: "relative max-w-sm", children: [
2527
- /* @__PURE__ */ jsx13(Search, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2528
- /* @__PURE__ */ jsx13(
2720
+ return /* @__PURE__ */ jsxs9("div", { className: "space-y-4", children: [
2721
+ /* @__PURE__ */ jsxs9("div", { className: "relative max-w-sm", children: [
2722
+ /* @__PURE__ */ jsx14(Search2, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2723
+ /* @__PURE__ */ jsx14(
2529
2724
  Input,
2530
2725
  {
2531
2726
  className: "pl-9",
@@ -2535,19 +2730,19 @@ var ThreadsView = ({
2535
2730
  }
2536
2731
  )
2537
2732
  ] }),
2538
- threads.length === 0 ? /* @__PURE__ */ jsxs8("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2539
- /* @__PURE__ */ jsx13(MessageSquare2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2540
- /* @__PURE__ */ jsx13("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2541
- ] }) : /* @__PURE__ */ jsx13("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ jsxs8(
2733
+ threads.length === 0 ? /* @__PURE__ */ jsxs9("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2734
+ /* @__PURE__ */ jsx14(MessageSquare2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2735
+ /* @__PURE__ */ jsx14("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2736
+ ] }) : /* @__PURE__ */ jsx14("div", { className: "space-y-2", children: threads.map((thread) => /* @__PURE__ */ jsxs9(
2542
2737
  "div",
2543
2738
  {
2544
2739
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
2545
2740
  onClick: () => onThreadClick?.(thread.threadId),
2546
2741
  children: [
2547
- /* @__PURE__ */ jsxs8("div", { className: "flex-1 min-w-0", children: [
2548
- /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2549
- /* @__PURE__ */ jsx13("p", { className: "font-medium truncate", children: thread.name }),
2550
- /* @__PURE__ */ jsx13(
2742
+ /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
2743
+ /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2744
+ /* @__PURE__ */ jsx14("p", { className: "font-medium truncate", children: thread.name }),
2745
+ /* @__PURE__ */ jsx14(
2551
2746
  Badge,
2552
2747
  {
2553
2748
  variant: thread.status === "archived" ? "secondary" : "default",
@@ -2556,18 +2751,18 @@ var ThreadsView = ({
2556
2751
  }
2557
2752
  )
2558
2753
  ] }),
2559
- /* @__PURE__ */ jsx13("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
2754
+ /* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm text-muted-foreground truncate", children: thread.summary ?? thread.lastMessagePreview ?? "No summary yet" })
2560
2755
  ] }),
2561
- /* @__PURE__ */ jsxs8("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
2562
- /* @__PURE__ */ jsxs8("p", { children: [
2756
+ /* @__PURE__ */ jsxs9("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
2757
+ /* @__PURE__ */ jsxs9("p", { children: [
2563
2758
  formatNumber2(thread.messageCount),
2564
2759
  " messages"
2565
2760
  ] }),
2566
- /* @__PURE__ */ jsxs8("p", { children: [
2761
+ /* @__PURE__ */ jsxs9("p", { children: [
2567
2762
  thread.participantIds.length,
2568
2763
  " participants"
2569
2764
  ] }),
2570
- /* @__PURE__ */ jsx13("p", { children: formatDate2(thread.lastActivityAt) })
2765
+ /* @__PURE__ */ jsx14("p", { children: formatDate(thread.lastActivityAt) })
2571
2766
  ] })
2572
2767
  ]
2573
2768
  },
@@ -2575,7 +2770,7 @@ var ThreadsView = ({
2575
2770
  )) })
2576
2771
  ] });
2577
2772
  };
2578
- function formatDate2(value) {
2773
+ function formatDate(value) {
2579
2774
  if (!value) return "No activity";
2580
2775
  const date = new Date(value);
2581
2776
  if (Number.isNaN(date.getTime())) return value;
@@ -2601,7 +2796,7 @@ import {
2601
2796
  Wrench,
2602
2797
  Cpu
2603
2798
  } from "lucide-react";
2604
- import { jsx as jsx14, jsxs as jsxs9 } from "react/jsx-runtime";
2799
+ import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
2605
2800
  var MESSAGES_PAGE_SIZE = 50;
2606
2801
  var ThreadDetailView = ({
2607
2802
  threadId,
@@ -2659,36 +2854,36 @@ var ThreadDetailView = ({
2659
2854
  }
2660
2855
  }, [threadId, pageInfo, isLoadingMore, config.baseUrl, config.getRequestHeaders]);
2661
2856
  if (isLoading) {
2662
- return /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx14(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
2857
+ return /* @__PURE__ */ jsx15("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx15(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
2663
2858
  }
2664
2859
  if (error) {
2665
- return /* @__PURE__ */ jsxs9("div", { className: "space-y-4 py-10 text-center", children: [
2666
- /* @__PURE__ */ jsx14("p", { className: "text-destructive font-medium", children: error.message }),
2667
- /* @__PURE__ */ jsxs9("div", { className: "flex justify-center gap-2", children: [
2668
- /* @__PURE__ */ jsxs9(Button, { variant: "outline", onClick: onBack, children: [
2669
- /* @__PURE__ */ jsx14(ArrowLeft, { className: "mr-2 h-4 w-4" }),
2860
+ return /* @__PURE__ */ jsxs10("div", { className: "space-y-4 py-10 text-center", children: [
2861
+ /* @__PURE__ */ jsx15("p", { className: "text-destructive font-medium", children: error.message }),
2862
+ /* @__PURE__ */ jsxs10("div", { className: "flex justify-center gap-2", children: [
2863
+ /* @__PURE__ */ jsxs10(Button, { variant: "outline", onClick: onBack, children: [
2864
+ /* @__PURE__ */ jsx15(ArrowLeft, { className: "mr-2 h-4 w-4" }),
2670
2865
  "Back"
2671
2866
  ] }),
2672
- /* @__PURE__ */ jsx14(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
2867
+ /* @__PURE__ */ jsx15(Button, { variant: "destructive", onClick: () => void loadInitial(), children: config.labels.retry })
2673
2868
  ] })
2674
2869
  ] });
2675
2870
  }
2676
- return /* @__PURE__ */ jsxs9("div", { className: "space-y-6", children: [
2677
- /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-4", children: [
2678
- /* @__PURE__ */ jsx14(
2871
+ return /* @__PURE__ */ jsxs10("div", { className: "space-y-6", children: [
2872
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-4", children: [
2873
+ /* @__PURE__ */ jsx15(
2679
2874
  Button,
2680
2875
  {
2681
2876
  variant: "ghost",
2682
2877
  size: "icon",
2683
2878
  className: "mt-1 shrink-0",
2684
2879
  onClick: onBack,
2685
- children: /* @__PURE__ */ jsx14(ArrowLeft, { className: "h-4 w-4" })
2880
+ children: /* @__PURE__ */ jsx15(ArrowLeft, { className: "h-4 w-4" })
2686
2881
  }
2687
2882
  ),
2688
- /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
2689
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2", children: [
2690
- /* @__PURE__ */ jsx14("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
2691
- /* @__PURE__ */ jsx14(
2883
+ /* @__PURE__ */ jsxs10("div", { className: "flex-1 min-w-0", children: [
2884
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
2885
+ /* @__PURE__ */ jsx15("h2", { className: "text-xl font-semibold truncate", children: thread?.name ?? threadId }),
2886
+ /* @__PURE__ */ jsx15(
2692
2887
  Badge,
2693
2888
  {
2694
2889
  variant: thread?.status === "archived" ? "secondary" : "default",
@@ -2696,31 +2891,31 @@ var ThreadDetailView = ({
2696
2891
  }
2697
2892
  )
2698
2893
  ] }),
2699
- thread?.summary && /* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
2700
- /* @__PURE__ */ jsxs9("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
2701
- thread?.createdAt && /* @__PURE__ */ jsxs9("span", { children: [
2894
+ thread?.summary && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-sm text-muted-foreground", children: thread.summary }),
2895
+ /* @__PURE__ */ jsxs10("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
2896
+ thread?.createdAt && /* @__PURE__ */ jsxs10("span", { children: [
2702
2897
  "Created ",
2703
- formatDate3(thread.createdAt)
2898
+ formatDate2(thread.createdAt)
2704
2899
  ] }),
2705
- thread?.updatedAt && /* @__PURE__ */ jsxs9("span", { children: [
2900
+ thread?.updatedAt && /* @__PURE__ */ jsxs10("span", { children: [
2706
2901
  "Updated ",
2707
- formatDate3(thread.updatedAt)
2902
+ formatDate2(thread.updatedAt)
2708
2903
  ] }),
2709
- thread?.participants && /* @__PURE__ */ jsxs9("span", { children: [
2904
+ thread?.participants && /* @__PURE__ */ jsxs10("span", { children: [
2710
2905
  thread.participants.length,
2711
2906
  " participants"
2712
2907
  ] })
2713
2908
  ] })
2714
2909
  ] })
2715
2910
  ] }),
2716
- /* @__PURE__ */ jsxs9("div", { className: "space-y-1", children: [
2717
- /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs9("h3", { className: "text-sm font-medium text-muted-foreground", children: [
2911
+ /* @__PURE__ */ jsxs10("div", { className: "space-y-1", children: [
2912
+ /* @__PURE__ */ jsx15("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxs10("h3", { className: "text-sm font-medium text-muted-foreground", children: [
2718
2913
  "Messages (",
2719
2914
  messages.length,
2720
2915
  pageInfo?.hasMoreBefore ? "+" : "",
2721
2916
  ")"
2722
2917
  ] }) }),
2723
- pageInfo?.hasMoreBefore && /* @__PURE__ */ jsx14("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxs9(
2918
+ pageInfo?.hasMoreBefore && /* @__PURE__ */ jsx15("div", { className: "flex justify-center py-2", children: /* @__PURE__ */ jsxs10(
2724
2919
  Button,
2725
2920
  {
2726
2921
  variant: "ghost",
@@ -2728,12 +2923,12 @@ var ThreadDetailView = ({
2728
2923
  onClick: () => void loadMore(),
2729
2924
  disabled: isLoadingMore,
2730
2925
  children: [
2731
- isLoadingMore ? /* @__PURE__ */ jsx14(Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx14(ChevronUp2, { className: "mr-2 h-3 w-3" }),
2926
+ isLoadingMore ? /* @__PURE__ */ jsx15(Loader2, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx15(ChevronUp2, { className: "mr-2 h-3 w-3" }),
2732
2927
  "Load older messages"
2733
2928
  ]
2734
2929
  }
2735
2930
  ) }),
2736
- /* @__PURE__ */ jsx14("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ jsx14("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ jsx14("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ jsx14(MessageRow, { message }, message.id)) }) })
2931
+ /* @__PURE__ */ jsx15("div", { className: "rounded-lg border bg-card", children: messages.length === 0 ? /* @__PURE__ */ jsx15("p", { className: "p-6 text-center text-sm text-muted-foreground", children: "No messages in this thread yet." }) : /* @__PURE__ */ jsx15("div", { className: "divide-y", children: messages.map((message) => /* @__PURE__ */ jsx15(MessageRow, { message }, message.id)) }) })
2737
2932
  ] })
2738
2933
  ] });
2739
2934
  };
@@ -2741,43 +2936,43 @@ function MessageRow({ message }) {
2741
2936
  const [expanded, setExpanded] = useState4(false);
2742
2937
  const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
2743
2938
  const hasReasoning = !!message.reasoning;
2744
- return /* @__PURE__ */ jsx14("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-start gap-3", children: [
2745
- /* @__PURE__ */ jsx14(SenderIcon, { senderType: message.senderType }),
2746
- /* @__PURE__ */ jsxs9("div", { className: "flex-1 min-w-0", children: [
2747
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-2 text-xs", children: [
2748
- /* @__PURE__ */ jsx14("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
2749
- /* @__PURE__ */ jsx14(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
2750
- message.createdAt && /* @__PURE__ */ jsx14("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
2939
+ return /* @__PURE__ */ jsx15("div", { className: "px-4 py-3", children: /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-3", children: [
2940
+ /* @__PURE__ */ jsx15(SenderIcon, { senderType: message.senderType }),
2941
+ /* @__PURE__ */ jsxs10("div", { className: "flex-1 min-w-0", children: [
2942
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2 text-xs", children: [
2943
+ /* @__PURE__ */ jsx15("span", { className: "font-medium", children: message.senderId ?? message.senderUserId ?? message.senderType }),
2944
+ /* @__PURE__ */ jsx15(Badge, { variant: "outline", className: "text-[10px] px-1.5 py-0", children: message.senderType }),
2945
+ message.createdAt && /* @__PURE__ */ jsx15("span", { className: "text-muted-foreground", children: formatTimestamp(message.createdAt) })
2751
2946
  ] }),
2752
- message.content && /* @__PURE__ */ jsx14("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
2753
- (hasToolCalls || hasReasoning) && /* @__PURE__ */ jsxs9("div", { className: "mt-2 space-y-2", children: [
2754
- hasToolCalls && /* @__PURE__ */ jsxs9(
2947
+ message.content && /* @__PURE__ */ jsx15("p", { className: "mt-1 text-sm whitespace-pre-wrap break-words", children: message.content }),
2948
+ (hasToolCalls || hasReasoning) && /* @__PURE__ */ jsxs10("div", { className: "mt-2 space-y-2", children: [
2949
+ hasToolCalls && /* @__PURE__ */ jsxs10(
2755
2950
  "button",
2756
2951
  {
2757
2952
  type: "button",
2758
2953
  onClick: () => setExpanded(!expanded),
2759
2954
  className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
2760
2955
  children: [
2761
- /* @__PURE__ */ jsx14(Wrench, { className: "h-3 w-3" }),
2956
+ /* @__PURE__ */ jsx15(Wrench, { className: "h-3 w-3" }),
2762
2957
  message.toolCalls.length,
2763
2958
  " tool call",
2764
2959
  message.toolCalls.length > 1 ? "s" : ""
2765
2960
  ]
2766
2961
  }
2767
2962
  ),
2768
- hasReasoning && /* @__PURE__ */ jsxs9(
2963
+ hasReasoning && /* @__PURE__ */ jsxs10(
2769
2964
  "button",
2770
2965
  {
2771
2966
  type: "button",
2772
2967
  onClick: () => setExpanded(!expanded),
2773
2968
  className: "inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors",
2774
2969
  children: [
2775
- /* @__PURE__ */ jsx14(Cpu, { className: "h-3 w-3" }),
2970
+ /* @__PURE__ */ jsx15(Cpu, { className: "h-3 w-3" }),
2776
2971
  "Reasoning"
2777
2972
  ]
2778
2973
  }
2779
2974
  ),
2780
- expanded && /* @__PURE__ */ jsx14("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
2975
+ expanded && /* @__PURE__ */ jsx15("pre", { className: "mt-2 rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(
2781
2976
  {
2782
2977
  ...hasToolCalls ? { toolCalls: message.toolCalls } : {},
2783
2978
  ...hasReasoning ? { reasoning: message.reasoning } : {}
@@ -2793,16 +2988,16 @@ function SenderIcon({ senderType }) {
2793
2988
  const base = "flex h-7 w-7 shrink-0 items-center justify-center rounded-full";
2794
2989
  switch (senderType) {
2795
2990
  case "agent":
2796
- return /* @__PURE__ */ jsx14("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ jsx14(Bot2, { className: "h-3.5 w-3.5" }) });
2991
+ return /* @__PURE__ */ jsx15("div", { className: cn(base, "bg-primary/10 text-primary"), children: /* @__PURE__ */ jsx15(Bot2, { className: "h-3.5 w-3.5" }) });
2797
2992
  case "user":
2798
- return /* @__PURE__ */ jsx14("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ jsx14(User, { className: "h-3.5 w-3.5" }) });
2993
+ return /* @__PURE__ */ jsx15("div", { className: cn(base, "bg-secondary text-secondary-foreground"), children: /* @__PURE__ */ jsx15(User, { className: "h-3.5 w-3.5" }) });
2799
2994
  case "tool":
2800
- return /* @__PURE__ */ jsx14("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx14(Wrench, { className: "h-3.5 w-3.5" }) });
2995
+ return /* @__PURE__ */ jsx15("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx15(Wrench, { className: "h-3.5 w-3.5" }) });
2801
2996
  default:
2802
- return /* @__PURE__ */ jsx14("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx14(Cpu, { className: "h-3.5 w-3.5" }) });
2997
+ return /* @__PURE__ */ jsx15("div", { className: cn(base, "bg-muted text-muted-foreground"), children: /* @__PURE__ */ jsx15(Cpu, { className: "h-3.5 w-3.5" }) });
2803
2998
  }
2804
2999
  }
2805
- function formatDate3(value) {
3000
+ function formatDate2(value) {
2806
3001
  const date = new Date(value);
2807
3002
  if (Number.isNaN(date.getTime())) return value;
2808
3003
  return date.toLocaleDateString(void 0, {
@@ -2824,8 +3019,8 @@ function formatTimestamp(value) {
2824
3019
  }
2825
3020
 
2826
3021
  // src/components/views/ParticipantsView.tsx
2827
- import { Search as Search2, Users as Users2 } from "lucide-react";
2828
- import { jsx as jsx15, jsxs as jsxs10 } from "react/jsx-runtime";
3022
+ import { Search as Search3, Users as Users3 } from "lucide-react";
3023
+ import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
2829
3024
  var ParticipantsView = ({
2830
3025
  config,
2831
3026
  participants,
@@ -2833,10 +3028,10 @@ var ParticipantsView = ({
2833
3028
  onSearchChange,
2834
3029
  onParticipantClick
2835
3030
  }) => {
2836
- return /* @__PURE__ */ jsxs10("div", { className: "space-y-4", children: [
2837
- /* @__PURE__ */ jsxs10("div", { className: "relative max-w-sm", children: [
2838
- /* @__PURE__ */ jsx15(Search2, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2839
- /* @__PURE__ */ jsx15(
3031
+ return /* @__PURE__ */ jsxs11("div", { className: "space-y-4", children: [
3032
+ /* @__PURE__ */ jsxs11("div", { className: "relative max-w-sm", children: [
3033
+ /* @__PURE__ */ jsx16(Search3, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3034
+ /* @__PURE__ */ jsx16(
2840
3035
  Input,
2841
3036
  {
2842
3037
  className: "pl-9",
@@ -2846,33 +3041,33 @@ var ParticipantsView = ({
2846
3041
  }
2847
3042
  )
2848
3043
  ] }),
2849
- participants.length === 0 ? /* @__PURE__ */ jsxs10("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
2850
- /* @__PURE__ */ jsx15(Users2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
2851
- /* @__PURE__ */ jsx15("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
2852
- ] }) : /* @__PURE__ */ jsx15("div", { className: "space-y-2", children: participants.map((p) => /* @__PURE__ */ jsxs10(
3044
+ participants.length === 0 ? /* @__PURE__ */ jsxs11("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3045
+ /* @__PURE__ */ jsx16(Users3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3046
+ /* @__PURE__ */ jsx16("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
3047
+ ] }) : /* @__PURE__ */ jsx16("div", { className: "space-y-2", children: participants.map((p) => /* @__PURE__ */ jsxs11(
2853
3048
  "div",
2854
3049
  {
2855
3050
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
2856
3051
  onClick: () => onParticipantClick?.(p.externalId),
2857
3052
  children: [
2858
- /* @__PURE__ */ jsxs10("div", { className: "flex-1 min-w-0", children: [
2859
- /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
2860
- /* @__PURE__ */ jsx15("p", { className: "font-medium truncate", children: p.displayName }),
2861
- /* @__PURE__ */ jsx15(Badge, { variant: "outline", className: "shrink-0 text-xs", children: p.participantType }),
2862
- /* @__PURE__ */ jsx15(Badge, { variant: p.isGlobal ? "default" : "secondary", className: "shrink-0 text-xs", children: p.isGlobal ? config.labels.scopeGlobal : config.labels.scopeScoped })
3053
+ /* @__PURE__ */ jsxs11("div", { className: "flex-1 min-w-0", children: [
3054
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
3055
+ /* @__PURE__ */ jsx16("p", { className: "font-medium truncate", children: p.displayName }),
3056
+ /* @__PURE__ */ jsx16(Badge, { variant: "outline", className: "shrink-0 text-xs", children: p.participantType }),
3057
+ /* @__PURE__ */ jsx16(Badge, { variant: p.isGlobal ? "default" : "secondary", className: "shrink-0 text-xs", children: p.isGlobal ? config.labels.scopeGlobal : config.labels.scopeScoped })
2863
3058
  ] }),
2864
- /* @__PURE__ */ jsx15("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
3059
+ /* @__PURE__ */ jsx16("p", { className: "mt-1 text-xs text-muted-foreground", children: p.externalId })
2865
3060
  ] }),
2866
- /* @__PURE__ */ jsxs10("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
2867
- /* @__PURE__ */ jsxs10("p", { children: [
3061
+ /* @__PURE__ */ jsxs11("div", { className: "text-right text-xs text-muted-foreground shrink-0 space-y-1", children: [
3062
+ /* @__PURE__ */ jsxs11("p", { children: [
2868
3063
  formatNumber3(p.messageCount),
2869
3064
  " messages"
2870
3065
  ] }),
2871
- /* @__PURE__ */ jsxs10("p", { children: [
3066
+ /* @__PURE__ */ jsxs11("p", { children: [
2872
3067
  formatNumber3(p.threadCount),
2873
3068
  " threads"
2874
3069
  ] }),
2875
- /* @__PURE__ */ jsx15("p", { children: formatDate4(p.lastActivityAt) })
3070
+ /* @__PURE__ */ jsx16("p", { children: formatDate3(p.lastActivityAt) })
2876
3071
  ] })
2877
3072
  ]
2878
3073
  },
@@ -2880,7 +3075,7 @@ var ParticipantsView = ({
2880
3075
  )) })
2881
3076
  ] });
2882
3077
  };
2883
- function formatDate4(value) {
3078
+ function formatDate3(value) {
2884
3079
  if (!value) return "No activity";
2885
3080
  const date = new Date(value);
2886
3081
  if (Number.isNaN(date.getTime())) return value;
@@ -2893,7 +3088,7 @@ function formatNumber3(value) {
2893
3088
  // src/components/views/ParticipantDetailView.tsx
2894
3089
  import { useCallback as useCallback4, useEffect as useEffect6, useState as useState5 } from "react";
2895
3090
  import { ArrowLeft as ArrowLeft2, Loader2 as Loader22, Save } from "lucide-react";
2896
- import { jsx as jsx16, jsxs as jsxs11 } from "react/jsx-runtime";
3091
+ import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
2897
3092
  var ParticipantDetailView = ({
2898
3093
  participantId,
2899
3094
  config,
@@ -2943,25 +3138,25 @@ var ParticipantDetailView = ({
2943
3138
  }
2944
3139
  };
2945
3140
  if (isLoading) {
2946
- return /* @__PURE__ */ jsx16("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx16(Loader22, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
3141
+ return /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx17(Loader22, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
2947
3142
  }
2948
- return /* @__PURE__ */ jsxs11("div", { className: "space-y-6", children: [
2949
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-4", children: [
2950
- /* @__PURE__ */ jsx16(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ jsx16(ArrowLeft2, { className: "h-4 w-4" }) }),
2951
- /* @__PURE__ */ jsxs11("div", { className: "flex-1 min-w-0", children: [
2952
- /* @__PURE__ */ jsx16("h2", { className: "text-xl font-semibold truncate", children: participantId }),
2953
- /* @__PURE__ */ jsx16("p", { className: "text-sm text-muted-foreground", children: "Participant Detail" })
3143
+ return /* @__PURE__ */ jsxs12("div", { className: "space-y-6", children: [
3144
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-4", children: [
3145
+ /* @__PURE__ */ jsx17(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ jsx17(ArrowLeft2, { className: "h-4 w-4" }) }),
3146
+ /* @__PURE__ */ jsxs12("div", { className: "flex-1 min-w-0", children: [
3147
+ /* @__PURE__ */ jsx17("h2", { className: "text-xl font-semibold truncate", children: participantId }),
3148
+ /* @__PURE__ */ jsx17("p", { className: "text-sm text-muted-foreground", children: "Participant Detail" })
2954
3149
  ] }),
2955
- /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
2956
- saveMessage && /* @__PURE__ */ jsx16("span", { className: "text-xs text-emerald-600", children: saveMessage }),
2957
- /* @__PURE__ */ jsxs11(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
2958
- isSaving ? /* @__PURE__ */ jsx16(Loader22, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx16(Save, { className: "mr-2 h-3 w-3" }),
3150
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
3151
+ saveMessage && /* @__PURE__ */ jsx17("span", { className: "text-xs text-emerald-600", children: saveMessage }),
3152
+ /* @__PURE__ */ jsxs12(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
3153
+ isSaving ? /* @__PURE__ */ jsx17(Loader22, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx17(Save, { className: "mr-2 h-3 w-3" }),
2959
3154
  "Save"
2960
3155
  ] })
2961
3156
  ] })
2962
3157
  ] }),
2963
- error && /* @__PURE__ */ jsx16("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
2964
- /* @__PURE__ */ jsx16("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ jsx16(
3158
+ error && /* @__PURE__ */ jsx17("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3159
+ /* @__PURE__ */ jsx17("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ jsx17(
2965
3160
  "textarea",
2966
3161
  {
2967
3162
  className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
@@ -2974,8 +3169,8 @@ var ParticipantDetailView = ({
2974
3169
  };
2975
3170
 
2976
3171
  // src/components/views/AgentsView.tsx
2977
- import { Search as Search3, Bot as Bot3 } from "lucide-react";
2978
- import { jsx as jsx17, jsxs as jsxs12 } from "react/jsx-runtime";
3172
+ import { Search as Search4, Bot as Bot3 } from "lucide-react";
3173
+ import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
2979
3174
  var AgentsView = ({
2980
3175
  config,
2981
3176
  agents,
@@ -2983,10 +3178,10 @@ var AgentsView = ({
2983
3178
  onSearchChange,
2984
3179
  onAgentClick
2985
3180
  }) => {
2986
- return /* @__PURE__ */ jsxs12("div", { className: "space-y-4", children: [
2987
- /* @__PURE__ */ jsxs12("div", { className: "relative max-w-sm", children: [
2988
- /* @__PURE__ */ jsx17(Search3, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
2989
- /* @__PURE__ */ jsx17(
3181
+ return /* @__PURE__ */ jsxs13("div", { className: "space-y-4", children: [
3182
+ /* @__PURE__ */ jsxs13("div", { className: "relative max-w-sm", children: [
3183
+ /* @__PURE__ */ jsx18(Search4, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3184
+ /* @__PURE__ */ jsx18(
2990
3185
  Input,
2991
3186
  {
2992
3187
  className: "pl-9",
@@ -2996,48 +3191,48 @@ var AgentsView = ({
2996
3191
  }
2997
3192
  )
2998
3193
  ] }),
2999
- agents.length === 0 ? /* @__PURE__ */ jsxs12("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3000
- /* @__PURE__ */ jsx17(Bot3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3001
- /* @__PURE__ */ jsx17("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
3002
- ] }) : /* @__PURE__ */ jsx17("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => /* @__PURE__ */ jsxs12(
3194
+ agents.length === 0 ? /* @__PURE__ */ jsxs13("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3195
+ /* @__PURE__ */ jsx18(Bot3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3196
+ /* @__PURE__ */ jsx18("p", { className: "mt-3 text-sm text-muted-foreground", children: searchValue ? config.labels.noResults : config.labels.emptyDescription })
3197
+ ] }) : /* @__PURE__ */ jsx18("div", { className: "grid gap-4 md:grid-cols-2 lg:grid-cols-3", children: agents.map((agent) => /* @__PURE__ */ jsxs13(
3003
3198
  "div",
3004
3199
  {
3005
3200
  className: "rounded-lg border bg-card p-5 transition-colors hover:bg-muted/50 cursor-pointer",
3006
3201
  onClick: () => onAgentClick?.(agent.agentId),
3007
3202
  children: [
3008
- /* @__PURE__ */ jsxs12("div", { className: "flex items-start justify-between gap-3", children: [
3009
- /* @__PURE__ */ jsxs12("div", { className: "min-w-0", children: [
3010
- /* @__PURE__ */ jsx17("p", { className: "font-medium truncate", children: agent.displayName }),
3011
- /* @__PURE__ */ jsx17("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
3203
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-start justify-between gap-3", children: [
3204
+ /* @__PURE__ */ jsxs13("div", { className: "min-w-0", children: [
3205
+ /* @__PURE__ */ jsx18("p", { className: "font-medium truncate", children: agent.displayName }),
3206
+ /* @__PURE__ */ jsx18("p", { className: "mt-1 truncate text-xs text-muted-foreground", children: agent.description ?? agent.agentId })
3012
3207
  ] }),
3013
- /* @__PURE__ */ jsx17(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
3208
+ /* @__PURE__ */ jsx18(Badge, { variant: "outline", className: "shrink-0", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
3014
3209
  ] }),
3015
- /* @__PURE__ */ jsxs12("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
3016
- /* @__PURE__ */ jsxs12("span", { children: [
3210
+ /* @__PURE__ */ jsxs13("div", { className: "mt-4 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
3211
+ /* @__PURE__ */ jsxs13("span", { children: [
3017
3212
  formatNumber4(agent.messageCount),
3018
3213
  " messages"
3019
3214
  ] }),
3020
- /* @__PURE__ */ jsxs12("span", { children: [
3215
+ /* @__PURE__ */ jsxs13("span", { children: [
3021
3216
  formatNumber4(agent.llmCallCount),
3022
3217
  " LLM calls"
3023
3218
  ] }),
3024
- /* @__PURE__ */ jsxs12("span", { children: [
3219
+ /* @__PURE__ */ jsxs13("span", { children: [
3025
3220
  formatNumber4(agent.toolCallMessageCount),
3026
3221
  " tool calls"
3027
3222
  ] }),
3028
- /* @__PURE__ */ jsxs12("span", { children: [
3223
+ /* @__PURE__ */ jsxs13("span", { children: [
3029
3224
  formatNumber4(agent.totalTokens),
3030
3225
  " tokens"
3031
3226
  ] })
3032
3227
  ] }),
3033
- /* @__PURE__ */ jsx17("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate5(agent.lastActivityAt) })
3228
+ /* @__PURE__ */ jsx18("p", { className: "mt-3 text-xs text-muted-foreground", children: formatDate4(agent.lastActivityAt) })
3034
3229
  ]
3035
3230
  },
3036
3231
  `${agent.namespace}:${agent.agentId}`
3037
3232
  )) })
3038
3233
  ] });
3039
3234
  };
3040
- function formatDate5(value) {
3235
+ function formatDate4(value) {
3041
3236
  if (!value) return "No activity";
3042
3237
  const date = new Date(value);
3043
3238
  if (Number.isNaN(date.getTime())) return value;
@@ -3049,7 +3244,7 @@ function formatNumber4(value) {
3049
3244
 
3050
3245
  // src/components/views/AgentDetailView.tsx
3051
3246
  import { ArrowLeft as ArrowLeft3, Bot as Bot4 } from "lucide-react";
3052
- import { jsx as jsx18, jsxs as jsxs13 } from "react/jsx-runtime";
3247
+ import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3053
3248
  var AgentDetailView = ({
3054
3249
  agentId,
3055
3250
  config,
@@ -3058,13 +3253,13 @@ var AgentDetailView = ({
3058
3253
  }) => {
3059
3254
  const agent = agents.find((a) => a.agentId === agentId);
3060
3255
  if (!agent) {
3061
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-4 py-10 text-center", children: [
3062
- /* @__PURE__ */ jsxs13("p", { className: "text-muted-foreground", children: [
3256
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-4 py-10 text-center", children: [
3257
+ /* @__PURE__ */ jsxs14("p", { className: "text-muted-foreground", children: [
3063
3258
  "Agent not found: ",
3064
3259
  agentId
3065
3260
  ] }),
3066
- /* @__PURE__ */ jsxs13(Button, { variant: "outline", onClick: onBack, children: [
3067
- /* @__PURE__ */ jsx18(ArrowLeft3, { className: "mr-2 h-4 w-4" }),
3261
+ /* @__PURE__ */ jsxs14(Button, { variant: "outline", onClick: onBack, children: [
3262
+ /* @__PURE__ */ jsx19(ArrowLeft3, { className: "mr-2 h-4 w-4" }),
3068
3263
  " Back"
3069
3264
  ] })
3070
3265
  ] });
@@ -3080,43 +3275,43 @@ var AgentDetailView = ({
3080
3275
  { label: "Cache Created", value: agent.cacheCreationInputTokens },
3081
3276
  { label: "Total Tokens", value: agent.totalTokens }
3082
3277
  ];
3083
- return /* @__PURE__ */ jsxs13("div", { className: "space-y-6", children: [
3084
- /* @__PURE__ */ jsxs13("div", { className: "flex items-start gap-4", children: [
3085
- /* @__PURE__ */ jsx18(Button, { variant: "ghost", size: "icon", className: "mt-1 shrink-0", onClick: onBack, children: /* @__PURE__ */ jsx18(ArrowLeft3, { className: "h-4 w-4" }) }),
3086
- /* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0", children: [
3087
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-3", children: [
3088
- /* @__PURE__ */ jsx18("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx18(Bot4, { className: "h-5 w-5" }) }),
3089
- /* @__PURE__ */ jsxs13("div", { children: [
3090
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
3091
- /* @__PURE__ */ jsx18("h2", { className: "text-xl font-semibold", children: agent.displayName }),
3092
- /* @__PURE__ */ jsx18(Badge, { variant: "outline", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
3278
+ return /* @__PURE__ */ jsxs14("div", { className: "space-y-6", children: [
3279
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-start gap-4", children: [
3280
+ /* @__PURE__ */ jsx19(Button, { variant: "ghost", size: "icon", className: "mt-1 shrink-0", onClick: onBack, children: /* @__PURE__ */ jsx19(ArrowLeft3, { className: "h-4 w-4" }) }),
3281
+ /* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
3282
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-3", children: [
3283
+ /* @__PURE__ */ jsx19("div", { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary", children: /* @__PURE__ */ jsx19(Bot4, { className: "h-5 w-5" }) }),
3284
+ /* @__PURE__ */ jsxs14("div", { children: [
3285
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
3286
+ /* @__PURE__ */ jsx19("h2", { className: "text-xl font-semibold", children: agent.displayName }),
3287
+ /* @__PURE__ */ jsx19(Badge, { variant: "outline", children: agent.isConfigured ? config.labels.configured : config.labels.unconfigured })
3093
3288
  ] }),
3094
- agent.description && /* @__PURE__ */ jsx18("p", { className: "text-sm text-muted-foreground", children: agent.description })
3289
+ agent.description && /* @__PURE__ */ jsx19("p", { className: "text-sm text-muted-foreground", children: agent.description })
3095
3290
  ] })
3096
3291
  ] }),
3097
- /* @__PURE__ */ jsxs13("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
3098
- /* @__PURE__ */ jsxs13("span", { children: [
3292
+ /* @__PURE__ */ jsxs14("div", { className: "mt-2 flex flex-wrap gap-4 text-xs text-muted-foreground", children: [
3293
+ /* @__PURE__ */ jsxs14("span", { children: [
3099
3294
  "ID: ",
3100
3295
  agent.agentId
3101
3296
  ] }),
3102
- /* @__PURE__ */ jsxs13("span", { children: [
3297
+ /* @__PURE__ */ jsxs14("span", { children: [
3103
3298
  "Namespace: ",
3104
3299
  agent.namespace
3105
3300
  ] }),
3106
- agent.lastActivityAt && /* @__PURE__ */ jsxs13("span", { children: [
3301
+ agent.lastActivityAt && /* @__PURE__ */ jsxs14("span", { children: [
3107
3302
  "Last active: ",
3108
- formatDate6(agent.lastActivityAt)
3303
+ formatDate5(agent.lastActivityAt)
3109
3304
  ] })
3110
3305
  ] })
3111
3306
  ] })
3112
3307
  ] }),
3113
- /* @__PURE__ */ jsx18("div", { className: "grid gap-4 sm:grid-cols-3 lg:grid-cols-3", children: stats.map((stat) => /* @__PURE__ */ jsxs13("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
3114
- /* @__PURE__ */ jsx18("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
3115
- /* @__PURE__ */ jsx18("p", { className: "mt-2 text-2xl font-semibold tracking-tight", children: new Intl.NumberFormat().format(stat.value) })
3308
+ /* @__PURE__ */ jsx19("div", { className: "grid gap-4 sm:grid-cols-3 lg:grid-cols-3", children: stats.map((stat) => /* @__PURE__ */ jsxs14("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
3309
+ /* @__PURE__ */ jsx19("p", { className: "text-sm font-medium text-muted-foreground", children: stat.label }),
3310
+ /* @__PURE__ */ jsx19("p", { className: "mt-2 text-2xl font-semibold tracking-tight", children: new Intl.NumberFormat().format(stat.value) })
3116
3311
  ] }, stat.label)) })
3117
3312
  ] });
3118
3313
  };
3119
- function formatDate6(value) {
3314
+ function formatDate5(value) {
3120
3315
  const date = new Date(value);
3121
3316
  if (Number.isNaN(date.getTime())) return value;
3122
3317
  return date.toLocaleString(void 0, { month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
@@ -3124,8 +3319,8 @@ function formatDate6(value) {
3124
3319
 
3125
3320
  // src/components/views/CollectionItemsView.tsx
3126
3321
  import { useCallback as useCallback5, useEffect as useEffect7, useState as useState6 } from "react";
3127
- import { Loader2 as Loader23, Plus, Search as Search4, Database as Database2 } from "lucide-react";
3128
- import { jsx as jsx19, jsxs as jsxs14 } from "react/jsx-runtime";
3322
+ import { Loader2 as Loader23, Plus, Search as Search5, Database as Database3 } from "lucide-react";
3323
+ import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
3129
3324
  var CollectionItemsView = ({
3130
3325
  collection,
3131
3326
  config,
@@ -3171,17 +3366,17 @@ var CollectionItemsView = ({
3171
3366
  if (keys.length === 0) return "(empty)";
3172
3367
  return keys.slice(0, 3).map((k) => `${k}: ${JSON.stringify(rest[k])?.slice(0, 30)}`).join(", ");
3173
3368
  };
3174
- return /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
3175
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between gap-4", children: [
3176
- /* @__PURE__ */ jsx19("h2", { className: "text-lg font-semibold capitalize", children: collection }),
3177
- onCreateNew && /* @__PURE__ */ jsxs14(Button, { size: "sm", onClick: onCreateNew, children: [
3178
- /* @__PURE__ */ jsx19(Plus, { className: "mr-2 h-3 w-3" }),
3369
+ return /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
3370
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between gap-4", children: [
3371
+ /* @__PURE__ */ jsx20("h2", { className: "text-lg font-semibold capitalize", children: collection }),
3372
+ onCreateNew && /* @__PURE__ */ jsxs15(Button, { size: "sm", onClick: onCreateNew, children: [
3373
+ /* @__PURE__ */ jsx20(Plus, { className: "mr-2 h-3 w-3" }),
3179
3374
  " New"
3180
3375
  ] })
3181
3376
  ] }),
3182
- /* @__PURE__ */ jsxs14("div", { className: "relative max-w-sm", children: [
3183
- /* @__PURE__ */ jsx19(Search4, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3184
- /* @__PURE__ */ jsx19(
3377
+ /* @__PURE__ */ jsxs15("div", { className: "relative max-w-sm", children: [
3378
+ /* @__PURE__ */ jsx20(Search5, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3379
+ /* @__PURE__ */ jsx20(
3185
3380
  Input,
3186
3381
  {
3187
3382
  className: "pl-9",
@@ -3191,20 +3386,20 @@ var CollectionItemsView = ({
3191
3386
  }
3192
3387
  )
3193
3388
  ] }),
3194
- error && /* @__PURE__ */ jsx19("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3195
- isLoading ? /* @__PURE__ */ jsx19("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx19(Loader23, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs14("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3196
- /* @__PURE__ */ jsx19(Database2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3197
- /* @__PURE__ */ jsx19("p", { className: "mt-3 text-sm text-muted-foreground", children: search ? config.labels.noResults : `No items in ${collection}` })
3198
- ] }) : /* @__PURE__ */ jsx19("div", { className: "space-y-2", children: items.map((item, idx) => {
3389
+ error && /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3390
+ isLoading ? /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx20(Loader23, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : items.length === 0 ? /* @__PURE__ */ jsxs15("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3391
+ /* @__PURE__ */ jsx20(Database3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3392
+ /* @__PURE__ */ jsx20("p", { className: "mt-3 text-sm text-muted-foreground", children: search ? config.labels.noResults : `No items in ${collection}` })
3393
+ ] }) : /* @__PURE__ */ jsx20("div", { className: "space-y-2", children: items.map((item, idx) => {
3199
3394
  const itemId = getItemId(item);
3200
- return /* @__PURE__ */ jsx19(
3395
+ return /* @__PURE__ */ jsx20(
3201
3396
  "div",
3202
3397
  {
3203
3398
  className: "flex items-center gap-4 rounded-lg border bg-card p-4 transition-colors hover:bg-muted/50 cursor-pointer",
3204
3399
  onClick: () => onItemClick?.(itemId),
3205
- children: /* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0", children: [
3206
- /* @__PURE__ */ jsx19("p", { className: "font-medium font-mono text-sm truncate", children: itemId }),
3207
- /* @__PURE__ */ jsx19("p", { className: "mt-1 text-xs text-muted-foreground truncate", children: getItemPreview(item) })
3400
+ children: /* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-0", children: [
3401
+ /* @__PURE__ */ jsx20("p", { className: "font-medium font-mono text-sm truncate", children: itemId }),
3402
+ /* @__PURE__ */ jsx20("p", { className: "mt-1 text-xs text-muted-foreground truncate", children: getItemPreview(item) })
3208
3403
  ] })
3209
3404
  },
3210
3405
  itemId + idx
@@ -3216,7 +3411,7 @@ var CollectionItemsView = ({
3216
3411
  // src/components/views/CollectionItemDetailView.tsx
3217
3412
  import { useCallback as useCallback6, useEffect as useEffect8, useState as useState7 } from "react";
3218
3413
  import { ArrowLeft as ArrowLeft5, Loader2 as Loader24, Save as Save2, Trash2 } from "lucide-react";
3219
- import { jsx as jsx20, jsxs as jsxs15 } from "react/jsx-runtime";
3414
+ import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
3220
3415
  var CollectionItemDetailView = ({
3221
3416
  collection,
3222
3417
  itemId,
@@ -3290,15 +3485,15 @@ var CollectionItemDetailView = ({
3290
3485
  }
3291
3486
  };
3292
3487
  if (isLoading) {
3293
- return /* @__PURE__ */ jsx20("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx20(Loader24, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
3488
+ return /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx21(Loader24, { className: "h-6 w-6 animate-spin text-muted-foreground" }) });
3294
3489
  }
3295
- return /* @__PURE__ */ jsxs15("div", { className: "space-y-6", children: [
3296
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-4", children: [
3297
- /* @__PURE__ */ jsx20(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ jsx20(ArrowLeft5, { className: "h-4 w-4" }) }),
3298
- /* @__PURE__ */ jsx20("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx20("h2", { className: "text-xl font-semibold truncate capitalize", children: isNew ? `New ${collection} item` : `${collection} / ${itemId}` }) }),
3299
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
3300
- saveMessage && /* @__PURE__ */ jsx20("span", { className: "text-xs text-emerald-600", children: saveMessage }),
3301
- !isNew && /* @__PURE__ */ jsxs15(
3490
+ return /* @__PURE__ */ jsxs16("div", { className: "space-y-6", children: [
3491
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-4", children: [
3492
+ /* @__PURE__ */ jsx21(Button, { variant: "ghost", size: "icon", onClick: onBack, children: /* @__PURE__ */ jsx21(ArrowLeft5, { className: "h-4 w-4" }) }),
3493
+ /* @__PURE__ */ jsx21("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx21("h2", { className: "text-xl font-semibold truncate capitalize", children: isNew ? `New ${collection} item` : `${collection} / ${itemId}` }) }),
3494
+ /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2", children: [
3495
+ saveMessage && /* @__PURE__ */ jsx21("span", { className: "text-xs text-emerald-600", children: saveMessage }),
3496
+ !isNew && /* @__PURE__ */ jsxs16(
3302
3497
  Button,
3303
3498
  {
3304
3499
  variant: "destructive",
@@ -3306,19 +3501,19 @@ var CollectionItemDetailView = ({
3306
3501
  onClick: () => void handleDelete(),
3307
3502
  disabled: isDeleting,
3308
3503
  children: [
3309
- isDeleting ? /* @__PURE__ */ jsx20(Loader24, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx20(Trash2, { className: "mr-2 h-3 w-3" }),
3504
+ isDeleting ? /* @__PURE__ */ jsx21(Loader24, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx21(Trash2, { className: "mr-2 h-3 w-3" }),
3310
3505
  "Delete"
3311
3506
  ]
3312
3507
  }
3313
3508
  ),
3314
- /* @__PURE__ */ jsxs15(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
3315
- isSaving ? /* @__PURE__ */ jsx20(Loader24, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx20(Save2, { className: "mr-2 h-3 w-3" }),
3509
+ /* @__PURE__ */ jsxs16(Button, { size: "sm", onClick: () => void handleSave(), disabled: isSaving, children: [
3510
+ isSaving ? /* @__PURE__ */ jsx21(Loader24, { className: "mr-2 h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx21(Save2, { className: "mr-2 h-3 w-3" }),
3316
3511
  isNew ? "Create" : "Save"
3317
3512
  ] })
3318
3513
  ] })
3319
3514
  ] }),
3320
- error && /* @__PURE__ */ jsx20("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3321
- /* @__PURE__ */ jsx20("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ jsx20(
3515
+ error && /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3516
+ /* @__PURE__ */ jsx21("div", { className: "rounded-lg border bg-card", children: /* @__PURE__ */ jsx21(
3322
3517
  "textarea",
3323
3518
  {
3324
3519
  className: "w-full min-h-[400px] p-4 font-mono text-sm bg-transparent resize-y focus:outline-none",
@@ -3332,8 +3527,8 @@ var CollectionItemDetailView = ({
3332
3527
 
3333
3528
  // src/components/views/EventsView.tsx
3334
3529
  import { useCallback as useCallback7, useState as useState8 } from "react";
3335
- import { Activity as Activity2, Loader2 as Loader25, Search as Search5 } from "lucide-react";
3336
- import { jsx as jsx21, jsxs as jsxs16 } from "react/jsx-runtime";
3530
+ import { Activity as Activity3, Loader2 as Loader25, Search as Search6 } from "lucide-react";
3531
+ import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
3337
3532
  var STATUS_VARIANTS = {
3338
3533
  pending: "outline",
3339
3534
  processing: "default",
@@ -3366,13 +3561,13 @@ var EventsView = ({ config }) => {
3366
3561
  setIsLoading(false);
3367
3562
  }
3368
3563
  }, [threadId, config.baseUrl, config.getRequestHeaders]);
3369
- return /* @__PURE__ */ jsxs16("div", { className: "space-y-6", children: [
3370
- /* @__PURE__ */ jsxs16("div", { className: "flex items-end gap-3 max-w-lg", children: [
3371
- /* @__PURE__ */ jsxs16("div", { className: "flex-1", children: [
3372
- /* @__PURE__ */ jsx21("label", { className: "text-sm font-medium mb-1 block", children: "Thread ID" }),
3373
- /* @__PURE__ */ jsxs16("div", { className: "relative", children: [
3374
- /* @__PURE__ */ jsx21(Search5, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3375
- /* @__PURE__ */ jsx21(
3564
+ return /* @__PURE__ */ jsxs17("div", { className: "space-y-6", children: [
3565
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-end gap-3 max-w-lg", children: [
3566
+ /* @__PURE__ */ jsxs17("div", { className: "flex-1", children: [
3567
+ /* @__PURE__ */ jsx22("label", { className: "text-sm font-medium mb-1 block", children: "Thread ID" }),
3568
+ /* @__PURE__ */ jsxs17("div", { className: "relative", children: [
3569
+ /* @__PURE__ */ jsx22(Search6, { className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
3570
+ /* @__PURE__ */ jsx22(
3376
3571
  Input,
3377
3572
  {
3378
3573
  className: "pl-9",
@@ -3384,55 +3579,55 @@ var EventsView = ({ config }) => {
3384
3579
  )
3385
3580
  ] })
3386
3581
  ] }),
3387
- /* @__PURE__ */ jsxs16(Button, { onClick: () => void handleSearch(), disabled: isLoading || !threadId.trim(), children: [
3388
- isLoading ? /* @__PURE__ */ jsx21(Loader25, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3582
+ /* @__PURE__ */ jsxs17(Button, { onClick: () => void handleSearch(), disabled: isLoading || !threadId.trim(), children: [
3583
+ isLoading ? /* @__PURE__ */ jsx22(Loader25, { className: "mr-2 h-4 w-4 animate-spin" }) : null,
3389
3584
  "Inspect"
3390
3585
  ] })
3391
3586
  ] }),
3392
- error && /* @__PURE__ */ jsx21("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3393
- !hasSearched ? /* @__PURE__ */ jsxs16("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3394
- /* @__PURE__ */ jsx21(Activity2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3395
- /* @__PURE__ */ jsx21("p", { className: "mt-3 text-sm text-muted-foreground", children: "Enter a thread ID to inspect its next pending queue event." })
3396
- ] }) : isLoading ? /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx21(Loader25, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : !event ? /* @__PURE__ */ jsxs16("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3397
- /* @__PURE__ */ jsx21(Activity2, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3398
- /* @__PURE__ */ jsx21("p", { className: "mt-3 text-sm text-muted-foreground", children: "No pending events found for this thread." })
3399
- ] }) : /* @__PURE__ */ jsxs16("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
3400
- /* @__PURE__ */ jsxs16("div", { className: "flex items-start justify-between gap-3", children: [
3401
- /* @__PURE__ */ jsxs16("div", { children: [
3402
- /* @__PURE__ */ jsx21("p", { className: "font-medium", children: event.eventType }),
3403
- /* @__PURE__ */ jsx21("p", { className: "text-xs text-muted-foreground font-mono mt-1", children: event.id })
3587
+ error && /* @__PURE__ */ jsx22("div", { className: "rounded-lg border border-destructive/50 bg-destructive/10 p-3 text-sm text-destructive", children: error }),
3588
+ !hasSearched ? /* @__PURE__ */ jsxs17("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3589
+ /* @__PURE__ */ jsx22(Activity3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3590
+ /* @__PURE__ */ jsx22("p", { className: "mt-3 text-sm text-muted-foreground", children: "Enter a thread ID to inspect its next pending queue event." })
3591
+ ] }) : isLoading ? /* @__PURE__ */ jsx22("div", { className: "flex items-center justify-center py-20", children: /* @__PURE__ */ jsx22(Loader25, { className: "h-6 w-6 animate-spin text-muted-foreground" }) }) : !event ? /* @__PURE__ */ jsxs17("div", { className: "rounded-xl border border-dashed p-10 text-center", children: [
3592
+ /* @__PURE__ */ jsx22(Activity3, { className: "mx-auto h-8 w-8 text-muted-foreground/50" }),
3593
+ /* @__PURE__ */ jsx22("p", { className: "mt-3 text-sm text-muted-foreground", children: "No pending events found for this thread." })
3594
+ ] }) : /* @__PURE__ */ jsxs17("div", { className: "rounded-lg border bg-card p-5 space-y-4", children: [
3595
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-start justify-between gap-3", children: [
3596
+ /* @__PURE__ */ jsxs17("div", { children: [
3597
+ /* @__PURE__ */ jsx22("p", { className: "font-medium", children: event.eventType }),
3598
+ /* @__PURE__ */ jsx22("p", { className: "text-xs text-muted-foreground font-mono mt-1", children: event.id })
3404
3599
  ] }),
3405
- /* @__PURE__ */ jsx21(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
3600
+ /* @__PURE__ */ jsx22(Badge, { variant: STATUS_VARIANTS[event.status] ?? "outline", children: event.status })
3406
3601
  ] }),
3407
- /* @__PURE__ */ jsxs16("div", { className: "grid gap-3 sm:grid-cols-2 text-sm", children: [
3408
- event.traceId && /* @__PURE__ */ jsxs16("div", { children: [
3409
- /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "Trace:" }),
3602
+ /* @__PURE__ */ jsxs17("div", { className: "grid gap-3 sm:grid-cols-2 text-sm", children: [
3603
+ event.traceId && /* @__PURE__ */ jsxs17("div", { children: [
3604
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: "Trace:" }),
3410
3605
  " ",
3411
- /* @__PURE__ */ jsx21("span", { className: "font-mono text-xs", children: event.traceId })
3606
+ /* @__PURE__ */ jsx22("span", { className: "font-mono text-xs", children: event.traceId })
3412
3607
  ] }),
3413
- event.parentEventId && /* @__PURE__ */ jsxs16("div", { children: [
3414
- /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "Parent:" }),
3608
+ event.parentEventId && /* @__PURE__ */ jsxs17("div", { children: [
3609
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: "Parent:" }),
3415
3610
  " ",
3416
- /* @__PURE__ */ jsx21("span", { className: "font-mono text-xs", children: event.parentEventId })
3611
+ /* @__PURE__ */ jsx22("span", { className: "font-mono text-xs", children: event.parentEventId })
3417
3612
  ] }),
3418
- event.priority != null && /* @__PURE__ */ jsxs16("div", { children: [
3419
- /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "Priority:" }),
3613
+ event.priority != null && /* @__PURE__ */ jsxs17("div", { children: [
3614
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: "Priority:" }),
3420
3615
  " ",
3421
3616
  event.priority
3422
3617
  ] }),
3423
- event.createdAt && /* @__PURE__ */ jsxs16("div", { children: [
3424
- /* @__PURE__ */ jsx21("span", { className: "text-muted-foreground", children: "Created:" }),
3618
+ event.createdAt && /* @__PURE__ */ jsxs17("div", { children: [
3619
+ /* @__PURE__ */ jsx22("span", { className: "text-muted-foreground", children: "Created:" }),
3425
3620
  " ",
3426
3621
  formatTimestamp2(event.createdAt)
3427
3622
  ] })
3428
3623
  ] }),
3429
- event.payload != null && /* @__PURE__ */ jsxs16("div", { children: [
3430
- /* @__PURE__ */ jsx21("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Payload" }),
3431
- /* @__PURE__ */ jsx21("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(event.payload, null, 2) })
3624
+ event.payload != null && /* @__PURE__ */ jsxs17("div", { children: [
3625
+ /* @__PURE__ */ jsx22("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Payload" }),
3626
+ /* @__PURE__ */ jsx22("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-60", children: JSON.stringify(event.payload, null, 2) })
3432
3627
  ] }),
3433
- event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ jsxs16("div", { children: [
3434
- /* @__PURE__ */ jsx21("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
3435
- /* @__PURE__ */ jsx21("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-40", children: JSON.stringify(event.metadata, null, 2) })
3628
+ event.metadata != null && Object.keys(event.metadata).length > 0 && /* @__PURE__ */ jsxs17("div", { children: [
3629
+ /* @__PURE__ */ jsx22("p", { className: "text-xs font-medium text-muted-foreground mb-1", children: "Metadata" }),
3630
+ /* @__PURE__ */ jsx22("pre", { className: "rounded-md bg-muted p-3 text-xs overflow-auto max-h-40", children: JSON.stringify(event.metadata, null, 2) })
3436
3631
  ] })
3437
3632
  ] })
3438
3633
  ] });
@@ -3450,7 +3645,7 @@ function formatTimestamp2(value) {
3450
3645
  }
3451
3646
 
3452
3647
  // src/CopilotzAdmin.tsx
3453
- import { jsx as jsx22, jsxs as jsxs17 } from "react/jsx-runtime";
3648
+ import { jsx as jsx23, jsxs as jsxs18 } from "react/jsx-runtime";
3454
3649
  var CopilotzAdmin = ({
3455
3650
  config: userConfig,
3456
3651
  className
@@ -3462,6 +3657,8 @@ var CopilotzAdmin = ({
3462
3657
  const [route, setRoute] = useState9({ page: config.defaultPage });
3463
3658
  const [namespace, setNamespace] = useState9(config.namespace);
3464
3659
  const [collections, setCollections] = useState9([]);
3660
+ const [headerControls, setHeaderControls] = useState9(null);
3661
+ const [headerRefresh, setHeaderRefresh] = useState9(null);
3465
3662
  const [threadSearch, setThreadSearch] = useState9("");
3466
3663
  const [participantSearch, setParticipantSearch] = useState9("");
3467
3664
  const [agentSearch, setAgentSearch] = useState9("");
@@ -3542,18 +3739,18 @@ var CopilotzAdmin = ({
3542
3739
  }
3543
3740
  })();
3544
3741
  if (admin.isLoading && !admin.overview) {
3545
- return /* @__PURE__ */ jsx22(Card, { className: cn("border-border", className), children: /* @__PURE__ */ jsx22(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
3742
+ return /* @__PURE__ */ jsx23(Card, { className: cn("border-border", className), children: /* @__PURE__ */ jsx23(CardContent, { className: "text-muted-foreground flex items-center justify-center min-h-[200px]", children: config.labels.loading }) });
3546
3743
  }
3547
3744
  if (admin.error && !admin.overview) {
3548
- return /* @__PURE__ */ jsx22(Card, { className: cn("border-destructive/50 bg-destructive/10", className), children: /* @__PURE__ */ jsxs17(CardContent, { className: "space-y-4", children: [
3549
- /* @__PURE__ */ jsx22("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
3550
- /* @__PURE__ */ jsx22(Button, { variant: "destructive", onClick: () => void admin.refresh(), children: config.labels.retry })
3745
+ return /* @__PURE__ */ jsx23(Card, { className: cn("border-destructive/50 bg-destructive/10", className), children: /* @__PURE__ */ jsxs18(CardContent, { className: "space-y-4", children: [
3746
+ /* @__PURE__ */ jsx23("p", { className: "text-base font-semibold text-destructive", children: admin.error.message }),
3747
+ /* @__PURE__ */ jsx23(Button, { variant: "destructive", onClick: () => void admin.refresh(), children: config.labels.retry })
3551
3748
  ] }) });
3552
3749
  }
3553
3750
  const renderCurrentView = () => {
3554
3751
  switch (route.page) {
3555
3752
  case "dashboard":
3556
- return /* @__PURE__ */ jsx22(
3753
+ return /* @__PURE__ */ jsx23(
3557
3754
  DashboardView,
3558
3755
  {
3559
3756
  config,
@@ -3570,11 +3767,13 @@ var CopilotzAdmin = ({
3570
3767
  onThreadSearchChange: setThreadSearch,
3571
3768
  onParticipantSearchChange: setParticipantSearch,
3572
3769
  onAgentSearchChange: setAgentSearch,
3573
- onThreadClick: handleThreadClick
3770
+ onThreadClick: handleThreadClick,
3771
+ setHeaderControls,
3772
+ setHeaderRefresh
3574
3773
  }
3575
3774
  );
3576
3775
  case "threads":
3577
- return /* @__PURE__ */ jsx22(
3776
+ return /* @__PURE__ */ jsx23(
3578
3777
  ThreadsView,
3579
3778
  {
3580
3779
  config,
@@ -3585,9 +3784,9 @@ var CopilotzAdmin = ({
3585
3784
  }
3586
3785
  );
3587
3786
  case "thread-detail":
3588
- return route.resourceId ? /* @__PURE__ */ jsx22(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
3787
+ return route.resourceId ? /* @__PURE__ */ jsx23(ThreadDetailView, { threadId: route.resourceId, config, onBack: handleBackToThreads }) : null;
3589
3788
  case "participants":
3590
- return /* @__PURE__ */ jsx22(
3789
+ return /* @__PURE__ */ jsx23(
3591
3790
  ParticipantsView,
3592
3791
  {
3593
3792
  config,
@@ -3598,9 +3797,9 @@ var CopilotzAdmin = ({
3598
3797
  }
3599
3798
  );
3600
3799
  case "participant-detail":
3601
- return route.resourceId ? /* @__PURE__ */ jsx22(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
3800
+ return route.resourceId ? /* @__PURE__ */ jsx23(ParticipantDetailView, { participantId: route.resourceId, config, onBack: handleBackToParticipants }) : null;
3602
3801
  case "agents":
3603
- return /* @__PURE__ */ jsx22(
3802
+ return /* @__PURE__ */ jsx23(
3604
3803
  AgentsView,
3605
3804
  {
3606
3805
  config,
@@ -3611,9 +3810,9 @@ var CopilotzAdmin = ({
3611
3810
  }
3612
3811
  );
3613
3812
  case "agent-detail":
3614
- return route.resourceId ? /* @__PURE__ */ jsx22(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
3813
+ return route.resourceId ? /* @__PURE__ */ jsx23(AgentDetailView, { agentId: route.resourceId, config, agents: admin.agents, onBack: handleBackToAgents }) : null;
3615
3814
  case "collection-items":
3616
- return route.collection ? /* @__PURE__ */ jsx22(
3815
+ return route.collection ? /* @__PURE__ */ jsx23(
3617
3816
  CollectionItemsView,
3618
3817
  {
3619
3818
  collection: route.collection,
@@ -3624,7 +3823,7 @@ var CopilotzAdmin = ({
3624
3823
  }
3625
3824
  ) : null;
3626
3825
  case "collection-item-detail":
3627
- return route.collection ? /* @__PURE__ */ jsx22(
3826
+ return route.collection ? /* @__PURE__ */ jsx23(
3628
3827
  CollectionItemDetailView,
3629
3828
  {
3630
3829
  collection: route.collection,
@@ -3635,12 +3834,12 @@ var CopilotzAdmin = ({
3635
3834
  }
3636
3835
  ) : null;
3637
3836
  case "events":
3638
- return /* @__PURE__ */ jsx22(EventsView, { config });
3837
+ return /* @__PURE__ */ jsx23(EventsView, { config });
3639
3838
  default:
3640
3839
  return null;
3641
3840
  }
3642
3841
  };
3643
- return /* @__PURE__ */ jsx22(TooltipProvider, { children: /* @__PURE__ */ jsx22(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ jsxs17(
3842
+ return /* @__PURE__ */ jsx23(TooltipProvider, { children: /* @__PURE__ */ jsx23(SidebarProvider, { defaultOpen: config.sidebar.defaultOpen, children: /* @__PURE__ */ jsxs18(
3644
3843
  "div",
3645
3844
  {
3646
3845
  className: cn(
@@ -3648,7 +3847,7 @@ var CopilotzAdmin = ({
3648
3847
  className
3649
3848
  ),
3650
3849
  children: [
3651
- /* @__PURE__ */ jsx22(
3850
+ /* @__PURE__ */ jsx23(
3652
3851
  AdminSidebar,
3653
3852
  {
3654
3853
  config,
@@ -3661,21 +3860,24 @@ var CopilotzAdmin = ({
3661
3860
  onNamespaceChange: setNamespace
3662
3861
  }
3663
3862
  ),
3664
- /* @__PURE__ */ jsx22(SidebarInset, { children: /* @__PURE__ */ jsxs17("div", { className: "flex flex-col h-full min-h-0", children: [
3665
- /* @__PURE__ */ jsx22(
3863
+ /* @__PURE__ */ jsx23(SidebarInset, { children: /* @__PURE__ */ jsxs18("div", { className: "flex flex-col h-full min-h-0", children: [
3864
+ /* @__PURE__ */ jsx23(
3666
3865
  AdminHeader,
3667
3866
  {
3668
3867
  config,
3669
3868
  currentRoute: route,
3670
- range: admin.filters.range,
3671
- interval: admin.filters.interval,
3672
- onRangeChange: admin.setRange,
3673
- onIntervalChange: admin.setInterval,
3674
- onRefresh: () => void admin.refresh(),
3675
- isLoading: admin.isLoading
3869
+ onRefresh: () => {
3870
+ if (route.page === "dashboard" && headerRefresh) {
3871
+ headerRefresh();
3872
+ return;
3873
+ }
3874
+ void admin.refresh();
3875
+ },
3876
+ isLoading: admin.isLoading,
3877
+ controls: route.page === "dashboard" ? headerControls : null
3676
3878
  }
3677
3879
  ),
3678
- /* @__PURE__ */ jsx22("div", { className: "flex-1 overflow-auto p-6", children: renderCurrentView() })
3880
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-auto p-4", children: renderCurrentView() })
3679
3881
  ] }) })
3680
3882
  ]
3681
3883
  }