@acarmisc/backstage-plugin-litellm 0.32.0 → 0.33.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/components/ManageTeamDialog.d.ts +10 -1
- package/dist/index.cjs.js +261 -181
- package/dist/index.cjs.js.map +3 -3
- package/dist/index.esm.js +261 -181
- package/dist/index.esm.js.map +2 -2
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -3184,6 +3184,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3184
3184
|
const [memberBudget, setMemberBudget] = useState6("");
|
|
3185
3185
|
const [memberBusy, setMemberBusy] = useState6(false);
|
|
3186
3186
|
const [memberError, setMemberError] = useState6(null);
|
|
3187
|
+
const [pendingMembers, setPendingMembers] = useState6([]);
|
|
3187
3188
|
const [kbIds, setKbIds] = useState6([]);
|
|
3188
3189
|
const [kbBusy, setKbBusy] = useState6(false);
|
|
3189
3190
|
const [kbError, setKbError] = useState6(null);
|
|
@@ -3194,8 +3195,17 @@ var init_ManageTeamDialog = __esm({
|
|
|
3194
3195
|
const maxBudgetCeiling = config?.teamManagement?.maxBudgetCeiling ?? FALLBACK_BUDGET_CEILING;
|
|
3195
3196
|
const hideBudgetForManagers = config?.display?.hideTeamBudgetForManagers ?? false;
|
|
3196
3197
|
const budgetWriteOnly = hideBudgetForManagers && mode === "edit";
|
|
3197
|
-
const
|
|
3198
|
-
const
|
|
3198
|
+
const creating = mode === "create";
|
|
3199
|
+
const members = useMemo4(
|
|
3200
|
+
() => creating ? pendingMembers.map((p) => ({
|
|
3201
|
+
user_id: p.userEntityRef,
|
|
3202
|
+
user_email: p.label,
|
|
3203
|
+
role: "user"
|
|
3204
|
+
})) : team?.members_with_roles ?? [],
|
|
3205
|
+
[creating, pendingMembers, team]
|
|
3206
|
+
);
|
|
3207
|
+
const showMembers = !!canManageMembers || !!membersOnly;
|
|
3208
|
+
const wide = showMembers && !membersOnly;
|
|
3199
3209
|
const catalogApi = useApi3(catalogApiRef);
|
|
3200
3210
|
const [searchUsers, setSearchUsers] = useState6([]);
|
|
3201
3211
|
const [usersLoading, setUsersLoading] = useState6(false);
|
|
@@ -3240,8 +3250,8 @@ var init_ManageTeamDialog = __esm({
|
|
|
3240
3250
|
email,
|
|
3241
3251
|
label: email ? `${displayName} (${email})` : displayName
|
|
3242
3252
|
};
|
|
3243
|
-
}).filter((o) => !(o.email && existingEmails.has(o.email.toLowerCase()))).sort((a, b) => a.label.localeCompare(b.label));
|
|
3244
|
-
}, [searchUsers, members]);
|
|
3253
|
+
}).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));
|
|
3254
|
+
}, [searchUsers, members, pendingMembers]);
|
|
3245
3255
|
useEffect4(() => {
|
|
3246
3256
|
return () => {
|
|
3247
3257
|
if (debounceTimerRef.current) {
|
|
@@ -3275,6 +3285,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3275
3285
|
setMemberRef("");
|
|
3276
3286
|
setMemberBudget("");
|
|
3277
3287
|
setMemberError(null);
|
|
3288
|
+
setPendingMembers([]);
|
|
3278
3289
|
setKbIds(team?.object_permission?.vector_stores ?? []);
|
|
3279
3290
|
setKbError(null);
|
|
3280
3291
|
setMcpIds(team?.object_permission?.mcp_servers ?? []);
|
|
@@ -3333,7 +3344,13 @@ var init_ManageTeamDialog = __esm({
|
|
|
3333
3344
|
...budgetDuration && { budget_duration: budgetDuration }
|
|
3334
3345
|
};
|
|
3335
3346
|
}
|
|
3336
|
-
await onSubmit(
|
|
3347
|
+
await onSubmit(
|
|
3348
|
+
payload,
|
|
3349
|
+
creating ? pendingMembers.map(({ userEntityRef, maxBudgetInTeam }) => ({
|
|
3350
|
+
userEntityRef,
|
|
3351
|
+
...maxBudgetInTeam !== void 0 && { maxBudgetInTeam }
|
|
3352
|
+
})) : void 0
|
|
3353
|
+
);
|
|
3337
3354
|
onClose();
|
|
3338
3355
|
} catch (err) {
|
|
3339
3356
|
setError(err instanceof Error ? err.message : "An error occurred");
|
|
@@ -3342,13 +3359,26 @@ var init_ManageTeamDialog = __esm({
|
|
|
3342
3359
|
}
|
|
3343
3360
|
};
|
|
3344
3361
|
const handleAddMember = async () => {
|
|
3345
|
-
if (!
|
|
3362
|
+
if (!memberRef.trim() || !creating && !onAddMember) return;
|
|
3346
3363
|
setMemberError(null);
|
|
3347
3364
|
const budget = !membersOnly && memberBudget ? parseFloat(memberBudget) : void 0;
|
|
3348
3365
|
if (budget !== void 0 && (isNaN(budget) || budget <= 0)) {
|
|
3349
3366
|
setMemberError("Max budget in team must be a positive number");
|
|
3350
3367
|
return;
|
|
3351
3368
|
}
|
|
3369
|
+
if (creating) {
|
|
3370
|
+
const ref = memberRef.trim();
|
|
3371
|
+
if (!pendingMembers.some((p) => p.userEntityRef === ref)) {
|
|
3372
|
+
setPendingMembers((list) => [
|
|
3373
|
+
...list,
|
|
3374
|
+
{ userEntityRef: ref, label: memberQuery.trim() || ref, maxBudgetInTeam: budget }
|
|
3375
|
+
]);
|
|
3376
|
+
}
|
|
3377
|
+
setMemberQuery("");
|
|
3378
|
+
setMemberRef("");
|
|
3379
|
+
setMemberBudget("");
|
|
3380
|
+
return;
|
|
3381
|
+
}
|
|
3352
3382
|
try {
|
|
3353
3383
|
setMemberBusy(true);
|
|
3354
3384
|
await onAddMember(memberRef.trim(), budget);
|
|
@@ -3362,6 +3392,10 @@ var init_ManageTeamDialog = __esm({
|
|
|
3362
3392
|
}
|
|
3363
3393
|
};
|
|
3364
3394
|
const handleRemoveMember = async (userId) => {
|
|
3395
|
+
if (creating) {
|
|
3396
|
+
setPendingMembers((list) => list.filter((p) => p.userEntityRef !== userId));
|
|
3397
|
+
return;
|
|
3398
|
+
}
|
|
3365
3399
|
if (!onRemoveMember) return;
|
|
3366
3400
|
setMemberError(null);
|
|
3367
3401
|
try {
|
|
@@ -3415,13 +3449,14 @@ var init_ManageTeamDialog = __esm({
|
|
|
3415
3449
|
}
|
|
3416
3450
|
return { disabled: false };
|
|
3417
3451
|
};
|
|
3452
|
+
const submitLabel = creating ? "Create team" : "Save";
|
|
3418
3453
|
const getDialogTitle = () => {
|
|
3419
3454
|
if (membersOnly) {
|
|
3420
3455
|
return `Manage members \u2014 ${team?.team_alias || "Untitled team"}`;
|
|
3421
3456
|
}
|
|
3422
3457
|
return mode === "create" ? "Create Team" : "Edit Team";
|
|
3423
3458
|
};
|
|
3424
|
-
return /* @__PURE__ */ jsxs10(Dialog3, { open, onClose, maxWidth: "sm", fullWidth: true, children: [
|
|
3459
|
+
return /* @__PURE__ */ jsxs10(Dialog3, { open, onClose, maxWidth: wide ? "md" : "sm", fullWidth: true, children: [
|
|
3425
3460
|
/* @__PURE__ */ jsx11(DialogTitle3, { children: getDialogTitle() }),
|
|
3426
3461
|
/* @__PURE__ */ jsxs10(DialogContent3, { sx: { pt: 2, display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3427
3462
|
error && /* @__PURE__ */ jsx11(Alert2, { severity: "error", children: error }),
|
|
@@ -3430,186 +3465,215 @@ var init_ManageTeamDialog = __esm({
|
|
|
3430
3465
|
team?.members_with_roles?.find((m) => m.user_id === currentUserId)?.role || "member",
|
|
3431
3466
|
" you can add or remove members. Budgets and models are managed by your platform admins."
|
|
3432
3467
|
] }),
|
|
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 }),
|
|
3468
|
+
/* @__PURE__ */ jsxs10(
|
|
3469
|
+
Box10,
|
|
3470
|
+
{
|
|
3471
|
+
sx: {
|
|
3472
|
+
display: "grid",
|
|
3473
|
+
gridTemplateColumns: {
|
|
3474
|
+
xs: "1fr",
|
|
3475
|
+
md: wide ? "minmax(0, 1fr) minmax(0, 1fr)" : "1fr"
|
|
3476
|
+
},
|
|
3477
|
+
gap: 3,
|
|
3478
|
+
alignItems: "start"
|
|
3479
|
+
},
|
|
3480
|
+
children: [
|
|
3481
|
+
!membersOnly && /* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", flexDirection: "column", gap: 2 }, children: [
|
|
3482
|
+
wide && /* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", children: "Settings" }),
|
|
3510
3483
|
/* @__PURE__ */ jsx11(
|
|
3511
|
-
|
|
3484
|
+
TextField3,
|
|
3512
3485
|
{
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3486
|
+
label: "Team Alias",
|
|
3487
|
+
value: alias,
|
|
3488
|
+
onChange: (e) => setAlias(e.target.value),
|
|
3489
|
+
disabled: submitting,
|
|
3490
|
+
fullWidth: true
|
|
3517
3491
|
}
|
|
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,
|
|
3492
|
+
),
|
|
3493
|
+
/* @__PURE__ */ jsx11(
|
|
3494
|
+
Autocomplete2,
|
|
3532
3495
|
{
|
|
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);
|
|
3496
|
+
multiple: true,
|
|
3497
|
+
options: modelNames,
|
|
3498
|
+
value: models,
|
|
3499
|
+
onChange: (_, newValue) => setModels(newValue),
|
|
3500
|
+
disabled: submitting,
|
|
3501
|
+
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3502
|
+
TextField3,
|
|
3503
|
+
{
|
|
3504
|
+
...params,
|
|
3505
|
+
label: "Models",
|
|
3506
|
+
required: true,
|
|
3507
|
+
helperText: "Only models your admin allow-listed for teams. At least one is required."
|
|
3508
|
+
}
|
|
3509
|
+
)
|
|
3558
3510
|
}
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3511
|
+
),
|
|
3512
|
+
/* @__PURE__ */ jsxs10(
|
|
3513
|
+
Box10,
|
|
3514
|
+
{
|
|
3515
|
+
sx: {
|
|
3516
|
+
display: "grid",
|
|
3517
|
+
gridTemplateColumns: { xs: "1fr", sm: "1fr 1fr" },
|
|
3518
|
+
gap: 2
|
|
3519
|
+
},
|
|
3520
|
+
children: [
|
|
3521
|
+
/* @__PURE__ */ jsx11(
|
|
3522
|
+
TextField3,
|
|
3523
|
+
{
|
|
3524
|
+
label: budgetWriteOnly ? "New Max Budget ($)" : "Max Budget ($)",
|
|
3525
|
+
type: "number",
|
|
3526
|
+
value: maxBudget,
|
|
3527
|
+
onChange: (e) => setMaxBudget(e.target.value),
|
|
3528
|
+
disabled: submitting || unlimited,
|
|
3529
|
+
inputProps: { min: 0, max: maxBudgetCeiling },
|
|
3530
|
+
helperText: budgetWriteOnly ? "Current budget is hidden \u2014 leave blank to keep it, or enter a new value" : `Maximum: $${maxBudgetCeiling}`,
|
|
3531
|
+
fullWidth: true
|
|
3532
|
+
}
|
|
3533
|
+
),
|
|
3534
|
+
/* @__PURE__ */ jsx11(
|
|
3535
|
+
TextField3,
|
|
3536
|
+
{
|
|
3537
|
+
select: true,
|
|
3538
|
+
label: "Budget Duration",
|
|
3539
|
+
value: budgetDuration,
|
|
3540
|
+
onChange: (e) => setBudgetDuration(e.target.value),
|
|
3541
|
+
disabled: submitting || unlimited,
|
|
3542
|
+
helperText: "Spend-reset period for the team budget",
|
|
3543
|
+
fullWidth: true,
|
|
3544
|
+
children: durationOptions.map((o) => /* @__PURE__ */ jsx11(MenuItem2, { value: o.value, children: o.label }, o.value))
|
|
3545
|
+
}
|
|
3546
|
+
)
|
|
3547
|
+
]
|
|
3564
3548
|
}
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
disabled: memberBusy,
|
|
3569
|
-
sx: { flex: 1, minWidth: 260 },
|
|
3570
|
-
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3571
|
-
TextField3,
|
|
3549
|
+
),
|
|
3550
|
+
allowUnlimitedBudget && /* @__PURE__ */ jsx11(
|
|
3551
|
+
FormControlLabel2,
|
|
3572
3552
|
{
|
|
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
|
-
}
|
|
3553
|
+
control: /* @__PURE__ */ jsx11(Checkbox2, { checked: unlimited, onChange: (e) => setUnlimited(e.target.checked), disabled: submitting }),
|
|
3554
|
+
label: "Unlimited Budget"
|
|
3585
3555
|
}
|
|
3586
3556
|
)
|
|
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
|
-
|
|
3557
|
+
] }),
|
|
3558
|
+
showMembers && /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3559
|
+
/* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", sx: { mb: creating ? 0.25 : 1 }, children: creating ? "Initial members" : "Members" }),
|
|
3560
|
+
creating && /* @__PURE__ */ jsx11(Typography8, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: "Added as team users right after the team is created." }),
|
|
3561
|
+
memberError && /* @__PURE__ */ jsx11(Alert2, { severity: "error", sx: { mb: 1 }, onClose: () => setMemberError(null), children: memberError }),
|
|
3562
|
+
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: [
|
|
3563
|
+
/* @__PURE__ */ jsx11(TableHead2, { children: /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3564
|
+
/* @__PURE__ */ jsx11(TableCell2, { children: "User" }),
|
|
3565
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: "Role" }),
|
|
3566
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", sx: { width: 40 } })
|
|
3567
|
+
] }) }),
|
|
3568
|
+
/* @__PURE__ */ jsx11(TableBody2, { children: members.map((m) => /* @__PURE__ */ jsxs10(TableRow2, { children: [
|
|
3569
|
+
/* @__PURE__ */ jsx11(TableCell2, { children: m.user_email ? /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3570
|
+
/* @__PURE__ */ jsx11(Typography8, { variant: "body2", children: m.user_email }),
|
|
3571
|
+
/* @__PURE__ */ jsx11(
|
|
3572
|
+
Typography8,
|
|
3573
|
+
{
|
|
3574
|
+
variant: "caption",
|
|
3575
|
+
color: "text.secondary",
|
|
3576
|
+
sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", fontSize: 11 },
|
|
3577
|
+
children: m.user_id
|
|
3578
|
+
}
|
|
3579
|
+
)
|
|
3580
|
+
] }) : /* @__PURE__ */ jsx11(
|
|
3581
|
+
Typography8,
|
|
3582
|
+
{
|
|
3583
|
+
variant: "body2",
|
|
3584
|
+
sx: { fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace" },
|
|
3585
|
+
children: m.user_id
|
|
3586
|
+
}
|
|
3587
|
+
) }),
|
|
3588
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: /* @__PURE__ */ jsx11(StatusPill, { label: m.role, tone: m.role === "admin" ? "accent" : "neutral", dot: false }) }),
|
|
3589
|
+
/* @__PURE__ */ jsx11(TableCell2, { align: "right", children: (() => {
|
|
3590
|
+
const { disabled, reason } = isRemovalDisabled(m.user_id, m.role);
|
|
3591
|
+
return /* @__PURE__ */ jsx11(Tooltip4, { title: reason ?? "", children: /* @__PURE__ */ jsx11("span", { children: /* @__PURE__ */ jsx11(
|
|
3592
|
+
IconButton4,
|
|
3593
|
+
{
|
|
3594
|
+
edge: "end",
|
|
3595
|
+
size: "small",
|
|
3596
|
+
"aria-label": `remove ${m.user_id}`,
|
|
3597
|
+
disabled: memberBusy || disabled,
|
|
3598
|
+
onClick: () => handleRemoveMember(m.user_id),
|
|
3599
|
+
children: /* @__PURE__ */ jsx11(DeleteIcon, { fontSize: "small" })
|
|
3600
|
+
}
|
|
3601
|
+
) }) });
|
|
3602
|
+
})() })
|
|
3603
|
+
] }, m.user_id)) })
|
|
3604
|
+
] }) }),
|
|
3605
|
+
/* @__PURE__ */ jsxs10(Box10, { sx: { display: "flex", gap: 1, alignItems: "flex-start", flexWrap: "wrap" }, children: [
|
|
3606
|
+
/* @__PURE__ */ jsx11(
|
|
3607
|
+
Autocomplete2,
|
|
3608
|
+
{
|
|
3609
|
+
freeSolo: true,
|
|
3610
|
+
autoHighlight: true,
|
|
3611
|
+
options: userOptions,
|
|
3612
|
+
loading: usersLoading,
|
|
3613
|
+
inputValue: memberQuery,
|
|
3614
|
+
onInputChange: (_, newInputValue, reason) => {
|
|
3615
|
+
setMemberQuery(newInputValue);
|
|
3616
|
+
if (reason === "input" || reason === "clear") {
|
|
3617
|
+
setMemberRef(newInputValue);
|
|
3618
|
+
handleUserSearch(newInputValue);
|
|
3619
|
+
}
|
|
3620
|
+
},
|
|
3621
|
+
onChange: (_, newValue) => {
|
|
3622
|
+
if (newValue && typeof newValue !== "string") {
|
|
3623
|
+
setMemberQuery(newValue.label);
|
|
3624
|
+
setMemberRef(newValue.ref);
|
|
3625
|
+
}
|
|
3626
|
+
},
|
|
3627
|
+
getOptionLabel: (o) => typeof o === "string" ? o : o.label,
|
|
3628
|
+
isOptionEqualToValue: (o, v) => o.ref === (typeof v === "string" ? v : v.ref),
|
|
3629
|
+
disabled: memberBusy,
|
|
3630
|
+
sx: { flex: "1 1 240px" },
|
|
3631
|
+
renderInput: (params) => /* @__PURE__ */ jsx11(
|
|
3632
|
+
TextField3,
|
|
3633
|
+
{
|
|
3634
|
+
...params,
|
|
3635
|
+
label: "Add member",
|
|
3636
|
+
placeholder: "Search by name or email\u2026",
|
|
3637
|
+
size: "small",
|
|
3638
|
+
helperText: "Pick a catalog user, or paste a user entity ref",
|
|
3639
|
+
InputProps: {
|
|
3640
|
+
...params.InputProps,
|
|
3641
|
+
endAdornment: /* @__PURE__ */ jsxs10(Fragment4, { children: [
|
|
3642
|
+
usersLoading ? /* @__PURE__ */ jsx11(CircularProgress3, { color: "inherit", size: 14 }) : null,
|
|
3643
|
+
params.InputProps.endAdornment
|
|
3644
|
+
] })
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
)
|
|
3648
|
+
}
|
|
3649
|
+
),
|
|
3650
|
+
!membersOnly && /* @__PURE__ */ jsx11(
|
|
3651
|
+
TextField3,
|
|
3652
|
+
{
|
|
3653
|
+
label: "Max budget in team ($)",
|
|
3654
|
+
type: "number",
|
|
3655
|
+
value: memberBudget,
|
|
3656
|
+
onChange: (e) => setMemberBudget(e.target.value),
|
|
3657
|
+
disabled: memberBusy,
|
|
3658
|
+
size: "small",
|
|
3659
|
+
sx: { width: 150 }
|
|
3660
|
+
}
|
|
3661
|
+
),
|
|
3662
|
+
/* @__PURE__ */ jsx11(
|
|
3663
|
+
Button4,
|
|
3664
|
+
{
|
|
3665
|
+
onClick: handleAddMember,
|
|
3666
|
+
disabled: memberBusy || !memberRef.trim(),
|
|
3667
|
+
variant: "outlined",
|
|
3668
|
+
sx: { mt: 0.5 },
|
|
3669
|
+
children: "Add"
|
|
3670
|
+
}
|
|
3671
|
+
)
|
|
3672
|
+
] })
|
|
3673
|
+
] })
|
|
3674
|
+
]
|
|
3675
|
+
}
|
|
3676
|
+
),
|
|
3613
3677
|
!membersOnly && showKnowledgeBases && /* @__PURE__ */ jsxs10(Box10, { children: [
|
|
3614
3678
|
/* @__PURE__ */ jsx11(Divider2, { sx: { my: 1 } }),
|
|
3615
3679
|
/* @__PURE__ */ jsx11(Typography8, { variant: "subtitle2", sx: { mb: 1 }, children: "Knowledge Bases" }),
|
|
@@ -3667,7 +3731,7 @@ var init_ManageTeamDialog = __esm({
|
|
|
3667
3731
|
] }),
|
|
3668
3732
|
/* @__PURE__ */ jsxs10(DialogActions3, { children: [
|
|
3669
3733
|
/* @__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..." :
|
|
3734
|
+
!membersOnly && /* @__PURE__ */ jsx11(Button4, { onClick: handleSubmit, disabled: submitting, variant: "contained", children: submitting ? "Saving..." : submitLabel })
|
|
3671
3735
|
] })
|
|
3672
3736
|
] });
|
|
3673
3737
|
};
|
|
@@ -6521,7 +6585,7 @@ var init_LiteLLMPage = __esm({
|
|
|
6521
6585
|
membersOnly: manageTeam?.mode === "members",
|
|
6522
6586
|
currentUserId: userInfo?.user_id,
|
|
6523
6587
|
memberManagerRoles: liteLlmConfig?.teamManagement?.memberManagerRoles,
|
|
6524
|
-
onSubmit: async (payload) => {
|
|
6588
|
+
onSubmit: async (payload, initialMembers) => {
|
|
6525
6589
|
try {
|
|
6526
6590
|
if (manageTeam?.mode === "edit" && manageTeam.team) {
|
|
6527
6591
|
const loadedAt = manageTeam.team.metadata?.updated_at_iso;
|
|
@@ -6531,7 +6595,23 @@ var init_LiteLLMPage = __esm({
|
|
|
6531
6595
|
...typeof loadedAt === "string" ? { expectedUpdatedAtIso: loadedAt } : {}
|
|
6532
6596
|
});
|
|
6533
6597
|
} else {
|
|
6534
|
-
await api.createTeam(payload);
|
|
6598
|
+
const created = await api.createTeam(payload);
|
|
6599
|
+
const failed = [];
|
|
6600
|
+
for (const m of initialMembers ?? []) {
|
|
6601
|
+
try {
|
|
6602
|
+
await api.addTeamMember(created.team_id, m);
|
|
6603
|
+
} catch (e) {
|
|
6604
|
+
failed.push(`${m.userEntityRef} (${e.message})`);
|
|
6605
|
+
}
|
|
6606
|
+
}
|
|
6607
|
+
if (failed.length) {
|
|
6608
|
+
alertApi.post({
|
|
6609
|
+
message: `Team created, but some members could not be added: ${failed.join(", ")}`,
|
|
6610
|
+
severity: "warning"
|
|
6611
|
+
});
|
|
6612
|
+
refreshTeams();
|
|
6613
|
+
return;
|
|
6614
|
+
}
|
|
6535
6615
|
}
|
|
6536
6616
|
const alert = toastFor("teamSaveSuccess");
|
|
6537
6617
|
if (alert) alertApi.post(alert);
|