mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-08 03:08:45 +00:00
Merge pull request #25398 from BerriAI/litellm_team_settings_router
[Feature] UI - Teams: Allow Editing Router Settings After Team Creation
This commit is contained in:
commit
c25b4b2ce8
3 changed files with 77 additions and 3 deletions
|
|
@ -241,9 +241,13 @@ const RouterSettingsAccordion = forwardRef<RouterSettingsAccordionRef, RouterSet
|
|||
key !== "fallbacks"
|
||||
) {
|
||||
const inputEl = document.querySelector(`input[name="${key}"]`) as HTMLInputElement | null;
|
||||
if (inputEl && inputEl.value !== undefined && inputEl.value !== "") {
|
||||
const parsed = parseInputValue(key, inputEl.value, value);
|
||||
return [key, parsed];
|
||||
if (inputEl) {
|
||||
if (inputEl.value !== undefined && inputEl.value !== "") {
|
||||
const parsed = parseInputValue(key, inputEl.value, value);
|
||||
return [key, parsed];
|
||||
}
|
||||
// Input exists but is empty — user cleared it, set to null
|
||||
return [key, null];
|
||||
}
|
||||
return [key, value];
|
||||
} else if (key === "routing_strategy") {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ vi.mock("@/components/networking", () => ({
|
|||
fetchMCPAccessGroups: vi.fn(),
|
||||
getTeamPermissionsCall: vi.fn(),
|
||||
organizationInfoCall: vi.fn(),
|
||||
getRouterSettingsCall: vi.fn().mockResolvedValue({ fields: [] }),
|
||||
}));
|
||||
|
||||
vi.mock("@/components/utils/dataUtils", () => ({
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ import ObjectPermissionsView from "../object_permissions_view";
|
|||
import NumericalInput from "../shared/numerical_input";
|
||||
import VectorStoreSelector from "../vector_store_management/VectorStoreSelector";
|
||||
import EditLoggingSettings from "./EditLoggingSettings";
|
||||
import RouterSettingsAccordion, { RouterSettingsAccordionRef } from "../common_components/RouterSettingsAccordion";
|
||||
import MemberModal from "./EditMembership";
|
||||
import MemberPermissions from "./member_permissions";
|
||||
import {
|
||||
|
|
@ -99,6 +100,7 @@ export interface TeamData {
|
|||
access_group_models?: string[];
|
||||
access_group_mcp_server_ids?: string[];
|
||||
access_group_agent_ids?: string[];
|
||||
router_settings?: Record<string, any>;
|
||||
guardrails?: string[];
|
||||
policies?: string[];
|
||||
object_permission?: {
|
||||
|
|
@ -189,6 +191,7 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [isTeamSaving, setIsTeamSaving] = useState(false);
|
||||
const routerSettingsRef = React.useRef<RouterSettingsAccordionRef>(null);
|
||||
const [organization, setOrganization] = useState<Organization | null>(null);
|
||||
const { userRole, userId } = useAuthorized();
|
||||
const { data: userOrganizations = [] } = useOrganizations();
|
||||
|
|
@ -587,6 +590,26 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
updateData.access_group_ids = values.access_group_ids;
|
||||
}
|
||||
|
||||
// Handle router_settings - read fresh values from DOM at save time.
|
||||
const currentRouterSettings = routerSettingsRef.current?.getValue();
|
||||
if (currentRouterSettings?.router_settings) {
|
||||
const isMeaningfulValue = (value: unknown) =>
|
||||
value !== null &&
|
||||
value !== undefined &&
|
||||
value !== "" &&
|
||||
value !== false &&
|
||||
!(Array.isArray(value) && value.length === 0);
|
||||
|
||||
const hasNewValues = Object.values(currentRouterSettings.router_settings).some(isMeaningfulValue);
|
||||
const hadExistingSettings = info.router_settings &&
|
||||
Object.values(info.router_settings).some(isMeaningfulValue);
|
||||
|
||||
// Send if there are new values OR if the user is clearing existing ones
|
||||
if (hasNewValues || hadExistingSettings) {
|
||||
updateData.router_settings = currentRouterSettings.router_settings;
|
||||
}
|
||||
}
|
||||
|
||||
const response = await teamUpdateCall(accessToken, updateData);
|
||||
|
||||
NotificationsManager.success("Team settings updated successfully");
|
||||
|
|
@ -1121,6 +1144,14 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
</Form.List>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item label="Router Settings">
|
||||
<RouterSettingsAccordion
|
||||
ref={routerSettingsRef}
|
||||
accessToken={accessToken || ""}
|
||||
value={info.router_settings ? { router_settings: info.router_settings } : undefined}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
label={
|
||||
<span>
|
||||
|
|
@ -1441,6 +1472,44 @@ const TeamInfoView: React.FC<TeamInfoProps> = ({
|
|||
<div>TPM Limit: {info.team_member_budget_table?.tpm_limit || "No Limit"}</div>
|
||||
<div>RPM Limit: {info.team_member_budget_table?.rpm_limit || "No Limit"}</div>
|
||||
</div>
|
||||
<div>
|
||||
<Text className="font-medium">Router Settings</Text>
|
||||
{info.router_settings && Object.values(info.router_settings).some(
|
||||
(v) => v !== null && v !== undefined && v !== "" && !(Array.isArray(v) && v.length === 0)
|
||||
) ? (
|
||||
<div className="mt-1 space-y-1">
|
||||
{info.router_settings.routing_strategy && (
|
||||
<div>
|
||||
Routing Strategy:{" "}
|
||||
<Badge color="blue">{info.router_settings.routing_strategy}</Badge>
|
||||
</div>
|
||||
)}
|
||||
{info.router_settings.num_retries != null && (
|
||||
<div>Number of Retries: {info.router_settings.num_retries}</div>
|
||||
)}
|
||||
{info.router_settings.allowed_fails != null && (
|
||||
<div>Allowed Failures: {info.router_settings.allowed_fails}</div>
|
||||
)}
|
||||
{info.router_settings.cooldown_time != null && (
|
||||
<div>Cooldown Time: {info.router_settings.cooldown_time}s</div>
|
||||
)}
|
||||
{info.router_settings.timeout != null && (
|
||||
<div>Timeout: {info.router_settings.timeout}s</div>
|
||||
)}
|
||||
{info.router_settings.retry_after != null && (
|
||||
<div>Retry After: {info.router_settings.retry_after}s</div>
|
||||
)}
|
||||
{info.router_settings.fallbacks && Array.isArray(info.router_settings.fallbacks) && info.router_settings.fallbacks.length > 0 && (
|
||||
<div>Fallbacks: {info.router_settings.fallbacks.length} configured</div>
|
||||
)}
|
||||
{info.router_settings.enable_tag_filtering && (
|
||||
<div>Tag Filtering: Enabled</div>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-gray-400">No router settings configured</div>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Text className="font-medium">Organization ID</Text>
|
||||
<div>{info.organization_id}</div>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue