@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 +33 -41
- package/dist/index.cjs.js.map +2 -2
- package/dist/index.esm.js +37 -45
- package/dist/index.esm.js.map +3 -3
- package/dist/types.d.ts +1 -0
- package/package.json +1 -1
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:
|
|
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) =>
|
|
283
|
-
|
|
284
|
-
{
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
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: "
|
|
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(
|