@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.
@@ -1,6 +1,6 @@
1
1
  import { FC } from 'react';
2
2
  import { type KeyFilterType } from '../keyFilter';
3
- import { VirtualKey } from '../types';
3
+ import { TeamInfo, VirtualKey } from '../types';
4
4
  interface KeysTableProps {
5
5
  keys: VirtualKey[];
6
6
  /** Opens the shared key form dialog in create mode (rendered at page level). */
@@ -16,6 +16,8 @@ interface KeysTableProps {
16
16
  }>;
17
17
  filter?: KeyFilterType;
18
18
  onClearFilter?: () => void;
19
+ /** Used to show team names instead of raw team ids. */
20
+ teams?: TeamInfo[];
19
21
  }
20
22
  export declare const KeysTable: FC<KeysTableProps>;
21
23
  export {};
@@ -1,5 +1,5 @@
1
1
  import { FC } from 'react';
2
- import { TeamInfo, TeamMemberUsage, UsageMetrics } from '../types';
2
+ import { McpServerInfo, TeamInfo, TeamMemberUsage, UsageMetrics, VectorStoreInfo } from '../types';
3
3
  /**
4
4
  * Per-member usage for the period, sorted by spend. Dollars are replaced by
5
5
  * the share of team spend when the backend hides them.
@@ -27,6 +27,10 @@ interface TeamUsageProps {
27
27
  onManageMembers?: (team: TeamInfo) => void;
28
28
  /** Teams are synced from an identity provider: show a badge, no write controls. */
29
29
  readOnly?: boolean;
30
+ /** Used to show knowledge base names instead of raw ids. */
31
+ vectorStores?: VectorStoreInfo[];
32
+ /** Used to show MCP server names instead of raw ids. */
33
+ mcpServers?: McpServerInfo[];
30
34
  }
31
35
  export declare const TeamUsage: FC<TeamUsageProps>;
32
36
  export {};
package/dist/index.cjs.js CHANGED
@@ -1721,7 +1721,7 @@ function compareKeys(a, b, sortKey) {
1721
1721
  return 0;
1722
1722
  }
1723
1723
  }
