@acarmisc/backstage-plugin-litellm 0.43.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +4 -1
- package/dist/components/GenerateKeyDialog.d.ts +21 -0
- package/dist/components/TeamUsage.d.ts +14 -1
- package/dist/index.cjs.js +101 -7
- package/dist/index.cjs.js.map +2 -2
- package/dist/index.esm.js +101 -7
- package/dist/index.esm.js.map +2 -2
- package/dist/permissions.d.ts +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +2 -2
package/dist/index.esm.js
CHANGED
|
@@ -299,6 +299,12 @@ var init_api = __esm({
|
|
|
299
299
|
end_date: endDate
|
|
300
300
|
});
|
|
301
301
|
}
|
|
302
|
+
async getTeamKeyUsage(teamId, startDate, endDate) {
|
|
303
|
+
return this.get(`/teams/${encodeURIComponent(teamId)}/usage/keys`, {
|
|
304
|
+
start_date: startDate,
|
|
305
|
+
end_date: endDate
|
|
306
|
+
});
|
|
307
|
+
}
|
|
302
308
|
async getSpendLogs(params) {
|
|
303
309
|
const strParams = {
|
|
304
310
|
start_date: params.startDate,
|
|
@@ -5078,7 +5084,7 @@ function budgetStatValue(hidden, budget) {
|
|
|
5078
5084
|
if (budget > 0) return fmtUsd2(budget);
|
|
5079
5085
|
return "Unlimited";
|
|
5080
5086
|
}
|
|
5081
|
-
var fmtUsd2, monoSx, MemberUsageTable, TeamCard, TeamUsage;
|
|
5087
|
+
var fmtUsd2, monoSx, MemberUsageTable, TeamKeyUsageTable, TeamCard, TeamUsage;
|
|
5082
5088
|
var init_TeamUsage = __esm({
|
|
5083
5089
|
"src/components/TeamUsage.tsx"() {
|
|
5084
5090
|
"use strict";
|
|
@@ -5120,7 +5126,47 @@ var init_TeamUsage = __esm({
|
|
|
5120
5126
|
}) })
|
|
5121
5127
|
] }) });
|
|
5122
5128
|
};
|
|
5123
|
-
|
|
5129
|
+
TeamKeyUsageTable = ({ usage }) => {
|
|
5130
|
+
const hidden = usage.budget_hidden === true;
|
|
5131
|
+
if (!usage.keys.length) {
|
|
5132
|
+
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "This team has no keys." });
|
|
5133
|
+
}
|
|
5134
|
+
return /* @__PURE__ */ jsx15(TableContainer4, { component: Paper8, variant: "outlined", sx: { borderRadius: 1.5 }, children: /* @__PURE__ */ jsxs14(Table4, { size: "small", sx: dataTableSx, "aria-label": "Keys by member", children: [
|
|
5135
|
+
/* @__PURE__ */ jsx15(TableHead4, { children: /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5136
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: "Key" }),
|
|
5137
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: "Owner" }),
|
|
5138
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: "Created" }),
|
|
5139
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: "Status" }),
|
|
5140
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Spend" }),
|
|
5141
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Budget" }),
|
|
5142
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Tokens" }),
|
|
5143
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Requests" })
|
|
5144
|
+
] }) }),
|
|
5145
|
+
/* @__PURE__ */ jsx15(TableBody4, { children: usage.keys.map((k) => {
|
|
5146
|
+
const owner = k.display_name ?? k.user_email ?? k.user_id;
|
|
5147
|
+
return /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5148
|
+
/* @__PURE__ */ jsxs14(TableCell4, { children: [
|
|
5149
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", children: k.key_alias ?? k.key }),
|
|
5150
|
+
k.key_alias && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", sx: monoSx, children: k.key })
|
|
5151
|
+
] }),
|
|
5152
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: owner ?? /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "\u2014" }) }),
|
|
5153
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: fmtDateShort(k.created_at) }),
|
|
5154
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: /* @__PURE__ */ jsx15(
|
|
5155
|
+
StatusPill,
|
|
5156
|
+
{
|
|
5157
|
+
label: k.blocked ? "Blocked" : "Active",
|
|
5158
|
+
tone: k.blocked ? "danger" : "success"
|
|
5159
|
+
}
|
|
5160
|
+
) }),
|
|
5161
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtUsd2(k.spend) }),
|
|
5162
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: k.max_budget === void 0 ? "Unlimited" : fmtUsd2(k.max_budget) }),
|
|
5163
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtCompact(k.total_tokens) }),
|
|
5164
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: k.api_requests.toLocaleString() })
|
|
5165
|
+
] }, k.key);
|
|
5166
|
+
}) })
|
|
5167
|
+
] }) });
|
|
5168
|
+
};
|
|
5169
|
+
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, memberUsageFailed, keyUsage, keyUsageLoading, keyUsageFailed, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5124
5170
|
const [expanded, setExpanded] = useState9(false);
|
|
5125
5171
|
const chart = useChartTheme();
|
|
5126
5172
|
const handleExpandChange = (newExpanded) => {
|
|
@@ -5319,9 +5365,17 @@ var init_TeamUsage = __esm({
|
|
|
5319
5365
|
renderNamedTags("Knowledge bases", team.object_permission?.vector_stores, vectorStores),
|
|
5320
5366
|
renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
|
|
5321
5367
|
renderDailySpendSection(),
|
|
5322
|
-
(memberUsageLoading || memberUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5368
|
+
(memberUsageLoading || memberUsage || memberUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5323
5369
|
sectionLabel("Usage by member"),
|
|
5324
|
-
memberUsage
|
|
5370
|
+
memberUsage && /* @__PURE__ */ jsx15(MemberUsageTable, { usage: memberUsage }),
|
|
5371
|
+
!memberUsage && memberUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-member usage" }),
|
|
5372
|
+
!memberUsage && !memberUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5373
|
+
] }),
|
|
5374
|
+
(keyUsageLoading || keyUsage || keyUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5375
|
+
sectionLabel("Keys by member"),
|
|
5376
|
+
keyUsage && /* @__PURE__ */ jsx15(TeamKeyUsageTable, { usage: keyUsage }),
|
|
5377
|
+
!keyUsage && keyUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-key usage" }),
|
|
5378
|
+
!keyUsage && !keyUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5325
5379
|
] }),
|
|
5326
5380
|
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5327
5381
|
sectionLabel("Members"),
|
|
@@ -5379,6 +5433,10 @@ var init_TeamUsage = __esm({
|
|
|
5379
5433
|
getTeamUsageLoading,
|
|
5380
5434
|
getTeamMemberUsage,
|
|
5381
5435
|
getTeamMemberUsageLoading,
|
|
5436
|
+
getTeamKeyUsage,
|
|
5437
|
+
getTeamKeyUsageLoading,
|
|
5438
|
+
getTeamMemberUsageFailed,
|
|
5439
|
+
getTeamKeyUsageFailed,
|
|
5382
5440
|
canManage,
|
|
5383
5441
|
onEditTeam,
|
|
5384
5442
|
canCreate,
|
|
@@ -5442,6 +5500,10 @@ var init_TeamUsage = __esm({
|
|
|
5442
5500
|
usageLoading: getTeamUsageLoading(team.team_id),
|
|
5443
5501
|
memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
|
|
5444
5502
|
memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
|
|
5503
|
+
keyUsage: getTeamKeyUsage?.(team.team_id) ?? null,
|
|
5504
|
+
keyUsageLoading: getTeamKeyUsageLoading?.(team.team_id) ?? false,
|
|
5505
|
+
memberUsageFailed: getTeamMemberUsageFailed?.(team.team_id) ?? false,
|
|
5506
|
+
keyUsageFailed: getTeamKeyUsageFailed?.(team.team_id) ?? false,
|
|
5445
5507
|
canManage,
|
|
5446
5508
|
onEditTeam,
|
|
5447
5509
|
canManageMembers: canManageMembers?.(team),
|
|
@@ -6290,7 +6352,7 @@ function initDateRange() {
|
|
|
6290
6352
|
else start.setDate(start.getDate() - 7);
|
|
6291
6353
|
return { start, end };
|
|
6292
6354
|
}
|
|
6293
|
-
var PERIOD_LS_KEY2, PAGE_TABS, isPageTab, LiteLLMPage;
|
|
6355
|
+
var PERIOD_LS_KEY2, PAGE_TABS, isPageTab, isRefusal, LiteLLMPage;
|
|
6294
6356
|
var init_LiteLLMPage = __esm({
|
|
6295
6357
|
"src/components/LiteLLMPage.tsx"() {
|
|
6296
6358
|
"use strict";
|
|
@@ -6311,6 +6373,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6311
6373
|
PERIOD_LS_KEY2 = "litellm_usage_period";
|
|
6312
6374
|
PAGE_TABS = ["overview", "keys", "teams", "models", "insights"];
|
|
6313
6375
|
isPageTab = (v) => !!v && PAGE_TABS.includes(v);
|
|
6376
|
+
isRefusal = (err) => err instanceof ApiError && (err.status === 403 || err.status === 404);
|
|
6314
6377
|
LiteLLMPage = () => {
|
|
6315
6378
|
const api = useApi4(liteLlmApiRef);
|
|
6316
6379
|
const alertApi = useApi4(alertApiRef2);
|
|
@@ -6394,6 +6457,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6394
6457
|
const [teamUsageLoading, setTeamUsageLoading] = useState11({});
|
|
6395
6458
|
const [memberUsageCache, setMemberUsageCache] = useState11({});
|
|
6396
6459
|
const [memberUsageLoading, setMemberUsageLoading] = useState11({});
|
|
6460
|
+
const [keyUsageCache, setKeyUsageCache] = useState11({});
|
|
6461
|
+
const [keyUsageLoading, setKeyUsageLoading] = useState11({});
|
|
6462
|
+
const [memberUsageFailed, setMemberUsageFailed] = useState11({});
|
|
6463
|
+
const [keyUsageFailed, setKeyUsageFailed] = useState11({});
|
|
6397
6464
|
const { value: userInfo, loading: userLoading, error: userError } = useAsync(
|
|
6398
6465
|
() => api.getUserInfo(),
|
|
6399
6466
|
[api]
|
|
@@ -6460,6 +6527,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6460
6527
|
setTeamUsageLoading({});
|
|
6461
6528
|
setMemberUsageCache({});
|
|
6462
6529
|
setMemberUsageLoading({});
|
|
6530
|
+
setKeyUsageCache({});
|
|
6531
|
+
setKeyUsageLoading({});
|
|
6532
|
+
setMemberUsageFailed({});
|
|
6533
|
+
setKeyUsageFailed({});
|
|
6463
6534
|
}, [setDateRange, setCurrentPreset]);
|
|
6464
6535
|
const loadTeamUsage = useCallback4(async (teamId) => {
|
|
6465
6536
|
if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
|
|
@@ -6483,12 +6554,28 @@ var init_LiteLLMPage = __esm({
|
|
|
6483
6554
|
const endDate = toLocalDay(dateRange.end);
|
|
6484
6555
|
const data = await api.getTeamMemberUsage(teamId, startDate, endDate);
|
|
6485
6556
|
setMemberUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6486
|
-
} catch {
|
|
6557
|
+
} catch (err) {
|
|
6487
6558
|
setMemberUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6559
|
+
setMemberUsageFailed((prev) => ({ ...prev, [teamId]: !isRefusal(err) }));
|
|
6488
6560
|
} finally {
|
|
6489
6561
|
setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6490
6562
|
}
|
|
6491
6563
|
}, [api, dateRange, memberUsageCache, memberUsageLoading]);
|
|
6564
|
+
const loadKeyUsage = useCallback4(async (teamId) => {
|
|
6565
|
+
if (keyUsageCache[teamId] !== void 0 || keyUsageLoading[teamId]) return;
|
|
6566
|
+
setKeyUsageLoading((prev) => ({ ...prev, [teamId]: true }));
|
|
6567
|
+
try {
|
|
6568
|
+
const startDate = toLocalDay(dateRange.start);
|
|
6569
|
+
const endDate = toLocalDay(dateRange.end);
|
|
6570
|
+
const data = await api.getTeamKeyUsage(teamId, startDate, endDate);
|
|
6571
|
+
setKeyUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6572
|
+
} catch (err) {
|
|
6573
|
+
setKeyUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6574
|
+
setKeyUsageFailed((prev) => ({ ...prev, [teamId]: !isRefusal(err) }));
|
|
6575
|
+
} finally {
|
|
6576
|
+
setKeyUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6577
|
+
}
|
|
6578
|
+
}, [api, dateRange, keyUsageCache, keyUsageLoading]);
|
|
6492
6579
|
const allowedModels = useMemo9(() => {
|
|
6493
6580
|
if (!allModels?.length) return [];
|
|
6494
6581
|
const userModels = userInfo?.models;
|
|
@@ -6786,6 +6873,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6786
6873
|
getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
|
|
6787
6874
|
getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
|
|
6788
6875
|
getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
|
|
6876
|
+
getTeamKeyUsage: (teamId) => keyUsageCache[teamId] ?? null,
|
|
6877
|
+
getTeamKeyUsageLoading: (teamId) => keyUsageLoading[teamId] ?? false,
|
|
6878
|
+
getTeamMemberUsageFailed: (teamId) => memberUsageFailed[teamId] ?? false,
|
|
6879
|
+
getTeamKeyUsageFailed: (teamId) => keyUsageFailed[teamId] ?? false,
|
|
6789
6880
|
canManage: teamMgmtEnabled && canManageTeam && !readOnly,
|
|
6790
6881
|
onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
|
|
6791
6882
|
canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
|
|
@@ -6797,7 +6888,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6797
6888
|
readOnly,
|
|
6798
6889
|
onTeamExpand: (team) => {
|
|
6799
6890
|
loadTeamUsage(team.team_id);
|
|
6800
|
-
if (liteLlmConfig?.teamUsage?.memberBreakdown)
|
|
6891
|
+
if (liteLlmConfig?.teamUsage?.memberBreakdown) {
|
|
6892
|
+
loadMemberUsage(team.team_id);
|
|
6893
|
+
loadKeyUsage(team.team_id);
|
|
6894
|
+
}
|
|
6801
6895
|
}
|
|
6802
6896
|
}
|
|
6803
6897
|
);
|