@acarmisc/backstage-plugin-litellm 0.34.0 → 0.35.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/TeamUsage.d.ts +11 -1
- package/dist/index.cjs.js +76 -3
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +76 -3
- package/dist/index.esm.js.map +2 -2
- package/dist/types.d.ts +6 -1
- package/package.json +2 -2
package/dist/index.esm.js
CHANGED
|
@@ -285,6 +285,12 @@ var init_api = __esm({
|
|
|
285
285
|
end_date: endDate
|
|
286
286
|
});
|
|
287
287
|
}
|
|
288
|
+
async getTeamMemberUsage(teamId, startDate, endDate) {
|
|
289
|
+
return this.get(`/teams/${encodeURIComponent(teamId)}/usage/members`, {
|
|
290
|
+
start_date: startDate,
|
|
291
|
+
end_date: endDate
|
|
292
|
+
});
|
|
293
|
+
}
|
|
288
294
|
async getConfig() {
|
|
289
295
|
return this.get("/config");
|
|
290
296
|
}
|
|
@@ -5010,13 +5016,49 @@ function budgetStatValue(hidden, budget) {
|
|
|
5010
5016
|
if (budget > 0) return fmtUsd2(budget);
|
|
5011
5017
|
return "Unlimited";
|
|
5012
5018
|
}
|
|
5013
|
-
var fmtUsd2, TeamCard, TeamUsage;
|
|
5019
|
+
var fmtUsd2, monoSx, MemberUsageTable, TeamCard, TeamUsage;
|
|
5014
5020
|
var init_TeamUsage = __esm({
|
|
5015
5021
|
"src/components/TeamUsage.tsx"() {
|
|
5016
5022
|
"use strict";
|
|
5017
5023
|
init_ui();
|
|
5018
5024
|
fmtUsd2 = (n) => `$${(n ?? 0).toFixed(2)}`;
|
|
5019
|
-
|
|
5025
|
+
monoSx = { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 };
|
|
5026
|
+
MemberUsageTable = ({ usage }) => {
|
|
5027
|
+
const hidden = usage.budget_hidden === true;
|
|
5028
|
+
if (!usage.members.length) {
|
|
5029
|
+
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "No members or activity in this period." });
|
|
5030
|
+
}
|
|
5031
|
+
return /* @__PURE__ */ jsx15(TableContainer4, { component: Paper8, variant: "outlined", sx: { borderRadius: 1.5 }, children: /* @__PURE__ */ jsxs14(Table4, { size: "small", sx: dataTableSx, "aria-label": "Usage by member", children: [
|
|
5032
|
+
/* @__PURE__ */ jsx15(TableHead4, { children: /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5033
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: "Member" }),
|
|
5034
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Spend" }),
|
|
5035
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Share" }),
|
|
5036
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Tokens" }),
|
|
5037
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Requests" }),
|
|
5038
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Success" }),
|
|
5039
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: "Keys" })
|
|
5040
|
+
] }) }),
|
|
5041
|
+
/* @__PURE__ */ jsx15(TableBody4, { children: usage.members.map((m) => {
|
|
5042
|
+
const name = m.display_name ?? m.user_email ?? m.user_id;
|
|
5043
|
+
let sub = null;
|
|
5044
|
+
if (m.display_name) sub = m.user_email ?? m.user_id;
|
|
5045
|
+
else if (m.user_email && m.user_id !== m.user_email) sub = m.user_id;
|
|
5046
|
+
return /* @__PURE__ */ jsxs14(TableRow4, { children: [
|
|
5047
|
+
/* @__PURE__ */ jsx15(TableCell4, { children: m.user_id === null ? /* @__PURE__ */ jsx15(MuiTooltip, { title: "Activity of keys that were deleted or have no owner", children: /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", sx: { fontStyle: "italic" }, children: "Unattributed" }) }) : /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
5048
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", children: name }),
|
|
5049
|
+
sub && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", sx: monoSx, children: sub })
|
|
5050
|
+
] }) }),
|
|
5051
|
+
!hidden && /* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtUsd2(m.spend) }),
|
|
5052
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: `${m.spend_share_pct.toFixed(m.spend_share_pct > 0 && m.spend_share_pct < 1 ? 1 : 0)}%` }),
|
|
5053
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: fmtCompact(m.total_tokens) }),
|
|
5054
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.api_requests.toLocaleString() }),
|
|
5055
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.success_rate === null ? "\u2014" : `${m.success_rate.toFixed(0)}%` }),
|
|
5056
|
+
/* @__PURE__ */ jsx15(TableCell4, { align: "right", children: m.user_id === null ? "\u2014" : m.key_count })
|
|
5057
|
+
] }, m.user_id ?? "__unattributed");
|
|
5058
|
+
}) })
|
|
5059
|
+
] }) });
|
|
5060
|
+
};
|
|
5061
|
+
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
|
|
5020
5062
|
const [expanded, setExpanded] = useState9(false);
|
|
5021
5063
|
const chart = useChartTheme();
|
|
5022
5064
|
const handleExpandChange = (newExpanded) => {
|
|
@@ -5209,6 +5251,10 @@ var init_TeamUsage = __esm({
|
|
|
5209
5251
|
team.models?.length ? /* @__PURE__ */ jsx15(Box14, { display: "flex", gap: 0.5, flexWrap: "wrap", children: team.models.map((m) => /* @__PURE__ */ jsx15(TagChip, { label: m, title: m }, m)) }) : /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "All models allowed" })
|
|
5210
5252
|
] }),
|
|
5211
5253
|
renderDailySpendSection(),
|
|
5254
|
+
(memberUsageLoading || memberUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5255
|
+
sectionLabel("Usage by member"),
|
|
5256
|
+
memberUsage ? /* @__PURE__ */ jsx15(MemberUsageTable, { usage: memberUsage }) : /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5257
|
+
] }),
|
|
5212
5258
|
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5213
5259
|
sectionLabel("Members"),
|
|
5214
5260
|
team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
|
|
@@ -5263,6 +5309,8 @@ var init_TeamUsage = __esm({
|
|
|
5263
5309
|
loading,
|
|
5264
5310
|
getTeamUsage,
|
|
5265
5311
|
getTeamUsageLoading,
|
|
5312
|
+
getTeamMemberUsage,
|
|
5313
|
+
getTeamMemberUsageLoading,
|
|
5266
5314
|
canManage,
|
|
5267
5315
|
onEditTeam,
|
|
5268
5316
|
canCreate,
|
|
@@ -5322,6 +5370,8 @@ var init_TeamUsage = __esm({
|
|
|
5322
5370
|
team,
|
|
5323
5371
|
usage: getTeamUsage(team.team_id),
|
|
5324
5372
|
usageLoading: getTeamUsageLoading(team.team_id),
|
|
5373
|
+
memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
|
|
5374
|
+
memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
|
|
5325
5375
|
canManage,
|
|
5326
5376
|
onEditTeam,
|
|
5327
5377
|
canManageMembers: canManageMembers?.(team),
|
|
@@ -6134,6 +6184,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6134
6184
|
const keyFormOpen = generateDialogOpen || !!keyToEdit;
|
|
6135
6185
|
const [teamUsageCache, setTeamUsageCache] = useState12({});
|
|
6136
6186
|
const [teamUsageLoading, setTeamUsageLoading] = useState12({});
|
|
6187
|
+
const [memberUsageCache, setMemberUsageCache] = useState12({});
|
|
6188
|
+
const [memberUsageLoading, setMemberUsageLoading] = useState12({});
|
|
6137
6189
|
const { value: userInfo, loading: userLoading, error: userError } = useAsync2(
|
|
6138
6190
|
() => api.getUserInfo(),
|
|
6139
6191
|
[api]
|
|
@@ -6194,6 +6246,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6194
6246
|
}
|
|
6195
6247
|
setTeamUsageCache({});
|
|
6196
6248
|
setTeamUsageLoading({});
|
|
6249
|
+
setMemberUsageCache({});
|
|
6250
|
+
setMemberUsageLoading({});
|
|
6197
6251
|
}, [setDateRange, setCurrentPreset]);
|
|
6198
6252
|
const loadTeamUsage = useCallback4(async (teamId) => {
|
|
6199
6253
|
if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
|
|
@@ -6209,6 +6263,20 @@ var init_LiteLLMPage = __esm({
|
|
|
6209
6263
|
setTeamUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6210
6264
|
}
|
|
6211
6265
|
}, [api, dateRange, teamUsageCache, teamUsageLoading]);
|
|
6266
|
+
const loadMemberUsage = useCallback4(async (teamId) => {
|
|
6267
|
+
if (memberUsageCache[teamId] !== void 0 || memberUsageLoading[teamId]) return;
|
|
6268
|
+
setMemberUsageLoading((prev) => ({ ...prev, [teamId]: true }));
|
|
6269
|
+
try {
|
|
6270
|
+
const startDate = toLocalDay(dateRange.start);
|
|
6271
|
+
const endDate = toLocalDay(dateRange.end);
|
|
6272
|
+
const data = await api.getTeamMemberUsage(teamId, startDate, endDate);
|
|
6273
|
+
setMemberUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6274
|
+
} catch {
|
|
6275
|
+
setMemberUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6276
|
+
} finally {
|
|
6277
|
+
setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6278
|
+
}
|
|
6279
|
+
}, [api, dateRange, memberUsageCache, memberUsageLoading]);
|
|
6212
6280
|
const allowedModels = useMemo9(() => {
|
|
6213
6281
|
if (!allModels?.length) return [];
|
|
6214
6282
|
const userModels = userInfo?.models;
|
|
@@ -6503,6 +6571,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6503
6571
|
loading: teamsLoading,
|
|
6504
6572
|
getTeamUsage: (teamId) => teamUsageCache[teamId] ?? null,
|
|
6505
6573
|
getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
|
|
6574
|
+
getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
|
|
6575
|
+
getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
|
|
6506
6576
|
canManage: teamMgmtEnabled && canManageTeam && !readOnly,
|
|
6507
6577
|
onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
|
|
6508
6578
|
canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
|
|
@@ -6510,7 +6580,10 @@ var init_LiteLLMPage = __esm({
|
|
|
6510
6580
|
canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
|
|
6511
6581
|
onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
|
|
6512
6582
|
readOnly,
|
|
6513
|
-
onTeamExpand: (team) =>
|
|
6583
|
+
onTeamExpand: (team) => {
|
|
6584
|
+
loadTeamUsage(team.team_id);
|
|
6585
|
+
if (liteLlmConfig?.teamUsage?.memberBreakdown) loadMemberUsage(team.team_id);
|
|
6586
|
+
}
|
|
6514
6587
|
}
|
|
6515
6588
|
);
|
|
6516
6589
|
})(),
|