@acarmisc/backstage-plugin-litellm 0.43.0 → 0.44.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/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
- TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
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, keyUsage, keyUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
5124
5170
  const [expanded, setExpanded] = useState9(false);
5125
5171
  const chart = useChartTheme();
5126
5172
  const handleExpandChange = (newExpanded) => {
@@ -5323,6 +5369,10 @@ var init_TeamUsage = __esm({
5323
5369
  sectionLabel("Usage by member"),
5324
5370
  memberUsage ? /* @__PURE__ */ jsx15(MemberUsageTable, { usage: memberUsage }) : /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
5325
5371
  ] }),
5372
+ (keyUsageLoading || keyUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
5373
+ sectionLabel("Keys by member"),
5374
+ keyUsage ? /* @__PURE__ */ jsx15(TeamKeyUsageTable, { usage: keyUsage }) : /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
5375
+ ] }),
5326
5376
  /* @__PURE__ */ jsxs14(Box14, { children: [
5327
5377
  sectionLabel("Members"),
5328
5378
  team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
@@ -5379,6 +5429,8 @@ var init_TeamUsage = __esm({
5379
5429
  getTeamUsageLoading,
5380
5430
  getTeamMemberUsage,
5381
5431
  getTeamMemberUsageLoading,
5432
+ getTeamKeyUsage,
5433
+ getTeamKeyUsageLoading,
5382
5434
  canManage,
5383
5435
  onEditTeam,
5384
5436
  canCreate,
@@ -5442,6 +5494,8 @@ var init_TeamUsage = __esm({
5442
5494
  usageLoading: getTeamUsageLoading(team.team_id),
5443
5495
  memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
5444
5496
  memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
5497
+ keyUsage: getTeamKeyUsage?.(team.team_id) ?? null,
5498
+ keyUsageLoading: getTeamKeyUsageLoading?.(team.team_id) ?? false,
5445
5499
  canManage,
5446
5500
  onEditTeam,
5447
5501
  canManageMembers: canManageMembers?.(team),
@@ -6394,6 +6448,8 @@ var init_LiteLLMPage = __esm({
6394
6448
  const [teamUsageLoading, setTeamUsageLoading] = useState11({});
6395
6449
  const [memberUsageCache, setMemberUsageCache] = useState11({});
6396
6450
  const [memberUsageLoading, setMemberUsageLoading] = useState11({});
6451
+ const [keyUsageCache, setKeyUsageCache] = useState11({});
6452
+ const [keyUsageLoading, setKeyUsageLoading] = useState11({});
6397
6453
  const { value: userInfo, loading: userLoading, error: userError } = useAsync(
6398
6454
  () => api.getUserInfo(),
6399
6455
  [api]
@@ -6460,6 +6516,8 @@ var init_LiteLLMPage = __esm({
6460
6516
  setTeamUsageLoading({});
6461
6517
  setMemberUsageCache({});
6462
6518
  setMemberUsageLoading({});
6519
+ setKeyUsageCache({});
6520
+ setKeyUsageLoading({});
6463
6521
  }, [setDateRange, setCurrentPreset]);
6464
6522
  const loadTeamUsage = useCallback4(async (teamId) => {
6465
6523
  if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
@@ -6489,6 +6547,20 @@ var init_LiteLLMPage = __esm({
6489
6547
  setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
6490
6548
  }
6491
6549
  }, [api, dateRange, memberUsageCache, memberUsageLoading]);
6550
+ const loadKeyUsage = useCallback4(async (teamId) => {
6551
+ if (keyUsageCache[teamId] !== void 0 || keyUsageLoading[teamId]) return;
6552
+ setKeyUsageLoading((prev) => ({ ...prev, [teamId]: true }));
6553
+ try {
6554
+ const startDate = toLocalDay(dateRange.start);
6555
+ const endDate = toLocalDay(dateRange.end);
6556
+ const data = await api.getTeamKeyUsage(teamId, startDate, endDate);
6557
+ setKeyUsageCache((prev) => ({ ...prev, [teamId]: data }));
6558
+ } catch {
6559
+ setKeyUsageCache((prev) => ({ ...prev, [teamId]: null }));
6560
+ } finally {
6561
+ setKeyUsageLoading((prev) => ({ ...prev, [teamId]: false }));
6562
+ }
6563
+ }, [api, dateRange, keyUsageCache, keyUsageLoading]);
6492
6564
  const allowedModels = useMemo9(() => {
6493
6565
  if (!allModels?.length) return [];
6494
6566
  const userModels = userInfo?.models;
@@ -6786,6 +6858,8 @@ var init_LiteLLMPage = __esm({
6786
6858
  getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
6787
6859
  getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
6788
6860
  getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
6861
+ getTeamKeyUsage: (teamId) => keyUsageCache[teamId] ?? null,
6862
+ getTeamKeyUsageLoading: (teamId) => keyUsageLoading[teamId] ?? false,
6789
6863
  canManage: teamMgmtEnabled && canManageTeam && !readOnly,
6790
6864
  onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
6791
6865
  canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
@@ -6797,7 +6871,10 @@ var init_LiteLLMPage = __esm({
6797
6871
  readOnly,
6798
6872
  onTeamExpand: (team) => {
6799
6873
  loadTeamUsage(team.team_id);
6800
- if (liteLlmConfig?.teamUsage?.memberBreakdown) loadMemberUsage(team.team_id);
6874
+ if (liteLlmConfig?.teamUsage?.memberBreakdown) {
6875
+ loadMemberUsage(team.team_id);
6876
+ loadKeyUsage(team.team_id);
6877
+ }
6801
6878
  }
6802
6879
  }
6803
6880
  );