@acarmisc/backstage-plugin-litellm 0.44.0 → 0.46.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/components/GenerateKeyDialog.d.ts +21 -0
- package/dist/components/TeamUsage.d.ts +7 -3
- package/dist/index.cjs.js +80 -40
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +80 -40
- package/dist/index.esm.js.map +2 -2
- package/dist/permissions.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -5084,47 +5084,70 @@ function budgetStatValue(hidden, budget) {
|
|
|
5084
5084
|
if (budget > 0) return fmtUsd2(budget);
|
|
5085
5085
|
return "Unlimited";
|
|
5086
5086
|
}
|
|
5087
|
-
var fmtUsd2, monoSx,
|
|
5087
|
+
var fmtUsd2, monoSx, fmtShare, MemberUsageCards, TeamKeyUsageTable, TeamCard, TeamUsage;
|
|
5088
5088
|
var init_TeamUsage = __esm({
|
|
5089
5089
|
"src/components/TeamUsage.tsx"() {
|
|
5090
5090
|
"use strict";
|
|
5091
5091
|
init_ui();
|
|
5092
5092
|
fmtUsd2 = (n) => `$${(n ?? 0).toFixed(2)}`;
|
|
5093
5093
|
monoSx = { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 };
|
|
5094
|
-
|
|
5094
|
+
fmtShare = (pct) => `${pct.toFixed(pct > 0 && pct < 1 ? 1 : 0)}%`;
|
|
5095
|
+
MemberUsageCards = ({ usage }) => {
|
|
5095
5096
|
const hidden = usage.budget_hidden === true;
|
|
5096
5097
|
if (!usage.members.length) {
|
|
5097
5098
|
return /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "No members or activity in this period." });
|
|
5098
5099
|
}
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5108
|
-
|
|
5109
|
-
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5115
|
-
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
|
|
5125
|
-
|
|
5126
|
-
|
|
5127
|
-
|
|
5100
|
+
const people = usage.members.filter((m) => m.user_id !== null).length;
|
|
5101
|
+
return /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5102
|
+
!hidden && people > 0 && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", sx: { display: "block", mb: 1 }, children: `Team spend ${fmtUsd2(usage.total_spend)} \xB7 avg ${fmtUsd2(usage.total_spend / people)} per member` }),
|
|
5103
|
+
/* @__PURE__ */ jsx15(
|
|
5104
|
+
Box14,
|
|
5105
|
+
{
|
|
5106
|
+
role: "list",
|
|
5107
|
+
"aria-label": "Usage by member",
|
|
5108
|
+
sx: { display: "grid", gap: 1.5, gridTemplateColumns: "repeat(auto-fill, minmax(230px, 1fr))" },
|
|
5109
|
+
children: usage.members.map((m) => {
|
|
5110
|
+
const name = m.display_name ?? m.user_email ?? m.user_id;
|
|
5111
|
+
let sub = null;
|
|
5112
|
+
if (m.display_name) sub = m.user_email ?? m.user_id;
|
|
5113
|
+
else if (m.user_email && m.user_id !== m.user_email) sub = m.user_id;
|
|
5114
|
+
const stats = [
|
|
5115
|
+
["Tokens", fmtCompact(m.total_tokens)],
|
|
5116
|
+
["Requests", m.api_requests.toLocaleString()],
|
|
5117
|
+
["Success", m.success_rate === null ? "\u2014" : `${m.success_rate.toFixed(0)}%`],
|
|
5118
|
+
["Keys", m.user_id === null ? "\u2014" : String(m.key_count)]
|
|
5119
|
+
];
|
|
5120
|
+
return /* @__PURE__ */ jsxs14(
|
|
5121
|
+
Paper8,
|
|
5122
|
+
{
|
|
5123
|
+
role: "listitem",
|
|
5124
|
+
variant: "outlined",
|
|
5125
|
+
sx: { borderRadius: 1.5, p: 1.5, minWidth: 0 },
|
|
5126
|
+
children: [
|
|
5127
|
+
/* @__PURE__ */ jsxs14(Box14, { display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 1, children: [
|
|
5128
|
+
/* @__PURE__ */ jsx15(Box14, { minWidth: 0, 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: [
|
|
5129
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", fontWeight: 600, noWrap: true, children: name }),
|
|
5130
|
+
sub && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", noWrap: true, sx: { ...monoSx, display: "block" }, children: sub })
|
|
5131
|
+
] }) }),
|
|
5132
|
+
m.role && /* @__PURE__ */ jsx15(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false })
|
|
5133
|
+
] }),
|
|
5134
|
+
/* @__PURE__ */ jsxs14(Box14, { mt: 1.5, display: "flex", alignItems: "baseline", justifyContent: "space-between", children: [
|
|
5135
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "h6", component: "span", sx: { lineHeight: 1.2 }, children: hidden ? fmtShare(m.spend_share_pct) : fmtUsd2(m.spend) }),
|
|
5136
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: hidden ? "of team usage" : `${fmtShare(m.spend_share_pct)} of team` })
|
|
5137
|
+
] }),
|
|
5138
|
+
/* @__PURE__ */ jsx15(Box14, { mt: 0.75, children: /* @__PURE__ */ jsx15(Meter, { value: m.spend_share_pct, ariaLabel: `${name ?? "Unattributed"} share of team spend` }) }),
|
|
5139
|
+
/* @__PURE__ */ jsx15(Box14, { mt: 1.5, display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 0.5, children: stats.map(([label, value]) => /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5140
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", display: "block", children: label }),
|
|
5141
|
+
/* @__PURE__ */ jsx15(Typography12, { variant: "body2", children: value })
|
|
5142
|
+
] }, label)) })
|
|
5143
|
+
]
|
|
5144
|
+
},
|
|
5145
|
+
m.user_id ?? "__unattributed"
|
|
5146
|
+
);
|
|
5147
|
+
})
|
|
5148
|
+
}
|
|
5149
|
+
)
|
|
5150
|
+
] });
|
|
5128
5151
|
};
|
|
5129
5152
|
TeamKeyUsageTable = ({ usage }) => {
|
|
5130
5153
|
const hidden = usage.budget_hidden === true;
|
|
@@ -5166,7 +5189,7 @@ var init_TeamUsage = __esm({
|
|
|
5166
5189
|
}) })
|
|
5167
5190
|
] }) });
|
|
5168
5191
|
};
|
|
5169
|
-
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, keyUsage, keyUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5192
|
+
TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, memberUsageFailed, keyUsage, keyUsageLoading, keyUsageFailed, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
|
|
5170
5193
|
const [expanded, setExpanded] = useState9(false);
|
|
5171
5194
|
const chart = useChartTheme();
|
|
5172
5195
|
const handleExpandChange = (newExpanded) => {
|
|
@@ -5365,15 +5388,19 @@ var init_TeamUsage = __esm({
|
|
|
5365
5388
|
renderNamedTags("Knowledge bases", team.object_permission?.vector_stores, vectorStores),
|
|
5366
5389
|
renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
|
|
5367
5390
|
renderDailySpendSection(),
|
|
5368
|
-
(memberUsageLoading || memberUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5391
|
+
(memberUsageLoading || memberUsage || memberUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5369
5392
|
sectionLabel("Usage by member"),
|
|
5370
|
-
memberUsage
|
|
5393
|
+
memberUsage && /* @__PURE__ */ jsx15(MemberUsageCards, { usage: memberUsage }),
|
|
5394
|
+
!memberUsage && memberUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-member usage" }),
|
|
5395
|
+
!memberUsage && !memberUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5371
5396
|
] }),
|
|
5372
|
-
(keyUsageLoading || keyUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5397
|
+
(keyUsageLoading || keyUsage || keyUsageFailed) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
|
|
5373
5398
|
sectionLabel("Keys by member"),
|
|
5374
|
-
keyUsage
|
|
5399
|
+
keyUsage && /* @__PURE__ */ jsx15(TeamKeyUsageTable, { usage: keyUsage }),
|
|
5400
|
+
!keyUsage && keyUsageFailed && /* @__PURE__ */ jsx15(Typography12, { variant: "caption", color: "text.secondary", children: "Could not load per-key usage" }),
|
|
5401
|
+
!keyUsage && !keyUsageFailed && /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
|
|
5375
5402
|
] }),
|
|
5376
|
-
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5403
|
+
!memberUsage && /* @__PURE__ */ jsxs14(Box14, { children: [
|
|
5377
5404
|
sectionLabel("Members"),
|
|
5378
5405
|
team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
|
|
5379
5406
|
TableContainer4,
|
|
@@ -5431,6 +5458,8 @@ var init_TeamUsage = __esm({
|
|
|
5431
5458
|
getTeamMemberUsageLoading,
|
|
5432
5459
|
getTeamKeyUsage,
|
|
5433
5460
|
getTeamKeyUsageLoading,
|
|
5461
|
+
getTeamMemberUsageFailed,
|
|
5462
|
+
getTeamKeyUsageFailed,
|
|
5434
5463
|
canManage,
|
|
5435
5464
|
onEditTeam,
|
|
5436
5465
|
canCreate,
|
|
@@ -5496,6 +5525,8 @@ var init_TeamUsage = __esm({
|
|
|
5496
5525
|
memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
|
|
5497
5526
|
keyUsage: getTeamKeyUsage?.(team.team_id) ?? null,
|
|
5498
5527
|
keyUsageLoading: getTeamKeyUsageLoading?.(team.team_id) ?? false,
|
|
5528
|
+
memberUsageFailed: getTeamMemberUsageFailed?.(team.team_id) ?? false,
|
|
5529
|
+
keyUsageFailed: getTeamKeyUsageFailed?.(team.team_id) ?? false,
|
|
5499
5530
|
canManage,
|
|
5500
5531
|
onEditTeam,
|
|
5501
5532
|
canManageMembers: canManageMembers?.(team),
|
|
@@ -6344,7 +6375,7 @@ function initDateRange() {
|
|
|
6344
6375
|
else start.setDate(start.getDate() - 7);
|
|
6345
6376
|
return { start, end };
|
|
6346
6377
|
}
|
|
6347
|
-
var PERIOD_LS_KEY2, PAGE_TABS, isPageTab, LiteLLMPage;
|
|
6378
|
+
var PERIOD_LS_KEY2, PAGE_TABS, isPageTab, isRefusal, LiteLLMPage;
|
|
6348
6379
|
var init_LiteLLMPage = __esm({
|
|
6349
6380
|
"src/components/LiteLLMPage.tsx"() {
|
|
6350
6381
|
"use strict";
|
|
@@ -6365,6 +6396,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6365
6396
|
PERIOD_LS_KEY2 = "litellm_usage_period";
|
|
6366
6397
|
PAGE_TABS = ["overview", "keys", "teams", "models", "insights"];
|
|
6367
6398
|
isPageTab = (v) => !!v && PAGE_TABS.includes(v);
|
|
6399
|
+
isRefusal = (err) => err instanceof ApiError && (err.status === 403 || err.status === 404);
|
|
6368
6400
|
LiteLLMPage = () => {
|
|
6369
6401
|
const api = useApi4(liteLlmApiRef);
|
|
6370
6402
|
const alertApi = useApi4(alertApiRef2);
|
|
@@ -6450,6 +6482,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6450
6482
|
const [memberUsageLoading, setMemberUsageLoading] = useState11({});
|
|
6451
6483
|
const [keyUsageCache, setKeyUsageCache] = useState11({});
|
|
6452
6484
|
const [keyUsageLoading, setKeyUsageLoading] = useState11({});
|
|
6485
|
+
const [memberUsageFailed, setMemberUsageFailed] = useState11({});
|
|
6486
|
+
const [keyUsageFailed, setKeyUsageFailed] = useState11({});
|
|
6453
6487
|
const { value: userInfo, loading: userLoading, error: userError } = useAsync(
|
|
6454
6488
|
() => api.getUserInfo(),
|
|
6455
6489
|
[api]
|
|
@@ -6518,6 +6552,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6518
6552
|
setMemberUsageLoading({});
|
|
6519
6553
|
setKeyUsageCache({});
|
|
6520
6554
|
setKeyUsageLoading({});
|
|
6555
|
+
setMemberUsageFailed({});
|
|
6556
|
+
setKeyUsageFailed({});
|
|
6521
6557
|
}, [setDateRange, setCurrentPreset]);
|
|
6522
6558
|
const loadTeamUsage = useCallback4(async (teamId) => {
|
|
6523
6559
|
if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
|
|
@@ -6541,8 +6577,9 @@ var init_LiteLLMPage = __esm({
|
|
|
6541
6577
|
const endDate = toLocalDay(dateRange.end);
|
|
6542
6578
|
const data = await api.getTeamMemberUsage(teamId, startDate, endDate);
|
|
6543
6579
|
setMemberUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6544
|
-
} catch {
|
|
6580
|
+
} catch (err) {
|
|
6545
6581
|
setMemberUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6582
|
+
setMemberUsageFailed((prev) => ({ ...prev, [teamId]: !isRefusal(err) }));
|
|
6546
6583
|
} finally {
|
|
6547
6584
|
setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6548
6585
|
}
|
|
@@ -6555,8 +6592,9 @@ var init_LiteLLMPage = __esm({
|
|
|
6555
6592
|
const endDate = toLocalDay(dateRange.end);
|
|
6556
6593
|
const data = await api.getTeamKeyUsage(teamId, startDate, endDate);
|
|
6557
6594
|
setKeyUsageCache((prev) => ({ ...prev, [teamId]: data }));
|
|
6558
|
-
} catch {
|
|
6595
|
+
} catch (err) {
|
|
6559
6596
|
setKeyUsageCache((prev) => ({ ...prev, [teamId]: null }));
|
|
6597
|
+
setKeyUsageFailed((prev) => ({ ...prev, [teamId]: !isRefusal(err) }));
|
|
6560
6598
|
} finally {
|
|
6561
6599
|
setKeyUsageLoading((prev) => ({ ...prev, [teamId]: false }));
|
|
6562
6600
|
}
|
|
@@ -6860,6 +6898,8 @@ var init_LiteLLMPage = __esm({
|
|
|
6860
6898
|
getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
|
|
6861
6899
|
getTeamKeyUsage: (teamId) => keyUsageCache[teamId] ?? null,
|
|
6862
6900
|
getTeamKeyUsageLoading: (teamId) => keyUsageLoading[teamId] ?? false,
|
|
6901
|
+
getTeamMemberUsageFailed: (teamId) => memberUsageFailed[teamId] ?? false,
|
|
6902
|
+
getTeamKeyUsageFailed: (teamId) => keyUsageFailed[teamId] ?? false,
|
|
6863
6903
|
canManage: teamMgmtEnabled && canManageTeam && !readOnly,
|
|
6864
6904
|
onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
|
|
6865
6905
|
canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
|