@acarmisc/backstage-plugin-litellm 0.42.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
@@ -265,6 +265,10 @@ var init_api = __esm({
265
265
  async getVectorStores() {
266
266
  return this.get("/vector-stores");
267
267
  }
268
+ // Names only, readable by any signed-in user; never used for the picker.
269
+ async getObjectNames() {
270
+ return this.get("/object-names");
271
+ }
268
272
  async setTeamKnowledgeBases(teamId, vectorStores) {
269
273
  return this.put(
270
274
  `/teams/${encodeURIComponent(teamId)}/knowledge-bases`,
@@ -295,6 +299,12 @@ var init_api = __esm({
295
299
  end_date: endDate
296
300
  });
297
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
+ }
298
308
  async getSpendLogs(params) {
299
309
  const strParams = {
300
310
  start_date: params.startDate,
@@ -3225,9 +3235,11 @@ var init_ManageTeamDialog = __esm({
3225
3235
  onRemoveMember,
3226
3236
  canManageKnowledgeBases,
3227
3237
  vectorStores,
3238
+ vectorStoreNames,
3228
3239
  onSaveKnowledgeBases,
3229
3240
  canManageMcpServers,
3230
3241
  mcpServers,
3242
+ mcpServerNames,
3231
3243
  onSaveMcpServers,
3232
3244
  membersOnly,
3233
3245
  currentUserId,
@@ -3496,10 +3508,10 @@ var init_ManageTeamDialog = __esm({
3496
3508
  const durationOptions = BUDGET_DURATION_OPTIONS.some((o) => o.value === budgetDuration) ? BUDGET_DURATION_OPTIONS : [...BUDGET_DURATION_OPTIONS, { value: budgetDuration, label: budgetDuration }];
3497
3509
  const showKnowledgeBases = mode === "edit" && !!canManageKnowledgeBases;
3498
3510
  const kbOptions = (vectorStores ?? []).map((v) => v.id);
3499
- const kbLabel = (id) => (vectorStores ?? []).find((v) => v.id === id)?.name ?? id;
3511
+ const kbLabel = (id) => (vectorStoreNames ?? []).find((v) => v.id === id)?.name ?? id;
3500
3512
  const showMcpServers = mode === "edit" && !!canManageMcpServers;
3501
3513
  const mcpOptions = (mcpServers ?? []).map((s) => s.id);
3502
- const mcpLabel = (id) => (mcpServers ?? []).find((s) => s.id === id)?.name ?? id;
3514
+ const mcpLabel = (id) => (mcpServerNames ?? []).find((s) => s.id === id)?.name ?? id;
3503
3515
  const isRemovalDisabled = (memberUserId, memberRole) => {
3504
3516
  if (!membersOnly) return { disabled: false };
3505
3517
  if (memberUserId === currentUserId) {
@@ -5072,7 +5084,7 @@ function budgetStatValue(hidden, budget) {
5072
5084
  if (budget > 0) return fmtUsd2(budget);
5073
5085
  return "Unlimited";
5074
5086
  }
5075
- var fmtUsd2, monoSx, MemberUsageTable, TeamCard, TeamUsage;
5087
+ var fmtUsd2, monoSx, MemberUsageTable, TeamKeyUsageTable, TeamCard, TeamUsage;
5076
5088
  var init_TeamUsage = __esm({
5077
5089
  "src/components/TeamUsage.tsx"() {
5078
5090
  "use strict";
@@ -5114,7 +5126,47 @@ var init_TeamUsage = __esm({
5114
5126
  }) })
5115
5127
  ] }) });
5116
5128
  };
5117
- 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 }) => {
5118
5170
  const [expanded, setExpanded] = useState9(false);
5119
5171
  const chart = useChartTheme();
5120
5172
  const handleExpandChange = (newExpanded) => {
@@ -5317,6 +5369,10 @@ var init_TeamUsage = __esm({
5317
5369
  sectionLabel("Usage by member"),
5318
5370
  memberUsage ? /* @__PURE__ */ jsx15(MemberUsageTable, { usage: memberUsage }) : /* @__PURE__ */ jsx15(Box14, { display: "flex", justifyContent: "center", py: 2, children: /* @__PURE__ */ jsx15(CircularProgress4, { size: 22 }) })
5319
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
+ ] }),
5320
5376
  /* @__PURE__ */ jsxs14(Box14, { children: [
5321
5377
  sectionLabel("Members"),
5322
5378
  team.members_with_roles?.length ? /* @__PURE__ */ jsx15(
@@ -5373,6 +5429,8 @@ var init_TeamUsage = __esm({
5373
5429
  getTeamUsageLoading,
5374
5430
  getTeamMemberUsage,
5375
5431
  getTeamMemberUsageLoading,
5432
+ getTeamKeyUsage,
5433
+ getTeamKeyUsageLoading,
5376
5434
  canManage,
5377
5435
  onEditTeam,
5378
5436
  canCreate,
@@ -5436,6 +5494,8 @@ var init_TeamUsage = __esm({
5436
5494
  usageLoading: getTeamUsageLoading(team.team_id),
5437
5495
  memberUsage: getTeamMemberUsage?.(team.team_id) ?? null,
5438
5496
  memberUsageLoading: getTeamMemberUsageLoading?.(team.team_id) ?? false,
5497
+ keyUsage: getTeamKeyUsage?.(team.team_id) ?? null,
5498
+ keyUsageLoading: getTeamKeyUsageLoading?.(team.team_id) ?? false,
5439
5499
  canManage,
5440
5500
  onEditTeam,
5441
5501
  canManageMembers: canManageMembers?.(team),
@@ -6388,6 +6448,8 @@ var init_LiteLLMPage = __esm({
6388
6448
  const [teamUsageLoading, setTeamUsageLoading] = useState11({});
6389
6449
  const [memberUsageCache, setMemberUsageCache] = useState11({});
6390
6450
  const [memberUsageLoading, setMemberUsageLoading] = useState11({});
6451
+ const [keyUsageCache, setKeyUsageCache] = useState11({});
6452
+ const [keyUsageLoading, setKeyUsageLoading] = useState11({});
6391
6453
  const { value: userInfo, loading: userLoading, error: userError } = useAsync(
6392
6454
  () => api.getUserInfo(),
6393
6455
  [api]
@@ -6424,6 +6486,10 @@ var init_LiteLLMPage = __esm({
6424
6486
  () => api.getMcpServers().catch(() => []),
6425
6487
  [api]
6426
6488
  );
6489
+ const { value: objectNames } = useAsync(
6490
+ () => api.getObjectNames().catch(() => ({ vector_stores: [], mcp_servers: [] })),
6491
+ [api]
6492
+ );
6427
6493
  const teams = useMemo9(() => {
6428
6494
  if (!allTeams?.length) return [];
6429
6495
  if (!userInfo) return allTeams;
@@ -6450,6 +6516,8 @@ var init_LiteLLMPage = __esm({
6450
6516
  setTeamUsageLoading({});
6451
6517
  setMemberUsageCache({});
6452
6518
  setMemberUsageLoading({});
6519
+ setKeyUsageCache({});
6520
+ setKeyUsageLoading({});
6453
6521
  }, [setDateRange, setCurrentPreset]);
6454
6522
  const loadTeamUsage = useCallback4(async (teamId) => {
6455
6523
  if (teamUsageCache[teamId] !== void 0 || teamUsageLoading[teamId]) return;
@@ -6479,6 +6547,20 @@ var init_LiteLLMPage = __esm({
6479
6547
  setMemberUsageLoading((prev) => ({ ...prev, [teamId]: false }));
6480
6548
  }
6481
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]);
6482
6564
  const allowedModels = useMemo9(() => {
6483
6565
  if (!allModels?.length) return [];
6484
6566
  const userModels = userInfo?.models;
@@ -6776,18 +6858,23 @@ var init_LiteLLMPage = __esm({
6776
6858
  getTeamUsageLoading: (teamId) => teamUsageLoading[teamId] ?? false,
6777
6859
  getTeamMemberUsage: (teamId) => memberUsageCache[teamId] ?? null,
6778
6860
  getTeamMemberUsageLoading: (teamId) => memberUsageLoading[teamId] ?? false,
6861
+ getTeamKeyUsage: (teamId) => keyUsageCache[teamId] ?? null,
6862
+ getTeamKeyUsageLoading: (teamId) => keyUsageLoading[teamId] ?? false,
6779
6863
  canManage: teamMgmtEnabled && canManageTeam && !readOnly,
6780
6864
  onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
6781
6865
  canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
6782
6866
  onCreateTeam: () => setManageTeam({ mode: "create" }),
6783
- vectorStores: vectorStores ?? [],
6784
- mcpServers: mcpServers ?? [],
6867
+ vectorStores: objectNames?.vector_stores ?? [],
6868
+ mcpServers: objectNames?.mcp_servers ?? [],
6785
6869
  canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
6786
6870
  onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
6787
6871
  readOnly,
6788
6872
  onTeamExpand: (team) => {
6789
6873
  loadTeamUsage(team.team_id);
6790
- if (liteLlmConfig?.teamUsage?.memberBreakdown) loadMemberUsage(team.team_id);
6874
+ if (liteLlmConfig?.teamUsage?.memberBreakdown) {
6875
+ loadMemberUsage(team.team_id);
6876
+ loadKeyUsage(team.team_id);
6877
+ }
6791
6878
  }
6792
6879
  }
6793
6880
  );
@@ -6913,6 +7000,7 @@ var init_LiteLLMPage = __esm({
6913
7000
  },
6914
7001
  canManageKnowledgeBases: teamMgmtEnabled && objectPermsEnabled && canManageKnowledgeBases,
6915
7002
  vectorStores: vectorStores ?? [],
7003
+ vectorStoreNames: objectNames?.vector_stores ?? [],
6916
7004
  onSaveKnowledgeBases: async (vectorStoreIds) => {
6917
7005
  if (!manageTeam?.team) return;
6918
7006
  try {
@@ -6931,6 +7019,7 @@ var init_LiteLLMPage = __esm({
6931
7019
  },
6932
7020
  canManageMcpServers: teamMgmtEnabled && objectPermsEnabled && canManageMcpServers,
6933
7021
  mcpServers: mcpServers ?? [],
7022
+ mcpServerNames: objectNames?.mcp_servers ?? [],
6934
7023
  onSaveMcpServers: async (mcpServerIds) => {
6935
7024
  if (!manageTeam?.team) return;
6936
7025
  try {