@copilotz/admin 0.3.8 → 0.6.0

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