@copilotz/admin 0.3.8 → 0.3.9

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
@@ -52,7 +52,7 @@ __export(index_exports, {
52
52
  module.exports = __toCommonJS(index_exports);
53
53
 
54
54
  // src/CopilotzAdmin.tsx
55
- var import_react7 = require("react");
55
+ var import_react8 = require("react");
56
56
 
57
57
  // src/config.ts
58
58
  var defaultAdminConfig = {
@@ -85,7 +85,21 @@ var defaultAdminConfig = {
85
85
  activeThreadsCard: "Active threads",
86
86
  participantsCard: "Participants",
87
87
  tokensCard: "LLM tokens",
88
+ costCard: "LLM cost",
88
89
  queueCard: "Queued events",
90
+ llmUsageTitle: "LLM Usage",
91
+ usageMetricLabel: "Metric",
92
+ usageDimensionLabel: "Usage type",
93
+ usageMetricTokens: "Tokens",
94
+ usageMetricCost: "Cost",
95
+ usageTotal: "Total",
96
+ usageInput: "Input",
97
+ usageOutput: "Output",
98
+ usageReasoning: "Reasoning",
99
+ usageCacheRead: "Cache read",
100
+ usageCacheWrite: "Cache write",
101
+ usageCallsDetail: "LLM calls",
102
+ usageUnavailableDetail: "Available when provider-native usage exists",
89
103
  statusActive: "Active",
90
104
  statusArchived: "Archived",
91
105
  scopeGlobal: "Global",
@@ -1530,6 +1544,9 @@ var AdminHeader = ({
1530
1544
  ] }) }) });
1531
1545
  };
1532
1546
 
1547
+ // src/components/views/DashboardView.tsx
1548
+ var import_react2 = __toESM(require("react"), 1);
1549
+
1533
1550
  // src/components/ui/badge.tsx
1534
1551
  var import_react_slot3 = require("@radix-ui/react-slot");
1535
1552
  var import_class_variance_authority3 = require("class-variance-authority");
@@ -1585,6 +1602,23 @@ var DashboardView = ({
1585
1602
  onAgentSearchChange,
1586
1603
  onThreadClick
1587
1604
  }) => {
1605
+ const [usageMetricKind, setUsageMetricKind] = import_react2.default.useState(
1606
+ "tokens"
1607
+ );
1608
+ const [usageDimension, setUsageDimension] = import_react2.default.useState(
1609
+ "total"
1610
+ );
1611
+ const llmSummaryValue = overview ? getOverviewUsageValue(overview, usageMetricKind, usageDimension) : 0;
1612
+ const llmSummaryLabel = getUsageSummaryLabel(
1613
+ config.labels,
1614
+ usageMetricKind,
1615
+ usageDimension
1616
+ );
1617
+ const usageBreakdownCards = USAGE_DIMENSIONS.map((dimension) => ({
1618
+ dimension,
1619
+ label: getUsageDimensionLabel(config.labels, dimension),
1620
+ value: overview ? getOverviewUsageValue(overview, usageMetricKind, dimension) : 0
1621
+ }));
1588
1622
  const cards = [
1589
1623
  {
1590
1624
  label: config.labels.messagesCard,
@@ -1602,9 +1636,10 @@ var DashboardView = ({
1602
1636
  detail: `${overview?.participantTotals.agents ?? 0} agents`
1603
1637
  },
1604
1638
  {
1605
- label: config.labels.tokensCard,
1606
- value: overview?.llmTotals.totalTokens ?? 0,
1607
- detail: `${overview?.llmTotals.totalCalls ?? 0} calls`
1639
+ label: llmSummaryLabel,
1640
+ value: llmSummaryValue,
1641
+ detail: `${overview?.llmTotals.totalCalls ?? 0} ${config.labels.usageCallsDetail}`,
1642
+ metricKind: usageMetricKind
1608
1643
  },
1609
1644
  {
1610
1645
  label: config.labels.queueCard,
@@ -1626,13 +1661,81 @@ var DashboardView = ({
1626
1661
  className: "rounded-xl border bg-card p-5 shadow-sm",
1627
1662
  children: [
1628
1663
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
1629
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatNumber(card.value) }),
1664
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-3xl font-semibold tracking-tight", children: formatMetricValue(
1665
+ card.value,
1666
+ card.metricKind ?? "tokens"
1667
+ ) }),
1630
1668
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-2 text-xs text-muted-foreground", children: card.detail })
1631
1669
  ]
1632
1670
  },
1633
1671
  card.label
1634
1672
  )) })
1635
1673
  ] }),
