@acarmisc/backstage-plugin-litellm 0.3.0 → 0.3.2

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
@@ -165,7 +165,7 @@ var init_DashboardHeader = __esm({
165
165
  });
166
166
 
167
167
  // src/components/KeysTable.tsx
168
- var import_react2, import_material2, import_icons_material2, maskKey, formatDate, emptyForm, keyToEditForm, KeysTable;
168
+ var import_react2, import_material2, import_icons_material2, maskKey, shortKeyId, formatDate, emptyForm, keyToEditForm, KeysTable;
169
169
  var init_KeysTable = __esm({
170
170
  "src/components/KeysTable.tsx"() {
171
171
  "use strict";
@@ -176,6 +176,11 @@ var init_KeysTable = __esm({
176
176
  if (key.length <= 8) return "***";
177
177
  return `${key.slice(0, 4)}...${key.slice(-4)}`;
178
178
  };
179
+ shortKeyId = (token) => {
180
+ if (!token) return "-";
181
+ if (token.length <= 16) return token;
182
+ return `${token.slice(0, 12)}\u2026`;
183
+ };
179
184
  formatDate = (dateStr) => {
180
185
  try {
181
186
  return new Date(dateStr).toLocaleDateString();
@@ -187,7 +192,7 @@ var init_KeysTable = __esm({
187
192
  alias: "",
188
193
  models: [],
189
194
  duration: "30d",
190
- max_budget: void 0,
195
+ max_budget: 100,
191
196
  tpm_limit: void 0,
192
197
  team_id: void 0,
193
198
  key_type: "llm_api"
@@ -209,16 +214,9 @@ var init_KeysTable = __esm({
209
214
  onDeleteKey
210
215
  }) => {
211
216
  const [generateModalOpen, setGenerateModalOpen] = (0, import_react2.useState)(false);
212
- const [showKeyValue, setShowKeyValue] = (0, import_react2.useState)(null);
213
217
  const [newKeyValue, setNewKeyValue] = (0, import_react2.useState)(null);
214
218
  const [formData, setFormData] = (0, import_react2.useState)(emptyForm());
215
219
  const [submitting, setSubmitting] = (0, import_react2.useState)(false);
216
- (0, import_react2.useEffect)(() => {
217
- if (!generateModalOpen) return;
218
- if (!formData.team_id && teams.length > 0) {
219
- setFormData((f) => ({ ...f, team_id: teams[0].team_id }));
220
- }
221
- }, [generateModalOpen, teams, formData.team_id]);
222
220
  const canGenerate = true;
223
221
  const [editingKey, setEditingKey] = (0, import_react2.useState)(null);
224
222
  const [editForm, setEditForm] = (0, import_react2.useState)({});
@@ -232,10 +230,6 @@ var init_KeysTable = __esm({
232
230
  const response = await onGenerateKey(formData);
233
231
  setNewKeyValue(response.key);
234
232
  setFormData(emptyForm());
235
- setTimeout(() => {
236
- setGenerateModalOpen(false);
237
- setNewKeyValue(null);
238
- }, 1500);
239
233
  } catch (error) {
240
234
  console.error("Failed to generate key:", error);
241
235
  } finally {
@@ -279,32 +273,26 @@ var init_KeysTable = __esm({
279
273
  onClick: () => setGenerateModalOpen(true)
280
274
  },
281
275
  "Generate New Key"
282
- )), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableContainer, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Table, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableHead, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Alias"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Key"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Created"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Spend"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Budget"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "TPM Limit"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Models"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { align: "right" }, "Actions"))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableBody, null, loading ? /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { colSpan: 8, align: "center" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.CircularProgress, { size: 24 }))) : keys.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { colSpan: 8, align: "center" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { color: "text.secondary" }, "No keys found"))) : keys.map((key) => /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, { key: key.key }, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.key_alias || "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { display: "flex", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ import_react2.default.createElement(
283
- import_material2.Typography,
284
- {
285
- variant: "body2",
286
- component: "code",
287
- color: "primary",
288
- sx: {
289
- fontFamily: "monospace",
290
- backgroundColor: "background.default",
291
- px: 1,
292
- py: 0.5,
293
- borderRadius: 1,
294
- maxWidth: "250px",
295
- overflow: "hidden",
296
- textOverflow: "ellipsis"
297
- }
298
- },
299
- showKeyValue === key.key ? key.key : maskKey(key.key)
300
- ), /* @__PURE__ */ import_react2.default.createElement(
301
- import_material2.IconButton,
302
- {
303
- size: "small",
304
- onClick: () => setShowKeyValue(showKeyValue === key.key ? null : key.key)
305
- },
306
- showKeyValue === key.key ? /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.VisibilityOff, null) : /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.Visibility, null)
307
- ), /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { size: "small", onClick: () => copyToClipboard(key.key) }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.ContentCopy, { fontSize: "small" })))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, formatDate(key.created_at)), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "$", key.spend?.toFixed(4) || "0.00"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.max_budget ? `$${key.max_budget}` : "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.tpm_limit || "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { display: "flex", gap: 0.5, flexWrap: "wrap" }, key.models?.slice(0, 2).map((model) => /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { key: model, label: model, size: "small" })), (key.models?.length || 0) > 2 && /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { label: `+${(key.models?.length || 0) - 2}`, size: "small", variant: "outlined" }))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { align: "right" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { onClick: () => handleOpenEdit(key) }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.Edit, { fontSize: "small" })), /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { color: "error", onClick: () => onDeleteKey(key.key) }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.Delete, null))))))))), /* @__PURE__ */ import_react2.default.createElement(import_material2.Dialog, { open: generateModalOpen, onClose: handleCloseModal, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react2.default.createElement(import_material2.DialogTitle, null, newKeyValue ? "Key Generated" : "Generate New Key"), /* @__PURE__ */ import_react2.default.createElement(import_material2.DialogContent, null, newKeyValue ? /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", color: "text.secondary", gutterBottom: true }, "Copy this key now. You won't be able to see it again."), /* @__PURE__ */ import_react2.default.createElement(
276
+ )), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableContainer, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Table, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableHead, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Alias"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Key ID"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Created"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Spend"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Budget"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "TPM Limit"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "Models"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { align: "right" }, "Actions"))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableBody, null, loading ? /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { colSpan: 8, align: "center" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.CircularProgress, { size: 24 }))) : keys.length === 0 ? /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { colSpan: 8, align: "center" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { color: "text.secondary" }, "No keys found"))) : keys.map((key) => {
277
+ const keyId = key.token ?? key.key;
278
+ return /* @__PURE__ */ import_react2.default.createElement(import_material2.TableRow, { key: keyId }, /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.key_alias || "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { display: "flex", alignItems: "center", gap: 0.5 }, /* @__PURE__ */ import_react2.default.createElement(
279
+ import_material2.Typography,
280
+ {
281
+ variant: "body2",
282
+ component: "code",
283
+ color: "text.secondary",
284
+ title: keyId,
285
+ sx: {
286
+ fontFamily: "monospace",
287
+ backgroundColor: "background.default",
288
+ px: 1,
289
+ py: 0.5,
290
+ borderRadius: 1
291
+ }
292
+ },
293
+ shortKeyId(keyId)
294
+ ), /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { size: "small", onClick: () => copyToClipboard(keyId), title: "Copy Key ID" }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.ContentCopy, { fontSize: "small" })))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, formatDate(key.created_at)), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, "$", key.spend?.toFixed(4) || "0.00"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.max_budget ? `$${key.max_budget}` : "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, key.tpm_limit || "-"), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, { display: "flex", gap: 0.5, flexWrap: "wrap" }, key.models?.slice(0, 2).map((model) => /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { key: model, label: model, size: "small" })), (key.models?.length || 0) > 2 && /* @__PURE__ */ import_react2.default.createElement(import_material2.Chip, { label: `+${(key.models?.length || 0) - 2}`, size: "small", variant: "outlined" }))), /* @__PURE__ */ import_react2.default.createElement(import_material2.TableCell, { align: "right" }, /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { onClick: () => handleOpenEdit(key) }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.Edit, { fontSize: "small" })), /* @__PURE__ */ import_react2.default.createElement(import_material2.IconButton, { color: "error", onClick: () => onDeleteKey(key.key) }, /* @__PURE__ */ import_react2.default.createElement(import_icons_material2.Delete, null))));
295
+ }))))), /* @__PURE__ */ import_react2.default.createElement(import_material2.Dialog, { open: generateModalOpen, onClose: handleCloseModal, maxWidth: "sm", fullWidth: true }, /* @__PURE__ */ import_react2.default.createElement(import_material2.DialogTitle, null, newKeyValue ? "Key Generated" : "Generate New Key"), /* @__PURE__ */ import_react2.default.createElement(import_material2.DialogContent, null, newKeyValue ? /* @__PURE__ */ import_react2.default.createElement(import_material2.Box, null, /* @__PURE__ */ import_react2.default.createElement(import_material2.Typography, { variant: "body2", color: "text.secondary", gutterBottom: true }, "Copy this key now. You won't be able to see it again."), /* @__PURE__ */ import_react2.default.createElement(
308
296
  import_material2.Box,
309
297
  {
310
298
  display: "flex",
@@ -313,7 +301,9 @@ var init_KeysTable = __esm({
313
301
  mt: 2,
314
302
  p: 2,
315
303
  sx: {
316
- backgroundColor: "grey.100",
304
+ backgroundColor: "action.hover",
305
+ border: "1px solid",
306
+ borderColor: "divider",
317
307
  borderRadius: 1
318
308
  }
319
309
  },
@@ -333,6 +323,7 @@ var init_KeysTable = __esm({
333
323
  label: "Alias",
334
324
  value: formData.alias || "",
335
325
  onChange: (e) => setFormData({ ...formData, alias: e.target.value }),
326
+ required: true,
336
327
  fullWidth: true
337
328
  }
338
329
  ), /* @__PURE__ */ import_react2.default.createElement(
@@ -376,7 +367,7 @@ var init_KeysTable = __esm({
376
367
  value: selectedModels,
377
368
  onChange: (_e, selected) => setFormData({ ...formData, models: selected.map((m) => m.model_name) }),
378
369
  renderOption: (props, m) => /* @__PURE__ */ import_react2.default.createElement("li", { ...props }, m.model_name, m.supports_function_calling && " \u{1F527}", m.supports_vision && " \u{1F441}\uFE0F"),
379
- renderInput: (params) => /* @__PURE__ */ import_react2.default.createElement(import_material2.TextField, { ...params, label: "Models", fullWidth: true })
370
+ renderInput: (params) => /* @__PURE__ */ import_react2.default.createElement(import_material2.TextField, { ...params, label: "Models", helperText: "Leave empty to allow all models", fullWidth: true })
380
371
  }
381
372
  ), /* @__PURE__ */ import_react2.default.createElement(
382
373
  import_material2.TextField,
@@ -385,6 +376,7 @@ var init_KeysTable = __esm({
385
376
  type: "number",
386
377
  value: formData.max_budget ?? "",
387
378
  onChange: (e) => setFormData({ ...formData, max_budget: e.target.value ? Number(e.target.value) : void 0 }),
379
+ required: true,
388
380
  fullWidth: true
389
381
  }
390
382
  ), /* @__PURE__ */ import_react2.default.createElement(