@acarmisc/backstage-plugin-litellm 0.32.0 → 0.34.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/README.md +55 -66
- package/dist/components/KeyFormDialog.d.ts +0 -2
- package/dist/components/LiteLLMBudgetGauges.d.ts +0 -1
- package/dist/components/ManageTeamDialog.d.ts +10 -1
- package/dist/components/keyFormHelpers.d.ts +0 -1
- package/dist/hooks/useCopyToClipboard.d.ts +0 -5
- package/dist/index.cjs.js +272 -225
- package/dist/index.cjs.js.map +4 -4
- package/dist/index.d.ts +2 -3
- package/dist/index.esm.js +283 -237
- package/dist/index.esm.js.map +4 -4
- package/package.json +4 -10
- package/dist/components/GenerateKeyDialog.d.ts +0 -21
- package/dist/permissions.d.ts +0 -1
package/dist/index.esm.js
CHANGED
|
@@ -1823,8 +1823,6 @@ var init_KeysTable = __esm({
|
|
|
1823
1823
|
setPruneSubmitting(true);
|
|
1824
1824
|
try {
|
|
1825
1825
|
await onPruneExpiredKeys();
|
|
1826
|
-
} catch (error) {
|
|
1827
|
-
console.error("Failed to prune expired keys:", error);
|
|
1828
1826
|
} finally {
|
|
1829
1827
|
setPruneSubmitting(false);
|
|
1830
1828
|
setPruneConfirmCount(null);
|
|
@@ -1893,7 +1891,8 @@ var init_KeysTable = __esm({
|
|
|
1893
1891
|
bgcolor: alpha7(theme.palette.text.primary, theme.palette.mode === "dark" ? 0.08 : 0.05),
|
|
1894
1892
|
px: 0.75,
|
|
1895
1893
|
py: 0.375,
|
|
1896
|
-
borderRadius: "5px"
|
|
1894
|
+
borderRadius: "5px",
|
|
1895
|
+
whiteSpace: "nowrap"
|
|
1897
1896
|
}),
|
|
1898
1897
|
children: shortKeyId(keyId)
|
|
1899
1898
|
}
|
|
@@ -3184,6 +3183,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3184
3183
|
const [memberBudget, setMemberBudget] = useState6("");
|
|
3185
3184
|
const [memberBusy, setMemberBusy] = useState6(false);
|
|
3186
3185
|
const [memberError, setMemberError] = useState6(null);
|
|
3186
|
+
const [pendingMembers, setPendingMembers] = useState6([]);
|
|
3187
3187
|
const [kbIds, setKbIds] = useState6([]);
|
|
3188
3188
|
const [kbBusy, setKbBusy] = useState6(false);
|
|
3189
3189
|
const [kbError, setKbError] = useState6(null);
|
|
@@ -3194,8 +3194,17 @@ var init_ManageTeamDialog = __esm({
|
|
|
3194
3194
|
const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling ?? FALLBACK_BUDGET_CEILING;
|
|
3195
3195
|
const hideBudgetForManagers = config?.display?.hideTeamBudgetForManagers ?? false;
|
|
3196
3196
|
const budgetWriteOnly = hideBudgetForManagers && mode === "edit";
|
|
3197
|
-
const
|
|
3198
|
-
const
|
|
3197
|
+
const creating = mode === "create";
|
|
3198
|
+
const members = useMemo4(
|
|
3199
|
+
() => creating ? pendingMembers.map((p) => ({
|
|
3200
|
+
user_id: p.userEntityRef,
|
|
3201
|
+
user_email: p.label,
|
|
3202
|
+
role: "user"
|
|
3203
|
+
})) : team?.members_with_roles ?? [],
|
|
3204
|
+
[creating, pendingMembers, team]
|
|
3205
|
+
);
|
|
3206
|
+
const showMembers = !!canManageMembers || !!membersOnly;
|
|
3207
|
+
const wide = showMembers && !membersOnly;
|
|
3199
3208
|
const catalogApi = useApi3(catalogApiRef);
|
|
3200
3209
|
const [searchUsers, setSearchUsers] = useState6([]);
|
|
3201
3210
|
const [usersLoading, setUsersLoading] = useState6(false);
|
|
@@ -3240,8 +3249,8 @@ var init_ManageTeamDialog = __esm({
|
|
|
3240
3249
|
email,
|
|
3241
3250
|
label: email ? `${displayName} (${email})` : displayName
|
|
3242
3251
|
};
|
|
3243
|
-
}).filter((o) => !(o.email && existingEmails.has(o.email.toLowerCase()))).sort((a, b) => a.label.localeCompare(b.label));
|
|
3244
|
-
}, [searchUsers, members]);
|
|
3252
|
+
}).filter((o) => !(o.email && existingEmails.has(o.email.toLowerCase()))).filter((o) => !pendingMembers.some((p) => p.userEntityRef === o.ref)).sort((a, b) => a.label.localeCompare(b.label));
|
|
3253
|
+
}, [searchUsers, members, pendingMembers]);
|
|
3245
3254
|
useEffect4(() => {
|
|
3246
3255
|
return () => {
|
|
3247
3256
|
if (debounceTimerRef.current) {
|
|
@@ -3275,6 +3284,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3275
3284
|
setMemberRef("");
|
|
3276
3285
|
setMemberBudget("");
|
|
3277
3286
|
setMemberError(null);
|
|
3287
|
+
setPendingMembers([]);
|
|
3278
3288
|
setKbIds(team?.object_permission?.vector_stores ?? []);
|
|
3279
3289
|
setKbError(null);
|
|
3280
3290
|
setMcpIds(team?.object_permission?.mcp_servers ?? []);
|
|
@@ -3333,7 +3343,13 @@ var init_ManageTeamDialog = __esm({
|
|
|
3333
3343
|
...budgetDuration && { budget_duration: budgetDuration }
|
|
3334
3344
|
};
|
|
3335
3345
|
}
|
|
3336
|
-
await onSubmit(
|
|
3346
|
+
await onSubmit(
|
|
3347
|
+
payload,
|
|
3348
|
+
creating ? pendingMembers.map(({ userEntityRef, maxBudgetInTeam }) => ({
|
|
3349
|
+
userEntityRef,
|
|
3350
|
+
...maxBudgetInTeam !== void 0 && { maxBudgetInTeam }
|
|
3351
|
+
})) : void 0
|
|
3352
|
+
);
|
|
3337
3353
|
onClose();
|
|
3338
3354
|
} catch (err) {
|
|
3339
3355
|
setError(err instanceof Error ? err.message : "An error occurred");
|
|
@@ -3342,13 +3358,26 @@ var init_ManageTeamDialog = __esm({
|
|
|
3342
3358
|
}
|
|
3343
3359
|
};
|
|
3344
3360
|
const handleAddMember = async () => {
|
|
3345
|
-
if (!
|
|
3361
|
+
if (!memberRef.trim() || !creating && !onAddMember) return;
|
|
3346
3362
|
setMemberError(null);
|
|
3347
3363
|
const budget = !membersOnly && memberBudget ? parseFloat(memberBudget) : void 0;
|
|
3348
3364
|
if (budget !== void 0 && (isNaN(budget) || budget <= 0)) {
|
|
3349
3365
|
setMemberError("Max budget in team must be a positive number");
|
|
3350
3366
|
return;
|
|
3351
3367
|
}
|
|
3368
|
+
if (creating) {
|
|
3369
|
+
const ref = memberRef.trim();
|
|
3370
|
+
if (!pendingMembers.some((p) => p.userEntityRef === ref)) {
|
|
3371
|
+
setPendingMembers((list) => [
|
|
3372
|
+
...list,
|
|
3373
|
+
{ userEntityRef: ref, label: memberQuery.trim() || ref, maxBudgetInTeam: budget }
|
|
3374
|
+
]);
|
|
3375
|
+
}
|
|
3376
|
+
setMemberQuery("");
|
|
3377
|
+
setMemberRef("");
|
|
3378
|
+
setMemberBudget("");
|
|
3379
|
+
return;
|
|
3380
|
+
}
|
|
3352
3381
|
try {
|
|
3353
3382
|
setMemberBusy(true);
|
|
3354
3383
|
await onAddMember(memberRef.trim(), budget);
|
|
@@ -3362,6 +3391,10 @@ var init_ManageTeamDialog = __esm({
|
|
|
3362
3391
|
}
|
|
3363
3392
|
};
|
|
3364
3393
|
const handleRemoveMember = async (userId) => {
|
|
3394
|
+
if (creating) {
|
|
3395
|
+
setPendingMembers((list) => list.filter((p) => p.userEntityRef !== userId));
|
|
3396
|
+
return;
|
|
3397
|
+
}
|
|
3365
3398
|
if (!onRemoveMember) return;
|
|
3366
3399
|
setMemberError(null);
|
|
3367
3400
|
try {
|
|
@@ -3415,13 +3448,14 @@ var init_ManageTeamDialog = __esm({
|
|
|
3415
3448
|
}
|
|
3416
3449
|
return { disabled: false };
|
|
3417
3450
|
};
|
|
3451
|
+
const submitLabel = creating ? "Create team" : "Save";
|
|
3418
3452
|
const getDialogTitle = () => {
|
|
3419
3453
|
if (membersOnly) {
|
|
3420
3454
|
return `Manage members \u2014 ${team?.team_alias || "Untitled team"}`;
|
|
3421
3455
|
}
|
|
3422
3456
|
return mode === "create" ? "Create Team" : "Edit Team";
|
|
3423
3457
|
};
|
|
3424
|
-
return /* @__PURE__ */ jsxs10(Dialog3, { open, onClose, maxWidth: "sm", fullWidth: true, children: [
|
|
3458
|
+
return /* @__PURE__ */ jsxs10(Dialog3, { open, onClose, maxWidth: wide ? "md" : "sm", fullWidth: true, children: [
|
|
3425
3459
|
/* @__PURE__ */ jsx11(DialogTitle3, { children: getDialogTitle() }),
|
|
3426
3460
|
/* @__PURE__ */ jsxs10(DialogContent3, { sx: { pt: 2, display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3427
3461
|
error && /* @__PURE__ */ jsx11(Alert2, { severity: "error", children: error }),
|
|
@@ -3430,186 +3464,215 @@ var init_ManageTeamDialog = __esm({
|
|
|
3430
3464
|
team?.members_with_roles?.find((m) => m.user_id === currentUserId)?.role || "member",
|
|
3431
3465
|
" you can add or remove members. Budgets and models are managed by your platform admins."
|
|
3432
3466
|
] }),
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
{
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
options: modelNames,
|
|
3449
|
-
value: models,
|
|
3450
|
-
onChange: (_, newValue) => setModels(newValue),
|
|
3451
|
-
disabled: submitting,
|
|
3452
|
-
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3453
|
-
TextField3,
|
|
3454
|
-
{
|
|
3455
|
-
...params,
|
|
3456
|
-
label: "Models",
|
|
3457
|
-
required: true,
|
|
3458
|
-
helperText: "At least one model is required here \u2014 this delegated flow only grants access to models your admin has allow-listed for team creation, not every proxy model. (Teams with no model restriction shown elsewhere were configured directly in LiteLLM.)"
|
|
3459
|
-
}
|
|
3460
|
-
)
|
|
3461
|
-
}
|
|
3462
|
-
),
|
|
3463
|
-
/* @__PURE__ */ jsx11(
|
|
3464
|
-
TextField3,
|
|
3465
|
-
{
|
|
3466
|
-
label: budgetWriteOnly ? "New Max Budget ($)" : "Max Budget ($)",
|
|
3467
|
-
type: "number",
|
|
3468
|
-
value: maxBudget,
|
|
3469
|
-
onChange: (e) => setMaxBudget(e.target.value),
|
|
3470
|
-
disabled: submitting || unlimited,
|
|
3471
|
-
inputProps: { min: 0, max: maxBudgetCeiling },
|
|
3472
|
-
helperText: budgetWriteOnly ? "Current budget is hidden \u2014 leave blank to keep it, or enter a new value" : `Maximum: $${maxBudgetCeiling}`,
|
|
3473
|
-
fullWidth: true
|
|
3474
|
-
}
|
|
3475
|
-
),
|
|
3476
|
-
allowUnlimitedBudget && /* @__PURE__ */ jsx11(
|
|
3477
|
-
FormControlLabel2,
|
|
3478
|
-
{
|
|
3479
|
-
control: /* @__PURE__ */ jsx11(Checkbox2, { checked: unlimited, onChange: (e) => setUnlimited(e.target.checked), disabled: submitting }),
|
|
3480
|
-
label: "Unlimited Budget"
|
|
3481
|
-
}
|
|
3482
|
-
),
|
|
3483
|
-
/* @__PURE__ */ jsx11(
|
|
3484
|
-
TextField3,
|
|
3485
|
-
{
|
|
3486
|
-
select: true,
|
|
3487
|
-
label: "Budget Duration",
|
|
3488
|
-
value: budgetDuration,
|
|
3489
|
-
onChange: (e) => setBudgetDuration(e.target.value),
|
|
3490
|
-
disabled: submitting || unlimited,
|
|
3491
|
-
helperText: "Spend-reset period for the team budget",
|
|
3492
|
-
fullWidth: true,
|
|
3493
|
-
children: durationOptions.map((o) => /* @__PURE__ */ jsx11(MenuItem2, { value: o.value, children: o.label }, o.value))
|
|
3494
|
-
}
|
|
3495
|
-
)
|
|
3496
|
-
] }),
|
|
3497
|
-
showMembers && /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3498
|
-
/* @__PURE__ */ jsx11(Divider2, { sx: { my: 1 } }),
|
|
3499
|
-
/* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", sx: { mb: 1 }, children: "Members" }),
|
|
3500
|
-
memberError && /* @__PURE__ */ jsx11(Alert2, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null), children: memberError }),
|
|
3501
|
-
members.length === 0 ? /* @__PURE__ */ jsx11(Typography8, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: "No members yet." }) : /* @__PURE__ */ jsx11(TableContainer2, { component: Paper4, variant: "outlined", sx: { borderRadius: 1.5, mb: 1.5 }, children: /* @__PURE__ */ jsxs10(Table2, { size: "small", sx: dataTableSx, children: [
|
|
3502
|
-
/* @__PURE__ */ jsx11(TableHead2, { children: /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3503
|
-
/* @__PURE__ */ jsx11(TableCell2, { children: "User" }),
|
|
3504
|
-
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: "Role" }),
|
|
3505
|
-
/* @__PURE__ */ jsx11(TableCell2, { align: "right", sx: { width: 40 } })
|
|
3506
|
-
] }) }),
|
|
3507
|
-
/* @__PURE__ */ jsx11(TableBody2, { children: members.map((m) => /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3508
|
-
/* @__PURE__ */ jsx11(TableCell2, { children: m.user_email ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3509
|
-
/* @__PURE__ */ jsx11(Typography8, { variant: "body2", children: m.user_email }),
|
|
3467
|
+
/* @__PURE__ */ jsxs10(
|
|
3468
|
+
Box10,
|
|
3469
|
+
{
|
|
3470
|
+
sx: {
|
|
3471
|
+
display: "grid",
|
|
3472
|
+
gridTemplateColumns: {
|
|
3473
|
+
xs: "1fr",
|
|
3474
|
+
md: wide ? "minmax(0, 1fr) minmax(0, 1fr)" : "1fr"
|
|
3475
|
+
},
|
|
3476
|
+
gap: 3,
|
|
3477
|
+
alignItems: "start"
|
|
3478
|
+
},
|
|
3479
|
+
children: [
|
|
3480
|
+
!membersOnly && /* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3481
|
+
wide && /* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", children: "Settings" }),
|
|
3510
3482
|
/* @__PURE__ */ jsx11(
|
|
3511
|
-
|
|
3483
|
+
TextField3,
|
|
3512
3484
|
{
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3485
|
+
label: "Team Alias",
|
|
3486
|
+
value: alias,
|
|
3487
|
+
onChange: (e) => setAlias(e.target.value),
|
|
3488
|
+
disabled: submitting,
|
|
3489
|
+
fullWidth: true
|
|
3517
3490
|
}
|
|
3518
|
-
)
|
|
3519
|
-
|
|
3520
|
-
|
|
3521
|
-
{
|
|
3522
|
-
variant: "body2",
|
|
3523
|
-
sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" },
|
|
3524
|
-
children: m.user_id
|
|
3525
|
-
}
|
|
3526
|
-
) }),
|
|
3527
|
-
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: /* @__PURE__ */ jsx11(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false }) }),
|
|
3528
|
-
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: (() => {
|
|
3529
|
-
const { disabled, reason } = isRemovalDisabled(m.user_id, m.role);
|
|
3530
|
-
return /* @__PURE__ */ jsx11(Tooltip4, { title: reason ?? "", children: /* @__PURE__ */ jsx11("span", { children: /* @__PURE__ */ jsx11(
|
|
3531
|
-
IconButton4,
|
|
3491
|
+
),
|
|
3492
|
+
/* @__PURE__ */ jsx11(
|
|
3493
|
+
Autocomplete2,
|
|
3532
3494
|
{
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
{
|
|
3548
|
-
freeSolo: true,
|
|
3549
|
-
autoHighlight: true,
|
|
3550
|
-
options: userOptions,
|
|
3551
|
-
loading: usersLoading,
|
|
3552
|
-
inputValue: memberQuery,
|
|
3553
|
-
onInputChange: (_, newInputValue, reason) => {
|
|
3554
|
-
setMemberQuery(newInputValue);
|
|
3555
|
-
if (reason === "input" || reason === "clear") {
|
|
3556
|
-
setMemberRef(newInputValue);
|
|
3557
|
-
handleUserSearch(newInputValue);
|
|
3495
|
+
multiple: true,
|
|
3496
|
+
options: modelNames,
|
|
3497
|
+
value: models,
|
|
3498
|
+
onChange: (_, newValue) => setModels(newValue),
|
|
3499
|
+
disabled: submitting,
|
|
3500
|
+
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3501
|
+
TextField3,
|
|
3502
|
+
{
|
|
3503
|
+
...params,
|
|
3504
|
+
label: "Models",
|
|
3505
|
+
required: true,
|
|
3506
|
+
helperText: "Only models your admin allow-listed for teams. At least one is required."
|
|
3507
|
+
}
|
|
3508
|
+
)
|
|
3558
3509
|
}
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3510
|
+
),
|
|
3511
|
+
/* @__PURE__ */ jsxs10(
|
|
3512
|
+
Box10,
|
|
3513
|
+
{
|
|
3514
|
+
sx: {
|
|
3515
|
+
display: "grid",
|
|
3516
|
+
gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
|
|
3517
|
+
gap: 2
|
|
3518
|
+
},
|
|
3519
|
+
children: [
|
|
3520
|
+
/* @__PURE__ */ jsx11(
|
|
3521
|
+
TextField3,
|
|
3522
|
+
{
|
|
3523
|
+
label: budgetWriteOnly ? "New Max Budget ($)" : "Max Budget ($)",
|
|
3524
|
+
type: "number",
|
|
3525
|
+
value: maxBudget,
|
|
3526
|
+
onChange: (e) => setMaxBudget(e.target.value),
|
|
3527
|
+
disabled: submitting || unlimited,
|
|
3528
|
+
inputProps: { min: 0, max: maxBudgetCeiling },
|
|
3529
|
+
helperText: budgetWriteOnly ? "Current budget is hidden \u2014 leave blank to keep it, or enter a new value" : `Maximum: $${maxBudgetCeiling}`,
|
|
3530
|
+
fullWidth: true
|
|
3531
|
+
}
|
|
3532
|
+
),
|
|
3533
|
+
/* @__PURE__ */ jsx11(
|
|
3534
|
+
TextField3,
|
|
3535
|
+
{
|
|
3536
|
+
select: true,
|
|
3537
|
+
label: "Budget Duration",
|
|
3538
|
+
value: budgetDuration,
|
|
3539
|
+
onChange: (e) => setBudgetDuration(e.target.value),
|
|
3540
|
+
disabled: submitting || unlimited,
|
|
3541
|
+
helperText: "Spend-reset period for the team budget",
|
|
3542
|
+
fullWidth: true,
|
|
3543
|
+
children: durationOptions.map((o) => /* @__PURE__ */ jsx11(MenuItem2, { value: o.value, children: o.label }, o.value))
|
|
3544
|
+
}
|
|
3545
|
+
)
|
|
3546
|
+
]
|
|
3564
3547
|
}
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
disabled: memberBusy,
|
|
3569
|
-
sx: { flex: 1, minWidth: 260 },
|
|
3570
|
-
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3571
|
-
TextField3,
|
|
3548
|
+
),
|
|
3549
|
+
allowUnlimitedBudget && /* @__PURE__ */ jsx11(
|
|
3550
|
+
FormControlLabel2,
|
|
3572
3551
|
{
|
|
3573
|
-
|
|
3574
|
-
label: "
|
|
3575
|
-
placeholder: "Search by name or email\u2026",
|
|
3576
|
-
size: "small",
|
|
3577
|
-
helperText: "Pick a catalog user, or paste a user entity ref",
|
|
3578
|
-
InputProps: {
|
|
3579
|
-
...params.InputProps,
|
|
3580
|
-
endAdornment: /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3581
|
-
usersLoading ? /* @__PURE__ */ jsx11(CircularProgress3, { color: "inherit", size: 14 }) : null,
|
|
3582
|
-
params.InputProps.endAdornment
|
|
3583
|
-
] })
|
|
3584
|
-
}
|
|
3552
|
+
control: /* @__PURE__ */ jsx11(Checkbox2, { checked: unlimited, onChange: (e) => setUnlimited(e.target.checked), disabled: submitting }),
|
|
3553
|
+
label: "Unlimited Budget"
|
|
3585
3554
|
}
|
|
3586
3555
|
)
|
|
3587
|
-
}
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3556
|
+
] }),
|
|
3557
|
+
showMembers && /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3558
|
+
/* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", sx: { mb: creating ? 0.25 : 1 }, children: creating ? "Initial members" : "Members" }),
|
|
3559
|
+
creating && /* @__PURE__ */ jsx11(Typography8, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: "Added as team users right after the team is created." }),
|
|
3560
|
+
memberError && /* @__PURE__ */ jsx11(Alert2, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null), children: memberError }),
|
|
3561
|
+
members.length === 0 ? /* @__PURE__ */ jsx11(Typography8, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: creating ? "No members picked yet \u2014 you can also add them later." : "No members yet." }) : /* @__PURE__ */ jsx11(TableContainer2, { component: Paper4, variant: "outlined", sx: { borderRadius: 1.5, mb: 1.5 }, children: /* @__PURE__ */ jsxs10(Table2, { size: "small", sx: dataTableSx, children: [
|
|
3562
|
+
/* @__PURE__ */ jsx11(TableHead2, { children: /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3563
|
+
/* @__PURE__ */ jsx11(TableCell2, { children: "User" }),
|
|
3564
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: "Role" }),
|
|
3565
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", sx: { width: 40 } })
|
|
3566
|
+
] }) }),
|
|
3567
|
+
/* @__PURE__ */ jsx11(TableBody2, { children: members.map((m) => /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3568
|
+
/* @__PURE__ */ jsx11(TableCell2, { children: m.user_email ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3569
|
+
/* @__PURE__ */ jsx11(Typography8, { variant: "body2", children: m.user_email }),
|
|
3570
|
+
/* @__PURE__ */ jsx11(
|
|
3571
|
+
Typography8,
|
|
3572
|
+
{
|
|
3573
|
+
variant: "caption",
|
|
3574
|
+
color: "text.secondary",
|
|
3575
|
+
sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 },
|
|
3576
|
+
children: m.user_id
|
|
3577
|
+
}
|
|
3578
|
+
)
|
|
3579
|
+
] }) : /* @__PURE__ */ jsx11(
|
|
3580
|
+
Typography8,
|
|
3581
|
+
{
|
|
3582
|
+
variant: "body2",
|
|
3583
|
+
sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" },
|
|
3584
|
+
children: m.user_id
|
|
3585
|
+
}
|
|
3586
|
+
) }),
|
|
3587
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: /* @__PURE__ */ jsx11(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false }) }),
|
|
3588
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: (() => {
|
|
3589
|
+
const { disabled, reason } = isRemovalDisabled(m.user_id, m.role);
|
|
3590
|
+
return /* @__PURE__ */ jsx11(Tooltip4, { title: reason ?? "", children: /* @__PURE__ */ jsx11("span", { children: /* @__PURE__ */ jsx11(
|
|
3591
|
+
IconButton4,
|
|
3592
|
+
{
|
|
3593
|
+
edge: "end",
|
|
3594
|
+
size: "small",
|
|
3595
|
+
"aria-label": `remove ${m.user_id}`,
|
|
3596
|
+
disabled: memberBusy || disabled,
|
|
3597
|
+
onClick: () => handleRemoveMember(m.user_id),
|
|
3598
|
+
children: /* @__PURE__ */ jsx11(DeleteIcon, { fontSize: "small" })
|
|
3599
|
+
}
|
|
3600
|
+
) }) });
|
|
3601
|
+
})() })
|
|
3602
|
+
] }, m.user_id)) })
|
|
3603
|
+
] }) }),
|
|
3604
|
+
/* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", gap: 1, alignItems: "flex-start", flexWrap: "wrap" }, children: [
|
|
3605
|
+
/* @__PURE__ */ jsx11(
|
|
3606
|
+
Autocomplete2,
|
|
3607
|
+
{
|
|
3608
|
+
freeSolo: true,
|
|
3609
|
+
autoHighlight: true,
|
|
3610
|
+
options: userOptions,
|
|
3611
|
+
loading: usersLoading,
|
|
3612
|
+
inputValue: memberQuery,
|
|
3613
|
+
onInputChange: (_, newInputValue, reason) => {
|
|
3614
|
+
setMemberQuery(newInputValue);
|
|
3615
|
+
if (reason === "input" || reason === "clear") {
|
|
3616
|
+
setMemberRef(newInputValue);
|
|
3617
|
+
handleUserSearch(newInputValue);
|
|
3618
|
+
}
|
|
3619
|
+
},
|
|
3620
|
+
onChange: (_, newValue) => {
|
|
3621
|
+
if (newValue && typeof newValue !== "string") {
|
|
3622
|
+
setMemberQuery(newValue.label);
|
|
3623
|
+
setMemberRef(newValue.ref);
|
|
3624
|
+
}
|
|
3625
|
+
},
|
|
3626
|
+
getOptionLabel: (o) => typeof o === "string" ? o : o.label,
|
|
3627
|
+
isOptionEqualToValue: (o, v) => o.ref === (typeof v === "string" ? v : v.ref),
|
|
3628
|
+
disabled: memberBusy,
|
|
3629
|
+
sx: { flex: "1 1 240px" },
|
|
3630
|
+
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3631
|
+
TextField3,
|
|
3632
|
+
{
|
|
3633
|
+
...params,
|
|
3634
|
+
label: "Add member",
|
|
3635
|
+
placeholder: "Search by name or email\u2026",
|
|
3636
|
+
size: "small",
|
|
3637
|
+
helperText: "Pick a catalog user, or paste a user entity ref",
|
|
3638
|
+
InputProps: {
|
|
3639
|
+
...params.InputProps,
|
|
3640
|
+
endAdornment: /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3641
|
+
usersLoading ? /* @__PURE__ */ jsx11(CircularProgress3, { color: "inherit", size: 14 }) : null,
|
|
3642
|
+
params.InputProps.endAdornment
|
|
3643
|
+
] })
|
|
3644
|
+
}
|
|
3645
|
+
}
|
|
3646
|
+
)
|
|
3647
|
+
}
|
|
3648
|
+
),
|
|
3649
|
+
!membersOnly && /* @__PURE__ */ jsx11(
|
|
3650
|
+
TextField3,
|
|
3651
|
+
{
|
|
3652
|
+
label: "Max budget in team ($)",
|
|
3653
|
+
type: "number",
|
|
3654
|
+
value: memberBudget,
|
|
3655
|
+
onChange: (e) => setMemberBudget(e.target.value),
|
|
3656
|
+
disabled: memberBusy,
|
|
3657
|
+
size: "small",
|
|
3658
|
+
sx: { width: 150 }
|
|
3659
|
+
}
|
|
3660
|
+
),
|
|
3661
|
+
/* @__PURE__ */ jsx11(
|
|
3662
|
+
Button4,
|
|
3663
|
+
{
|
|
3664
|
+
onClick: handleAddMember,
|
|
3665
|
+
disabled: memberBusy || !memberRef.trim(),
|
|
3666
|
+
variant: "outlined",
|
|
3667
|
+
sx: { mt: 0.5 },
|
|
3668
|
+
children: "Add"
|
|
3669
|
+
}
|
|
3670
|
+
)
|
|
3671
|
+
] })
|
|
3672
|
+
] })
|
|
3673
|
+
]
|
|
3674
|
+
}
|
|
3675
|
+
),
|
|
3613
3676
|
!membersOnly && showKnowledgeBases && /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3614
3677
|
/* @__PURE__ */ jsx11(Divider2, { sx: { my: 1 } }),
|
|
3615
3678
|
/* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", sx: { mb: 1 }, children: "Knowledge Bases" }),
|
|
@@ -3667,7 +3730,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3667
3730
|
] }),
|
|
3668
3731
|
/* @__PURE__ */ jsxs10(DialogActions3, { children: [
|
|
3669
3732
|
/* @__PURE__ */ jsx11(Button4, { onClick: onClose, disabled: submitting, children: membersOnly ? "Done" : "Cancel" }),
|
|
3670
|
-
!membersOnly && /* @__PURE__ */ jsx11(Button4, { onClick: handleSubmit, disabled: submitting, variant: "contained", children: submitting ? "Saving..." :
|
|
3733
|
+
!membersOnly && /* @__PURE__ */ jsx11(Button4, { onClick: handleSubmit, disabled: submitting, variant: "contained", children: submitting ? "Saving..." : submitLabel })
|
|
3671
3734
|
] })
|
|
3672
3735
|
] });
|
|
3673
3736
|
};
|
|
@@ -5836,28 +5899,6 @@ var init_dates = __esm({
|
|
|
5836
5899
|
}
|
|
5837
5900
|
});
|
|
5838
5901
|
|
|
5839
|
-
// src/permissions.ts
|
|
5840
|
-
import {
|
|
5841
|
-
litellmKeyCreatePermission,
|
|
5842
|
-
litellmKeyRevokePermission as litellmKeyRevokePermission2,
|
|
5843
|
-
litellmKeyManagePermission as litellmKeyManagePermission2,
|
|
5844
|
-
litellmKeyResetSpendPermission as litellmKeyResetSpendPermission2,
|
|
5845
|
-
litellmKeyUnblockPermission as litellmKeyUnblockPermission2,
|
|
5846
|
-
litellmAuditReadPermission,
|
|
5847
|
-
litellmTeamCreatePermission,
|
|
5848
|
-
litellmTeamManagePermission,
|
|
5849
|
-
litellmTeamMembersManagePermission,
|
|
5850
|
-
litellmTeamKnowledgebaseManagePermission,
|
|
5851
|
-
litellmTeamMcpManagePermission,
|
|
5852
|
-
litellmTeamDeletePermission,
|
|
5853
|
-
litellmPermissions
|
|
5854
|
-
} from "@acarmisc/backstage-plugin-litellm-common";
|
|
5855
|
-
var init_permissions = __esm({
|
|
5856
|
-
"src/permissions.ts"() {
|
|
5857
|
-
"use strict";
|
|
5858
|
-
}
|
|
5859
|
-
});
|
|
5860
|
-
|
|
5861
5902
|
// src/feedback.ts
|
|
5862
5903
|
function toastFor(kind, errorMsg) {
|
|
5863
5904
|
switch (kind) {
|
|
@@ -5969,6 +6010,13 @@ import { useAsync as useAsync2, useAsyncRetry } from "react-use";
|
|
|
5969
6010
|
import { useApi as useApi4, alertApiRef as alertApiRef2 } from "@backstage/core-plugin-api";
|
|
5970
6011
|
import { Content, Progress } from "@backstage/core-components";
|
|
5971
6012
|
import { usePermission as usePermission3 } from "@backstage/plugin-permission-react";
|
|
6013
|
+
import {
|
|
6014
|
+
litellmTeamCreatePermission,
|
|
6015
|
+
litellmTeamManagePermission,
|
|
6016
|
+
litellmTeamMembersManagePermission,
|
|
6017
|
+
litellmTeamKnowledgebaseManagePermission,
|
|
6018
|
+
litellmTeamMcpManagePermission
|
|
6019
|
+
} from "@acarmisc/backstage-plugin-litellm-common";
|
|
5972
6020
|
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
5973
6021
|
function initDateRange() {
|
|
5974
6022
|
let preset = "7d";
|
|
@@ -5999,7 +6047,6 @@ var init_LiteLLMPage = __esm({
|
|
|
5999
6047
|
init_AuditLog();
|
|
6000
6048
|
init_api();
|
|
6001
6049
|
init_dates();
|
|
6002
|
-
init_permissions();
|
|
6003
6050
|
init_feedback();
|
|
6004
6051
|
init_teamMemberManager();
|
|
6005
6052
|
init_unprovisionedCopy();
|
|
@@ -6521,7 +6568,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6521
6568
|
membersOnly: manageTeam?.mode === "members",
|
|
6522
6569
|
currentUserId: userInfo?.user_id,
|
|
6523
6570
|
memberManagerRoles: liteLlmConfig?.teamManagement?.memberManagerRoles,
|
|
6524
|
-
onSubmit: async (payload) => {
|
|
6571
|
+
onSubmit: async (payload, initialMembers) => {
|
|
6525
6572
|
try {
|
|
6526
6573
|
if (manageTeam?.mode === "edit" && manageTeam.team) {
|
|
6527
6574
|
const loadedAt = manageTeam.team.metadata?.updated_at_iso;
|
|
@@ -6531,7 +6578,23 @@ var init_LiteLLMPage = __esm({
|
|
|
6531
6578
|
...typeof loadedAt === "string" ? { expectedUpdatedAtIso: loadedAt } : {}
|
|
6532
6579
|
});
|
|
6533
6580
|
} else {
|
|
6534
|
-
await api.createTeam(payload);
|
|
6581
|
+
const created = await api.createTeam(payload);
|
|
6582
|
+
const failed = [];
|
|
6583
|
+
for (const m of initialMembers ?? []) {
|
|
6584
|
+
try {
|
|
6585
|
+
await api.addTeamMember(created.team_id, m);
|
|
6586
|
+
} catch (e) {
|
|
6587
|
+
failed.push(`${m.userEntityRef} (${e.message})`);
|
|
6588
|
+
}
|
|
6589
|
+
}
|
|
6590
|
+
if (failed.length) {
|
|
6591
|
+
alertApi.post({
|
|
6592
|
+
message: `Team created, but some members could not be added: ${failed.join(", ")}`,
|
|
6593
|
+
severity: "warning"
|
|
6594
|
+
});
|
|
6595
|
+
refreshTeams();
|
|
6596
|
+
return;
|
|
6597
|
+
}
|
|
6535
6598
|
}
|
|
6536
6599
|
const alert = toastFor("teamSaveSuccess");
|
|
6537
6600
|
if (alert) alertApi.post(alert);
|
|
@@ -7536,36 +7599,18 @@ var LiteLLMBudgetGauges = ({
|
|
|
7536
7599
|
// src/index.ts
|
|
7537
7600
|
init_KeyFormDialog();
|
|
7538
7601
|
init_GenerateKeyButton();
|
|
7539
|
-
|
|
7540
|
-
// src/components/GenerateKeyDialog.tsx
|
|
7541
|
-
init_KeyFormDialog();
|
|
7542
|
-
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
7543
|
-
var GenerateKeyDialog = (props) => /* @__PURE__ */ jsx22(
|
|
7544
|
-
KeyFormDialog,
|
|
7545
|
-
{
|
|
7546
|
-
open: props.open,
|
|
7547
|
-
onClose: props.onClose,
|
|
7548
|
-
mode: "create",
|
|
7549
|
-
keys: props.keys,
|
|
7550
|
-
models: props.models,
|
|
7551
|
-
teams: props.teams,
|
|
7552
|
-
username: props.username,
|
|
7553
|
-
keyGenerationSettings: props.keyGenerationSettings,
|
|
7554
|
-
onCreateKey: props.onGenerateKey,
|
|
7555
|
-
onUpdateKey: async () => {
|
|
7556
|
-
},
|
|
7557
|
-
onGetConfig: props.onGetConfig
|
|
7558
|
-
}
|
|
7559
|
-
);
|
|
7560
|
-
|
|
7561
|
-
// src/index.ts
|
|
7562
7602
|
init_ManageTeamDialog();
|
|
7563
7603
|
init_api();
|
|
7564
|
-
|
|
7604
|
+
import {
|
|
7605
|
+
litellmTeamCreatePermission as litellmTeamCreatePermission2,
|
|
7606
|
+
litellmTeamManagePermission as litellmTeamManagePermission2,
|
|
7607
|
+
litellmTeamMembersManagePermission as litellmTeamMembersManagePermission2,
|
|
7608
|
+
litellmTeamKnowledgebaseManagePermission as litellmTeamKnowledgebaseManagePermission2,
|
|
7609
|
+
litellmTeamMcpManagePermission as litellmTeamMcpManagePermission2
|
|
7610
|
+
} from "@acarmisc/backstage-plugin-litellm-common";
|
|
7565
7611
|
export {
|
|
7566
7612
|
DashboardHeader,
|
|
7567
7613
|
GenerateKeyButton,
|
|
7568
|
-
GenerateKeyDialog,
|
|
7569
7614
|
KeyFormDialog,
|
|
7570
7615
|
KeysTable,
|
|
7571
7616
|
LiteLLMBudgetGauges,
|
|
@@ -7576,12 +7621,13 @@ export {
|
|
|
7576
7621
|
ManageTeamDialog,
|
|
7577
7622
|
TeamUsage,
|
|
7578
7623
|
UsageStats,
|
|
7624
|
+
litellmPlugin as default,
|
|
7579
7625
|
liteLlmApiRef,
|
|
7580
7626
|
litellmPlugin,
|
|
7581
|
-
litellmTeamCreatePermission,
|
|
7582
|
-
litellmTeamKnowledgebaseManagePermission,
|
|
7583
|
-
litellmTeamManagePermission,
|
|
7584
|
-
litellmTeamMcpManagePermission,
|
|
7585
|
-
litellmTeamMembersManagePermission
|
|
7627
|
+
litellmTeamCreatePermission2 as litellmTeamCreatePermission,
|
|
7628
|
+
litellmTeamKnowledgebaseManagePermission2 as litellmTeamKnowledgebaseManagePermission,
|
|
7629
|
+
litellmTeamManagePermission2 as litellmTeamManagePermission,
|
|
7630
|
+
litellmTeamMcpManagePermission2 as litellmTeamMcpManagePermission,
|
|
7631
|
+
litellmTeamMembersManagePermission2 as litellmTeamMembersManagePermission
|
|
7586
7632
|
};
|
|
7587
7633
|
//# sourceMappingURL=index.esm.js.map
|