@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.cjs.js CHANGED
@@ -3007,7 +3007,7 @@ function fmtTokens(n) {
3007
3007
  if (n >= 1e3) return `${(n / 1e3).toFixed(0)}K`;
3008
3008
  return String(n);
3009
3009
  }
3010
- var import_react8, import_Box8, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_Typography8, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, import_TextField5, import_InputAdornment2, import_icons_material6, ALL_PROXY_MODELS2, ModelsTable;
3010
+ var import_react8, import_Box8, import_Table5, import_TableBody5, import_TableCell5, import_TableContainer5, import_TableHead5, import_TableRow5, import_Typography8, import_MenuItem4, import_Select, import_FormControl, import_InputLabel, import_TextField5, import_InputAdornment2, import_icons_material6, import_ContentCopy, import_Tooltip, import_Snackbar, import_Alert3, import_styles5, ALL_PROXY_MODELS2, ModelsTable;
3011
3011
  var init_ModelsTable = __esm({
3012
3012
  "src/components/ModelsTable.tsx"() {
3013
3013
  "use strict";
@@ -3024,15 +3024,15 @@ var init_ModelsTable = __esm({
3024
3024
  import_Select = __toESM(require("@mui/material/Select"));
3025
3025
  import_FormControl = __toESM(require("@mui/material/FormControl"));
3026
3026
  import_InputLabel = __toESM(require("@mui/material/InputLabel"));
3027
+ import_TextField5 = __toESM(require("@mui/material/TextField"));
3028
+ import_InputAdornment2 = __toESM(require("@mui/material/InputAdornment"));
3029
+ import_icons_material6 = require("@mui/icons-material");
3027
3030
  import_ContentCopy = __toESM(require("@mui/icons-material/ContentCopy"));
3028
3031
  import_Tooltip = __toESM(require("@mui/material/Tooltip"));
3029
3032
  import_Snackbar = __toESM(require("@mui/material/Snackbar"));
3030
3033
  import_Alert3 = __toESM(require("@mui/material/Alert"));
3031
3034
  init_ui();
3032
3035
  import_styles5 = require("@mui/material/styles");
3033
- import_TextField5 = __toESM(require("@mui/material/TextField"));
3034
- import_InputAdornment2 = __toESM(require("@mui/material/InputAdornment"));
3035
- import_icons_material6 = require("@mui/icons-material");
3036
3036
  ALL_PROXY_MODELS2 = "all-proxy-models";
3037
3037
  ModelsTable = ({ allModels, teams, loading }) => {
3038
3038
  const theme = (0, import_styles5.useTheme)();
@@ -3043,17 +3043,17 @@ var init_ModelsTable = __esm({
3043
3043
  () => teams.find((t) => t.team_id === selectedTeamId) ?? null,
3044
3044
  [teams, selectedTeamId]
3045
3045
  );
3046
- const filteredModels = (0, import_react8.useMemo)(() => {
3046
+ const teamModels = (0, import_react8.useMemo)(() => {
3047
3047
  if (!selectedTeam) return [];
3048
- let result = allModels.filter((model) => isModelAllowedByTeam2(model, selectedTeam.models));
3049
- if (filterText.trim()) {
3050
- const q = filterText.toLowerCase();
3051
- result = result.filter(
3052
- (model) => model.model_name.toLowerCase().includes(q) || (model.access_groups || []).some((group) => group.toLowerCase().includes(q))
3053
- );
3054
- }
3055
- return result;
3056
- }, [allModels, selectedTeam, filterText]);
3048
+ return allModels.filter((model) => isModelAllowedByTeam2(model, selectedTeam.models));
3049
+ }, [allModels, selectedTeam]);
3050
+ const filteredModels = (0, import_react8.useMemo)(() => {
3051
+ const q = filterText.trim().toLowerCase();
3052
+ if (!q) return teamModels;
3053
+ return teamModels.filter(
3054
+ (model) => model.model_name.toLowerCase().includes(q) || (model.access_groups || []).some((group) => group.toLowerCase().includes(q))
3055
+ );
3056
+ }, [teamModels, filterText]);
3057
3057
  const handleCopyModelId = (0, import_react8.useCallback)((modelId) => {
3058
3058
  navigator.clipboard.writeText(modelId).then(() => setCopiedSnackbar(true));
3059
3059
  }, []);
@@ -3075,9 +3075,9 @@ var init_ModelsTable = __esm({
3075
3075
  SectionCard,
3076
3076
  {
3077
3077
  title: "Available Models",
3078
- subtitle: selectedTeam ? `${filteredModels.length} model${filteredModels.length !== 1 ? "s" : ""} in ${selectedTeam.team_alias ?? selectedTeam.team_id}` : "Select a team to view its models"
3078
+ subtitle: selectedTeam ? `${filteredModels.length}${filterText.trim() ? ` of ${teamModels.length}` : ""} model${filteredModels.length === 1 ? "" : "s"}` : "Select a team to view its models"
3079
3079
  },
3080
- /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { px: 2.5, pb: 2.5, pt: 1 } }, /* @__PURE__ */ import_react8.default.createElement(import_FormControl.default, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ import_react8.default.createElement(import_InputLabel.default, { id: "team-select-label" }, "Team"), /* @__PURE__ */ import_react8.default.createElement(
3080
+ /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { px: 2.5, pb: 2.5, pt: 1, display: "flex", gap: 2, flexWrap: "wrap" } }, /* @__PURE__ */ import_react8.default.createElement(import_FormControl.default, { size: "small", sx: { minWidth: 240, mb: 2 } }, /* @__PURE__ */ import_react8.default.createElement(import_InputLabel.default, { id: "team-select-label" }, "Team"), /* @__PURE__ */ import_react8.default.createElement(
3081
3081
  import_Select.default,
3082
3082
  {
3083
3083
  labelId: "team-select-label",
@@ -3093,6 +3093,7 @@ var init_ModelsTable = __esm({
3093
3093
  size: "small",
3094
3094
  value: filterText,
3095
3095
  onChange: (e) => setFilterText(e.target.value),
3096
+ disabled: !selectedTeamId,
3096
3097
  sx: { minWidth: 240, mb: 2 },
3097
3098
  InputProps: {
3098
3099
  startAdornment: /* @__PURE__ */ import_react8.default.createElement(import_InputAdornment2.default, { position: "start" }, /* @__PURE__ */ import_react8.default.createElement(import_icons_material6.Search, { fontSize: "small" }))
@@ -3107,14 +3108,32 @@ var init_ModelsTable = __esm({
3107
3108
  hint: "Each team may have a different set of models assigned"
3108
3109
  }
3109
3110
  ),
3110
- !loading && selectedTeamId && filteredModels.length === 0 && /* @__PURE__ */ import_react8.default.createElement(
3111
+ !loading && selectedTeamId && teamModels.length === 0 && /* @__PURE__ */ import_react8.default.createElement(
3111
3112
  EmptyState,
3112
3113
  {
3113
3114
  message: "No models available for this team",
3114
3115
  hint: allModels.length === 0 ? "No models are configured in the system" : "None of the team's assigned models were found in the catalog"
3115
3116
  }
3116
3117
  ),
3117
- !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react8.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react8.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Model ID"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Mode"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Input Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Output Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Input"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Output"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Capabilities"))), /* @__PURE__ */ import_react8.default.createElement(import_TableBody5.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: m.model_name, title: m.model_name }), /* @__PURE__ */ import_react8.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react8.default.createElement(
3118
+ !loading && selectedTeamId && teamModels.length > 0 && filteredModels.length === 0 && /* @__PURE__ */ import_react8.default.createElement(
3119
+ EmptyState,
3120
+ {
3121
+ message: "No models match your search",
3122
+ hint: "Try a different search term"
3123
+ }
3124
+ ),
3125
+ !loading && filteredModels.length > 0 && /* @__PURE__ */ import_react8.default.createElement(import_TableContainer5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Table5.default, { size: "small", sx: dataTableSx }, /* @__PURE__ */ import_react8.default.createElement(import_TableHead5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Model ID"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Mode"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Input Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Output Cost"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Input"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, { align: "right" }, "Max Output"), /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, "Capabilities"))), /* @__PURE__ */ import_react8.default.createElement(import_TableBody5.default, null, filteredModels.map((m) => /* @__PURE__ */ import_react8.default.createElement(import_TableRow5.default, { key: m.model_name, hover: true }, /* @__PURE__ */ import_react8.default.createElement(import_TableCell5.default, null, /* @__PURE__ */ import_react8.default.createElement(import_Box8.default, { sx: { display: "flex", alignItems: "center", gap: 0.5 } }, /* @__PURE__ */ import_react8.default.createElement(import_Tooltip.default, { title: m.model_name, placement: "top" }, /* @__PURE__ */ import_react8.default.createElement(
3126
+ "span",
3127
+ {
3128
+ role: "button",
3129
+ tabIndex: 0,
3130
+ "aria-label": "Copy model ID",
3131
+ onClick: () => handleCopyModelId(m.model_name),
3132
+ onKeyDown: (e) => e.key === "Enter" && handleCopyModelId(m.model_name),
3133
+ style: { cursor: "pointer", display: "inline-flex" }
3134
+ },
3135
+ /* @__PURE__ */ import_react8.default.createElement(TagChip, { label: m.model_name, title: "Copy model ID" })
3136
+ )), /* @__PURE__ */ import_react8.default.createElement(import_Tooltip.default, { title: "Copy model ID" }, /* @__PURE__ */ import_react8.default.createElement(
3118
3137
  import_Box8.default,
3119
3138
  {
3120
3139
  component: "span",