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