1724
- var import_react4, import_Table, import_TableBody, import_TableCell, import_TableContainer, import_TableHead, import_TableRow, import_TableSortLabel, import_Button2, import_IconButton, import_Box7, import_Typography5, import_Dialog, import_DialogTitle, import_DialogContent, import_DialogActions, import_TextField, import_CircularProgress, import_Skeleton2, import_InputAdornment, import_Tooltip, import_Chip, import_styles7, import_icons_material2, import_plugin_permission_react, import_backstage_plugin_litellm_common, import_jsx_runtime8, shortKeyId, formatDate, KeysTable;
1724
+ var import_react4, import_Table, import_TableBody, import_TableCell, import_TableContainer, import_TableHead, import_TableRow, import_TableSortLabel, import_Button2, import_IconButton, import_Box7, import_Typography5, import_Dialog, import_DialogTitle, import_DialogContent, import_DialogActions, import_TextField, import_MenuItem, import_CircularProgress, import_Skeleton2, import_InputAdornment, import_Tooltip, import_Chip, import_styles7, import_icons_material2, import_plugin_permission_react, import_backstage_plugin_litellm_common, import_jsx_runtime8, shortKeyId, formatDate, KeysTable;
1725
1725
  var init_KeysTable = __esm({
1726
1726
  "src/components/KeysTable.tsx"() {
1727
1727
  "use strict";
@@ -1742,6 +1742,7 @@ var init_KeysTable = __esm({
1742
1742
  import_DialogContent = __toESM(require("@mui/material/DialogContent"));
1743
1743
  import_DialogActions = __toESM(require("@mui/material/DialogActions"));
1744
1744
  import_TextField = __toESM(require("@mui/material/TextField"));
1745
+ import_MenuItem = __toESM(require("@mui/material/MenuItem"));
1745
1746
  import_CircularProgress = __toESM(require("@mui/material/CircularProgress"));
1746
1747
  import_Skeleton2 = __toESM(require("@mui/material/Skeleton"));
1747
1748
  import_InputAdornment = __toESM(require("@mui/material/InputAdornment"));
@@ -1781,7 +1782,8 @@ var init_KeysTable = __esm({
1781
1782
  onDeleteKey,
1782
1783
  onPruneExpiredKeys,
1783
1784
  filter,
1784
- onClearFilter
1785
+ onClearFilter,
1786
+ teams
1785
1787
  }) => {
1786
1788
  const managePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyManagePermission });
1787
1789
  const revokePermission = (0, import_plugin_permission_react.usePermission)({ permission: import_backstage_plugin_litellm_common.litellmKeyRevokePermission });
@@ -1798,6 +1800,7 @@ var init_KeysTable = __esm({
1798
1800
  const [deleteSubmitting, setDeleteSubmitting] = (0, import_react4.useState)(false);
1799
1801
  const clipboard = useCopyToClipboard();
1800
1802
  const [filterText, setFilterText] = (0, import_react4.useState)("");
1803
+ const [teamFilter, setTeamFilter] = (0, import_react4.useState)("");
1801
1804
  const [sortKey, setSortKey] = (0, import_react4.useState)("created");
1802
1805
  const [sortDirection, setSortDirection] = (0, import_react4.useState)("desc");
1803
1806
  const handleSort = (nextSortKey) => {
@@ -1808,9 +1811,21 @@ var init_KeysTable = __esm({
1808
1811
  setSortDirection("asc");
1809
1812
  }
1810
1813
  };
1814
+ const teamNames = (0, import_react4.useMemo)(
1815
+ () => new Map((teams ?? []).map((t) => [t.team_id, t.team_alias || t.team_id])),
1816
+ [teams]
1817
+ );
1818
+ const teamLabel = (id) => teamNames.get(id) ?? id;
1819
+ const teamIds = (0, import_react4.useMemo)(
1820
+ () => [...new Set(keys.map((k) => k.team_id).filter((t) => !!t))].sort((a, b) => (teamNames.get(a) ?? a).localeCompare(teamNames.get(b) ?? b)),
1821
+ [keys, teamNames]
1822
+ );
1811
1823
  const filteredKeys = (0, import_react4.useMemo)(() => {
1812
1824
  let result = keys;
1813
1825
  result = filterKeysByStatus(result, filter);
1826
+ if (teamFilter) {
1827
+ result = result.filter((k) => k.team_id === teamFilter);
1828
+ }
1814
1829
  if (filterText.trim()) {
1815
1830
  const q = filterText.toLowerCase();
1816
1831
  result = result.filter(
@@ -1821,7 +1836,7 @@ var init_KeysTable = __esm({
1821
1836
  const comparison = compareKeys(a, b, sortKey);
1822
1837
  return sortDirection === "asc" ? comparison : -comparison;
1823
1838
  });
1824
- }, [keys, filterText, sortKey, sortDirection, filter]);
1839
+ }, [keys, filterText, teamFilter, sortKey, sortDirection, filter]);
1825
1840
  const handleOpenEdit = (k) => {
1826
1841
  onEditKey(k);
1827
1842
  };
@@ -1880,10 +1895,10 @@ var init_KeysTable = __esm({
1880
1895
  };
1881
1896
  const renderTableBody = () => {
1882
1897
  if (loading) {
1883
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableRow.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { colSpan: 8, sx: { py: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Skeleton2.default, { variant: "rounded", height: 140 }) }) });
1898
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableRow.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { colSpan: 9, sx: { py: 2 }, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Skeleton2.default, { variant: "rounded", height: 140 }) }) });
1884
1899
  }
1885
1900
  if (filteredKeys.length === 0) {
1886
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableRow.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { colSpan: 8, children: filterText ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1901
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableRow.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { colSpan: 9, children: filterText || teamFilter ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1887
1902
  EmptyState,
1888
1903
  {
1889
1904
  message: "No keys match that filter",
@@ -1927,6 +1942,7 @@ var init_KeysTable = __esm({
1927
1942
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography5.default, { variant: "body2", children: key.key_alias || "\u2014" }),
1928
1943
  key.blocked && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(StatusPill, { label: "Blocked", tone: "danger" })
1929
1944
  ] }) }),
1945
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_Typography5.default, { variant: "body2", color: "text.secondary", children: key.team_id ? teamLabel(key.team_id) : "\u2014" }) }),
1930
1946
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_Box7.default, { display: "flex", alignItems: "center", gap: 0.5, children: [
1931
1947
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1932
1948
  import_Typography5.default,
@@ -2019,7 +2035,7 @@ var init_KeysTable = __esm({
2019
2035
  SectionCard,
2020
2036
  {
2021
2037
  title: "Virtual Keys",
2022
- subtitle: loading ? "Loading\u2026" : `${filteredKeys.length}${filterText ? ` of ${keys.length}` : ""} key${filteredKeys.length === 1 ? "" : "s"}`,
2038
+ subtitle: loading ? "Loading\u2026" : `${filteredKeys.length}${filterText || teamFilter ? ` of ${keys.length}` : ""} key${filteredKeys.length === 1 ? "" : "s"}`,
2023
2039
  flush: true,
2024
2040
  actions: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
2025
2041
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
@@ -2036,6 +2052,21 @@ var init_KeysTable = __esm({
2036
2052
  }
2037
2053
  }
2038
2054
  ),
2055
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2056
+ import_TextField.default,
2057
+ {
2058
+ select: true,
2059
+ size: "small",
2060
+ label: "Team",
2061
+ value: teamFilter,
2062
+ onChange: (e) => setTeamFilter(e.target.value),
2063
+ sx: { minWidth: 160 },
2064
+ children: [
2065
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_MenuItem.default, { value: "", children: "All teams" }),
2066
+ teamIds.map((id) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_MenuItem.default, { value: id, children: teamLabel(id) }, id))
2067
+ ]
2068
+ }
2069
+ ),
2039
2070
  expiredKeys.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2040
2071
  import_Button2.default,
2041
2072
  {
@@ -2074,6 +2105,7 @@ var init_KeysTable = __esm({
2074
2105
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableContainer.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_Table.default, { size: "small", sx: dataTableSx, children: [
2075
2106
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableHead.default, { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_TableRow.default, { children: [
2076
2107
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { sortDirection: sortKey === "alias" ? sortDirection : false, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableSortLabel.default, { active: sortKey === "alias", direction: sortKey === "alias" ? sortDirection : "asc", onClick: () => handleSort("alias"), children: "Alias" }) }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: "Team" }),
2077
2109
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { children: "Key ID" }),
2078
2110
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { sortDirection: sortKey === "created" ? sortDirection : false, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableSortLabel.default, { active: sortKey === "created", direction: sortKey === "created" ? sortDirection : "asc", onClick: () => handleSort("created"), children: "Created" }) }),
2079
2111
  /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableCell.default, { sortDirection: sortKey === "expires" ? sortDirection : false, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_TableSortLabel.default, { active: sortKey === "expires", direction: sortKey === "expires" ? sortDirection : "asc", onClick: () => handleSort("expires"), children: "Expires" }) }),
@@ -2504,7 +2536,7 @@ function formatContextWindow(maxInput, maxOutput) {
2504
2536
  if (outPart) return `ctx ${outPart} out`;
2505
2537
  return null;
2506
2538
  }
2507
- var import_react6, import_Box9, import_Typography7, import_Dialog2, import_DialogTitle2, import_DialogContent2, import_DialogActions2, import_TextField2, import_MenuItem, import_Button3, import_IconButton3, import_CircularProgress2, import_Autocomplete, import_Checkbox, import_FormControlLabel, import_Alert, import_Accordion, import_AccordionSummary, import_AccordionDetails, import_Tooltip3, import_InputAdornment2, import_Chip2, import_icons_material4, import_plugin_permission_react2, import_backstage_plugin_litellm_common3, import_jsx_runtime10, KeyFormDialog;
2539
+ var import_react6, import_Box9, import_Typography7, import_Dialog2, import_DialogTitle2, import_DialogContent2, import_DialogActions2, import_TextField2, import_MenuItem2, import_Button3, import_IconButton3, import_CircularProgress2, import_Autocomplete, import_Checkbox, import_FormControlLabel, import_Alert, import_Accordion, import_AccordionSummary, import_AccordionDetails, import_Tooltip3, import_InputAdornment2, import_Chip2, import_icons_material4, import_plugin_permission_react2, import_backstage_plugin_litellm_common3, import_jsx_runtime10, KeyFormDialog;
2508
2540
  var init_KeyFormDialog = __esm({
2509
2541
  "src/components/KeyFormDialog.tsx"() {
2510
2542
  "use strict";
@@ -2516,7 +2548,7 @@ var init_KeyFormDialog = __esm({
2516
2548
  import_DialogContent2 = __toESM(require("@mui/material/DialogContent"));
2517
2549
  import_DialogActions2 = __toESM(require("@mui/material/DialogActions"));
2518
2550
  import_TextField2 = __toESM(require("@mui/material/TextField"));
2519
- import_MenuItem = __toESM(require("@mui/material/MenuItem"));
2551
+ import_MenuItem2 = __toESM(require("@mui/material/MenuItem"));
2520
2552
  import_Button3 = __toESM(require("@mui/material/Button"));
2521
2553
  import_IconButton3 = __toESM(require("@mui/material/IconButton"));
2522
2554
  import_CircularProgress2 = __toESM(require("@mui/material/CircularProgress"));
@@ -3066,7 +3098,7 @@ var init_KeyFormDialog = __esm({
3066
3098
  value: generateForm.duration || "30d",
3067
3099
  onChange: (e) => setFormData({ duration: e.target.value }),
3068
3100
  fullWidth: true,
3069
- children: import_backstage_plugin_litellm_common3.DEFAULT_KEY_DURATIONS.map((duration) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_MenuItem.default, { value: duration, children: (0, import_backstage_plugin_litellm_common3.formatDurationLabel)(duration) }, duration))
3101
+ children: import_backstage_plugin_litellm_common3.DEFAULT_KEY_DURATIONS.map((duration) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_MenuItem2.default, { value: duration, children: (0, import_backstage_plugin_litellm_common3.formatDurationLabel)(duration) }, duration))
3070
3102
  }
3071
3103
  ),
3072
3104
  generateForm.duration && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_Typography7.default, { variant: "caption", color: "text.secondary", children: expiryPreview(generateForm.duration) })
@@ -3156,7 +3188,7 @@ var init_KeyFormDialog = __esm({
3156
3188
  });
3157
3189
 
3158
3190
  // src/components/ManageTeamDialog.tsx
3159
- var import_react7, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete2, import_CircularProgress3, import_MenuItem2, import_Box10, import_Divider2, import_Typography8, import_IconButton4, import_Tooltip4, import_Paper4, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_icons_material5, import_core_plugin_api4, import_plugin_catalog_react, import_catalog_model, import_jsx_runtime11, BUDGET_DURATION_OPTIONS, DEFAULT_BUDGET_DURATION, FALLBACK_BUDGET_CEILING, ManageTeamDialog;
3191
+ var import_react7, import_Dialog3, import_DialogTitle3, import_DialogContent3, import_DialogActions3, import_TextField3, import_Button4, import_Alert2, import_Checkbox2, import_FormControlLabel2, import_Autocomplete2, import_CircularProgress3, import_MenuItem3, import_Box10, import_Divider2, import_Typography8, import_IconButton4, import_Tooltip4, import_Paper4, import_Table2, import_TableBody2, import_TableCell2, import_TableContainer2, import_TableHead2, import_TableRow2, import_icons_material5, import_core_plugin_api4, import_plugin_catalog_react, import_catalog_model, import_jsx_runtime11, BUDGET_DURATION_OPTIONS, DEFAULT_BUDGET_DURATION, FALLBACK_BUDGET_CEILING, ManageTeamDialog;
3160
3192
  var init_ManageTeamDialog = __esm({
3161
3193
  "src/components/ManageTeamDialog.tsx"() {
3162
3194
  "use strict";
@@ -3172,7 +3204,7 @@ var init_ManageTeamDialog = __esm({
3172
3204
  import_FormControlLabel2 = __toESM(require("@mui/material/FormControlLabel"));
3173
3205
  import_Autocomplete2 = __toESM(require("@mui/material/Autocomplete"));
3174
3206
  import_CircularProgress3 = __toESM(require("@mui/material/CircularProgress"));
3175
- import_MenuItem2 = __toESM(require("@mui/material/MenuItem"));
3207
+ import_MenuItem3 = __toESM(require("@mui/material/MenuItem"));
3176
3208
  import_Box10 = __toESM(require("@mui/material/Box"));
3177
3209
  import_Divider2 = __toESM(require("@mui/material/Divider"));
3178
3210
  import_Typography8 = __toESM(require("@mui/material/Typography"));
@@ -3590,7 +3622,7 @@ var init_ManageTeamDialog = __esm({
3590
3622
  disabled: submitting || unlimited,
3591
3623
  helperText: "Spend-reset period for the team budget",
3592
3624
  fullWidth: true,
3593
- children: durationOptions.map((o) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_MenuItem2.default, { value: o.value, children: o.label }, o.value))
3625
+ children: durationOptions.map((o) => /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_MenuItem3.default, { value: o.value, children: o.label }, o.value))
3594
3626
  }
3595
3627
  )
3596
3628
  ]
@@ -3970,7 +4002,7 @@ function rateTone(rate) {
3970
4002
  if (rate >= 0.9) return "warning";
3971
4003
  return "danger";
3972
4004
  }
3973
- var import_react8, import_Paper5, import_Box11, import_Typography9, import_TextField4, import_MenuItem3, import_Grid, import_Alert3, import_Button5, import_Table3, import_TableBody3, import_TableCell3, import_TableContainer3, import_TableHead3, import_TableRow3, import_Skeleton3, import_recharts, import_jsx_runtime12, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
4005
+ var import_react8, import_Paper5, import_Box11, import_Typography9, import_TextField4, import_MenuItem4, import_Grid, import_Alert3, import_Button5, import_Table3, import_TableBody3, import_TableCell3, import_TableContainer3, import_TableHead3, import_TableRow3, import_Skeleton3, import_recharts, import_jsx_runtime12, TOP_N_MODELS, PERIOD_LS_KEY, PRESET_LABELS, fmtPct, ChartSkeleton, ChartOrFallback, SuccessRateCell, UsageStats;
3974
4006
  var init_UsageStats = __esm({
3975
4007
  "src/components/UsageStats.tsx"() {
3976
4008
  "use strict";
@@ -3979,7 +4011,7 @@ var init_UsageStats = __esm({
3979
4011
  import_Box11 = __toESM(require("@mui/material/Box"));
3980
4012
  import_Typography9 = __toESM(require("@mui/material/Typography"));
3981
4013
  import_TextField4 = __toESM(require("@mui/material/TextField"));
3982
- import_MenuItem3 = __toESM(require("@mui/material/MenuItem"));
4014
+ import_MenuItem4 = __toESM(require("@mui/material/MenuItem"));
3983
4015
  import_Grid = __toESM(require("@mui/material/Grid"));
3984
4016
  import_Alert3 = __toESM(require("@mui/material/Alert"));
3985
4017
  import_Button5 = __toESM(require("@mui/material/Button"));
@@ -4237,7 +4269,7 @@ var init_UsageStats = __esm({
4237
4269
  value: currentPreset,
4238
4270
  onChange: (e) => handlePresetChange(e.target.value),
4239
4271
  sx: { minWidth: 160 },
4240
- children: Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem3.default, { value: p, children: PRESET_LABELS[p] }, p))
4272
+ children: Object.keys(PRESET_LABELS).map((p) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem4.default, { value: p, children: PRESET_LABELS[p] }, p))
4241
4273
  }
4242
4274
  );
4243
4275
  if (usageError) {
@@ -4298,8 +4330,8 @@ var init_UsageStats = __esm({
4298
4330
  onChange: (e) => setSelectedModel(e.target.value),
4299
4331
  sx: { minWidth: 220 },
4300
4332
  children: [
4301
- /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem3.default, { value: "all", children: "All models" }),
4302
- models.filter((m) => modelsInPeriod.includes(m.model_name)).map((m) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem3.default, { value: m.model_name, children: m.model_name }, m.model_name))
4333
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem4.default, { value: "all", children: "All models" }),
4334
+ models.filter((m) => modelsInPeriod.includes(m.model_name)).map((m) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_MenuItem4.default, { value: m.model_name, children: m.model_name }, m.model_name))
4303
4335
  ]
4304
4336
  }
4305
4337
  )
@@ -5079,7 +5111,7 @@ var init_TeamUsage = __esm({
5079
5111
  }) })
5080
5112
  ] }) });