1674
+ config.features.showOverview && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
1675
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between", children: [
1676
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.llmUsageTitle }),
1677
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "grid gap-3 sm:grid-cols-2", children: [
1678
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
1679
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: config.labels.usageMetricLabel }),
1680
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1681
+ Select,
1682
+ {
1683
+ value: usageMetricKind,
1684
+ onValueChange: (value) => setUsageMetricKind(value),
1685
+ children: [
1686
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectTrigger, { className: "h-9 w-full min-w-[160px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectValue, {}) }),
1687
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(SelectContent, { children: [
1688
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: "tokens", children: config.labels.usageMetricTokens }),
1689
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: "cost", children: config.labels.usageMetricCost })
1690
+ ] })
1691
+ ]
1692
+ }
1693
+ )
1694
+ ] }),
1695
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "space-y-1", children: [
1696
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium uppercase tracking-[0.18em] text-muted-foreground", children: config.labels.usageDimensionLabel }),
1697
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1698
+ Select,
1699
+ {
1700
+ value: usageDimension,
1701
+ onValueChange: (value) => setUsageDimension(value),
1702
+ children: [
1703
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectTrigger, { className: "h-9 w-full min-w-[160px]", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectValue, {}) }),
1704
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectContent, { children: USAGE_DIMENSIONS.map((dimension) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SelectItem, { value: dimension, children: getUsageDimensionLabel(config.labels, dimension) }, dimension)) })
1705
+ ]
1706
+ }
1707
+ )
1708
+ ] })
1709
+ ] })
1710
+ ] }),
1711
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "grid gap-4 sm:grid-cols-2 xl:grid-cols-3", children: usageBreakdownCards.map((card) => {
1712
+ const isSelected = card.dimension === usageDimension;
1713
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1714
+ "div",
1715
+ {
1716
+ className: cn(
1717
+ "rounded-xl border bg-card p-5 shadow-sm transition-colors",
1718
+ isSelected && "border-primary/60 ring-1 ring-primary/15"
1719
+ ),
1720
+ children: [
1721
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-start justify-between gap-3", children: [
1722
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1723
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm font-medium text-muted-foreground", children: card.label }),
1724
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "mt-3 text-2xl font-semibold tracking-tight", children: formatMetricValue(card.value, usageMetricKind) })
1725
+ ] }),
1726
+ isSelected && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: config.labels.usageDimensionLabel })
1727
+ ] }),
1728
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "mt-2 text-xs text-muted-foreground", children: [
1729
+ overview?.llmTotals.totalCalls ?? 0,
1730
+ " ",
1731
+ config.labels.usageCallsDetail
1732
+ ] })
1733
+ ]
1734
+ },
1735
+ card.dimension
1736
+ );
1737
+ }) })
1738
+ ] }),
1636
1739
  config.features.showActivity && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("section", { className: "space-y-4", children: [
1637
1740
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SectionHeading, { title: config.labels.activityTitle }),
1638
1741
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
@@ -1641,7 +1744,9 @@ var DashboardView = ({
1641
1744
  interval,
1642
1745
  labels: config.labels,
1643
1746
  maxBars: config.ui.maxActivityBars,
1644
- points: activity
1747
+ points: activity,
1748
+ usageDimension,
1749
+ usageMetricKind
1645
1750
  }
1646
1751
  )
1647
1752
  ] }),
@@ -1683,7 +1788,15 @@ var DashboardView = ({
1683
1788
  searchValue: agentSearch,
1684
1789
  setSearchValue: onAgentSearchChange,
1685
1790
  title: config.labels.agentsTitle,
1686
- children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(AgentsTable, { rows: agents, labels: config.labels })
1791
+ children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
1792
+ AgentsTable,
1793
+ {
1794
+ rows: agents,
1795
+ labels: config.labels,
1796
+ usageMetricKind,
1797
+ usageDimension
1798
+ }
1799
+ )
1687
1800
  }
1688
1801
  )
1689
1802
  ] })
@@ -1694,35 +1807,50 @@ function SectionHeading({ title }) {
1694
1807
  }
