@carlonicora/nextjs-jsonapi 1.141.3 → 1.143.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.
Files changed (117) hide show
  1. package/dist/AbstractService-B0T7h8fX.d.mts +124 -0
  2. package/dist/AbstractService-Cew0PD0L.d.ts +124 -0
  3. package/dist/{AssistantMessageInterface-DH1QwtC_.d.mts → AssistantMessageInterface-Ce8FcllX.d.mts} +1 -1
  4. package/dist/{AssistantMessageInterface-giWvsOrX.d.ts → AssistantMessageInterface-Dh0BpbP2.d.ts} +1 -1
  5. package/dist/{AuthComponent-DdxCFgUZ.d.mts → AuthComponent-Cik96ElA.d.mts} +1 -1
  6. package/dist/{AuthComponent-Cd7lcYif.d.ts → AuthComponent-DTTKu3VK.d.ts} +1 -1
  7. package/dist/{BlockNoteEditor-JTKEBS2W.mjs → BlockNoteEditor-34QM4UR5.mjs} +4 -4
  8. package/dist/{BlockNoteEditor-4OXY6BKF.js → BlockNoteEditor-LMKWUOJG.js} +19 -19
  9. package/dist/{BlockNoteEditor-4OXY6BKF.js.map → BlockNoteEditor-LMKWUOJG.js.map} +1 -1
  10. package/dist/{auth.interface-yivTb46w.d.ts → auth.interface-COmBjh89.d.ts} +1 -1
  11. package/dist/{auth.interface-r3XKYOrQ.d.mts → auth.interface-CkmZqat3.d.mts} +1 -1
  12. package/dist/billing/index.js +357 -357
  13. package/dist/billing/index.mjs +3 -3
  14. package/dist/{chunk-5GVY2M5X.mjs → chunk-BIL2WQEV.mjs} +264 -18
  15. package/dist/chunk-BIL2WQEV.mjs.map +1 -0
  16. package/dist/{chunk-AGKZCRG2.js → chunk-DS4IBFWA.js} +269 -23
  17. package/dist/chunk-DS4IBFWA.js.map +1 -0
  18. package/dist/{chunk-4TGGHNWL.js → chunk-F6PZZ4KI.js} +752 -752
  19. package/dist/chunk-F6PZZ4KI.js.map +1 -0
  20. package/dist/{chunk-KXTTYXJ6.mjs → chunk-HN5ED7OF.mjs} +2 -2
  21. package/dist/{chunk-K76QSQTC.mjs → chunk-UGSOBBZH.mjs} +28 -28
  22. package/dist/chunk-UGSOBBZH.mjs.map +1 -0
  23. package/dist/{chunk-SE2YSAER.js → chunk-UXJAS6C5.js} +7 -7
  24. package/dist/{chunk-SE2YSAER.js.map → chunk-UXJAS6C5.js.map} +1 -1
  25. package/dist/client/index.d.mts +5 -5
  26. package/dist/client/index.d.ts +5 -5
  27. package/dist/client/index.js +4 -4
  28. package/dist/client/index.mjs +3 -3
  29. package/dist/components/index.d.mts +6 -6
  30. package/dist/components/index.d.ts +6 -6
  31. package/dist/components/index.js +4 -4
  32. package/dist/components/index.mjs +3 -3
  33. package/dist/{config-BrkU_Ynz.d.ts → config-Cd5xTEfZ.d.ts} +1 -1
  34. package/dist/{config-snd2ToEB.d.mts → config-YyhFHxkU.d.mts} +1 -1
  35. package/dist/contexts/index.d.mts +4 -4
  36. package/dist/contexts/index.d.ts +4 -4
  37. package/dist/contexts/index.js +4 -4
  38. package/dist/contexts/index.mjs +3 -3
  39. package/dist/core/index.d.mts +24 -60
  40. package/dist/core/index.d.ts +24 -60
  41. package/dist/core/index.js +8 -2
  42. package/dist/core/index.js.map +1 -1
  43. package/dist/core/index.mjs +7 -1
  44. package/dist/features/help/index.d.mts +2 -2
  45. package/dist/features/help/index.d.ts +2 -2
  46. package/dist/features/help/index.js +37 -37
  47. package/dist/features/help/index.mjs +3 -3
  48. package/dist/features/tokenusage/index.css +29 -0
  49. package/dist/features/tokenusage/index.css.map +1 -0
  50. package/dist/features/tokenusage/index.d.mts +388 -0
  51. package/dist/features/tokenusage/index.d.ts +388 -0
  52. package/dist/features/tokenusage/index.js +1012 -0
  53. package/dist/features/tokenusage/index.js.map +1 -0
  54. package/dist/features/tokenusage/index.mjs +1012 -0
  55. package/dist/features/tokenusage/index.mjs.map +1 -0
  56. package/dist/index.d.mts +11 -9
  57. package/dist/index.d.ts +11 -9
  58. package/dist/index.js +9 -3
  59. package/dist/index.js.map +1 -1
  60. package/dist/index.mjs +8 -2
  61. package/dist/{notification.interface-LKFmZndR.d.ts → notification.interface--27exGde.d.ts} +6 -6
  62. package/dist/{notification.interface-B3kNUTZs.d.mts → notification.interface-CG1vqoxg.d.mts} +6 -6
  63. package/dist/{s3.service-BrmeMjtk.d.ts → s3.service-CpwA3sl_.d.ts} +4 -125
  64. package/dist/{s3.service-CXKV_OT-.d.mts → s3.service-Dt6MfuHr.d.mts} +4 -125
  65. package/dist/server/index.d.mts +5 -4
  66. package/dist/server/index.d.ts +5 -4
  67. package/dist/server/index.js +3 -3
  68. package/dist/server/index.mjs +1 -1
  69. package/dist/tokenusage-admin.module-5wJ_tZTj.d.ts +61 -0
  70. package/dist/tokenusage-admin.module-DQVT4O4j.d.mts +61 -0
  71. package/dist/{types-CQSjy7et.d.mts → types-Bq_UA8Lg.d.mts} +1 -1
  72. package/dist/{types-DHOxe8rc.d.ts → types-bsm8Fp55.d.ts} +1 -1
  73. package/dist/{usePageUrlGenerator-tjq2mlDV.d.ts → usePageUrlGenerator-J_ECv-oQ.d.ts} +1 -1
  74. package/dist/{usePageUrlGenerator-uOnyJ6j2.d.mts → usePageUrlGenerator-uKBjAKqC.d.mts} +1 -1
  75. package/dist/{useSocket-BsbaGPqE.d.ts → useSocket-DgGAQW6h.d.ts} +1 -1
  76. package/dist/{useSocket-BSjn1Rlb.d.mts → useSocket-M3YY0aTS.d.mts} +1 -1
  77. package/package.json +6 -1
  78. package/src/core/index.ts +5 -0
  79. package/src/core/registry/ModuleRegistry.ts +4 -0
  80. package/src/features/company/components/details/TokenStatusIndicator.tsx +9 -9
  81. package/src/features/company/data/company.interface.ts +6 -6
  82. package/src/features/company/data/company.ts +17 -17
  83. package/src/features/tokenusage/components/TokenUsageAdminContainer.tsx +189 -0
  84. package/src/features/tokenusage/components/TokenUsageAdminFilterBar.tsx +138 -0
  85. package/src/features/tokenusage/components/TokenUsageAdminTiles.tsx +177 -0
  86. package/src/features/tokenusage/components/TokenUsageBreakdownTable.tsx +160 -0
  87. package/src/features/tokenusage/components/TokenUsageRankedBar.tsx +99 -0
  88. package/src/features/tokenusage/components/TokenUsageTimelineChart.tsx +225 -0
  89. package/src/features/tokenusage/components/__tests__/TokenUsageAdminTiles.spec.tsx +42 -0
  90. package/src/features/tokenusage/components/__tests__/TokenUsageRankedBar.spec.tsx +41 -0
  91. package/src/features/tokenusage/components/__tests__/TokenUsageTimelineChart.spec.tsx +47 -0
  92. package/src/features/tokenusage/contexts/TokenUsageAdminContext.tsx +252 -0
  93. package/src/features/tokenusage/contexts/__tests__/TokenUsageAdminContext.spec.tsx +80 -0
  94. package/src/features/tokenusage/data/TokenUsageAdminService.ts +54 -0
  95. package/src/features/tokenusage/data/__tests__/tokenusage-admin-models.spec.ts +147 -0
  96. package/src/features/tokenusage/data/index.ts +8 -0
  97. package/src/features/tokenusage/data/tokenusage-admin-breakdown.interface.ts +18 -0
  98. package/src/features/tokenusage/data/tokenusage-admin-breakdown.ts +115 -0
  99. package/src/features/tokenusage/data/tokenusage-admin-summary.interface.ts +14 -0
  100. package/src/features/tokenusage/data/tokenusage-admin-summary.ts +90 -0
  101. package/src/features/tokenusage/data/tokenusage-admin-timeline.interface.ts +13 -0
  102. package/src/features/tokenusage/data/tokenusage-admin-timeline.ts +94 -0
  103. package/src/features/tokenusage/data/tokenusage-admin.types.ts +56 -0
  104. package/src/features/tokenusage/i18n-keys.ts +65 -0
  105. package/src/features/tokenusage/index.ts +30 -0
  106. package/src/features/tokenusage/lib/metrics.ts +69 -0
  107. package/src/features/tokenusage/lib/operation-label.ts +41 -0
  108. package/src/features/tokenusage/lib/palette.ts +197 -0
  109. package/src/features/tokenusage/tokenusage-admin.module.ts +22 -0
  110. package/src/features/user/contexts/CurrentUserContext.tsx +18 -18
  111. package/src/features/user/contexts/__tests__/CurrentUserContext.spec.tsx +21 -21
  112. package/dist/chunk-4TGGHNWL.js.map +0 -1
  113. package/dist/chunk-5GVY2M5X.mjs.map +0 -1
  114. package/dist/chunk-AGKZCRG2.js.map +0 -1
  115. package/dist/chunk-K76QSQTC.mjs.map +0 -1
  116. /package/dist/{BlockNoteEditor-JTKEBS2W.mjs.map → BlockNoteEditor-34QM4UR5.mjs.map} +0 -0
  117. /package/dist/{chunk-KXTTYXJ6.mjs.map → chunk-HN5ED7OF.mjs.map} +0 -0
