@copilotz/admin 0.9.36 → 0.9.38
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 +472 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +25 -4
- package/dist/index.d.ts +25 -4
- package/dist/index.js +480 -113
- package/dist/index.js.map +1 -1
- package/dist/styles.css +3 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,7 @@ __export(index_exports, {
|
|
|
63
63
|
formatUsageBucket: () => formatUsageBucket,
|
|
64
64
|
getUsageDimensionLabel: () => getUsageDimensionLabel,
|
|
65
65
|
getUsageGroupLabel: () => getUsageGroupLabel,
|
|
66
|
+
getUsageMetricLabel: () => getUsageMetricLabel,
|
|
66
67
|
getUsageRange: () => getUsageRange,
|
|
67
68
|
getUsageTotalValue: () => getUsageTotalValue,
|
|
68
69
|
mergeAdminConfig: () => mergeAdminConfig,
|
|
@@ -158,6 +159,21 @@ function normalizeMessagePage(payload) {
|
|
|
158
159
|
const pageInfo = isRecord(candidate) ? normalizeMessagePageInfo(candidate.pageInfo, data) : normalizeMessagePageInfo(void 0, data);
|
|
159
160
|
return { data, pageInfo };
|
|
160
161
|
}
|
|
162
|
+
function isQueueEvent(value) {
|
|
163
|
+
return isRecord(value) && typeof value.id === "string" && typeof value.threadId === "string" && typeof value.eventType === "string";
|
|
164
|
+
}
|
|
165
|
+
function normalizeQueueEvent(value) {
|
|
166
|
+
if (isQueueEvent(value)) return value;
|
|
167
|
+
if (isRecord(value) && isQueueEvent(value.data)) return value.data;
|
|
168
|
+
return void 0;
|
|
169
|
+
}
|
|
170
|
+
function normalizeQueueEvents(value) {
|
|
171
|
+
if (Array.isArray(value)) return value.filter(isQueueEvent);
|
|
172
|
+
if (isRecord(value) && Array.isArray(value.data)) {
|
|
173
|
+
return value.data.filter(isQueueEvent);
|
|
174
|
+
}
|
|
175
|
+
return [];
|
|
176
|
+
}
|
|
161
177
|
function createAdminClient(options = {}) {
|
|
162
178
|
const baseUrl = resolveBaseUrl(options.baseUrl);
|
|
163
179
|
const paths = { ...DEFAULT_PATHS, ...options.paths };
|
|
@@ -217,12 +233,16 @@ function createAdminClient(options = {}) {
|
|
|
217
233
|
metric: filters.metric,
|
|
218
234
|
groupBy: filters.groupBy,
|
|
219
235
|
attribution: filters.attribution,
|
|
236
|
+
kind: filters.kind,
|
|
220
237
|
threadId: filters.threadId,
|
|
221
238
|
participantId: filters.participantId,
|
|
222
239
|
participantType: filters.participantType,
|
|
223
240
|
namespace: filters.namespace,
|
|
224
241
|
provider: filters.provider,
|
|
225
|
-
model: filters.model
|
|
242
|
+
model: filters.model,
|
|
243
|
+
resource: filters.resource,
|
|
244
|
+
operation: filters.operation,
|
|
245
|
+
status: filters.status
|
|
226
246
|
}),
|
|
227
247
|
listThreads: async (listOptions = {}) => await requestJson(`${paths.adminBase}/threads`, {
|
|
228
248
|
search: listOptions.search,
|
|
@@ -260,9 +280,25 @@ function createAdminClient(options = {}) {
|
|
|
260
280
|
);
|
|
261
281
|
return normalizeMessagePage(payload);
|
|
262
282
|
},
|
|
263
|
-
|
|
264
|
-
`${paths.
|
|
265
|
-
|
|
283
|
+
listEvents: async (eventOptions = {}) => {
|
|
284
|
+
const payload = await requestJson(`${paths.adminBase}/events`, {
|
|
285
|
+
namespace: eventOptions.namespace,
|
|
286
|
+
threadId: eventOptions.threadId,
|
|
287
|
+
status: eventOptions.status,
|
|
288
|
+
eventType: eventOptions.eventType,
|
|
289
|
+
traceId: eventOptions.traceId,
|
|
290
|
+
search: eventOptions.search,
|
|
291
|
+
limit: String(eventOptions.limit ?? 50),
|
|
292
|
+
offset: eventOptions.offset ? String(eventOptions.offset) : void 0
|
|
293
|
+
});
|
|
294
|
+
return normalizeQueueEvents(payload);
|
|
295
|
+
},
|
|
296
|
+
getThreadEvent: async (threadId) => {
|
|
297
|
+
const payload = await requestJson(
|
|
298
|
+
`${paths.threadsBase}/${encodeURIComponent(threadId)}/events`
|
|
299
|
+
);
|
|
300
|
+
return normalizeQueueEvent(payload);
|
|
301
|
+
},
|
|
266
302
|
listCollections: async () => await requestJson(paths.collectionsBase),
|
|
267
303
|
listCollectionItems: async (collection, listOptions = {}) => await requestJson(
|
|
268
304
|
`${paths.collectionsBase}/${encodeURIComponent(collection)}`,
|
|
@@ -1469,7 +1505,11 @@ var EMPTY_USAGE_TOTALS = {
|
|
|
1469
1505
|
reasoningTokens: 0,
|
|
1470
1506
|
totalCalls: 0,
|
|
1471
1507
|
totalCostUsd: 0,
|
|
1472
|
-
|
|
1508
|
+
failedCalls: 0,
|
|
1509
|
+
totalCredits: 0,
|
|
1510
|
+
totalDurationMs: 0,
|
|
1511
|
+
totalTokens: 0,
|
|
1512
|
+
unpricedCalls: 0
|
|
1473
1513
|
};
|
|
1474
1514
|
var USAGE_CHART_COLORS = [
|
|
1475
1515
|
"hsl(var(--primary))",
|
|
@@ -1480,53 +1520,66 @@ var USAGE_CHART_COLORS = [
|
|
|
1480
1520
|
"hsl(var(--muted-foreground))"
|
|
1481
1521
|
];
|
|
1482
1522
|
function addUsageTotals(target, source) {
|
|
1483
|
-
target.cacheCreationInputCostUsd += source.cacheCreationInputCostUsd;
|
|
1484
|
-
target.cacheCreationInputTokens += source.cacheCreationInputTokens;
|
|
1485
|
-
target.cacheReadInputCostUsd += source.cacheReadInputCostUsd;
|
|
1486
|
-
target.cacheReadInputTokens += source.cacheReadInputTokens;
|
|
1487
|
-
target.inputCostUsd += source.inputCostUsd;
|
|
1488
|
-
target.inputTokens += source.inputTokens;
|
|
1489
|
-
target.outputCostUsd += source.outputCostUsd;
|
|
1490
|
-
target.outputTokens += source.outputTokens;
|
|
1491
|
-
target.reasoningCostUsd += source.reasoningCostUsd;
|
|
1492
|
-
target.reasoningTokens += source.reasoningTokens;
|
|
1493
|
-
target.totalCalls += source.totalCalls;
|
|
1494
|
-
target.totalCostUsd += source.totalCostUsd;
|
|
1495
|
-
target.
|
|
1523
|
+
target.cacheCreationInputCostUsd += safeUsageNumber(source.cacheCreationInputCostUsd);
|
|
1524
|
+
target.cacheCreationInputTokens += safeUsageNumber(source.cacheCreationInputTokens);
|
|
1525
|
+
target.cacheReadInputCostUsd += safeUsageNumber(source.cacheReadInputCostUsd);
|
|
1526
|
+
target.cacheReadInputTokens += safeUsageNumber(source.cacheReadInputTokens);
|
|
1527
|
+
target.inputCostUsd += safeUsageNumber(source.inputCostUsd);
|
|
1528
|
+
target.inputTokens += safeUsageNumber(source.inputTokens);
|
|
1529
|
+
target.outputCostUsd += safeUsageNumber(source.outputCostUsd);
|
|
1530
|
+
target.outputTokens += safeUsageNumber(source.outputTokens);
|
|
1531
|
+
target.reasoningCostUsd += safeUsageNumber(source.reasoningCostUsd);
|
|
1532
|
+
target.reasoningTokens += safeUsageNumber(source.reasoningTokens);
|
|
1533
|
+
target.totalCalls += safeUsageNumber(source.totalCalls);
|
|
1534
|
+
target.totalCostUsd += safeUsageNumber(source.totalCostUsd);
|
|
1535
|
+
target.failedCalls += safeUsageNumber(source.failedCalls);
|
|
1536
|
+
target.totalCredits += safeUsageNumber(source.totalCredits);
|
|
1537
|
+
target.totalDurationMs += safeUsageNumber(source.totalDurationMs);
|
|
1538
|
+
target.totalTokens += safeUsageNumber(source.totalTokens);
|
|
1539
|
+
target.unpricedCalls += safeUsageNumber(source.unpricedCalls);
|
|
1540
|
+
}
|
|
1541
|
+
function safeUsageNumber(value) {
|
|
1542
|
+
return typeof value === "number" && Number.isFinite(value) ? value : 0;
|
|
1496
1543
|
}
|
|
1497
1544
|
function getUsageTotalValue(totals, metricKind, dimension) {
|
|
1498
|
-
if (metricKind === "calls") return totals.totalCalls;
|
|
1545
|
+
if (metricKind === "calls") return safeUsageNumber(totals.totalCalls);
|
|
1546
|
+
if (metricKind === "duration") {
|
|
1547
|
+
return safeUsageNumber(totals.totalDurationMs);
|
|
1548
|
+
}
|
|
1549
|
+
if (metricKind === "credits") return safeUsageNumber(totals.totalCredits);
|
|
1550
|
+
if (metricKind === "failures") return safeUsageNumber(totals.failedCalls);
|
|
1551
|
+
if (metricKind === "unpriced") return safeUsageNumber(totals.unpricedCalls);
|
|
1499
1552
|
if (metricKind === "cost") {
|
|
1500
1553
|
switch (dimension) {
|
|
1501
1554
|
case "input":
|
|
1502
|
-
return totals.inputCostUsd;
|
|
1555
|
+
return safeUsageNumber(totals.inputCostUsd);
|
|
1503
1556
|
case "output":
|
|
1504
|
-
return totals.outputCostUsd;
|
|
1557
|
+
return safeUsageNumber(totals.outputCostUsd);
|
|
1505
1558
|
case "reasoning":
|
|
1506
|
-
return totals.reasoningCostUsd;
|
|
1559
|
+
return safeUsageNumber(totals.reasoningCostUsd);
|
|
1507
1560
|
case "cacheRead":
|
|
1508
|
-
return totals.cacheReadInputCostUsd;
|
|
1561
|
+
return safeUsageNumber(totals.cacheReadInputCostUsd);
|
|
1509
1562
|
case "cacheWrite":
|
|
1510
|
-
return totals.cacheCreationInputCostUsd;
|
|
1563
|
+
return safeUsageNumber(totals.cacheCreationInputCostUsd);
|
|
1511
1564
|
case "total":
|
|
1512
1565
|
default:
|
|
1513
|
-
return totals.totalCostUsd;
|
|
1566
|
+
return safeUsageNumber(totals.totalCostUsd);
|
|
1514
1567
|
}
|
|
1515
1568
|
}
|
|
1516
1569
|
switch (dimension) {
|
|
1517
1570
|
case "input":
|
|
1518
|
-
return totals.inputTokens;
|
|
1571
|
+
return safeUsageNumber(totals.inputTokens);
|
|
1519
1572
|
case "output":
|
|
1520
|
-
return totals.outputTokens;
|
|
1573
|
+
return safeUsageNumber(totals.outputTokens);
|
|
1521
1574
|
case "reasoning":
|
|
1522
|
-
return totals.reasoningTokens;
|
|
1575
|
+
return safeUsageNumber(totals.reasoningTokens);
|
|
1523
1576
|
case "cacheRead":
|
|
1524
|
-
return totals.cacheReadInputTokens;
|
|
1577
|
+
return safeUsageNumber(totals.cacheReadInputTokens);
|
|
1525
1578
|
case "cacheWrite":
|
|
1526
|
-
return totals.cacheCreationInputTokens;
|
|
1579
|
+
return safeUsageNumber(totals.cacheCreationInputTokens);
|
|
1527
1580
|
case "total":
|
|
1528
1581
|
default:
|
|
1529
|
-
return totals.totalTokens;
|
|
1582
|
+
return safeUsageNumber(totals.totalTokens);
|
|
1530
1583
|
}
|
|
1531
1584
|
}
|
|
1532
1585
|
function aggregateUsageRows(points, metricKind, dimension) {
|
|
@@ -1638,6 +1691,14 @@ function getUsageDimensionLabel(dimension) {
|
|
|
1638
1691
|
}
|
|
1639
1692
|
function getUsageGroupLabel(groupBy) {
|
|
1640
1693
|
switch (groupBy) {
|
|
1694
|
+
case "kind":
|
|
1695
|
+
return "Kind";
|
|
1696
|
+
case "resource":
|
|
1697
|
+
return "Resource";
|
|
1698
|
+
case "operation":
|
|
1699
|
+
return "Operation";
|
|
1700
|
+
case "status":
|
|
1701
|
+
return "Status";
|
|
1641
1702
|
case "thread":
|
|
1642
1703
|
return "Thread";
|
|
1643
1704
|
case "namespace":
|
|
@@ -1651,6 +1712,25 @@ function getUsageGroupLabel(groupBy) {
|
|
|
1651
1712
|
return "Participant";
|
|
1652
1713
|
}
|
|
1653
1714
|
}
|
|
1715
|
+
function getUsageMetricLabel(metricKind) {
|
|
1716
|
+
switch (metricKind) {
|
|
1717
|
+
case "cost":
|
|
1718
|
+
return "Spend";
|
|
1719
|
+
case "tokens":
|
|
1720
|
+
return "Tokens";
|
|
1721
|
+
case "duration":
|
|
1722
|
+
return "Duration";
|
|
1723
|
+
case "credits":
|
|
1724
|
+
return "Credits";
|
|
1725
|
+
case "failures":
|
|
1726
|
+
return "Failures";
|
|
1727
|
+
case "unpriced":
|
|
1728
|
+
return "Unpriced";
|
|
1729
|
+
case "calls":
|
|
1730
|
+
default:
|
|
1731
|
+
return "Calls";
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1654
1734
|
function formatUsageBucket(bucket, interval) {
|
|
1655
1735
|
const date = new Date(bucket);
|
|
1656
1736
|
if (Number.isNaN(date.getTime())) return bucket;
|
|
@@ -1693,6 +1773,9 @@ function formatMetricValue(value, metricKind) {
|
|
|
1693
1773
|
style: "currency"
|
|
1694
1774
|
}).format(value);
|
|
1695
1775
|
}
|
|
1776
|
+
if (metricKind === "duration") {
|
|
1777
|
+
return formatDuration(value);
|
|
1778
|
+
}
|
|
1696
1779
|
return formatNumber(value);
|
|
1697
1780
|
}
|
|
1698
1781
|
function formatCompactMetric(value, metricKind) {
|
|
@@ -1705,12 +1788,30 @@ function formatCompactMetric(value, metricKind) {
|
|
|
1705
1788
|
style: "currency"
|
|
1706
1789
|
}).format(value);
|
|
1707
1790
|
}
|
|
1791
|
+
if (metricKind === "duration") {
|
|
1792
|
+
if (value >= 36e5) return `${(value / 36e5).toFixed(1)}h`;
|
|
1793
|
+
if (value >= 6e4) return `${(value / 6e4).toFixed(1)}m`;
|
|
1794
|
+
if (value >= 1e3) return `${(value / 1e3).toFixed(1)}s`;
|
|
1795
|
+
return `${Math.round(value)}ms`;
|
|
1796
|
+
}
|
|
1708
1797
|
return new Intl.NumberFormat(void 0, {
|
|
1709
1798
|
compactDisplay: "short",
|
|
1710
1799
|
maximumFractionDigits: 1,
|
|
1711
1800
|
notation: "compact"
|
|
1712
1801
|
}).format(value);
|
|
1713
1802
|
}
|
|
1803
|
+
function formatDuration(value) {
|
|
1804
|
+
if (value >= 36e5) {
|
|
1805
|
+
return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 1 }).format(value / 36e5)} h`;
|
|
1806
|
+
}
|
|
1807
|
+
if (value >= 6e4) {
|
|
1808
|
+
return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 1 }).format(value / 6e4)} min`;
|
|
1809
|
+
}
|
|
1810
|
+
if (value >= 1e3) {
|
|
1811
|
+
return `${new Intl.NumberFormat(void 0, { maximumFractionDigits: 1 }).format(value / 1e3)} sec`;
|
|
1812
|
+
}
|
|
1813
|
+
return `${formatNumber(Math.round(value))} ms`;
|
|
1814
|
+
}
|
|
1714
1815
|
|
|
1715
1816
|
// src/modules/agents/index.tsx
|
|
1716
1817
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
@@ -2188,33 +2289,61 @@ function eventsModule() {
|
|
|
2188
2289
|
}]
|
|
2189
2290
|
};
|
|
2190
2291
|
}
|
|
2292
|
+
var EVENT_STATUSES = [
|
|
2293
|
+
"all",
|
|
2294
|
+
"pending",
|
|
2295
|
+
"processing",
|
|
2296
|
+
"completed",
|
|
2297
|
+
"failed",
|
|
2298
|
+
"expired",
|
|
2299
|
+
"overwritten"
|
|
2300
|
+
];
|
|
2191
2301
|
function EventsPage({ context }) {
|
|
2192
2302
|
const [threadId, setThreadId] = import_react4.default.useState("");
|
|
2193
|
-
const [status, setStatus] = import_react4.default.useState(
|
|
2194
|
-
|
|
2303
|
+
const [status, setStatus] = import_react4.default.useState(
|
|
2304
|
+
"all"
|
|
2305
|
+
);
|
|
2306
|
+
const [eventType, setEventType] = import_react4.default.useState("");
|
|
2195
2307
|
const [traceId, setTraceId] = import_react4.default.useState("");
|
|
2196
|
-
const [
|
|
2308
|
+
const [events, setEvents] = import_react4.default.useState([]);
|
|
2309
|
+
const [selectedEvent, setSelectedEvent] = import_react4.default.useState(null);
|
|
2197
2310
|
const [error, setError] = import_react4.default.useState(null);
|
|
2198
|
-
const [
|
|
2311
|
+
const [loading, setLoading] = import_react4.default.useState(false);
|
|
2312
|
+
const [hasLoaded, setHasLoaded] = import_react4.default.useState(false);
|
|
2199
2313
|
const inspect = async () => {
|
|
2200
|
-
|
|
2201
|
-
|
|
2314
|
+
setHasLoaded(true);
|
|
2315
|
+
setLoading(true);
|
|
2202
2316
|
setError(null);
|
|
2203
2317
|
try {
|
|
2204
|
-
const next = await context.client.
|
|
2205
|
-
|
|
2318
|
+
const next = await context.client.listEvents({
|
|
2319
|
+
namespace: context.scope.namespace || void 0,
|
|
2320
|
+
threadId: threadId.trim() || void 0,
|
|
2321
|
+
status: status === "all" ? void 0 : status,
|
|
2322
|
+
eventType: eventType.trim() || void 0,
|
|
2323
|
+
traceId: traceId.trim() || void 0,
|
|
2324
|
+
limit: 50
|
|
2325
|
+
});
|
|
2326
|
+
setEvents(next);
|
|
2327
|
+
setSelectedEvent(
|
|
2328
|
+
(current) => current && next.some((event) => event.id === current.id) ? current : next[0] ?? null
|
|
2329
|
+
);
|
|
2206
2330
|
} catch (cause) {
|
|
2207
2331
|
setError(cause instanceof Error ? cause.message : "Failed to load event");
|
|
2208
|
-
|
|
2332
|
+
setEvents([]);
|
|
2333
|
+
setSelectedEvent(null);
|
|
2334
|
+
} finally {
|
|
2335
|
+
setLoading(false);
|
|
2209
2336
|
}
|
|
2210
2337
|
};
|
|
2211
|
-
|
|
2338
|
+
import_react4.default.useEffect(() => {
|
|
2339
|
+
void inspect();
|
|
2340
|
+
}, [context.client, context.refreshKey, context.scope.namespace]);
|
|
2212
2341
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "space-y-4", children: [
|
|
2213
2342
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2214
2343
|
PageHeader,
|
|
2215
2344
|
{
|
|
2216
2345
|
title: "Events",
|
|
2217
|
-
description: "Queue and event inspection
|
|
2346
|
+
description: "Queue and event inspection across the active namespace."
|
|
2218
2347
|
}
|
|
2219
2348
|
),
|
|
2220
2349
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
@@ -2223,13 +2352,13 @@ function EventsPage({ context }) {
|
|
|
2223
2352
|
actions: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2224
2353
|
Button,
|
|
2225
2354
|
{
|
|
2226
|
-
disabled:
|
|
2355
|
+
disabled: loading,
|
|
2227
2356
|
onClick: () => void inspect(),
|
|
2228
2357
|
size: "sm",
|
|
2229
2358
|
type: "button",
|
|
2230
2359
|
children: [
|
|
2231
2360
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react8.Search, { className: "size-3" }),
|
|
2232
|
-
"Inspect"
|
|
2361
|
+
loading ? "Loading" : "Inspect"
|
|
2233
2362
|
]
|
|
2234
2363
|
}
|
|
2235
2364
|
),
|
|
@@ -2238,37 +2367,45 @@ function EventsPage({ context }) {
|
|
|
2238
2367
|
Input,
|
|
2239
2368
|
{
|
|
2240
2369
|
className: "h-8 w-[220px]",
|
|
2241
|
-
onChange: (
|
|
2242
|
-
onKeyDown: (
|
|
2243
|
-
if (
|
|
2370
|
+
onChange: (event) => setThreadId(event.target.value),
|
|
2371
|
+
onKeyDown: (event) => {
|
|
2372
|
+
if (event.key === "Enter") void inspect();
|
|
2244
2373
|
},
|
|
2245
2374
|
placeholder: "Thread ID",
|
|
2246
2375
|
value: threadId
|
|
2247
2376
|
}
|
|
2248
2377
|
),
|
|
2249
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.
|
|
2250
|
-
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
2379
|
+
Select,
|
|
2251
2380
|
{
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2381
|
+
value: status,
|
|
2382
|
+
onValueChange: (value) => setStatus(value),
|
|
2383
|
+
children: [
|
|
2384
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectTrigger, { className: "h-8 w-[150px] text-xs", "aria-label": "Status", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectValue, {}) }),
|
|
2385
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectContent, { children: EVENT_STATUSES.map((option) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectItem, { value: option, children: option === "all" ? "All statuses" : option }, option)) })
|
|
2386
|
+
]
|
|
2256
2387
|
}
|
|
2257
2388
|
),
|
|
2258
2389
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2259
2390
|
Input,
|
|
2260
2391
|
{
|
|
2261
2392
|
className: "h-8 w-[180px]",
|
|
2262
|
-
onChange: (
|
|
2393
|
+
onChange: (event) => setEventType(event.target.value),
|
|
2394
|
+
onKeyDown: (event) => {
|
|
2395
|
+
if (event.key === "Enter") void inspect();
|
|
2396
|
+
},
|
|
2263
2397
|
placeholder: "Event type",
|
|
2264
|
-
value:
|
|
2398
|
+
value: eventType
|
|
2265
2399
|
}
|
|
2266
2400
|
),
|
|
2267
2401
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2268
2402
|
Input,
|
|
2269
2403
|
{
|
|
2270
2404
|
className: "h-8 w-[180px]",
|
|
2271
|
-
onChange: (
|
|
2405
|
+
onChange: (event) => setTraceId(event.target.value),
|
|
2406
|
+
onKeyDown: (event) => {
|
|
2407
|
+
if (event.key === "Enter") void inspect();
|
|
2408
|
+
},
|
|
2272
2409
|
placeholder: "Trace ID",
|
|
2273
2410
|
value: traceId
|
|
2274
2411
|
}
|
|
@@ -2276,27 +2413,34 @@ function EventsPage({ context }) {
|
|
|
2276
2413
|
]
|
|
2277
2414
|
}
|
|
2278
2415
|
),
|
|
2279
|
-
error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !
|
|
2416
|
+
error ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(EmptyState, { title: "Unable to inspect event", description: error }) : !hasLoaded && loading ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2280
2417
|
EmptyState,
|
|
2281
2418
|
{
|
|
2282
2419
|
icon: import_lucide_react8.Activity,
|
|
2283
|
-
title: "
|
|
2284
|
-
description: "
|
|
2420
|
+
title: "Loading events",
|
|
2421
|
+
description: "Fetching recent queue events for the active namespace."
|
|
2285
2422
|
}
|
|
2286
2423
|
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "grid gap-4 xl:grid-cols-[1fr_420px]", children: [
|
|
2287
2424
|
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2288
2425
|
ResourceTable,
|
|
2289
2426
|
{
|
|
2290
|
-
rows,
|
|
2427
|
+
rows: events,
|
|
2291
2428
|
getRowKey: (row) => row.id,
|
|
2429
|
+
onRowClick: setSelectedEvent,
|
|
2292
2430
|
empty: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2293
2431
|
EmptyState,
|
|
2294
2432
|
{
|
|
2295
|
-
title: "No matching
|
|
2296
|
-
description: "No
|
|
2433
|
+
title: "No matching events",
|
|
2434
|
+
description: "No event rows matched the current filters."
|
|
2297
2435
|
}
|
|
2298
2436
|
),
|
|
2299
2437
|
columns: [
|
|
2438
|
+
{
|
|
2439
|
+
id: "thread",
|
|
2440
|
+
header: "Thread",
|
|
2441
|
+
className: "max-w-[180px] truncate font-mono text-xs",
|
|
2442
|
+
render: (row) => row.threadId
|
|
2443
|
+
},
|
|
2300
2444
|
{
|
|
2301
2445
|
id: "type",
|
|
2302
2446
|
header: "Type",
|
|
@@ -2320,7 +2464,20 @@ function EventsPage({ context }) {
|
|
|
2320
2464
|
]
|
|
2321
2465
|
}
|
|
2322
2466
|
),
|
|
2323
|
-
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2467
|
+
selectedEvent ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2468
|
+
JsonPanel,
|
|
2469
|
+
{
|
|
2470
|
+
title: "Event JSON",
|
|
2471
|
+
value: selectedEvent,
|
|
2472
|
+
minHeight: 420
|
|
2473
|
+
}
|
|
2474
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
2475
|
+
EmptyState,
|
|
2476
|
+
{
|
|
2477
|
+
title: "No event selected",
|
|
2478
|
+
description: "Select an event row to inspect its payload."
|
|
2479
|
+
}
|
|
2480
|
+
)
|
|
2324
2481
|
] })
|
|
2325
2482
|
] });
|
|
2326
2483
|
}
|
|
@@ -3138,6 +3295,22 @@ var USAGE_DIMENSIONS = [
|
|
|
3138
3295
|
"cacheRead",
|
|
3139
3296
|
"cacheWrite"
|
|
3140
3297
|
];
|
|
3298
|
+
var USAGE_WORKLOADS = [
|
|
3299
|
+
"all",
|
|
3300
|
+
"llm",
|
|
3301
|
+
"tool",
|
|
3302
|
+
"asset",
|
|
3303
|
+
"rag",
|
|
3304
|
+
"embedding"
|
|
3305
|
+
];
|
|
3306
|
+
var STATUS_OPTIONS = [
|
|
3307
|
+
"all",
|
|
3308
|
+
"completed",
|
|
3309
|
+
"failed",
|
|
3310
|
+
"cancelled",
|
|
3311
|
+
"aborted",
|
|
3312
|
+
"error"
|
|
3313
|
+
];
|
|
3141
3314
|
function usageModule() {
|
|
3142
3315
|
return {
|
|
3143
3316
|
group: "operate",
|
|
@@ -3164,11 +3337,12 @@ function UsagePage({ context }) {
|
|
|
3164
3337
|
"7d"
|
|
3165
3338
|
);
|
|
3166
3339
|
const [interval, setInterval] = import_react8.default.useState("day");
|
|
3340
|
+
const [workload, setWorkload] = import_react8.default.useState("all");
|
|
3167
3341
|
const [metricKind, setMetricKind] = import_react8.default.useState(
|
|
3168
|
-
"
|
|
3342
|
+
"calls"
|
|
3169
3343
|
);
|
|
3170
3344
|
const [dimension, setDimension] = import_react8.default.useState("total");
|
|
3171
|
-
const [groupBy, setGroupBy] = import_react8.default.useState("
|
|
3345
|
+
const [groupBy, setGroupBy] = import_react8.default.useState("kind");
|
|
3172
3346
|
const [attribution, setAttribution] = import_react8.default.useState(
|
|
3173
3347
|
"initiatedBy"
|
|
3174
3348
|
);
|
|
@@ -3177,6 +3351,11 @@ function UsagePage({ context }) {
|
|
|
3177
3351
|
const [participantId, setParticipantId] = import_react8.default.useState("");
|
|
3178
3352
|
const [provider, setProvider] = import_react8.default.useState("");
|
|
3179
3353
|
const [model, setModel] = import_react8.default.useState("");
|
|
3354
|
+
const [resource, setResource] = import_react8.default.useState("");
|
|
3355
|
+
const [operation, setOperation] = import_react8.default.useState("");
|
|
3356
|
+
const [status, setStatus] = import_react8.default.useState(
|
|
3357
|
+
"all"
|
|
3358
|
+
);
|
|
3180
3359
|
const [customFrom, setCustomFrom] = import_react8.default.useState("");
|
|
3181
3360
|
const [customTo, setCustomTo] = import_react8.default.useState("");
|
|
3182
3361
|
const [usage, setUsage] = import_react8.default.useState(null);
|
|
@@ -3186,6 +3365,32 @@ function UsagePage({ context }) {
|
|
|
3186
3365
|
() => getUsageRange(period, customFrom, customTo),
|
|
3187
3366
|
[customFrom, customTo, period]
|
|
3188
3367
|
);
|
|
3368
|
+
const metricOptions = import_react8.default.useMemo(
|
|
3369
|
+
() => getUsageMetricOptions(workload),
|
|
3370
|
+
[workload]
|
|
3371
|
+
);
|
|
3372
|
+
const groupOptions = import_react8.default.useMemo(
|
|
3373
|
+
() => getUsageGroupOptions(workload),
|
|
3374
|
+
[workload]
|
|
3375
|
+
);
|
|
3376
|
+
const showLlmFields = workload === "llm";
|
|
3377
|
+
const showResourceFields = workload !== "llm";
|
|
3378
|
+
const showDimension = metricKind === "tokens" || metricKind === "cost" && workload === "llm";
|
|
3379
|
+
import_react8.default.useEffect(() => {
|
|
3380
|
+
if (!metricOptions.includes(metricKind)) {
|
|
3381
|
+
setMetricKind(metricOptions[0]);
|
|
3382
|
+
}
|
|
3383
|
+
}, [metricKind, metricOptions]);
|
|
3384
|
+
import_react8.default.useEffect(() => {
|
|
3385
|
+
if (!groupOptions.includes(groupBy)) {
|
|
3386
|
+
setGroupBy(groupOptions[0]);
|
|
3387
|
+
}
|
|
3388
|
+
}, [groupBy, groupOptions]);
|
|
3389
|
+
import_react8.default.useEffect(() => {
|
|
3390
|
+
if (!showDimension && dimension !== "total") {
|
|
3391
|
+
setDimension("total");
|
|
3392
|
+
}
|
|
3393
|
+
}, [dimension, showDimension]);
|
|
3189
3394
|
import_react8.default.useEffect(() => {
|
|
3190
3395
|
let active = true;
|
|
3191
3396
|
setIsLoading(true);
|
|
@@ -3194,13 +3399,17 @@ function UsagePage({ context }) {
|
|
|
3194
3399
|
attribution,
|
|
3195
3400
|
from: range.from,
|
|
3196
3401
|
groupBy,
|
|
3402
|
+
kind: workload,
|
|
3197
3403
|
interval,
|
|
3198
3404
|
metric: metricKind,
|
|
3199
|
-
model: emptyToUndefined(model),
|
|
3405
|
+
model: showLlmFields ? emptyToUndefined(model) : void 0,
|
|
3200
3406
|
namespace: context.scope.namespace || void 0,
|
|
3407
|
+
operation: showResourceFields ? emptyToUndefined(operation) : void 0,
|
|
3201
3408
|
participantId: emptyToUndefined(participantId),
|
|
3202
3409
|
participantType,
|
|
3203
|
-
provider: emptyToUndefined(provider),
|
|
3410
|
+
provider: showLlmFields ? emptyToUndefined(provider) : void 0,
|
|
3411
|
+
resource: showResourceFields ? emptyToUndefined(resource) : void 0,
|
|
3412
|
+
status: status === "all" ? void 0 : status,
|
|
3204
3413
|
threadId: emptyToUndefined(threadId),
|
|
3205
3414
|
to: range.to
|
|
3206
3415
|
}).then((next) => {
|
|
@@ -3225,12 +3434,18 @@ function UsagePage({ context }) {
|
|
|
3225
3434
|
interval,
|
|
3226
3435
|
metricKind,
|
|
3227
3436
|
model,
|
|
3437
|
+
operation,
|
|
3228
3438
|
participantId,
|
|
3229
3439
|
participantType,
|
|
3230
3440
|
provider,
|
|
3231
3441
|
range.from,
|
|
3232
3442
|
range.to,
|
|
3233
|
-
|
|
3443
|
+
resource,
|
|
3444
|
+
showLlmFields,
|
|
3445
|
+
showResourceFields,
|
|
3446
|
+
status,
|
|
3447
|
+
threadId,
|
|
3448
|
+
workload
|
|
3234
3449
|
]);
|
|
3235
3450
|
const points = usage?.points ?? [];
|
|
3236
3451
|
const totals = usage?.totals ?? EMPTY_USAGE_TOTALS;
|
|
@@ -3247,9 +3462,10 @@ function UsagePage({ context }) {
|
|
|
3247
3462
|
PageHeader,
|
|
3248
3463
|
{
|
|
3249
3464
|
title: "Usage",
|
|
3250
|
-
description: "Inspect
|
|
3465
|
+
description: "Inspect metered LLM, tool, and resource activity by workload, actor, status, cost, duration, tokens, and credits.",
|
|
3251
3466
|
badges: [
|
|
3252
|
-
{ label:
|
|
3467
|
+
{ label: workload },
|
|
3468
|
+
{ label: getUsageMetricLabel(metricKind), variant: "secondary" },
|
|
3253
3469
|
{ label: getUsageGroupLabel(groupBy), variant: "secondary" },
|
|
3254
3470
|
...isLoading ? [{ label: "Loading" }] : []
|
|
3255
3471
|
]
|
|
@@ -3277,10 +3493,21 @@ function UsagePage({ context }) {
|
|
|
3277
3493
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3278
3494
|
UsageSelect,
|
|
3279
3495
|
{
|
|
3280
|
-
label: "
|
|
3496
|
+
label: "Workload",
|
|
3497
|
+
onValueChange: (value) => setWorkload(value),
|
|
3498
|
+
options: USAGE_WORKLOADS,
|
|
3499
|
+
value: workload,
|
|
3500
|
+
formatOption: getUsageKindLabel
|
|
3501
|
+
}
|
|
3502
|
+
),
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3504
|
+
UsageSelect,
|
|
3505
|
+
{
|
|
3506
|
+
label: "Measure",
|
|
3281
3507
|
onValueChange: (value) => setMetricKind(value),
|
|
3282
|
-
options:
|
|
3283
|
-
value: metricKind
|
|
3508
|
+
options: metricOptions,
|
|
3509
|
+
value: metricKind,
|
|
3510
|
+
formatOption: getUsageMetricLabel
|
|
3284
3511
|
}
|
|
3285
3512
|
),
|
|
3286
3513
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
@@ -3288,20 +3515,22 @@ function UsagePage({ context }) {
|
|
|
3288
3515
|
{
|
|
3289
3516
|
label: "Group",
|
|
3290
3517
|
onValueChange: (value) => setGroupBy(value),
|
|
3291
|
-
options:
|
|
3292
|
-
value: groupBy
|
|
3518
|
+
options: groupOptions,
|
|
3519
|
+
value: groupBy,
|
|
3520
|
+
formatOption: getUsageGroupLabel
|
|
3293
3521
|
}
|
|
3294
3522
|
),
|
|
3295
3523
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3296
3524
|
UsageSelect,
|
|
3297
3525
|
{
|
|
3298
|
-
label: "
|
|
3526
|
+
label: "Actor",
|
|
3299
3527
|
onValueChange: (value) => setAttribution(value),
|
|
3300
3528
|
options: ["initiatedBy", "generatedBy"],
|
|
3301
|
-
value: attribution
|
|
3529
|
+
value: attribution,
|
|
3530
|
+
formatOption: getUsageAttributionLabel
|
|
3302
3531
|
}
|
|
3303
3532
|
),
|
|
3304
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3533
|
+
showDimension && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3305
3534
|
UsageSelect,
|
|
3306
3535
|
{
|
|
3307
3536
|
label: "Dimension",
|
|
@@ -3336,12 +3565,21 @@ function UsagePage({ context }) {
|
|
|
3336
3565
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3337
3566
|
UsageSelect,
|
|
3338
3567
|
{
|
|
3339
|
-
label: "
|
|
3568
|
+
label: "Actor type",
|
|
3340
3569
|
onValueChange: (value) => setParticipantType(value),
|
|
3341
3570
|
options: ["all", "human", "agent", "job"],
|
|
3342
3571
|
value: participantType
|
|
3343
3572
|
}
|
|
3344
3573
|
),
|
|
3574
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3575
|
+
UsageSelect,
|
|
3576
|
+
{
|
|
3577
|
+
label: "Status",
|
|
3578
|
+
onValueChange: (value) => setStatus(value),
|
|
3579
|
+
options: STATUS_OPTIONS,
|
|
3580
|
+
value: status
|
|
3581
|
+
}
|
|
3582
|
+
),
|
|
3345
3583
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3346
3584
|
Input,
|
|
3347
3585
|
{
|
|
@@ -3360,46 +3598,86 @@ function UsagePage({ context }) {
|
|
|
3360
3598
|
value: participantId
|
|
3361
3599
|
}
|
|
3362
3600
|
),
|
|
3363
|
-
/* @__PURE__ */ (0, import_jsx_runtime27.
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3601
|
+
showResourceFields && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
3602
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3603
|
+
Input,
|
|
3604
|
+
{
|
|
3605
|
+
className: "h-8 w-[170px]",
|
|
3606
|
+
onChange: (event) => setResource(event.target.value),
|
|
3607
|
+
placeholder: "Resource / tool",
|
|
3608
|
+
value: resource
|
|
3609
|
+
}
|
|
3610
|
+
),
|
|
3611
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3612
|
+
Input,
|
|
3613
|
+
{
|
|
3614
|
+
className: "h-8 w-[150px]",
|
|
3615
|
+
onChange: (event) => setOperation(event.target.value),
|
|
3616
|
+
placeholder: "Operation",
|
|
3617
|
+
value: operation
|
|
3618
|
+
}
|
|
3619
|
+
)
|
|
3620
|
+
] }),
|
|
3621
|
+
showLlmFields && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
3622
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3623
|
+
Input,
|
|
3624
|
+
{
|
|
3625
|
+
className: "h-8 w-[140px]",
|
|
3626
|
+
onChange: (event) => setProvider(event.target.value),
|
|
3627
|
+
placeholder: "Provider",
|
|
3628
|
+
value: provider
|
|
3629
|
+
}
|
|
3630
|
+
),
|
|
3631
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3632
|
+
Input,
|
|
3633
|
+
{
|
|
3634
|
+
className: "h-8 w-[140px]",
|
|
3635
|
+
onChange: (event) => setModel(event.target.value),
|
|
3636
|
+
placeholder: "Model",
|
|
3637
|
+
value: model
|
|
3638
|
+
}
|
|
3639
|
+
)
|
|
3640
|
+
] })
|
|
3381
3641
|
] }),
|
|
3382
3642
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3383
3643
|
MetricStrip,
|
|
3384
3644
|
{
|
|
3385
3645
|
items: [
|
|
3386
3646
|
{
|
|
3387
|
-
detail: `${totals.
|
|
3647
|
+
detail: `${formatMetricValue(totals.unpricedCalls, "unpriced")} unpriced`,
|
|
3388
3648
|
icon: import_lucide_react12.DollarSign,
|
|
3389
|
-
label: "
|
|
3649
|
+
label: "Spend",
|
|
3390
3650
|
value: formatMetricValue(totals.totalCostUsd, "cost")
|
|
3391
3651
|
},
|
|
3392
3652
|
{
|
|
3393
|
-
detail: `${formatMetricValue(totals.
|
|
3653
|
+
detail: `${formatMetricValue(totals.failedCalls, "failures")} failed`,
|
|
3394
3654
|
icon: import_lucide_react12.Activity,
|
|
3655
|
+
label: "Calls",
|
|
3656
|
+
value: formatMetricValue(totals.totalCalls, "calls")
|
|
3657
|
+
},
|
|
3658
|
+
{
|
|
3659
|
+
detail: "Tool and resource runtime",
|
|
3660
|
+
icon: import_lucide_react12.Clock,
|
|
3661
|
+
label: "Duration",
|
|
3662
|
+
value: formatMetricValue(totals.totalDurationMs, "duration")
|
|
3663
|
+
},
|
|
3664
|
+
{
|
|
3665
|
+
detail: `${formatMetricValue(totals.inputTokens, "tokens")} input`,
|
|
3666
|
+
icon: import_lucide_react12.Sparkles,
|
|
3395
3667
|
label: "Tokens",
|
|
3396
3668
|
value: formatMetricValue(totals.totalTokens, "tokens")
|
|
3397
3669
|
},
|
|
3398
3670
|
{
|
|
3399
|
-
detail:
|
|
3400
|
-
icon: import_lucide_react12.
|
|
3401
|
-
label: "
|
|
3402
|
-
value: formatMetricValue(totals.
|
|
3671
|
+
detail: "Custom metering",
|
|
3672
|
+
icon: import_lucide_react12.Coins,
|
|
3673
|
+
label: "Credits",
|
|
3674
|
+
value: formatMetricValue(totals.totalCredits, "credits")
|
|
3675
|
+
},
|
|
3676
|
+
{
|
|
3677
|
+
detail: "Failed or aborted work",
|
|
3678
|
+
icon: import_lucide_react12.AlertTriangle,
|
|
3679
|
+
label: "Failures",
|
|
3680
|
+
value: formatMetricValue(totals.failedCalls, "failures")
|
|
3403
3681
|
}
|
|
3404
3682
|
]
|
|
3405
3683
|
}
|
|
@@ -3408,7 +3686,7 @@ function UsagePage({ context }) {
|
|
|
3408
3686
|
EmptyState,
|
|
3409
3687
|
{
|
|
3410
3688
|
title: "No usage",
|
|
3411
|
-
description: "
|
|
3689
|
+
description: "Metered LLM, tool, and resource records will appear here after work is captured in the usage ledger."
|
|
3412
3690
|
}
|
|
3413
3691
|
) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
3414
3692
|
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(Card, { className: "h-[320px] py-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(CardContent, { className: "h-full px-3", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(UsageChart, { chartState, metricKind }) }) }),
|
|
@@ -3487,6 +3765,7 @@ function UsageRowsTable({
|
|
|
3487
3765
|
totals
|
|
3488
3766
|
}) {
|
|
3489
3767
|
const totalValue = getUsageTotalValue(totals, metricKind, dimension);
|
|
3768
|
+
const valueHeader = (metricKind === "tokens" || metricKind === "cost") && dimension !== "total" ? `${getUsageDimensionLabel(dimension)} ${getUsageMetricLabel(metricKind)}` : getUsageMetricLabel(metricKind);
|
|
3490
3769
|
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
3491
3770
|
ResourceTable,
|
|
3492
3771
|
{
|
|
@@ -3504,7 +3783,7 @@ function UsageRowsTable({
|
|
|
3504
3783
|
{
|
|
3505
3784
|
align: "right",
|
|
3506
3785
|
id: "value",
|
|
3507
|
-
header:
|
|
3786
|
+
header: valueHeader,
|
|
3508
3787
|
render: (row) => formatMetricValue(row.value, metricKind)
|
|
3509
3788
|
},
|
|
3510
3789
|
{
|
|
@@ -3521,20 +3800,100 @@ function UsageRowsTable({
|
|
|
3521
3800
|
},
|
|
3522
3801
|
{
|
|
3523
3802
|
align: "right",
|
|
3524
|
-
id: "
|
|
3525
|
-
header: "
|
|
3526
|
-
render: (row) => formatMetricValue(
|
|
3803
|
+
id: "spend",
|
|
3804
|
+
header: "Spend",
|
|
3805
|
+
render: (row) => formatMetricValue(row.totalCostUsd, "cost")
|
|
3527
3806
|
},
|
|
3528
3807
|
{
|
|
3529
3808
|
align: "right",
|
|
3530
|
-
id: "
|
|
3531
|
-
header: "
|
|
3532
|
-
render: (row) => formatMetricValue(
|
|
3809
|
+
id: "duration",
|
|
3810
|
+
header: "Duration",
|
|
3811
|
+
render: (row) => formatMetricValue(row.totalDurationMs, "duration")
|
|
3812
|
+
},
|
|
3813
|
+
{
|
|
3814
|
+
align: "right",
|
|
3815
|
+
id: "tokens",
|
|
3816
|
+
header: "Tokens",
|
|
3817
|
+
render: (row) => formatMetricValue(row.totalTokens, "tokens")
|
|
3818
|
+
},
|
|
3819
|
+
{
|
|
3820
|
+
align: "right",
|
|
3821
|
+
id: "failures",
|
|
3822
|
+
header: "Failures",
|
|
3823
|
+
render: (row) => formatMetricValue(row.failedCalls, "failures")
|
|
3824
|
+
},
|
|
3825
|
+
{
|
|
3826
|
+
align: "right",
|
|
3827
|
+
id: "unpriced",
|
|
3828
|
+
header: "Unpriced",
|
|
3829
|
+
render: (row) => formatMetricValue(row.unpricedCalls, "unpriced")
|
|
3533
3830
|
}
|
|
3534
3831
|
]
|
|
3535
3832
|
}
|
|
3536
3833
|
);
|
|
3537
3834
|
}
|
|
3835
|
+
function getUsageMetricOptions(workload) {
|
|
3836
|
+
if (workload === "llm") {
|
|
3837
|
+
return ["cost", "tokens", "calls", "failures", "unpriced"];
|
|
3838
|
+
}
|
|
3839
|
+
if (workload === "tool") {
|
|
3840
|
+
return ["calls", "duration", "cost", "credits", "failures", "unpriced"];
|
|
3841
|
+
}
|
|
3842
|
+
return [
|
|
3843
|
+
"calls",
|
|
3844
|
+
"cost",
|
|
3845
|
+
"duration",
|
|
3846
|
+
"tokens",
|
|
3847
|
+
"credits",
|
|
3848
|
+
"failures",
|
|
3849
|
+
"unpriced"
|
|
3850
|
+
];
|
|
3851
|
+
}
|
|
3852
|
+
function getUsageGroupOptions(workload) {
|
|
3853
|
+
if (workload === "llm") {
|
|
3854
|
+
return ["participant", "model", "provider", "thread", "namespace", "status"];
|
|
3855
|
+
}
|
|
3856
|
+
if (workload === "tool") {
|
|
3857
|
+
return [
|
|
3858
|
+
"resource",
|
|
3859
|
+
"operation",
|
|
3860
|
+
"status",
|
|
3861
|
+
"participant",
|
|
3862
|
+
"thread",
|
|
3863
|
+
"namespace"
|
|
3864
|
+
];
|
|
3865
|
+
}
|
|
3866
|
+
return [
|
|
3867
|
+
"kind",
|
|
3868
|
+
"resource",
|
|
3869
|
+
"operation",
|
|
3870
|
+
"status",
|
|
3871
|
+
"participant",
|
|
3872
|
+
"thread",
|
|
3873
|
+
"namespace"
|
|
3874
|
+
];
|
|
3875
|
+
}
|
|
3876
|
+
function getUsageKindLabel(kind) {
|
|
3877
|
+
switch (kind) {
|
|
3878
|
+
case "all":
|
|
3879
|
+
return "All";
|
|
3880
|
+
case "llm":
|
|
3881
|
+
return "LLM";
|
|
3882
|
+
case "tool":
|
|
3883
|
+
return "Tools";
|
|
3884
|
+
case "asset":
|
|
3885
|
+
return "Assets";
|
|
3886
|
+
case "rag":
|
|
3887
|
+
return "RAG";
|
|
3888
|
+
case "embedding":
|
|
3889
|
+
return "Embeddings";
|
|
3890
|
+
default:
|
|
3891
|
+
return kind;
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
function getUsageAttributionLabel(attribution) {
|
|
3895
|
+
return attribution === "initiatedBy" ? "Initiator" : "Performer";
|
|
3896
|
+
}
|
|
3538
3897
|
function emptyToUndefined(value) {
|
|
3539
3898
|
const trimmed = value.trim();
|
|
3540
3899
|
return trimmed.length > 0 ? trimmed : void 0;
|
|
@@ -4023,6 +4382,7 @@ function useCopilotzAdmin(options = {}) {
|
|
|
4023
4382
|
formatUsageBucket,
|
|
4024
4383
|
getUsageDimensionLabel,
|
|
4025
4384
|
getUsageGroupLabel,
|
|
4385
|
+
getUsageMetricLabel,
|
|
4026
4386
|
getUsageRange,
|
|
4027
4387
|
getUsageTotalValue,
|
|
4028
4388
|
mergeAdminConfig,
|