1695
1808
  function ActivityChart(props) {
1696
1809
  const trimmedPoints = props.points.slice(-props.maxBars);
1697
- const maxMessages = Math.max(
1698
- ...trimmedPoints.map((point) => point.messageCount),
1810
+ const maxUsageValue = Math.max(
1811
+ ...trimmedPoints.map(
1812
+ (point) => getActivityUsageValue(
1813
+ point,
1814
+ props.usageMetricKind,
1815
+ props.usageDimension
1816
+ )
1817
+ ),
1699
1818
  1
1700
1819
  );
1701
- 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) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1702
- "div",
1703
- {
1704
- className: "flex min-w-0 flex-1 flex-col items-center gap-2",
1705
- children: [
1706
- /* @__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)(
1707
- "div",
1708
- {
1709
- className: "w-full rounded-md bg-primary transition-all",
1710
- style: {
1711
- height: `${Math.max(point.messageCount / maxMessages * 100, 8)}%`
1820
+ 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) => {
1821
+ const usageValue = getActivityUsageValue(
1822
+ point,
1823
+ props.usageMetricKind,
1824
+ props.usageDimension
1825
+ );
1826
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1827
+ "div",
1828
+ {
1829
+ className: "flex min-w-0 flex-1 flex-col items-center gap-2",
1830
+ children: [
1831
+ /* @__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)(
1832
+ "div",
1833
+ {
1834
+ className: "w-full rounded-md bg-primary transition-all",
1835
+ style: {
1836
+ height: `${Math.max(usageValue / maxUsageValue * 100, 8)}%`
1837
+ }
1712
1838
  }
1713
- }
1714
- ) }),
1715
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
1716
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
1717
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
1718
- formatNumber(point.messageCount),
1719
- " msg"
1839
+ ) }),
1840
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
1841
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-xs font-medium", children: formatBucket(point.bucket, props.interval) }),
1842
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-[11px] text-muted-foreground", children: formatMetricValue(usageValue, props.usageMetricKind) }),
1843
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("p", { className: "text-[11px] text-muted-foreground", children: [
1844
+ formatNumber(point.totalCalls),
1845
+ " ",
1846
+ props.labels.usageCallsDetail
1847
+ ] })
1720
1848
  ] })
1721
- ] })
1722
- ]
1723
- },
1724
- point.bucket
1725
- )) }) });
1849
+ ]
1850
+ },
1851
+ point.bucket
1852
+ );
1853
+ }) }) });
1726
1854
  }
1727
1855
  function DataTable(props) {
1728
1856
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "rounded-xl border bg-card p-5 shadow-sm", children: [
@@ -1818,7 +1946,9 @@ function ParticipantsTable({
1818
1946
  }
1819
1947
  function AgentsTable({
1820
1948
  rows,
1821
- labels
1949
+ labels,
1950
+ usageMetricKind,
1951
+ usageDimension
1822
1952
  }) {
1823
1953
  return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "space-y-3", children: rows.map((agent) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
1824
1954
  "div",
@@ -1832,24 +1962,30 @@ function AgentsTable({
1832
1962
  ] }),
1833
1963
  /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Badge, { variant: "outline", children: agent.isConfigured ? labels.configured : labels.unconfigured })
1834
1964
  ] }),
1835
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs text-muted-foreground", children: [
1836
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1837
- formatNumber(agent.messageCount),
1838
- " messages"
1839
- ] }),
1840
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1841
- formatNumber(agent.llmCallCount),
1842
- " LLM calls"
1843
- ] }),
1844
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1845
- formatNumber(agent.toolCallMessageCount),
1846
- " tool calls"
1847
- ] }),
1848
- /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { children: [
1849
- formatNumber(agent.totalTokens),
1850
- " tokens"
1851
- ] })
1852
- ] })
1965
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-3 grid grid-cols-2 gap-2 text-xs", children: [
1966
+ {
1967
+ label: "Messages",
1968
+ value: formatNumber(agent.messageCount)
1969
+ },
1970
+ {
1971
+ label: "LLM calls",
1972
+ value: formatNumber(agent.llmCallCount)
1973
+ },
1974
+ {
1975
+ label: "Tool calls",
1976
+ value: formatNumber(agent.toolCallMessageCount)
1977
+ },
1978
+ {
1979
+ label: getUsageSummaryLabel(labels, usageMetricKind, usageDimension),
1980
+ value: formatMetricValue(
1981
+ getAgentUsageValue(agent, usageMetricKind, usageDimension),
1982
+ usageMetricKind
1983
+ )
1984
+ }
1985
+ ].map((item) => /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { children: [
1986
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "font-medium text-foreground", children: item.value }),
1987
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-muted-foreground", children: item.label })
1988
+ ] }, item.label)) })
1853
1989
  ]
1854
1990
  },
1855
1991
  `${agent.namespace}:${agent.agentId}`
@@ -1881,6 +2017,151 @@ function formatDate(value) {
1881
2017
  function formatNumber(value) {
1882
2018
  return new Intl.NumberFormat().format(value);
1883
2019
  }
2020
+ var USAGE_DIMENSIONS = [
2021
+ "total",
2022
+ "input",
2023
+ "output",
2024
+ "reasoning",
2025
+ "cacheRead",
2026
+ "cacheWrite"
2027
+ ];
2028
+ function getUsageDimensionLabel(labels, dimension) {
2029
+ switch (dimension) {
2030
+ case "input":
2031
+ return labels.usageInput;
2032
+ case "output":
2033
+ return labels.usageOutput;
2034
+ case "reasoning":
2035
+ return labels.usageReasoning;
2036
+ case "cacheRead":
2037
+ return labels.usageCacheRead;
2038
+ case "cacheWrite":
2039
+ return labels.usageCacheWrite;
2040
+ case "total":
2041
+ default:
2042
+ return labels.usageTotal;
2043
+ }
2044
+ }
2045
+ function getUsageSummaryLabel(labels, metricKind, dimension) {
2046
+ const metricLabel = metricKind === "cost" ? labels.usageMetricCost : labels.usageMetricTokens;
2047
+ return `${getUsageDimensionLabel(labels, dimension)} ${metricLabel}`;
2048
+ }
2049
+ function getOverviewUsageValue(overview, metricKind, dimension) {
2050
+ const llmTotals = overview.llmTotals;
2051
+ if (metricKind === "cost") {
2052
+ switch (dimension) {
2053
+ case "input":
2054
+ return llmTotals.inputCostUsd;
2055
+ case "output":
2056
+ return llmTotals.outputCostUsd;
2057
+ case "reasoning":
2058
+ return llmTotals.reasoningCostUsd;
2059
+ case "cacheRead":
2060
+ return llmTotals.cacheReadInputCostUsd;
2061
+ case "cacheWrite":
2062
+ return llmTotals.cacheCreationInputCostUsd;
2063
+ case "total":
2064
+ default:
2065
+ return llmTotals.totalCostUsd;
2066
+ }
2067
+ }
2068
+ switch (dimension) {
2069
+ case "input":
2070
+ return llmTotals.inputTokens;
2071
+ case "output":
2072
+ return llmTotals.outputTokens;
2073
+ case "reasoning":
2074
+ return llmTotals.reasoningTokens;
2075
+ case "cacheRead":
2076
+ return llmTotals.cacheReadInputTokens;
2077
+ case "cacheWrite":
2078
+ return llmTotals.cacheCreationInputTokens;
2079
+ case "total":
2080
+ default:
2081
+ return llmTotals.totalTokens;
2082
+ }
2083
+ }
2084
+ function getAgentUsageValue(agent, metricKind, dimension) {
2085
+ if (metricKind === "cost") {
2086
+ switch (dimension) {
2087
+ case "input":
2088
+ return agent.inputCostUsd;
2089
+ case "output":
2090
+ return agent.outputCostUsd;
2091
+ case "reasoning":
2092
+ return agent.reasoningCostUsd;
2093
+ case "cacheRead":
2094
+ return agent.cacheReadInputCostUsd;
2095
+ case "cacheWrite":
2096
+ return agent.cacheCreationInputCostUsd;
2097
+ case "total":
2098
+ default:
2099
+ return agent.totalCostUsd;
2100
+ }
2101
+ }
2102
+ switch (dimension) {
2103
+ case "input":
2104
+ return agent.inputTokens;
2105
+ case "output":
2106
+ return agent.outputTokens;
2107
+ case "reasoning":
2108
+ return agent.reasoningTokens;
2109
+ case "cacheRead":
2110
+ return agent.cacheReadInputTokens;
2111
+ case "cacheWrite":
2112
+ return agent.cacheCreationInputTokens;
2113
+ case "total":
2114
+ default:
2115
+ return agent.totalTokens;
2116
+ }
2117
+ }
2118
+ function getActivityUsageValue(point, metricKind, dimension) {
2119
+ if (metricKind === "cost") {
2120
+ switch (dimension) {
2121
+ case "input":
2122
+ return point.inputCostUsd;
2123
+ case "output":
2124
+ return point.outputCostUsd;
2125
+ case "reasoning":
2126
+ return point.reasoningCostUsd;
2127
+ case "cacheRead":
2128
+ return point.cacheReadInputCostUsd;
2129
+ case "cacheWrite":
2130
+ return point.cacheCreationInputCostUsd;
2131
+ case "total":
2132
+ default:
2133
+ return point.totalCostUsd;
2134
+ }
2135
+ }
2136
+ switch (dimension) {
2137
+ case "input":
2138
+ return point.inputTokens;
2139
+ case "output":
2140
+ return point.outputTokens;
2141
+ case "reasoning":
2142
+ return point.reasoningTokens;
2143
+ case "cacheRead":
2144
+ return point.cacheReadInputTokens;
2145
+ case "cacheWrite":
2146
+ return point.cacheCreationInputTokens;
2147
+ case "total":
2148
+ default:
2149
+ return point.totalTokens;
2150
+ }
2151
+ }
2152
+ function formatMetricValue(value, metricKind) {
2153
+ if (metricKind === "cost") {
2154
+ const absoluteValue = Math.abs(value);
2155
+ const maximumFractionDigits = absoluteValue >= 1 ? 2 : absoluteValue >= 0.01 ? 4 : 6;
2156
+ return new Intl.NumberFormat(void 0, {
2157
+ style: "currency",
2158
+ currency: "USD",
2159
+ minimumFractionDigits: 2,
2160
+ maximumFractionDigits
2161
+ }).format(value);
2162
+ }
2163
+ return formatNumber(value);
2164
+ }
1884
2165
 
1885
2166
  // src/components/views/ThreadsView.tsx
1886
2167
  var import_lucide_react6 = require("lucide-react");
@@ -1961,7 +2242,7 @@ function formatNumber2(value) {
1961
2242
  }
1962
2243
 
1963
2244
  // src/components/views/ThreadDetailView.tsx
1964
- var import_react2 = require("react");
2245
+ var import_react3 = require("react");
1965
2246
  var import_lucide_react7 = require("lucide-react");
1966
2247
  var import_jsx_runtime14 = require("react/jsx-runtime");
1967
2248
  var MESSAGES_PAGE_SIZE = 50;
@@ -1970,17 +2251,17 @@ var ThreadDetailView = ({
1970
2251
  config,
1971
2252
  onBack
1972
2253
  }) => {
1973
- const [thread, setThread] = (0, import_react2.useState)(null);
1974
- const [messages, setMessages] = (0, import_react2.useState)([]);
1975
- const [pageInfo, setPageInfo] = (0, import_react2.useState)(null);
1976
- const [isLoading, setIsLoading] = (0, import_react2.useState)(true);
1977
- const [isLoadingMore, setIsLoadingMore] = (0, import_react2.useState)(false);
1978
- const [error, setError] = (0, import_react2.useState)(null);
2254
+ const [thread, setThread] = (0, import_react3.useState)(null);
2255
+ const [messages, setMessages] = (0, import_react3.useState)([]);
2256
+ const [pageInfo, setPageInfo] = (0, import_react3.useState)(null);
2257
+ const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
2258
+ const [isLoadingMore, setIsLoadingMore] = (0, import_react3.useState)(false);
2259
+ const [error, setError] = (0, import_react3.useState)(null);
1979
2260
  const fetchOptions = {
1980
2261
  baseUrl: config.baseUrl,
1981
2262
  getRequestHeaders: config.getRequestHeaders
1982
2263
  };
1983
- const loadInitial = (0, import_react2.useCallback)(async () => {
2264
+ const loadInitial = (0, import_react3.useCallback)(async () => {
1984
2265
  setIsLoading(true);
1985
2266
  setError(null);
1986
2267
  try {
@@ -1999,10 +2280,10 @@ var ThreadDetailView = ({
1999
2280
  setIsLoading(false);
2000
2281
  }
2001
2282
  }, [threadId, config.baseUrl, config.getRequestHeaders]);
2002
- (0, import_react2.useEffect)(() => {
2283
+ (0, import_react3.useEffect)(() => {
2003
2284
  void loadInitial();
2004
2285
  }, [loadInitial]);
2005
- const loadMore = (0, import_react2.useCallback)(async () => {
2286
+ const loadMore = (0, import_react3.useCallback)(async () => {
2006
2287
  if (!pageInfo?.hasMoreBefore || !pageInfo.oldestMessageId || isLoadingMore) {
2007
2288
  return;
2008
2289
  }
@@ -2100,7 +2381,7 @@ var ThreadDetailView = ({
2100
2381
  ] });
2101
2382
  };
2102
2383
  function MessageRow({ message }) {
2103
- const [expanded, setExpanded] = (0, import_react2.useState)(false);
2384
+ const [expanded, setExpanded] = (0, import_react3.useState)(false);
2104
2385
  const hasToolCalls = Array.isArray(message.toolCalls) && message.toolCalls.length > 0;
2105
2386
  const hasReasoning = !!message.reasoning;
2106
2387
  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: [
@@ -2253,7 +2534,7 @@ function formatNumber3(value) {
2253
2534
  }
2254
2535
 
2255
2536
  // src/components/views/ParticipantDetailView.tsx
2256
- var import_react3 = require("react");
2537
+ var import_react4 = require("react");
2257
2538
  var import_lucide_react9 = require("lucide-react");
2258
2539
  var import_jsx_runtime16 = require("react/jsx-runtime");
2259
2540
  var ParticipantDetailView = ({
@@ -2261,17 +2542,17 @@ var ParticipantDetailView = ({
2261
2542
  config,
2262
2543
  onBack
2263
2544
  }) => {
2264
- const [data, setData] = (0, import_react3.useState)(null);
2265
- const [editJson, setEditJson] = (0, import_react3.useState)("");
2266
- const [isLoading, setIsLoading] = (0, import_react3.useState)(true);
2267
- const [isSaving, setIsSaving] = (0, import_react3.useState)(false);
2268
- const [error, setError] = (0, import_react3.useState)(null);
2269
- const [saveMessage, setSaveMessage] = (0, import_react3.useState)(null);
2545
+ const [data, setData] = (0, import_react4.useState)(null);
2546
+ const [editJson, setEditJson] = (0, import_react4.useState)("");
2547
+ const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
2548
+ const [isSaving, setIsSaving] = (0, import_react4.useState)(false);
2549
+ const [error, setError] = (0, import_react4.useState)(null);
2550
+ const [saveMessage, setSaveMessage] = (0, import_react4.useState)(null);
2270
2551
  const fetchOptions = {
2271
2552
  baseUrl: config.baseUrl,
2272
2553
  getRequestHeaders: config.getRequestHeaders
2273
2554
  };
2274
- const load = (0, import_react3.useCallback)(async () => {
2555
+ const load = (0, import_react4.useCallback)(async () => {
2275
2556
  setIsLoading(true);
2276
2557
  setError(null);
2277
2558
  try {
@@ -2284,7 +2565,7 @@ var ParticipantDetailView = ({
2284
2565
  setIsLoading(false);
2285
2566
  }
2286
2567
  }, [participantId, config.baseUrl, config.getRequestHeaders]);
2287
- (0, import_react3.useEffect)(() => {
2568
+ (0, import_react4.useEffect)(() => {
2288
2569
  void load();
2289
2570
  }, [load]);
2290
2571
  const handleSave = async () => {
@@ -2485,7 +2766,7 @@ function formatDate6(value) {
2485
2766
  }
2486
2767
 
2487
2768
  // src/components/views/CollectionItemsView.tsx
2488
- var import_react4 = require("react");
2769
+ var import_react5 = require("react");
2489
2770
  var import_lucide_react12 = require("lucide-react");
2490
2771
  var import_jsx_runtime19 = require("react/jsx-runtime");
2491
2772
  var CollectionItemsView = ({
@@ -2495,15 +2776,15 @@ var CollectionItemsView = ({
2495
2776
  onItemClick,
2496
2777
  onCreateNew
2497
2778
  }) => {
2498
- const [items, setItems] = (0, import_react4.useState)([]);
2499
- const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
2500
- const [search, setSearch] = (0, import_react4.useState)("");
2501
- const [error, setError] = (0, import_react4.useState)(null);
2779
+ const [items, setItems] = (0, import_react5.useState)([]);
2780
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
2781
+ const [search, setSearch] = (0, import_react5.useState)("");
2782
+ const [error, setError] = (0, import_react5.useState)(null);
2502
2783
  const fetchOptions = {
2503
2784
  baseUrl: config.baseUrl,
2504
2785
  getRequestHeaders: config.getRequestHeaders
2505
2786
  };
2506
- const load = (0, import_react4.useCallback)(async () => {
2787
+ const load = (0, import_react5.useCallback)(async () => {
2507
2788
  setIsLoading(true);
2508
2789
  setError(null);
2509
2790
  try {
@@ -2519,7 +2800,7 @@ var CollectionItemsView = ({
2519
2800
  setIsLoading(false);
2520
2801
  }
2521
2802
  }, [collection, search, namespace, config.baseUrl, config.getRequestHeaders]);
2522
- (0, import_react4.useEffect)(() => {
2803
+ (0, import_react5.useEffect)(() => {
2523
2804
  void load();
2524
2805
  }, [load]);
2525
2806
  const getItemId = (item) => {
@@ -2576,7 +2857,7 @@ var CollectionItemsView = ({
2576
2857
  };
2577
2858
 
2578
2859
  // src/components/views/CollectionItemDetailView.tsx
2579
- var import_react5 = require("react");
2860
+ var import_react6 = require("react");
2580
2861
  var import_lucide_react13 = require("lucide-react");
2581
2862
  var import_jsx_runtime20 = require("react/jsx-runtime");
2582
2863
  var CollectionItemDetailView = ({
@@ -2588,17 +2869,17 @@ var CollectionItemDetailView = ({
2588
2869
  onDeleted
2589
2870
  }) => {
2590
2871
  const isNew = !itemId;
2591
- const [editJson, setEditJson] = (0, import_react5.useState)(isNew ? "{\n \n}" : "");
2592
- const [isLoading, setIsLoading] = (0, import_react5.useState)(!isNew);
2593
- const [isSaving, setIsSaving] = (0, import_react5.useState)(false);
2594
- const [isDeleting, setIsDeleting] = (0, import_react5.useState)(false);
2595
- const [error, setError] = (0, import_react5.useState)(null);
2596
- const [saveMessage, setSaveMessage] = (0, import_react5.useState)(null);
2872
+ const [editJson, setEditJson] = (0, import_react6.useState)(isNew ? "{\n \n}" : "");
2873
+ const [isLoading, setIsLoading] = (0, import_react6.useState)(!isNew);
2874
+ const [isSaving, setIsSaving] = (0, import_react6.useState)(false);
2875
+ const [isDeleting, setIsDeleting] = (0, import_react6.useState)(false);
2876
+ const [error, setError] = (0, import_react6.useState)(null);
2877
+ const [saveMessage, setSaveMessage] = (0, import_react6.useState)(null);
2597
2878
  const fetchOptions = {
2598
2879
  baseUrl: config.baseUrl,
2599
2880
  getRequestHeaders: config.getRequestHeaders
2600
2881
  };
2601
- const load = (0, import_react5.useCallback)(async () => {
2882
+ const load = (0, import_react6.useCallback)(async () => {
2602
2883
  if (!itemId) return;
2603
2884
  setIsLoading(true);
2604
2885
  setError(null);
@@ -2611,7 +2892,7 @@ var CollectionItemDetailView = ({
2611
2892
  setIsLoading(false);
2612
2893
  }
2613
2894
  }, [collection, itemId, namespace, config.baseUrl, config.getRequestHeaders]);
2614
- (0, import_react5.useEffect)(() => {
2895
+ (0, import_react6.useEffect)(() => {
2615
2896
  void load();
2616
2897
  }, [load]);
2617
2898
  const handleSave = async () => {
@@ -2693,7 +2974,7 @@ var CollectionItemDetailView = ({
2693
2974
  };
2694
2975
 
2695
2976
  // src/components/views/EventsView.tsx
2696
- var import_react6 = require("react");
2977
+ var import_react7 = require("react");
2697
2978
  var import_lucide_react14 = require("lucide-react");
2698
2979
  var import_jsx_runtime21 = require("react/jsx-runtime");
2699
2980
  var STATUS_VARIANTS = {
@@ -2705,16 +2986,16 @@ var STATUS_VARIANTS = {
2705
2986
  overwritten: "secondary"
2706
2987
  };
2707
2988
  var EventsView = ({ config }) => {
2708
- const [threadId, setThreadId] = (0, import_react6.useState)("");
2709
- const [event, setEvent] = (0, import_react6.useState)(null);
2710
- const [hasSearched, setHasSearched] = (0, import_react6.useState)(false);
2711
- const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
2712
- const [error, setError] = (0, import_react6.useState)(null);
2989
+ const [threadId, setThreadId] = (0, import_react7.useState)("");
2990
+ const [event, setEvent] = (0, import_react7.useState)(null);
2991
+ const [hasSearched, setHasSearched] = (0, import_react7.useState)(false);
2992
+ const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
2993
+ const [error, setError] = (0, import_react7.useState)(null);
2713
2994
  const fetchOptions = {
2714
2995
  baseUrl: config.baseUrl,
2715
2996
  getRequestHeaders: config.getRequestHeaders
2716
2997
  };
2717
- const handleSearch = (0, import_react6.useCallback)(async () => {
2998
+ const handleSearch = (0, import_react7.useCallback)(async () => {
2718
2999
  if (!threadId.trim()) return;
2719
3000
  setIsLoading(true);
2720
3001
  setError(null);
@@ -2817,19 +3098,19 @@ var CopilotzAdmin = ({
2817
3098
  config: userConfig,
2818
3099
  className
2819
3100
  }) => {
2820
- const config = (0, import_react7.useMemo)(
3101
+ const config = (0, import_react8.useMemo)(
2821
3102
  () => mergeAdminConfig(defaultAdminConfig, userConfig),
2822
3103
  [userConfig]
2823
3104
  );
2824
- const [route, setRoute] = (0, import_react7.useState)({ page: config.defaultPage });
2825
- const [namespace, setNamespace] = (0, import_react7.useState)(config.namespace);
2826
- const [collections, setCollections] = (0, import_react7.useState)([]);
2827
- const [threadSearch, setThreadSearch] = (0, import_react7.useState)("");
2828
- const [participantSearch, setParticipantSearch] = (0, import_react7.useState)("");
2829
- const [agentSearch, setAgentSearch] = (0, import_react7.useState)("");
2830
- const deferredThreadSearch = (0, import_react7.useDeferredValue)(threadSearch);
2831
- const deferredParticipantSearch = (0, import_react7.useDeferredValue)(participantSearch);
2832
- const deferredAgentSearch = (0, import_react7.useDeferredValue)(agentSearch);
3105
+ const [route, setRoute] = (0, import_react8.useState)({ page: config.defaultPage });
3106
+ const [namespace, setNamespace] = (0, import_react8.useState)(config.namespace);
3107
+ const [collections, setCollections] = (0, import_react8.useState)([]);
3108
+ const [threadSearch, setThreadSearch] = (0, import_react8.useState)("");
3109
+ const [participantSearch, setParticipantSearch] = (0, import_react8.useState)("");
3110
+ const [agentSearch, setAgentSearch] = (0, import_react8.useState)("");
3111
+ const deferredThreadSearch = (0, import_react8.useDeferredValue)(threadSearch);
3112
+ const deferredParticipantSearch = (0, import_react8.useDeferredValue)(participantSearch);
3113
+ const deferredAgentSearch = (0, import_react8.useDeferredValue)(agentSearch);
2833
3114
  const admin = useCopilotzAdmin({
2834
3115
  baseUrl: config.baseUrl,
2835
3116
  getRequestHeaders: config.getRequestHeaders,
@@ -2840,52 +3121,52 @@ var CopilotzAdmin = ({
2840
3121
  participantSearch: deferredParticipantSearch,
2841
3122
  agentSearch: deferredAgentSearch
2842
3123
  });
2843
- (0, import_react7.useEffect)(() => {
3124
+ (0, import_react8.useEffect)(() => {
2844
3125
  if (!config.features.showCollections) return;
2845
3126
  fetchCollectionNames({
2846
3127
  baseUrl: config.baseUrl,
2847
3128
  getRequestHeaders: config.getRequestHeaders
2848
3129
  }).then(setCollections).catch(() => setCollections([]));
2849
3130
  }, [config.baseUrl, config.getRequestHeaders, config.features.showCollections]);
2850
- const navigate = (0, import_react7.useCallback)(
3131
+ const navigate = (0, import_react8.useCallback)(
2851
3132
  (next) => {
2852
3133
  setRoute(next);
2853
3134
  config.onNavigate?.(next);
2854
3135
  },
2855
3136
  [config]
2856
3137
  );
2857
- const handleSidebarNavigate = (0, import_react7.useCallback)(
3138
+ const handleSidebarNavigate = (0, import_react8.useCallback)(
2858
3139
  (page) => navigate({ page }),
2859
3140
  [navigate]
2860
3141
  );
2861
- const handleSidebarRouteNavigate = (0, import_react7.useCallback)(
3142
+ const handleSidebarRouteNavigate = (0, import_react8.useCallback)(
2862
3143
  (r) => navigate(r),
2863
3144
  [navigate]
2864
3145
  );
2865
- const handleThreadClick = (0, import_react7.useCallback)(
3146
+ const handleThreadClick = (0, import_react8.useCallback)(
2866
3147
  (threadId) => navigate({ page: "thread-detail", resourceId: threadId }),
2867
3148
  [navigate]
2868
3149
  );
2869
- const handleBackToThreads = (0, import_react7.useCallback)(() => navigate({ page: "threads" }), [navigate]);
2870
- const handleParticipantClick = (0, import_react7.useCallback)(
3150
+ const handleBackToThreads = (0, import_react8.useCallback)(() => navigate({ page: "threads" }), [navigate]);
3151
+ const handleParticipantClick = (0, import_react8.useCallback)(
2871
3152
  (id) => navigate({ page: "participant-detail", resourceId: id }),
2872
3153
  [navigate]
2873
3154
  );
2874
- const handleBackToParticipants = (0, import_react7.useCallback)(() => navigate({ page: "participants" }), [navigate]);
2875
- const handleAgentClick = (0, import_react7.useCallback)(
3155
+ const handleBackToParticipants = (0, import_react8.useCallback)(() => navigate({ page: "participants" }), [navigate]);
3156
+ const handleAgentClick = (0, import_react8.useCallback)(
2876
3157
  (id) => navigate({ page: "agent-detail", resourceId: id }),
2877
3158
  [navigate]
2878
3159
  );
2879
- const handleBackToAgents = (0, import_react7.useCallback)(() => navigate({ page: "agents" }), [navigate]);
2880
- const handleCollectionItemClick = (0, import_react7.useCallback)(
3160
+ const handleBackToAgents = (0, import_react8.useCallback)(() => navigate({ page: "agents" }), [navigate]);
3161
+ const handleCollectionItemClick = (0, import_react8.useCallback)(
2881
3162
  (itemId) => navigate({ page: "collection-item-detail", resourceId: itemId, collection: route.collection }),
2882
3163
  [navigate, route.collection]
2883
3164
  );
2884
- const handleCollectionCreateNew = (0, import_react7.useCallback)(
3165
+ const handleCollectionCreateNew = (0, import_react8.useCallback)(
2885
3166
  () => navigate({ page: "collection-item-detail", resourceId: void 0, collection: route.collection }),
2886
3167
  [navigate, route.collection]
2887
3168
  );
2888
- const handleBackToCollectionItems = (0, import_react7.useCallback)(
3169
+ const handleBackToCollectionItems = (0, import_react8.useCallback)(
2889
3170
  () => navigate({ page: "collection-items", collection: route.collection }),
2890
3171
  [navigate, route.collection]
2891
3172
  );