@acarmisc/backstage-plugin-litellm 0.18.1 → 0.19.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
@@ -3004,14 +3004,14 @@ import MenuItem4 from "@mui/material/MenuItem";
3004
3004
  import Select from "@mui/material/Select";
3005
3005
  import FormControl from "@mui/material/FormControl";
3006
3006
  import InputLabel from "@mui/material/InputLabel";
3007
+ import TextField5 from "@mui/material/TextField";
3008
+ import InputAdornment2 from "@mui/material/InputAdornment";
3009
+ import { Search as Search2 } from "@mui/icons-material";
3007
3010
  import ContentCopyIcon from "@mui/icons-material/ContentCopy";
3008
3011
  import Tooltip3 from "@mui/material/Tooltip";
3009
3012
  import Snackbar from "@mui/material/Snackbar";
3010
3013
  import Alert3 from "@mui/material/Alert";
3011
3014
  import { alpha as alpha5, useTheme as useTheme2 } from "@mui/material/styles";
3012
- import TextField5 from "@mui/material/TextField";
3013
- import InputAdornment2 from "@mui/material/InputAdornment";
3014
- import { Search as Search2 } from "@mui/icons-material";
3015
3015
  function isModelAllowedByTeam2(model, teamModels) {
3016
3016
  if (!teamModels || teamModels.length === 0 || teamModels.includes(ALL_PROXY_MODELS2)) return true;
3017
3017
  return teamModels.includes(model.model_name) || !!model.access_groups?.some((group) => teamModels.includes(group));
@@ -3044,17 +3044,17 @@ var init_ModelsTable = __esm({
3044
3044
  () => teams.find((t) => t.team_id === selectedTeamId) ?? null,
3045
3045
  [teams, selectedTeamId]
3046
3046
  );
3047
- const filteredModels = useMemo6(() => {
3047
+ const teamModels = useMemo6(() => {
3048
3048
  if (!selectedTeam) return [];
3049
- let result = allModels.filter((model) => isModelAllowedByTeam2(model, selectedTeam.models));
3050
- if (filterText.trim()) {
3051
- const q = filterText.toLowerCase();
3052
- result = result.filter(
3053
- (model) => model.model_name.toLowerCase().includes(q) || (model.access_groups || []).some((group) => group.toLowerCase().includes(q))
3054
- );
3055
- }
3056
- return result;
3057
- }, [allModels, selectedTeam, filterText]);
3049
+ return allModels.filter((model) => isModelAllowedByTeam2(model, selectedTeam.models));
3050
+ }, [allModels, selectedTeam]);
3051
+ const filteredModels = useMemo6(() => {
3052
+ const q = filterText.trim().toLowerCase();
3053
+ if (!q) return teamModels;
3054
+ return teamModels.filter(
3055
+ (model) => model.model_name.toLowerCase().includes(q) || (model.access_groups || []).some((group) => group.toLowerCase().includes(q))
3056
+ );
3057
+ }, [teamModels, filterText]);
3058
3058
  const handleCopyModelId = useCallback((modelId) => {
3059
3059
  navigator.clipboard.writeText(modelId).then(() => setCopiedSnackbar(true));
3060
3060
  }, []);
@@ -3076,9 +3076,9 @@ var init_ModelsTable = __esm({
3076
3076
  SectionCard,
3077
3077
  {
3078
3078
  title: "Available Models",
3079
- subtitle: selectedTeam ? `${filteredModels.length} model${filteredModels.length !== 1 ? "s" : ""} in ${selectedTeam.team_alias ?? selectedTeam.team_id}` : "Select a team to view its models"
3079
+ subtitle: selectedTeam ? `${filteredModels.length}${filterText.trim() ? ` of ${teamModels.length}` : ""} model${filteredModels.length === 1 ? "" : "s"}` : "Select a team to view its models"
3080
3080
  },
3081
- /* @__PURE__ */ React8.createElement(Box8, { sx: { px: 2.5, pb: 2.5, pt: 1 } }, /* @__PURE__ */ React8.createElement(FormControl, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ React8.createElement(InputLabel, { id: "team-select-label" }, "Team"), /* @__PURE__ */ React8.createElement(
3081
+ /* @__PURE__ */ React8.createElement(Box8, { sx: { px: 2.5, pb: 2.5, pt: 1, display: "flex", gap: 2, flexWrap: "wrap" } }, /* @__PURE__ */ React8.createElement(FormControl, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ React8.createElement(InputLabel, { id: "team-select-label" }, "Team"), /* @__PURE__ */ React8.createElement(
3082
3082
  Select,
3083
3083
  {
3084
3084
  labelId: "team-select-label",
@@ -3094,6 +3094,7 @@ var init_ModelsTable = __esm({
3094
3094
  size: "small",
3095
3095
  value: filterText,
3096
3096
  onChange: (e) => setFilterText(e.target.value),
3097
+ disabled: !selectedTeamId,
3097
3098
  sx: { minWidth: 240, mb: 2 },
3098
3099
  InputProps: {
3099
3100
  startAdornment: /* @__PURE__ */ React8.createElement(InputAdornment2, { position: "start" }, /* @__PURE__ */ React8.createElement(Search2, { fontSize: "small" }))
@@ -3108,14 +3109,32 @@ var init_ModelsTable = __esm({
3108
3109
  hint: "Each team may have a different set of models assigned"
3109
3110
  }
3110
3111
  ),
3111
- !loading && selectedTeamId && filteredModels.length === 0 && /* @__PURE__ */ React8.createElement(
3112
+ !loading && selectedTeamId && teamModels.length === 0 && /* @__PURE__ */ React8.createElement(
3112
3113
  EmptyState,
3113
3114
  {
3114
3115
  message: "No models available for this team",
3115
3116
  hint: allModels.length === 0 ? "No models are configured in the system" : "None of the team's assigned models were found in the catalog"
3116
3117
  }
3117
3118
  ),
3118
- !loading && filteredModels.length > 0 && /* @__PURE__ */ React8.createElement(TableContainer5, null, /* @__PURE__ */ React8.createElement(Table5, { size: "small", sx: dataTableSx }, /* @__PURE__ */ React8.createElement(TableHead5, null, /* @__PURE__ */ React8.createElement(TableRow5, null, /* @__PURE__ */ React8.createElement(TableCell5, null, "Model ID"), /* @__PURE__ */ React8.createElement(TableCell5, null, "Mode"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Input Cost"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Output Cost"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Max Input"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Max Output"), /* @__PURE__ */ React8.createElement(TableCell5, null, "Capabilities"))), /* @__PURE__ */ React8.createElement(TableBody5, null, filteredModels.map((m) => /* @__PURE__ */ React8.createElement(TableRow5, { key: m.model_name, hover: true }, /* @__PURE__ */ React8.createElement(TableCell5, null, /* @__PURE__ */ React8.createElement(Box8, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React8.createElement(TagChip, { label: m.model_name, title: m.model_name }), /* @__PURE__ */ React8.createElement(Tooltip3, { title: "Copy model ID" }, /* @__PURE__ */ React8.createElement(
3119
+ !loading && selectedTeamId && teamModels.length > 0 && filteredModels.length === 0 && /* @__PURE__ */ React8.createElement(
3120
+ EmptyState,
3121
+ {
3122
+ message: "No models match your search",
3123
+ hint: "Try a different search term"
3124
+ }
3125
+ ),
3126
+ !loading && filteredModels.length > 0 && /* @__PURE__ */ React8.createElement(TableContainer5, null, /* @__PURE__ */ React8.createElement(Table5, { size: "small", sx: dataTableSx }, /* @__PURE__ */ React8.createElement(TableHead5, null, /* @__PURE__ */ React8.createElement(TableRow5, null, /* @__PURE__ */ React8.createElement(TableCell5, null, "Model ID"), /* @__PURE__ */ React8.createElement(TableCell5, null, "Mode"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Input Cost"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Output Cost"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Max Input"), /* @__PURE__ */ React8.createElement(TableCell5, { align: "right" }, "Max Output"), /* @__PURE__ */ React8.createElement(TableCell5, null, "Capabilities"))), /* @__PURE__ */ React8.createElement(TableBody5, null, filteredModels.map((m) => /* @__PURE__ */ React8.createElement(TableRow5, { key: m.model_name, hover: true }, /* @__PURE__ */ React8.createElement(TableCell5, null, /* @__PURE__ */ React8.createElement(Box8, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ React8.createElement(Tooltip3, { title: m.model_name, placement: "top" }, /* @__PURE__ */ React8.createElement(
3127
+ "span",
3128
+ {
3129
+ role: "button",
3130
+ tabIndex: 0,
3131
+ "aria-label": "Copy model ID",
3132
+ onClick: () => handleCopyModelId(m.model_name),
3133
+ onKeyDown: (e) => e.key === "Enter" && handleCopyModelId(m.model_name),
3134
+ style: { cursor: "pointer", display: "inline-flex" }
3135
+ },
3136
+ /* @__PURE__ */ React8.createElement(TagChip, { label: m.model_name, title: "Copy model ID" })
3137
+ )), /* @__PURE__ */ React8.createElement(Tooltip3, { title: "Copy model ID" }, /* @__PURE__ */ React8.createElement(
3119
3138
  Box8,
3120
3139
  {
3121
3140
  component: "span",