@@ -0,0 +1,1012 @@
1
+ "use client";
2
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+ var _chunkF6PZZ4KIjs = require('../../chunk-F6PZZ4KI.js');
30
+ require('../../chunk-UXJAS6C5.js');
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
42
+ var _chunkDS4IBFWAjs = require('../../chunk-DS4IBFWA.js');
43
+ require('../../chunk-LXKSUWAV.js');
44
+ require('../../chunk-IBS6NI7D.js');
45
+ require('../../chunk-QWCAOLBD.js');
46
+ require('../../chunk-3EPNHTMH.js');
47
+
48
+
49
+ var _chunk7QVYU63Ejs = require('../../chunk-7QVYU63E.js');
50
+
51
+ // src/features/tokenusage/contexts/TokenUsageAdminContext.tsx
52
+ var _nextintl = require('next-intl');
53
+ var _react = require('react');
54
+
55
+ // src/features/tokenusage/components/TokenUsageAdminFilterBar.tsx
56
+
57
+ var _jsxruntime = require('react/jsx-runtime');
58
+ var ALL_COMPANIES = "all";
59
+ function TokenUsageAdminFilterBar({ granularity, companyId, metric, companies, onChange }) {
60
+ const t = _nextintl.useTranslations.call(void 0, );
61
+ const companyItems = {
62
+ [ALL_COMPANIES]: t("token_usage.admin.all_companies"),
63
+ ...Object.fromEntries(companies.map((company) => [company.id, company.label]))
64
+ };
65
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-wrap items-center gap-2", children: [
66
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
67
+ _chunkF6PZZ4KIjs.DateRangeSelector,
68
+ {
69
+ onDateChange: (range) => {
70
+ if (!_optionalChain([range, 'optionalAccess', _ => _.from]) || !_optionalChain([range, 'optionalAccess', _2 => _2.to])) return;
71
+ onChange({ from: range.from.toISOString(), to: range.to.toISOString() });
72
+ }
73
+ }
74
+ ),
75
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
76
+ Segmented,
77
+ {
78
+ ariaLabel: t("token_usage.admin.granularity.label"),
79
+ value: granularity,
80
+ options: [
81
+ { value: "day", label: t("token_usage.admin.granularity.day") },
82
+ { value: "week", label: t("token_usage.admin.granularity.week") },
83
+ { value: "month", label: t("token_usage.admin.granularity.month") }
84
+ ],
85
+ onSelect: (value) => onChange({ granularity: value })
86
+ }
87
+ ),
88
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
89
+ Segmented,
90
+ {
91
+ ariaLabel: t("token_usage.admin.metric.label"),
92
+ value: metric,
93
+ options: [
94
+ { value: "cost", label: t("token_usage.admin.metric.cost") },
95
+ { value: "credits", label: t("token_usage.admin.metric.credits") },
96
+ { value: "tokens", label: t("token_usage.admin.metric.tokens") }
97
+ ],
98
+ onSelect: (value) => onChange({ metric: value })
99
+ }
100
+ ),
101
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
102
+ _chunkF6PZZ4KIjs.Select,
103
+ {
104
+ items: companyItems,
105
+ value: _nullishCoalesce(companyId, () => ( ALL_COMPANIES)),
106
+ onValueChange: (value) => onChange({ companyId: !value || value === ALL_COMPANIES ? void 0 : value }),
107
+ children: [
108
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectTrigger, { className: "w-56", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectValue, { placeholder: t("token_usage.admin.all_companies") }) }),
109
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.SelectContent, { children: [
110
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectItem, { value: ALL_COMPANIES, children: t("token_usage.admin.all_companies") }),
111
+ companies.map((company) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectItem, { value: company.id, children: company.label }, company.id))
112
+ ] })
113
+ ]
114
+ }
115
+ )
116
+ ] });
117
+ }
118
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageAdminFilterBar, "TokenUsageAdminFilterBar");
119
+ function Segmented({
120
+ ariaLabel,
121
+ value,
122
+ options,
123
+ onSelect
124
+ }) {
125
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
126
+ "div",
127
+ {
128
+ role: "group",
129
+ "aria-label": ariaLabel,
130
+ className: "border-border inline-flex items-center gap-0.5 rounded-md border p-0.5",
131
+ children: options.map((option) => {
132
+ const selected = option.value === value;
133
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
134
+ _chunkF6PZZ4KIjs.Button,
135
+ {
136
+ type: "button",
137
+ size: "sm",
138
+ variant: selected ? "default" : "ghost",
139
+ "aria-pressed": selected,
140
+ className: _chunkDS4IBFWAjs.cn.call(void 0, !selected && "text-muted-foreground"),
141
+ onClick: () => onSelect(option.value),
142
+ children: option.label
143
+ },
144
+ option.value
145
+ );
146
+ })
147
+ }
148
+ );
149
+ }
150
+ _chunk7QVYU63Ejs.__name.call(void 0, Segmented, "Segmented");
151
+
152
+ // src/features/tokenusage/data/TokenUsageAdminService.ts
153
+ function withFilters(endpoint, filters) {
154
+ endpoint.addAdditionalParam("from", filters.from);
155
+ endpoint.addAdditionalParam("to", filters.to);
156
+ if (filters.companyId) endpoint.addAdditionalParam("companyId", filters.companyId);
157
+ return endpoint;
158
+ }
159
+ _chunk7QVYU63Ejs.__name.call(void 0, withFilters, "withFilters");
160
+ var TokenUsageAdminService = class extends _chunkDS4IBFWAjs.AbstractService {
161
+ static {
162
+ _chunk7QVYU63Ejs.__name.call(void 0, this, "TokenUsageAdminService");
163
+ }
164
+ /** Six rows: {customer, platform, total} × {current, previous}. */
165
+ static async getSummary(filters) {
166
+ const endpoint = withFilters(new (0, _chunkDS4IBFWAjs.EndpointCreator)({ endpoint: _chunkDS4IBFWAjs.Modules.TokenUsageAdminSummary }), filters);
167
+ return this.callApi({
168
+ type: _chunkDS4IBFWAjs.Modules.TokenUsageAdminSummary,
169
+ method: "GET" /* GET */,
170
+ endpoint: endpoint.generate()
171
+ });
172
+ }
173
+ static async getTimeline(params) {
174
+ const endpoint = withFilters(new (0, _chunkDS4IBFWAjs.EndpointCreator)({ endpoint: _chunkDS4IBFWAjs.Modules.TokenUsageAdminTimeline }), params);
175
+ endpoint.addAdditionalParam("granularity", params.granularity);
176
+ endpoint.addAdditionalParam("stackBy", params.stackBy);
177
+ return this.callApi({
178
+ type: _chunkDS4IBFWAjs.Modules.TokenUsageAdminTimeline,
179
+ method: "GET" /* GET */,
180
+ endpoint: endpoint.generate()
181
+ });
182
+ }
183
+ static async getBreakdown(params) {
184
+ const endpoint = withFilters(new (0, _chunkDS4IBFWAjs.EndpointCreator)({ endpoint: _chunkDS4IBFWAjs.Modules.TokenUsageAdminBreakdown }), params);
185
+ endpoint.addAdditionalParam("dimension", params.dimension);
186
+ endpoint.addAdditionalParam("scope", params.scope);
187
+ if (params.limit !== void 0) endpoint.addAdditionalParam("limit", String(params.limit));
188
+ return this.callApi({
189
+ type: _chunkDS4IBFWAjs.Modules.TokenUsageAdminBreakdown,
190
+ method: "GET" /* GET */,
191
+ endpoint: endpoint.generate()
192
+ });
193
+ }
194
+ };
195
+
196
+ // src/features/tokenusage/contexts/TokenUsageAdminContext.tsx
197
+
198
+ var TOKEN_USAGE_ADMIN_PAGE_URL = "/administration/token-usage";
199
+ var DEFAULT_TOP_N = 10;
200
+ var TokenUsageAdminContext = _react.createContext.call(void 0, void 0);
201
+ function defaultRange() {
202
+ const now = /* @__PURE__ */ new Date();
203
+ const start = new Date(now.getFullYear(), now.getMonth(), 1, 0, 0, 0, 0);
204
+ return { from: start.toISOString(), to: now.toISOString() };
205
+ }
206
+ _chunk7QVYU63Ejs.__name.call(void 0, defaultRange, "defaultRange");
207
+ var TokenUsageAdminProvider = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, ({
208
+ children,
209
+ initialCompanyId,
210
+ initialFrom,
211
+ initialTo,
212
+ topN = DEFAULT_TOP_N
213
+ }) => {
214
+ const t = _nextintl.useTranslations.call(void 0, );
215
+ const generateUrl = _chunkF6PZZ4KIjs.usePageUrlGenerator.call(void 0, );
216
+ const [filters, setFilterState] = _react.useState.call(void 0, () => {
217
+ const range = defaultRange();
218
+ return {
219
+ from: _nullishCoalesce(initialFrom, () => ( range.from)),
220
+ to: _nullishCoalesce(initialTo, () => ( range.to)),
221
+ granularity: "day",
222
+ stackBy: "scope",
223
+ companyId: initialCompanyId,
224
+ metric: "cost"
225
+ };
226
+ });
227
+ const [summary, setSummary] = _react.useState.call(void 0, []);
228
+ const [timeline, setTimeline] = _react.useState.call(void 0, []);
229
+ const [byCompany, setByCompany] = _react.useState.call(void 0, []);
230
+ const [byUser, setByUser] = _react.useState.call(void 0, []);
231
+ const [byOperation, setByOperation] = _react.useState.call(void 0, []);
232
+ const [byCustomerOperation, setByCustomerOperation] = _react.useState.call(void 0, []);
233
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, true);
234
+ const [error, setError] = _react.useState.call(void 0, null);
235
+ const { from, to, granularity, stackBy, companyId, metric } = filters;
236
+ const singleCustomerMode = Boolean(companyId);
237
+ _react.useEffect.call(void 0, () => {
238
+ let cancelled = false;
239
+ setIsLoading(true);
240
+ setError(null);
241
+ const base = { from, to, companyId };
242
+ Promise.all([
243
+ TokenUsageAdminService.getSummary(base),
244
+ TokenUsageAdminService.getTimeline({ ...base, granularity, stackBy }),
245
+ TokenUsageAdminService.getBreakdown({ ...base, dimension: "company", scope: "customer", limit: topN }),
246
+ TokenUsageAdminService.getBreakdown({ ...base, dimension: "user", scope: "customer", limit: topN }),
247
+ // Platform spend is, by definition, the usage with no owning company, so
248
+ // filtering it by one is meaningless — the call is skipped entirely rather
249
+ // than issued and discarded.
250
+ companyId ? Promise.resolve([]) : TokenUsageAdminService.getBreakdown({ ...base, dimension: "operation", scope: "platform", limit: topN }),
251
+ // Customer spend by operation — unlike the platform panel this one IS
252
+ // meaningful under a company filter, so it is always requested.
253
+ TokenUsageAdminService.getBreakdown({ ...base, dimension: "operation", scope: "customer", limit: topN })
254
+ ]).then(([nextSummary, nextTimeline, nextByCompany, nextByUser, nextByOperation, nextByCustomerOperation]) => {
255
+ if (cancelled) return;
256
+ setSummary(_nullishCoalesce(nextSummary, () => ( [])));
257
+ setTimeline(_nullishCoalesce(nextTimeline, () => ( [])));
258
+ setByCompany(_nullishCoalesce(nextByCompany, () => ( [])));
259
+ setByUser(_nullishCoalesce(nextByUser, () => ( [])));
260
+ setByOperation(_nullishCoalesce(nextByOperation, () => ( [])));
261
+ setByCustomerOperation(_nullishCoalesce(nextByCustomerOperation, () => ( [])));
262
+ }).catch((err) => {
263
+ if (cancelled) return;
264
+ console.error("Failed to load administrative token usage:", err);
265
+ setError(err instanceof Error ? err.message : String(err));
266
+ }).finally(() => {
267
+ if (cancelled) return;
268
+ setIsLoading(false);
269
+ });
270
+ return () => {
271
+ cancelled = true;
272
+ };
273
+ }, [from, to, granularity, stackBy, companyId, topN]);
274
+ const setFilters = _react.useCallback.call(void 0, (next) => {
275
+ setFilterState((prev) => ({ ...prev, ...next }));
276
+ }, []);
277
+ const companies = _react.useMemo.call(void 0,
278
+ () => byCompany.filter((row) => row.id !== "other").map((row) => ({ id: row.id, label: row.label })),
279
+ [byCompany]
280
+ );
281
+ const breadcrumb = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => [
282
+ {
283
+ name: t("token_usage.admin.title"),
284
+ href: generateUrl({ page: TOKEN_USAGE_ADMIN_PAGE_URL })
285
+ }
286
+ ], "breadcrumb");
287
+ const title = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => ({
288
+ type: t("token_usage.admin.title"),
289
+ functions: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
290
+ TokenUsageAdminFilterBar,
291
+ {
292
+ from,
293
+ to,
294
+ granularity,
295
+ companyId,
296
+ metric,
297
+ companies,
298
+ onChange: setFilters
299
+ },
300
+ "tokenUsageAdminFilterBar"
301
+ )
302
+ }), "title");
303
+ const contextValue = _react.useMemo.call(void 0,
304
+ () => ({
305
+ summary,
306
+ timeline,
307
+ byCompany,
308
+ byUser,
309
+ byOperation,
310
+ byCustomerOperation,
311
+ companies,
312
+ filters,
313
+ setFilters,
314
+ singleCustomerMode,
315
+ isLoading,
316
+ error
317
+ }),
318
+ [
319
+ summary,
320
+ timeline,
321
+ byCompany,
322
+ byUser,
323
+ byOperation,
324
+ byCustomerOperation,
325
+ companies,
326
+ filters,
327
+ setFilters,
328
+ singleCustomerMode,
329
+ isLoading,
330
+ error
331
+ ]
332
+ );
333
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SharedProvider, { value: { breadcrumbs: breadcrumb(), title: title() }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageAdminContext.Provider, { value: contextValue, children }) });
334
+ }, "TokenUsageAdminProvider");
335
+ var useTokenUsageAdmin = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, () => {
336
+ const ctx = _react.useContext.call(void 0, TokenUsageAdminContext);
337
+ if (!ctx) {
338
+ throw new Error("useTokenUsageAdmin() called outside <TokenUsageAdminProvider>.");
339
+ }
340
+ return ctx;
341
+ }, "useTokenUsageAdmin");
342
+
343
+ // src/features/tokenusage/components/TokenUsageAdminContainer.tsx
344
+
345
+
346
+
347
+ // src/features/tokenusage/components/TokenUsageAdminTiles.tsx
348
+ var _lucidereact = require('lucide-react');
349
+
350
+
351
+ // src/features/tokenusage/lib/metrics.ts
352
+ var LOCALE = "it-IT";
353
+ function metricValue(row, metric) {
354
+ if (metric === "cost") return row.cost;
355
+ if (metric === "credits") return row.credits;
356
+ return row.tokensIn + row.tokensOut;
357
+ }
358
+ _chunk7QVYU63Ejs.__name.call(void 0, metricValue, "metricValue");
359
+ function formatDecimal(value, decimals) {
360
+ return value.toLocaleString(LOCALE, {
361
+ minimumFractionDigits: decimals,
362
+ maximumFractionDigits: decimals
363
+ });
364
+ }
365
+ _chunk7QVYU63Ejs.__name.call(void 0, formatDecimal, "formatDecimal");
366
+ function formatMetricValue(value, metric) {
367
+ if (metric === "cost") return `\u20AC ${formatDecimal(value, 2)}`;
368
+ if (metric === "credits") return formatDecimal(value, 2);
369
+ return formatDecimal(value, 0);
370
+ }
371
+ _chunk7QVYU63Ejs.__name.call(void 0, formatMetricValue, "formatMetricValue");
372
+ function formatPercent(value, decimals = 1) {
373
+ return `${formatDecimal(value, decimals)} %`;
374
+ }
375
+ _chunk7QVYU63Ejs.__name.call(void 0, formatPercent, "formatPercent");
376
+ function cacheHitPercentage(cached, tokensIn) {
377
+ if (!tokensIn) return 0;
378
+ return cached / tokensIn * 100;
379
+ }
380
+ _chunk7QVYU63Ejs.__name.call(void 0, cacheHitPercentage, "cacheHitPercentage");
381
+ function percentageDelta(current, previous) {
382
+ if (!previous) return void 0;
383
+ return Math.round((current - previous) / previous * 100);
384
+ }
385
+ _chunk7QVYU63Ejs.__name.call(void 0, percentageDelta, "percentageDelta");
386
+
387
+ // src/features/tokenusage/components/TokenUsageAdminTiles.tsx
388
+
389
+ var ZERO = { cost: 0, credits: 0, tokensIn: 0, tokensOut: 0, cached: 0, calls: 0 };
390
+ function TokenUsageAdminTiles({ summary, metric, singleCustomerMode }) {
391
+ const t = _nextintl.useTranslations.call(void 0, );
392
+ const rowFor = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (scope, window) => _nullishCoalesce(summary.find((r) => r.scope === scope && r.window === window), () => ( ZERO)), "rowFor");
393
+ const customerCurrent = rowFor("customer", "current");
394
+ const customerPrevious = rowFor("customer", "previous");
395
+ const platformCurrent = rowFor("platform", "current");
396
+ const platformPrevious = rowFor("platform", "previous");
397
+ const totalCurrent = rowFor("total", "current");
398
+ const totalPrevious = rowFor("total", "previous");
399
+ const averagePerCall = totalCurrent.calls ? totalCurrent.cost / totalCurrent.calls : 0;
400
+ const cacheHit = cacheHitPercentage(totalCurrent.cached, totalCurrent.tokensIn);
401
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid gap-3", children: [
402
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkDS4IBFWAjs.cn.call(void 0, "grid gap-3", singleCustomerMode ? "sm:grid-cols-1" : "sm:grid-cols-2"), children: [
403
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
404
+ LeadTile,
405
+ {
406
+ testId: "tile-customer",
407
+ label: t("token_usage.admin.customer_spend"),
408
+ value: formatMetricValue(metricValue(customerCurrent, metric), metric),
409
+ delta: percentageDelta(metricValue(customerCurrent, metric), metricValue(customerPrevious, metric)),
410
+ previousLabel: t("token_usage.admin.vs_previous")
411
+ }
412
+ ),
413
+ !singleCustomerMode && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
414
+ LeadTile,
415
+ {
416
+ testId: "tile-platform",
417
+ label: t("token_usage.admin.platform_spend"),
418
+ value: formatMetricValue(metricValue(platformCurrent, metric), metric),
419
+ delta: percentageDelta(metricValue(platformCurrent, metric), metricValue(platformPrevious, metric)),
420
+ previousLabel: t("token_usage.admin.vs_previous")
421
+ }
422
+ )
423
+ ] }),
424
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid gap-3 sm:grid-cols-3", children: [
425
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
426
+ SupportingTile,
427
+ {
428
+ testId: "tile-total",
429
+ label: t("token_usage.admin.total_cost"),
430
+ value: formatMetricValue(metricValue(totalCurrent, metric), metric),
431
+ delta: percentageDelta(metricValue(totalCurrent, metric), metricValue(totalPrevious, metric))
432
+ }
433
+ ),
434
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
435
+ SupportingTile,
436
+ {
437
+ testId: "tile-avg-per-call",
438
+ label: t("token_usage.admin.avg_per_call"),
439
+ value: `\u20AC ${formatDecimal(averagePerCall, 4)}`
440
+ }
441
+ ),
442
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
443
+ SupportingTile,
444
+ {
445
+ testId: "tile-cache-hit",
446
+ label: t("token_usage.admin.cache_hit"),
447
+ value: formatPercent(cacheHit)
448
+ }
449
+ )
450
+ ] })
451
+ ] });
452
+ }
453
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageAdminTiles, "TokenUsageAdminTiles");
454
+ function LeadTile({
455
+ testId,
456
+ label,
457
+ value,
458
+ delta,
459
+ previousLabel
460
+ }) {
461
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.Card, { "data-testid": testId, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.CardContent, { className: "grid gap-1", children: [
462
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: label }),
463
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-primary text-xl font-semibold tabular-nums", children: value }),
464
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center gap-1", children: [
465
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Delta, { testId: `${testId}-delta`, delta }),
466
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: previousLabel })
467
+ ] })
468
+ ] }) });
469
+ }
470
+ _chunk7QVYU63Ejs.__name.call(void 0, LeadTile, "LeadTile");
471
+ function SupportingTile({
472
+ testId,
473
+ label,
474
+ value,
475
+ delta
476
+ }) {
477
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.Card, { "data-testid": testId, size: "sm", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.CardContent, { className: "grid gap-1", children: [
478
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: label }),
479
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "flex items-center gap-2", children: [
480
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm font-medium tabular-nums", children: value }),
481
+ delta !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Delta, { testId: `${testId}-delta`, delta })
482
+ ] })
483
+ ] }) });
484
+ }
485
+ _chunk7QVYU63Ejs.__name.call(void 0, SupportingTile, "SupportingTile");
486
+ function Delta({ testId, delta }) {
487
+ if (delta === void 0) {
488
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": testId, className: "text-muted-foreground text-xs", children: "\u2014" });
489
+ }
490
+ const increased = delta >= 0;
491
+ const Icon = increased ? _lucidereact.ArrowUpIcon : _lucidereact.ArrowDownIcon;
492
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
493
+ "span",
494
+ {
495
+ "data-testid": testId,
496
+ className: _chunkDS4IBFWAjs.cn.call(void 0,
497
+ "inline-flex items-center gap-0.5 text-xs tabular-nums",
498
+ increased ? "text-success" : "text-destructive"
499
+ ),
500
+ children: [
501
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Icon, { "aria-hidden": true, className: "size-3" }),
502
+ formatDecimal(Math.abs(delta), 0),
503
+ " %"
504
+ ]
505
+ }
506
+ );
507
+ }
508
+ _chunk7QVYU63Ejs.__name.call(void 0, Delta, "Delta");
509
+
510
+ // src/features/tokenusage/components/TokenUsageBreakdownTable.tsx
511
+
512
+
513
+
514
+
515
+ function TokenUsageBreakdownTable({ rows, metric }) {
516
+ const t = _nextintl.useTranslations.call(void 0, );
517
+ const [sort, setSort] = _react.useState.call(void 0, void 0);
518
+ const showActiveUsers = rows.some((row) => row.activeUsers !== void 0);
519
+ const total = _react.useMemo.call(void 0, () => rows.reduce((sum, row) => sum + metricValue(row, metric), 0), [rows, metric]);
520
+ const sortValue = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (row, key) => {
521
+ switch (key) {
522
+ case "label":
523
+ return _nullishCoalesce(row.label, () => ( ""));
524
+ case "sublabel":
525
+ return _nullishCoalesce(row.sublabel, () => ( ""));
526
+ case "activeUsers":
527
+ return _nullishCoalesce(row.activeUsers, () => ( 0));
528
+ case "cacheHit":
529
+ return cacheHitPercentage(row.cached, row.tokensIn);
530
+ case "share":
531
+ return metricValue(row, metric);
532
+ default:
533
+ return row[key];
534
+ }
535
+ }, "sortValue");
536
+ const sortedRows = _react.useMemo.call(void 0, () => {
537
+ if (!sort) return rows;
538
+ const factor = sort.direction === "desc" ? -1 : 1;
539
+ return [...rows].sort((a, b) => {
540
+ const left = sortValue(a, sort.key);
541
+ const right = sortValue(b, sort.key);
542
+ if (typeof left === "string" || typeof right === "string") {
543
+ return String(left).localeCompare(String(right), "it-IT") * factor;
544
+ }
545
+ return (left - right) * factor;
546
+ });
547
+ }, [rows, sort, metric]);
548
+ const toggleSort = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (key) => setSort(
549
+ (current) => _optionalChain([current, 'optionalAccess', _3 => _3.key]) === key ? { key, direction: current.direction === "desc" ? "asc" : "desc" } : { key, direction: "desc" }
550
+ ), "toggleSort");
551
+ const columns = [
552
+ { key: "label", label: t("token_usage.admin.columns.label"), numeric: false },
553
+ { key: "sublabel", label: t("token_usage.admin.columns.sublabel"), numeric: false },
554
+ ...showActiveUsers ? [{ key: "activeUsers", label: t("token_usage.admin.columns.active_users"), numeric: true }] : [],
555
+ { key: "calls", label: t("token_usage.admin.columns.calls"), numeric: true },
556
+ { key: "tokensIn", label: t("token_usage.admin.columns.tokens_in"), numeric: true },
557
+ { key: "tokensOut", label: t("token_usage.admin.columns.tokens_out"), numeric: true },
558
+ // Reuses the tile's key rather than minting a column-specific one — same
559
+ // metric, same words.
560
+ { key: "cacheHit", label: t("token_usage.admin.cache_hit"), numeric: true },
561
+ { key: "cost", label: t("token_usage.admin.columns.cost"), numeric: true },
562
+ { key: "credits", label: t("token_usage.admin.columns.credits"), numeric: true },
563
+ { key: "share", label: t("token_usage.admin.columns.share"), numeric: true }
564
+ ];
565
+ return (
566
+ // The package's <Table> wraps itself in an `overflow-x-clip` container, which
567
+ // would swallow the overflow before this scroller ever saw it — hence the
568
+ // child override. Wide metric tables must scroll, never widen the page.
569
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "overflow-x-auto [&_[data-slot=table-container]]:overflow-x-visible", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Table, { children: [
570
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableRow, { children: columns.map((column) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableHead, { className: _chunkDS4IBFWAjs.cn.call(void 0, column.numeric && "text-right"), children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
571
+ "button",
572
+ {
573
+ type: "button",
574
+ onClick: () => toggleSort(column.key),
575
+ className: _chunkDS4IBFWAjs.cn.call(void 0,
576
+ "hover:text-primary inline-flex items-center gap-1 text-xs font-medium",
577
+ column.numeric && "flex-row-reverse"
578
+ ),
579
+ children: [
580
+ column.label,
581
+ _optionalChain([sort, 'optionalAccess', _4 => _4.key]) === column.key && (sort.direction === "desc" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowDownIcon, { "aria-hidden": true, className: "size-3" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _lucidereact.ArrowUpIcon, { "aria-hidden": true, className: "size-3" }))
582
+ ]
583
+ }
584
+ ) }, column.key)) }) }),
585
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableBody, { children: sortedRows.map((row) => {
586
+ const value = metricValue(row, metric);
587
+ const share = total > 0 ? value / total * 100 : 0;
588
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.TableRow, { "data-testid": `breakdown-row-${row.id}`, children: [
589
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-xs", children: row.id === "other" ? t("token_usage.admin.other") : row.label }),
590
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-muted-foreground text-xs", children: _nullishCoalesce(row.sublabel, () => ( "")) }),
591
+ showActiveUsers && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: row.activeUsers === void 0 ? "" : formatDecimal(row.activeUsers, 0) }),
592
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatDecimal(row.calls, 0) }),
593
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatDecimal(row.tokensIn, 0) }),
594
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatDecimal(row.tokensOut, 0) }),
595
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatPercent(cacheHitPercentage(row.cached, row.tokensIn)) }),
596
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatMetricValue(row.cost, "cost") }),
597
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatMetricValue(row.credits, "credits") }),
598
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.TableCell, { className: "text-right text-xs tabular-nums", children: formatPercent(share) })
599
+ ] }, row.id);
600
+ }) })
601
+ ] }) })
602
+ );
603
+ }
604
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageBreakdownTable, "TokenUsageBreakdownTable");
605
+
606
+ // src/features/tokenusage/components/TokenUsageRankedBar.tsx
607
+
608
+
609
+ // src/features/tokenusage/lib/operation-label.ts
610
+ var OPERATION_LABEL_NAMESPACE = "token_usage.types";
611
+ var toCamelCase = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (value) => {
612
+ const parts = value.split(/[^a-zA-Z0-9]+/).filter(Boolean);
613
+ if (parts.length === 0) return value;
614
+ return parts.map(
615
+ (part, index) => index === 0 ? part.charAt(0).toLowerCase() + part.slice(1) : part.charAt(0).toUpperCase() + part.slice(1)
616
+ ).join("");
617
+ }, "toCamelCase");
618
+ var operationLabel = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (type, translate, has) => {
619
+ const key = `${OPERATION_LABEL_NAMESPACE}.${toCamelCase(type)}`;
620
+ return has(key) ? translate(key) : type;
621
+ }, "operationLabel");
622
+
623
+ // src/features/tokenusage/lib/palette.ts
624
+ var CATEGORICAL_LIGHT = [
625
+ "#2a78d6",
626
+ "#eb6834",
627
+ "#1baf7a",
628
+ "#eda100",
629
+ "#e87ba4",
630
+ "#008300",
631
+ "#4a3aa7"
632
+ ];
633
+ var CATEGORICAL_DARK = [
634
+ "#3987e5",
635
+ "#d95926",
636
+ "#199e70",
637
+ "#c98500",
638
+ "#d55181",
639
+ "#008300",
640
+ "#9085e9"
641
+ ];
642
+ var CATEGORICAL_CEILING = CATEGORICAL_LIGHT.length;
643
+ var OTHER_COLOR = "#898781";
644
+ var SEQUENTIAL_RAMP_LIGHT = ["#104281", "#1c5cab", "#2a78d6", "#5598e7", "#86b6ef"];
645
+ var SEQUENTIAL_RAMP = SEQUENTIAL_RAMP_LIGHT;
646
+ var categoricalSet = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (mode) => mode === "dark" ? CATEGORICAL_DARK : CATEGORICAL_LIGHT, "categoricalSet");
647
+ function seriesColor(index, mode = "light") {
648
+ if (index < 0 || index >= CATEGORICAL_CEILING) return OTHER_COLOR;
649
+ return categoricalSet(mode)[index];
650
+ }
651
+ _chunk7QVYU63Ejs.__name.call(void 0, seriesColor, "seriesColor");
652
+
653
+ // src/features/tokenusage/components/TokenUsageRankedBar.tsx
654
+
655
+ function TokenUsageRankedBar({ rows, metric, emptyLabel, labelsAreOperationTypes = false }) {
656
+ const t = _nextintl.useTranslations.call(void 0, );
657
+ const renderLabel = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (row) => {
658
+ if (row.id === "other") return t("token_usage.admin.other");
659
+ if (!labelsAreOperationTypes) return row.label;
660
+ return operationLabel(
661
+ row.label,
662
+ (key) => t(key),
663
+ (key) => t.has(key)
664
+ );
665
+ }, "renderLabel");
666
+ if (rows.length === 0) {
667
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-muted-foreground py-6 text-center text-sm", children: emptyLabel });
668
+ }
669
+ const values = rows.map((row) => metricValue(row, metric));
670
+ const total = values.reduce((sum, value) => sum + value, 0);
671
+ const max = Math.max(...values, 0);
672
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grid gap-0.5", children: rows.map((row, index) => {
673
+ const value = values[index];
674
+ const isOther = row.id === "other";
675
+ const step = isOther ? SEQUENTIAL_RAMP.length - 1 : Math.min(index, SEQUENTIAL_RAMP.length - 1);
676
+ const width = max > 0 ? value / max * 100 : 0;
677
+ const share = total > 0 ? value / total * 100 : 0;
678
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid grid-cols-[minmax(0,1fr)_auto_auto] items-center gap-x-3 gap-y-0.5 py-0.5", children: [
679
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid min-w-0 gap-0.5", children: [
680
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground truncate text-xs", children: renderLabel(row) }),
681
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "bg-muted h-2 w-full overflow-hidden rounded-r-[4px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
682
+ "div",
683
+ {
684
+ "data-testid": `ranked-fill-${row.id}`,
685
+ "data-ramp-step": String(step),
686
+ className: "h-full rounded-r-[4px]",
687
+ style: { width: `${width}%`, backgroundColor: SEQUENTIAL_RAMP[step] }
688
+ }
689
+ ) })
690
+ ] }),
691
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": `ranked-value-${row.id}`, className: "text-right text-xs tabular-nums", children: formatMetricValue(value, metric) }),
692
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
693
+ "span",
694
+ {
695
+ "data-testid": `ranked-share-${row.id}`,
696
+ className: "text-muted-foreground w-16 text-right text-xs tabular-nums",
697
+ children: formatPercent(share)
698
+ }
699
+ )
700
+ ] }, row.id);
701
+ }) });
702
+ }
703
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageRankedBar, "TokenUsageRankedBar");
704
+
705
+ // src/features/tokenusage/components/TokenUsageTimelineChart.tsx
706
+
707
+ var _nextthemes = require('next-themes');
708
+
709
+ var _recharts = require('recharts');
710
+
711
+ var OTHER_SERIES = "other";
712
+ var bucketKey = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (date) => {
713
+ const y = date.getUTCFullYear();
714
+ const m = `${date.getUTCMonth() + 1}`.padStart(2, "0");
715
+ const d = `${date.getUTCDate()}`.padStart(2, "0");
716
+ return `${y}-${m}-${d}`;
717
+ }, "bucketKey");
718
+ var metricValue2 = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (row, metric) => {
719
+ if (metric === "cost") return row.cost;
720
+ if (metric === "credits") return row.credits;
721
+ return row.tokensIn + row.tokensOut;
722
+ }, "metricValue");
723
+ var inferGranularity = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (buckets) => {
724
+ if (buckets.length < 2) return "day";
725
+ const dayMs = 24 * 60 * 60 * 1e3;
726
+ let smallestGap = Number.POSITIVE_INFINITY;
727
+ for (let i = 1; i < buckets.length; i += 1) {
728
+ const gap = (Date.parse(buckets[i]) - Date.parse(buckets[i - 1])) / dayMs;
729
+ if (gap > 0 && gap < smallestGap) smallestGap = gap;
730
+ }
731
+ if (smallestGap >= 28) return "month";
732
+ if (smallestGap >= 7) return "week";
733
+ return "day";
734
+ }, "inferGranularity");
735
+ var bucketFormatter = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (granularity) => granularity === "month" ? new Intl.DateTimeFormat("it-IT", { month: "short", year: "numeric", timeZone: "UTC" }) : new Intl.DateTimeFormat("it-IT", { day: "numeric", month: "short", timeZone: "UTC" }), "bucketFormatter");
736
+ var compactNumber = new Intl.NumberFormat("it-IT", { notation: "compact", maximumFractionDigits: 1 });
737
+ function TokenUsageTimelineChart({ rows, metric, stackBy, className }) {
738
+ const t = _nextintl.useTranslations.call(void 0, );
739
+ const { resolvedTheme } = _nextthemes.useTheme.call(void 0, );
740
+ const mode = resolvedTheme === "dark" ? "dark" : "light";
741
+ const { chartData, seriesKeys } = _react.useMemo.call(void 0, () => {
742
+ if (rows.length === 0) return { chartData: [], seriesKeys: [] };
743
+ const totals = /* @__PURE__ */ new Map();
744
+ for (const row of rows) totals.set(row.series, (_nullishCoalesce(totals.get(row.series), () => ( 0))) + metricValue2(row, metric));
745
+ const ranked = [...totals.entries()].sort((a, b) => b[1] - a[1]).map(([series]) => series);
746
+ const named = ranked.slice(0, CATEGORICAL_CEILING);
747
+ const folded = new Set(ranked.slice(CATEGORICAL_CEILING));
748
+ const keys = folded.size > 0 ? [...named, OTHER_SERIES] : named;
749
+ const byBucket = /* @__PURE__ */ new Map();
750
+ for (const row of rows) {
751
+ const key = bucketKey(row.bucket);
752
+ let entry = byBucket.get(key);
753
+ if (!entry) {
754
+ entry = { bucket: key };
755
+ for (const series2 of keys) entry[series2] = 0;
756
+ byBucket.set(key, entry);
757
+ }
758
+ const series = folded.has(row.series) ? OTHER_SERIES : row.series;
759
+ entry[series] = entry[series] + metricValue2(row, metric);
760
+ }
761
+ return {
762
+ chartData: [...byBucket.values()].sort((a, b) => a.bucket.localeCompare(b.bucket)),
763
+ seriesKeys: keys
764
+ };
765
+ }, [rows, metric]);
766
+ const seriesLabel = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (series) => {
767
+ if (series === OTHER_SERIES) {
768
+ const key = "token_usage.series.other";
769
+ return t.has(key) ? t(key) : "Altro";
770
+ }
771
+ if (stackBy === "company") return series;
772
+ return operationLabel(
773
+ series,
774
+ (key) => t(key),
775
+ (key) => t.has(key)
776
+ );
777
+ }, "seriesLabel");
778
+ const chartConfig = _react.useMemo.call(void 0,
779
+ () => Object.fromEntries(seriesKeys.map((series) => [series, { label: seriesLabel(series) }])),
780
+ [seriesKeys, stackBy]
781
+ );
782
+ if (chartData.length === 0) {
783
+ const key = "token_usage.timeline.empty";
784
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: className ? `text-muted-foreground text-sm ${className}` : "text-muted-foreground text-sm", children: t.has(key) ? t(key) : "Nessun dato nel periodo selezionato" });
785
+ }
786
+ const granularity = inferGranularity(chartData.map((entry) => entry.bucket));
787
+ const formatBucket = bucketFormatter(granularity);
788
+ const seriesColorFor = /* @__PURE__ */ _chunk7QVYU63Ejs.__name.call(void 0, (series, index) => series === OTHER_SERIES ? OTHER_COLOR : seriesColor(index, mode), "seriesColorFor");
789
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className, children: [
790
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", "data-testid": "timeline-data", children: JSON.stringify(chartData) }),
791
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", "data-testid": "timeline-series", children: JSON.stringify(seriesKeys) }),
792
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.ChartContainer, { config: chartConfig, className: "aspect-auto h-72 w-full", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _recharts.BarChart, { accessibilityLayer: true, data: chartData, margin: { top: 8, right: 8, bottom: 0, left: 0 }, children: [
793
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _recharts.CartesianGrid, { vertical: false }),
794
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
795
+ _recharts.XAxis,
796
+ {
797
+ dataKey: "bucket",
798
+ tickLine: false,
799
+ axisLine: false,
800
+ tickMargin: 8,
801
+ minTickGap: 16,
802
+ tickFormatter: (value) => formatBucket.format(/* @__PURE__ */ new Date(`${value}T00:00:00.000Z`))
803
+ }
804
+ ),
805
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
806
+ _recharts.YAxis,
807
+ {
808
+ tickLine: false,
809
+ axisLine: false,
810
+ tickMargin: 8,
811
+ width: 48,
812
+ tickFormatter: (value) => compactNumber.format(value)
813
+ }
814
+ ),
815
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
816
+ _chunkF6PZZ4KIjs.ChartTooltip,
817
+ {
818
+ content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
819
+ _chunkF6PZZ4KIjs.ChartTooltipContent,
820
+ {
821
+ labelFormatter: (value) => formatBucket.format(/* @__PURE__ */ new Date(`${String(value)}T00:00:00.000Z`))
822
+ }
823
+ )
824
+ }
825
+ ),
826
+ seriesKeys.length >= 2 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.ChartLegend, { content: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.ChartLegendContent, {}) }) : null,
827
+ seriesKeys.map((series, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
828
+ _recharts.Bar,
829
+ {
830
+ dataKey: series,
831
+ stackId: "usage",
832
+ maxBarSize: 28,
833
+ fill: seriesColorFor(series, index),
834
+ stroke: "var(--background)",
835
+ strokeWidth: 2,
836
+ radius: index === seriesKeys.length - 1 ? [4, 4, 0, 0] : 0
837
+ },
838
+ series
839
+ ))
840
+ ] }) })
841
+ ] });
842
+ }
843
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageTimelineChart, "TokenUsageTimelineChart");
844
+
845
+ // src/features/tokenusage/components/TokenUsageAdminContainer.tsx
846
+
847
+ var STACK_BY_VALUES = ["scope", "type", "company"];
848
+ function TokenUsageAdminContainer() {
849
+ const t = _nextintl.useTranslations.call(void 0, );
850
+ const {
851
+ summary,
852
+ timeline,
853
+ byCompany,
854
+ byUser,
855
+ byOperation,
856
+ byCustomerOperation,
857
+ filters,
858
+ setFilters,
859
+ singleCustomerMode,
860
+ isLoading,
861
+ error
862
+ } = useTokenUsageAdmin();
863
+ const stackByItems = _react.useMemo.call(void 0,
864
+ () => ({
865
+ scope: t("token_usage.admin.stack.scope"),
866
+ type: t("token_usage.admin.stack.type"),
867
+ company: t("token_usage.admin.stack.company")
868
+ }),
869
+ [t]
870
+ );
871
+ if (error) {
872
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.RoundPageContainer, { fullWidth: true, forceHeader: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.Card, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-destructive text-xs/relaxed", children: error }) }) }) }) });
873
+ }
874
+ if (isLoading) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.RoundPageContainer, { fullWidth: true, forceHeader: true });
875
+ const emptyLabel = t("token_usage.admin.no_data");
876
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.RoundPageContainer, { fullWidth: true, forceHeader: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-full flex-col gap-4 p-4", children: [
877
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageAdminTiles, { summary, metric: filters.metric, singleCustomerMode }),
878
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
879
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: [
880
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.usage_over_time") }),
881
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardAction, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
882
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-muted-foreground text-xs", children: t("token_usage.admin.stack_by") }),
883
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
884
+ _chunkF6PZZ4KIjs.Select,
885
+ {
886
+ items: stackByItems,
887
+ value: filters.stackBy,
888
+ onValueChange: (value) => {
889
+ if (value) setFilters({ stackBy: value });
890
+ },
891
+ children: [
892
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectTrigger, { size: "sm", className: "w-36", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectValue, {}) }),
893
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectContent, { children: STACK_BY_VALUES.map((value) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.SelectItem, { value, children: stackByItems[value] }, value)) })
894
+ ]
895
+ }
896
+ )
897
+ ] }) })
898
+ ] }),
899
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageTimelineChart, { rows: timeline, metric: filters.metric, stackBy: filters.stackBy }) })
900
+ ] }),
901
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "grid gap-4 md:grid-cols-2", children: [
902
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
903
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.by_company") }) }),
904
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageRankedBar, { rows: byCompany, metric: filters.metric, emptyLabel }) })
905
+ ] }),
906
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
907
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.by_user") }) }),
908
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageRankedBar, { rows: byUser, metric: filters.metric, emptyLabel }) })
909
+ ] })
910
+ ] }),
911
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: _chunkDS4IBFWAjs.cn.call(void 0, "grid gap-4", !singleCustomerMode && "md:grid-cols-2"), children: [
912
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
913
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.customer_by_operation") }) }),
914
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
915
+ TokenUsageRankedBar,
916
+ {
917
+ rows: byCustomerOperation,
918
+ metric: filters.metric,
919
+ emptyLabel,
920
+ labelsAreOperationTypes: true
921
+ }
922
+ ) })
923
+ ] }),
924
+ !singleCustomerMode && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
925
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.platform_by_operation") }) }),
926
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
927
+ TokenUsageRankedBar,
928
+ {
929
+ rows: byOperation,
930
+ metric: filters.metric,
931
+ emptyLabel,
932
+ labelsAreOperationTypes: true
933
+ }
934
+ ) })
935
+ ] })
936
+ ] }),
937
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _chunkF6PZZ4KIjs.Card, { children: [
938
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardTitle, { children: t("token_usage.admin.detail") }) }),
939
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _chunkF6PZZ4KIjs.CardContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TokenUsageBreakdownTable, { rows: byCompany, metric: filters.metric }) })
940
+ ] })
941
+ ] }) });
942
+ }
943
+ _chunk7QVYU63Ejs.__name.call(void 0, TokenUsageAdminContainer, "TokenUsageAdminContainer");
944
+
945
+ // src/features/tokenusage/i18n-keys.ts
946
+ var TOKEN_USAGE_ADMIN_I18N_KEYS = [
947
+ // Page + KPI tiles
948
+ "token_usage.admin.title",
949
+ "token_usage.admin.customer_spend",
950
+ "token_usage.admin.platform_spend",
951
+ "token_usage.admin.total_cost",
952
+ "token_usage.admin.avg_per_call",
953
+ "token_usage.admin.cache_hit",
954
+ "token_usage.admin.vs_previous",
955
+ // Panel titles
956
+ "token_usage.admin.usage_over_time",
957
+ "token_usage.admin.by_company",
958
+ "token_usage.admin.by_user",
959
+ "token_usage.admin.customer_by_operation",
960
+ "token_usage.admin.platform_by_operation",
961
+ "token_usage.admin.detail",
962
+ // Shared states
963
+ "token_usage.admin.other",
964
+ "token_usage.admin.no_data",
965
+ // Filter bar
966
+ "token_usage.admin.all_companies",
967
+ "token_usage.admin.granularity.label",
968
+ "token_usage.admin.granularity.day",
969
+ "token_usage.admin.granularity.week",
970
+ "token_usage.admin.granularity.month",
971
+ "token_usage.admin.metric.label",
972
+ "token_usage.admin.metric.cost",
973
+ "token_usage.admin.metric.credits",
974
+ "token_usage.admin.metric.tokens",
975
+ // Timeline stacking control
976
+ "token_usage.admin.stack_by",
977
+ "token_usage.admin.stack.scope",
978
+ "token_usage.admin.stack.type",
979
+ "token_usage.admin.stack.company",
980
+ // Breakdown table columns
981
+ "token_usage.admin.columns.label",
982
+ "token_usage.admin.columns.sublabel",
983
+ "token_usage.admin.columns.calls",
984
+ "token_usage.admin.columns.tokens_in",
985
+ "token_usage.admin.columns.tokens_out",
986
+ "token_usage.admin.columns.cost",
987
+ "token_usage.admin.columns.credits",
988
+ "token_usage.admin.columns.share",
989
+ "token_usage.admin.columns.active_users",
990
+ // Timeline chart
991
+ "token_usage.series.other",
992
+ "token_usage.timeline.empty"
993
+ ];
994
+
995
+
996
+
997
+
998
+
999
+
1000
+
1001
+
1002
+
1003
+
1004
+
1005
+
1006
+
1007
+
1008
+
1009
+
1010
+
1011
+ exports.TOKEN_USAGE_ADMIN_I18N_KEYS = TOKEN_USAGE_ADMIN_I18N_KEYS; exports.TokenUsageAdminBreakdown = _chunkDS4IBFWAjs.TokenUsageAdminBreakdown; exports.TokenUsageAdminBreakdownModule = _chunkDS4IBFWAjs.TokenUsageAdminBreakdownModule; exports.TokenUsageAdminContainer = TokenUsageAdminContainer; exports.TokenUsageAdminFilterBar = TokenUsageAdminFilterBar; exports.TokenUsageAdminProvider = TokenUsageAdminProvider; exports.TokenUsageAdminService = TokenUsageAdminService; exports.TokenUsageAdminSummary = _chunkDS4IBFWAjs.TokenUsageAdminSummary; exports.TokenUsageAdminSummaryModule = _chunkDS4IBFWAjs.TokenUsageAdminSummaryModule; exports.TokenUsageAdminTiles = TokenUsageAdminTiles; exports.TokenUsageAdminTimeline = _chunkDS4IBFWAjs.TokenUsageAdminTimeline; exports.TokenUsageAdminTimelineModule = _chunkDS4IBFWAjs.TokenUsageAdminTimelineModule; exports.TokenUsageBreakdownTable = TokenUsageBreakdownTable; exports.TokenUsageRankedBar = TokenUsageRankedBar; exports.TokenUsageTimelineChart = TokenUsageTimelineChart; exports.useTokenUsageAdmin = useTokenUsageAdmin;
1012
+ //# sourceMappingURL=index.js.map