5081
5113
  };
5082
- TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand }) => {
5114
+ TeamCard = ({ team, usage, usageLoading, memberUsage, memberUsageLoading, canManage, onEditTeam, canManageMembers, onManageMembers, onExpand, vectorStores, mcpServers }) => {
5083
5115
  const [expanded, setExpanded] = (0, import_react10.useState)(false);
5084
5116
  const chart = useChartTheme();
5085
5117
  const handleExpandChange = (newExpanded) => {
@@ -5146,6 +5178,10 @@ var init_TeamUsage = __esm({
5146
5178
  children: label
5147
5179
  }
5148
5180
  );
5181
+ const renderNamedTags = (label, ids, items) => /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { mb: 2.5, children: [
5182
+ sectionLabel(label),
5183
+ ids?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", gap: 0.5, flexWrap: "wrap", children: ids.map((id) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TagChip, { label: items?.find((i) => i.id === id)?.name ?? id, title: id }, id)) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "None configured" })
5184
+ ] });
5149
5185
  return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Paper8.default, { variant: "outlined", sx: { borderRadius: 2, p: 2.5 }, children: [
5150
5186
  /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { display: "flex", alignItems: "center", gap: 1.5, children: [
5151
5187
  /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
@@ -5271,6 +5307,8 @@ var init_TeamUsage = __esm({
5271
5307
  sectionLabel("Models"),
5272
5308
  team.models?.length ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Box14.default, { display: "flex", gap: 0.5, flexWrap: "wrap", children: team.models.map((m) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(TagChip, { label: m, title: m }, m)) }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Typography12.default, { variant: "body2", color: "text.secondary", children: "All models allowed" })
5273
5309
  ] }),
5310
+ renderNamedTags("Knowledge bases", team.object_permission?.vector_stores, vectorStores),
5311
+ renderNamedTags("MCP servers", team.object_permission?.mcp_servers, mcpServers),
5274
5312
  renderDailySpendSection(),
5275
5313
  (memberUsageLoading || memberUsage) && /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_Box14.default, { mb: 2.5, children: [
5276
5314
  sectionLabel("Usage by member"),
@@ -5339,7 +5377,9 @@ var init_TeamUsage = __esm({
5339
5377
  onTeamExpand,
5340
5378
  canManageMembers,
5341
5379
  onManageMembers,
5342
- readOnly
5380
+ readOnly,
5381
+ vectorStores,
5382
+ mcpServers
5343
5383
  }) => {
5344
5384
  const readOnlyBadge = /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_Tooltip5.default, { title: "Teams and memberships are managed in your identity provider. Changes made here would be overwritten, so editing is disabled.", children: /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(
5345
5385
  import_Box14.default,
@@ -5397,7 +5437,9 @@ var init_TeamUsage = __esm({
5397
5437
  onEditTeam,
5398
5438
  canManageMembers: canManageMembers?.(team),
5399
5439
  onManageMembers,
5400
- onExpand: onTeamExpand
5440
+ onExpand: onTeamExpand,
5441
+ vectorStores,
5442
+ mcpServers
5401
5443
  },
5402
5444
  team.team_id
5403
5445
  )) })
@@ -5425,7 +5467,7 @@ function fmtTokens(n) {
5425
5467
  if (n >= 1e3) return `${(n / 1e3).toFixed(0)}K`;
5426
5468
  return String(n);
5427
5469
  }
5428
- var import_react11, import_Box15, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TableSortLabel2, import_Typography13, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_TextField5, import_InputAdornment3, import_icons_material8, import_ContentCopy, import_Tooltip6, import_Snackbar, import_Alert4, import_styles11, import_jsx_runtime16, ALL_PROXY_MODELS, ModelsTable;
5470
+ var import_react11, import_Box15, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_TableSortLabel2, import_Typography13, import_MenuItem5, import_Select, import_FormControl, import_InputLabel, import_TextField5, import_InputAdornment3, import_icons_material8, import_ContentCopy, import_Tooltip6, import_Snackbar, import_Alert4, import_styles11, import_jsx_runtime16, ALL_PROXY_MODELS, ModelsTable;
5429
5471
  var init_ModelsTable = __esm({
5430
5472
  "src/components/ModelsTable.tsx"() {
5431
5473
  "use strict";
@@ -5439,7 +5481,7 @@ var init_ModelsTable = __esm({
5439
5481
  import_TableRow5 = __toESM(require("@mui/material/TableRow"));
5440
5482
  import_TableSortLabel2 = __toESM(require("@mui/material/TableSortLabel"));
5441
5483
  import_Typography13 = __toESM(require("@mui/material/Typography"));
5442
- import_MenuItem4 = __toESM(require("@mui/material/MenuItem"));
5484
+ import_MenuItem5 = __toESM(require("@mui/material/MenuItem"));
5443
5485
  import_Select = __toESM(require("@mui/material/Select"));
5444
5486
  import_FormControl = __toESM(require("@mui/material/FormControl"));
5445
5487
  import_InputLabel = __toESM(require("@mui/material/InputLabel"));
@@ -5557,7 +5599,7 @@ var init_ModelsTable = __esm({
5557
5599
  value: selectedTeamId,
5558
5600
  label: "Team",
5559
5601
  onChange: (e) => setSelectedTeamId(e.target.value),
5560
- children: teams.map((t) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_MenuItem4.default, { value: t.team_id, children: t.team_alias ?? t.team_id }, t.team_id))
5602
+ children: teams.map((t) => /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(import_MenuItem5.default, { value: t.team_id, children: t.team_alias ?? t.team_id }, t.team_id))
5561
5603
  }
5562
5604
  )
5563
5605
  ] }),
@@ -6366,12 +6408,12 @@ var init_LiteLLMPage = __esm({
6366
6408
  const teamMgmtEnabled = liteLlmConfig?.teamManagement?.enabled ?? false;
6367
6409
  const objectPermsEnabled = liteLlmConfig?.teamManagement?.objectPermissionsEnabled ?? false;
6368
6410
  const { value: vectorStores } = (0, import_react_use2.useAsync)(
6369
- async () => objectPermsEnabled ? api.getVectorStores().catch(() => []) : [],
6370
- [api, objectPermsEnabled]
6411
+ () => api.getVectorStores().catch(() => []),
6412
+ [api]
6371
6413
  );
6372
6414
  const { value: mcpServers } = (0, import_react_use2.useAsync)(
6373
- async () => objectPermsEnabled ? api.getMcpServers().catch(() => []) : [],
6374
- [api, objectPermsEnabled]
6415
+ () => api.getMcpServers().catch(() => []),
6416
+ [api]
6375
6417
  );
6376
6418
  const teams = (0, import_react13.useMemo)(() => {
6377
6419
  if (!allTeams?.length) return [];
@@ -6697,7 +6739,8 @@ var init_LiteLLMPage = __esm({
6697
6739
  onDeleteKey: handleDeleteKey,
6698
6740
  onPruneExpiredKeys: handlePruneExpiredKeys,
6699
6741
  filter,
6700
- onClearFilter: clearFilter
6742
+ onClearFilter: clearFilter,
6743
+ teams: allTeams ?? []
6701
6744
  }
6702
6745
  );
6703
6746
  })(),
@@ -6728,6 +6771,8 @@ var init_LiteLLMPage = __esm({
6728
6771
  onEditTeam: (t) => setManageTeam({ mode: "edit", team: t }),
6729
6772
  canCreate: teamMgmtEnabled && canCreateTeam && !readOnly,
6730
6773
  onCreateTeam: () => setManageTeam({ mode: "create" }),
6774
+ vectorStores: vectorStores ?? [],
6775
+ mcpServers: mcpServers ?? [],
6731
6776
  canManageMembers: (t) => teamMgmtEnabled && canManageMembers && isTeamMemberManager(t, userInfo?.user_id, memberManagerRoles, readOnly),
6732
6777
  onManageMembers: (t) => setManageTeam({ mode: "members", team: t }),
6733
6778
  readOnly,
@@ -7113,7 +7158,7 @@ var import_Box19 = __toESM(require("@mui/material/Box"));
7113
7158
  var import_Typography17 = __toESM(require("@mui/material/Typography"));
7114
7159
  var import_FormControl2 = __toESM(require("@mui/material/FormControl"));
7115
7160
  var import_Select2 = __toESM(require("@mui/material/Select"));
7116
- var import_MenuItem5 = __toESM(require("@mui/material/MenuItem"));
7161
+ var import_MenuItem6 = __toESM(require("@mui/material/MenuItem"));
7117
7162
  var import_Skeleton7 = __toESM(require("@mui/material/Skeleton"));
7118
7163
  var import_recharts3 = require("recharts");
7119
7164
  var import_core_plugin_api7 = require("@backstage/core-plugin-api");
@@ -7250,9 +7295,9 @@ var LiteLLMHomeWidget = ({
7250
7295
  displayEmpty: true,
7251
7296
  inputProps: { "aria-label": "Usage period" },
7252
7297
  children: [
7253
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem5.default, { value: "today", children: "Today" }),
7254
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem5.default, { value: "7d", children: "7d" }),
7255
- /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem5.default, { value: "30d", children: "30d" })
7298
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "today", children: "Today" }),
7299
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "7d", children: "7d" }),
7300
+ /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_MenuItem6.default, { value: "30d", children: "30d" })
7256
7301
  ]
7257
7302
  }
7258
7303
  ) })