@acarmisc/backstage-plugin-litellm 0.40.0 → 0.42.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
@@ -1640,6 +1640,7 @@ import DialogTitle from "@mui/material/DialogTitle";
1640
1640
  import DialogContent from "@mui/material/DialogContent";
1641
1641
  import DialogActions from "@mui/material/DialogActions";
1642
1642
  import TextField from "@mui/material/TextField";
1643
+ import MenuItem from "@mui/material/MenuItem";
1643
1644
  import CircularProgress from "@mui/material/CircularProgress";
1644
1645
  import Skeleton2 from "@mui/material/Skeleton";
1645
1646
  import InputAdornment from "@mui/material/InputAdornment";
@@ -1761,7 +1762,8 @@ var init_KeysTable = __esm({
1761
1762
  onDeleteKey,
1762
1763
  onPruneExpiredKeys,
1763
1764
  filter,
1764
- onClearFilter
1765
+ onClearFilter,
1766
+ teams
1765
1767
  }) => {
1766
1768
  const managePermission = usePermission({ permission: litellmKeyManagePermission });
1767
1769
  const revokePermission = usePermission({ permission: litellmKeyRevokePermission });
@@ -1778,6 +1780,7 @@ var init_KeysTable = __esm({
1778
1780
  const [deleteSubmitting, setDeleteSubmitting] = useState3(false);
1779
1781
  const clipboard = useCopyToClipboard();
1780
1782
  const [filterText, setFilterText] = useState3("");
1783
+ const [teamFilter, setTeamFilter] = useState3("");
1781
1784
  const [sortKey, setSortKey] = useState3("created");
1782
1785
  const [sortDirection, setSortDirection] = useState3("desc");
1783
1786
  const handleSort = (nextSortKey) => {
@@ -1788,9 +1791,21 @@ var init_KeysTable = __esm({
1788
1791
  setSortDirection("asc");
1789
1792
  }
1790
1793
  };
1794
+ const teamNames = useMemo2(
1795
+ () => new Map((teams ?? []).map((t) => [t.team_id, t.team_alias || t.team_id])),
1796
+ [teams]
1797
+ );
1798
+ const teamLabel = (id) => teamNames.get(id) ?? id;
1799
+ const teamIds = useMemo2(
1800
+ () => [...new Set(keys.map((k) => k.team_id).filter((t) => !!t))].sort((a, b) => (teamNames.get(a) ?? a).localeCompare(teamNames.get(b) ?? b)),
1801
+ [keys, teamNames]
1802
+ );
1791
1803
  const filteredKeys = useMemo2(() => {
1792
1804
  let result = keys;
1793
1805
  result = filterKeysByStatus(result, filter);
1806
+ if (teamFilter) {
1807
+ result = result.filter((k) => k.team_id === teamFilter);
1808
+ }
1794
1809
  if (filterText.trim()) {
1795
1810
  const q = filterText.toLowerCase();
1796
1811
  result = result.filter(
@@ -1801,7 +1816,7 @@ var init_KeysTable = __esm({
1801
1816
  const comparison = compareKeys(a, b, sortKey);
1802
1817
  return sortDirection === "asc" ? comparison : -comparison;
1803
1818
  });
1804
- }, [keys, filterText, sortKey, sortDirection, filter]);
1819
+ }, [keys, filterText, teamFilter, sortKey, sortDirection, filter]);
1805
1820
  const handleOpenEdit = (k) => {
1806
1821
  onEditKey(k);
1807
1822
  };
@@ -1860,10 +1875,10 @@ var init_KeysTable = __esm({
1860
1875
  };
1861
1876
  const renderTableBody = () => {
1862
1877
  if (loading) {
1863
- return /* @__PURE__ */ jsx8(TableRow, { children: /* @__PURE__ */ jsx8(TableCell, { colSpan: 8, sx: { py: 2 }, children: /* @__PURE__ */ jsx8(Skeleton2, { variant: "rounded", height: 140 }) }) });
1878
+ return /* @__PURE__ */ jsx8(TableRow, { children: /* @__PURE__ */ jsx8(TableCell, { colSpan: 9, sx: { py: 2 }, children: /* @__PURE__ */ jsx8(Skeleton2, { variant: "rounded", height: 140 }) }) });
1864
1879
  }
1865
1880
  if (filteredKeys.length === 0) {
1866
- return /* @__PURE__ */ jsx8(TableRow, { children: /* @__PURE__ */ jsx8(TableCell, { colSpan: 8, children: filterText ? /* @__PURE__ */ jsx8(
1881
+ return /* @__PURE__ */ jsx8(TableRow, { children: /* @__PURE__ */ jsx8(TableCell, { colSpan: 9, children: filterText || teamFilter ? /* @__PURE__ */ jsx8(
1867
1882
  EmptyState,
1868
1883
  {
1869
1884
  message: "No keys match that filter",
@@ -1907,6 +1922,7 @@ var init_KeysTable = __esm({
1907
1922
  /* @__PURE__ */ jsx8(Typography5, { variant: "body2", children: key.key_alias || "\u2014" }),
1908
1923
  key.blocked && /* @__PURE__ */ jsx8(StatusPill, { label: "Blocked", tone: "danger" })
1909
1924
  ] }) }),
1925
+ /* @__PURE__ */ jsx8(TableCell, { children: /* @__PURE__ */ jsx8(Typography5, { variant: "body2", color: "text.secondary", children: key.team_id ? teamLabel(key.team_id) : "\u2014" }) }),
1910
1926
  /* @__PURE__ */ jsx8(TableCell, { children: /* @__PURE__ */ jsxs7(Box7, { display: "flex", alignItems: "center", gap: 0.5, children: [
1911
1927
  /* @__PURE__ */ jsx8(
1912
1928
  Typography5,
@@ -1999,7 +2015,7 @@ var init_KeysTable = __esm({
1999
2015
  SectionCard,
2000
2016
  {
2001
2017
  title: "Virtual Keys",
2002
- subtitle: loading ? "Loading\u2026" : `${filteredKeys.length}${filterText ? ` of ${keys.length}` : ""} key${filteredKeys.length === 1 ? "" : "s"}`,
2018
+ subtitle: loading ? "Loading\u2026" : `${filteredKeys.length}${filterText || teamFilter ? ` of ${keys.length}` : ""} key${filteredKeys.length === 1 ? "" : "s"}`,
2003
2019
  flush: true,
2004
2020
  actions: /* @__PURE__ */ jsxs7(Fragment2, { children: [
2005
2021
  /* @__PURE__ */ jsx8(
@@ -2016,6 +2032,21 @@ var init_KeysTable = __esm({
2016
2032
  }
2017
2033
  }
2018
2034
  ),
2035
+ /* @__PURE__ */ jsxs7(
2036
+ TextField,
2037
+ {
2038
+ select: true,
2039
+ size: "small",
2040
+ label: "Team",
2041
+ value: teamFilter,
2042
+ onChange: (e) => setTeamFilter(e.target.value),
2043
+ sx: { minWidth: 160 },
2044
+ children: [
2045
+ /* @__PURE__ */ jsx8(MenuItem, { value: "", children: "All teams" }),
2046
+ teamIds.map((id) => /* @__PURE__ */ jsx8(MenuItem, { value: id, children: teamLabel(id) }, id))
2047
+ ]
2048
+ }
2049
+ ),
2019
2050
  expiredKeys.length > 0 && /* @__PURE__ */ jsxs7(
2020
2051
  Button2,
2021
2052
  {
@@ -2054,6 +2085,7 @@ var init_KeysTable = __esm({
2054
2085
  /* @__PURE__ */ jsx8(TableContainer, { children: /* @__PURE__ */ jsxs7(Table, { size: "small", sx: dataTableSx, children: [
2055
2086
  /* @__PURE__ */ jsx8(TableHead, { children: /* @__PURE__ */ jsxs7(TableRow, { children: [
2056
2087
  /* @__PURE__ */ jsx8(TableCell, { sortDirection: sortKey === "alias" ? sortDirection : false, children: /* @__PURE__ */ jsx8(TableSortLabel, { active: sortKey === "alias", direction: sortKey === "alias" ? sortDirection : "asc", onClick: () => handleSort("alias"), children: "Alias" }) }),
2088
+ /* @__PURE__ */ jsx8(TableCell, { children: "Team" }),
2057
2089
  /* @__PURE__ */ jsx8(TableCell, { children: "Key ID" }),
2058
2090
  /* @__PURE__ */ jsx8(TableCell, { sortDirection: sortKey === "created" ? sortDirection : false, children: /* @__PURE__ */ jsx8(TableSortLabel, { active: sortKey === "created", direction: sortKey === "created" ? sortDirection : "asc", onClick: () => handleSort("created"), children: "Created" }) }),
2059
2091
  /* @__PURE__ */ jsx8(TableCell, { sortDirection: sortKey === "expires" ? sortDirection : false, children: /* @__PURE__ */ jsx8(TableSortLabel, { active: sortKey === "expires", direction: sortKey === "expires" ? sortDirection : "asc", onClick: () => handleSort("expires"), children: "Expires" }) }),
@@ -2472,7 +2504,7 @@ import DialogTitle2 from "@mui/material/DialogTitle";
2472
2504
  import DialogContent2 from "@mui/material/DialogContent";
2473
2505
  import DialogActions2 from "@mui/material/DialogActions";
2474
2506
  import TextField2 from "@mui/material/TextField";
2475
- import MenuItem from "@mui/material/MenuItem";
2507
+ import MenuItem2 from "@mui/material/MenuItem";
2476
2508
  import Button3 from "@mui/material/Button";
2477
2509
  import IconButton3 from "@mui/material/IconButton";
2478
2510
  import CircularProgress2 from "@mui/material/CircularProgress";
@@ -3046,7 +3078,7 @@ var init_KeyFormDialog = __esm({
3046
3078
  value: generateForm.duration || "30d",
3047
3079
  onChange: (e) => setFormData({ duration: e.target.value }),
3048
3080
  fullWidth: true,
3049
- children: DEFAULT_KEY_DURATIONS.map((duration) => /* @__PURE__ */ jsx10(MenuItem, { value: duration, children: formatDurationLabel(duration) }, duration))
3081
+ children: DEFAULT_KEY_DURATIONS.map((duration) => /* @__PURE__ */ jsx10(MenuItem2, { value: duration, children: formatDurationLabel(duration) }, duration))
3050
3082
  }
3051
3083
  ),
3052
3084
  generateForm.duration && /* @__PURE__ */ jsx10(Typography7, { variant: "caption", color: "text.secondary", children: expiryPreview(generateForm.duration) })
@@ -3148,7 +3180,7 @@ import Checkbox2 from "@mui/material/Checkbox";
3148
3180
  import FormControlLabel2 from "@mui/material/FormControlLabel";
3149
3181
  import Autocomplete2 from "@mui/material/Autocomplete";
3150
3182
  import CircularProgress3 from "@mui/material/CircularProgress";
3151
- import MenuItem2 from "@mui/material/MenuItem";
3183
+ import MenuItem3 from "@mui/material/MenuItem";
3152
3184
  import Box10 from "@mui/material/Box";
3153
3185
  import Divider2 from "@mui/material/Divider";
3154
3186
  import Typography8 from "@mui/material/Typography";
@@ -3570,7 +3602,7 @@ var init_ManageTeamDialog = __esm({
3570
3602
  disabled: submitting || unlimited,
3571
3603
  helperText: "Spend-reset period for the team budget",
3572
3604
  fullWidth: true,
3573
- children: durationOptions.map((o) => /* @__PURE__ */ jsx11(MenuItem2, { value: o.value, children: o.label }, o.value))
3605
+ children: durationOptions.map((o) => /* @__PURE__ */ jsx11(MenuItem3, { value: o.value, children: o.label }, o.value))
3574
3606
  }
3575
3607
  )
3576
3608
  ]
@@ -3950,7 +3982,7 @@ import Paper5 from "@mui/material/Paper";
3950
3982
  import Box11 from "@mui/material/Box";
3951
3983
  import Typography9 from "@mui/material/Typography";
3952
3984
  import TextField4 from "@mui/material/TextField";
3953
- import MenuItem3 from "@mui/material/MenuItem";
3985
+ import MenuItem4 from "@mui/material/MenuItem";
3954
3986
  import Grid from "@mui/material/Grid";
3955
3987
  import Alert3 from "@mui/material/Alert";
3956
3988
  import Button5 from "@mui/material/Button";
@@ -4232,7 +4264,7 @@ var init_UsageStats = __esm({
4232
4264
  value: currentPreset,
4233
4265
  onChange: (e) => handlePresetChange(e.target.value),
4234
4266
  sx: { minWidth: 160 },
4235
- children: Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ jsx12(MenuItem3, { value: p, children: PRESET_LABELS[p] }, p))
4267
+ children: Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ jsx12(MenuItem4, { value: p, children: PRESET_LABELS[p] }, p))
4236
4268
  }
4237
4269
  );
4238
4270
  if (usageError) {
@@ -4293,8 +4325,8 @@ var init_UsageStats = __esm({
4293
4325
  onChange: (e) => setSelectedModel(e.target.value),
4294
4326
  sx: { minWidth: 220 },
4295
4327
  children: [
4296
- /* @__PURE__ */ jsx12(MenuItem3, { value: "all", children: "All models" }),
4297
- models.filter((m) => modelsInPeriod.includes(m.model_name)).map((m) => /* @__PURE__ */ jsx12(MenuItem3, { value: m.model_name, children: m.model_name }, m.model_name))
4328
+ /* @__PURE__ */ jsx12(MenuItem4, { value: "all", children: "All models" }),
4329
+ models.filter((m) => modelsInPeriod.includes(m.model_name)).map((m) => /* @__PURE__ */ jsx12(MenuItem4, { value: m.model_name, children: m.model_name }, m.model_name))
4298
4330
  ]
4299
4331
  }
4300
4332
  )
@@ -5082,7 +5114,7 @@ var init_TeamUsage = __esm({
5082
5114
  }) })
5083
5115
  ] }) });
5084
5116
  };
5085
- TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
5117
+ TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
5086
5118
  const [expanded, setExpanded] = useState9(false);
5087
5119
  const chart = useChartTheme();
5088
5120
  const handleExpandChange = (newExpanded) => {
@@ -5149,6 +5181,10 @@ var init_TeamUsage = __esm({
5149
5181
  children: label
5150
5182
  }
5151
5183
  );
5184
+ const renderNamedTags = (label, ids, items) => /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
5185
+ sectionLabel(label),
5186
+ ids?.length ? /* @__PURE__ */ jsx15(Box14, { display: "flex", gap: 0.5, flexWrap: "wrap", children: ids.map((id) => /* @__PURE__ */ jsx15(TagChip, { label: items?.find((i) => i.id === id)?.name ?? id, title: id }, id)) }) : /* @__PURE__ */ jsx15(Typography12, { variant: "body2", color: "text.secondary", children: "None configured" })
5187
+ ] });
5152
5188
  return /* @__PURE__ */ jsxs14(Paper8, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 }, children: [
5153
5189
  /* @__PURE__ */ jsxs14(Box14, { display: "flex", alignItems: "center", gap: 1.5, children: [
5154
5190
  /* @__PURE__ */ jsx15(
@@ -5274,6 +5310,8 @@ var init_TeamUsage = __esm({
5274
5310
  sectionLabel("Models"),
5275
5311
  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" })
5276
5312
  ] }),
5313
+ renderNamedTags("Knowledge bases", team.object_permission?.vector_stores, vectorStores),
5314
+ renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
5277
5315
  renderDailySpendSection(),
5278
5316
  (memberUsageLoading || memberUsage) && /* @__PURE__ */ jsxs14(Box14, { mb: 2.5, children: [
5279
5317
  sectionLabel("Usage by member"),
@@ -5342,7 +5380,9 @@ var init_TeamUsage = __esm({
5342
5380
  onTeamExpand,
5343
5381
  canManageMembers,
5344
5382
  onManageMembers,
5345
- readOnly
5383
+ readOnly,
5384
+ vectorStores,
5385
+ mcpServers
5346
5386
  }) => {
5347
5387
  const readOnlyBadge = /* @__PURE__ */ jsx15(MuiTooltip, { title: "Teams and memberships are managed in your identity provider. Changes made here would be overwritten, so editing is disabled.", children: /* @__PURE__ */ jsxs14(
5348
5388
  Box14,
@@ -5400,7 +5440,9 @@ var init_TeamUsage = __esm({
5400
5440
  onEditTeam,
5401
5441
  canManageMembers: canManageMembers?.(team),
5402
5442
  onManageMembers,
5403
- onExpand: onTeamExpand
5443
+ onExpand: onTeamExpand,
5444
+ vectorStores,
5445
+ mcpServers
5404
5446
  },
5405
5447
  team.team_id
5406
5448
  )) })
@@ -5421,7 +5463,7 @@ import TableHead5 from "@mui/material/TableHead";
5421
5463
  import TableRow5 from "@mui/material/TableRow";
5422
5464
  import TableSortLabel2 from "@mui/material/TableSortLabel";
5423
5465
  import Typography13 from "@mui/material/Typography";
5424
- import MenuItem4 from "@mui/material/MenuItem";
5466
+ import MenuItem5 from "@mui/material/MenuItem";
5425
5467
  import Select from "@mui/material/Select";
5426
5468
  import FormControl from "@mui/material/FormControl";
5427
5469
  import InputLabel from "@mui/material/InputLabel";
@@ -5560,7 +5602,7 @@ var init_ModelsTable = __esm({
5560
5602
  value: selectedTeamId,
5561
5603
  label: "Team",
5562
5604
  onChange: (e) => setSelectedTeamId(e.target.value),
5563
- children: teams.map((t) => /* @__PURE__ */ jsx16(MenuItem4, { value: t.team_id, children: t.team_alias ?? t.team_id }, t.team_id))
5605
+ children: teams.map((t) => /* @__PURE__ */ jsx16(MenuItem5, { value: t.team_id, children: t.team_alias ?? t.team_id }, t.team_id))
5564
5606
  }
5565
5607
  )
5566
5608
  ] }),
@@ -6375,12 +6417,12 @@ var init_LiteLLMPage = __esm({
6375
6417
  const teamMgmtEnabled = liteLlmConfig?.teamManagement?.enabled ?? false;
6376
6418
  const objectPermsEnabled = liteLlmConfig?.teamManagement?.objectPermissionsEnabled ?? false;
6377
6419
  const { value: vectorStores } = useAsync(
6378
- async () => objectPermsEnabled ? api.getVectorStores().catch(() => []) : [],
6379
- [api, objectPermsEnabled]
6420
+ () => api.getVectorStores().catch(() => []),
6421
+ [api]
6380
6422
  );
6381
6423
  const { value: mcpServers } = useAsync(
6382
- async () => objectPermsEnabled ? api.getMcpServers().catch(() => []) : [],
6383
- [api, objectPermsEnabled]
6424
+ () => api.getMcpServers().catch(() => []),
6425
+ [api]
6384
6426
  );
6385
6427
  const teams = useMemo9(() => {
6386
6428
  if (!allTeams?.length) return [];
@@ -6706,7 +6748,8 @@ var init_LiteLLMPage = __esm({
6706
6748
  onDeleteKey: handleDeleteKey,
6707
6749
  onPruneExpiredKeys: handlePruneExpiredKeys,
6708
6750
  filter,
6709
- onClearFilter: clearFilter
6751
+ onClearFilter: clearFilter,
6752
+ teams: allTeams ?? []
6710
6753
  }
6711
6754
  );
6712
6755
  })(),
@@ -6737,6 +6780,8 @@ var init_LiteLLMPage = __esm({
6737
6780
  onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
6738
6781
  canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
6739
6782
  onCreateTeam: () => setManageTeam({ mode: "create" }),
6783
+ vectorStores: vectorStores ?? [],
6784
+ mcpServers: mcpServers ?? [],
6740
6785
  canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
6741
6786
  onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
6742
6787
  readOnly,
@@ -7109,7 +7154,7 @@ import Box19 from "@mui/material/Box";
7109
7154
  import Typography17 from "@mui/material/Typography";
7110
7155
  import FormControl2 from "@mui/material/FormControl";
7111
7156
  import Select2 from "@mui/material/Select";
7112
- import MenuItem5 from "@mui/material/MenuItem";
7157
+ import MenuItem6 from "@mui/material/MenuItem";
7113
7158
  import Skeleton7 from "@mui/material/Skeleton";
7114
7159
  import { AreaChart as AreaChart3, Area as Area3, XAxis as XAxis3, Tooltip as Tooltip8, ResponsiveContainer as ResponsiveContainer3 } from "recharts";
7115
7160
  import { useApi as useApi6 } from "@backstage/core-plugin-api";
@@ -7239,9 +7284,9 @@ var LiteLLMHomeWidget = ({
7239
7284
  displayEmpty: true,
7240
7285
  inputProps: { "aria-label": "Usage period" },
7241
7286
  children: [
7242
- /* @__PURE__ */ jsx21(MenuItem5, { value: "today", children: "Today" }),
7243
- /* @__PURE__ */ jsx21(MenuItem5, { value: "7d", children: "7d" }),
7244
- /* @__PURE__ */ jsx21(MenuItem5, { value: "30d", children: "30d" })
7287
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "today", children: "Today" }),
7288
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "7d", children: "7d" }),
7289
+ /* @__PURE__ */ jsx21(MenuItem6, { value: "30d", children: "30d" })
7245
7290
  ]
7246
7291
  }
7247
7292
  ) })