From 750e849d1228fddedf7dcddb9941d7c2ff191696 Mon Sep 17 00:00:00 2001 From: Krrish Dholakia Date: Mon, 13 Jul 2026 18:26:13 -0700 Subject: [PATCH] feat(ui): replace raw JSON input for optional_pre_call_checks with a multi-select The Router Settings page rendered optional_pre_call_checks as free-text JSON, requiring admins to know and correctly type the exact valid check names. Add a dedicated multi-select populated from the field's known options (already returned by /router/fields), matching how routing_strategy already gets its own selector instead of a raw text field. The value now flows through React state (like routing_strategy/enable_tag_filtering) instead of the page's DOM-querySelector-based save mechanism, since an antd Select doesn't produce a plain named for that mechanism to read. default_litellm_params keeps the raw-JSON editor since it has no fixed set of keys to offer as options. --- .../OptionalPreCallChecksSelector.test.tsx | 101 ++++++++++++++++++ .../OptionalPreCallChecksSelector.tsx | 55 ++++++++++ .../ReliabilityRetriesSection.test.tsx | 12 +++ .../ReliabilityRetriesSection.tsx | 3 +- .../RouterSettingsForm.test.tsx | 68 +++++++++++- .../router_settings/RouterSettingsForm.tsx | 20 ++++ .../components/router_settings/index.test.tsx | 81 ++++++++++++-- .../src/components/router_settings/index.tsx | 2 +- 8 files changed, 325 insertions(+), 17 deletions(-) create mode 100644 ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.test.tsx create mode 100644 ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.tsx diff --git a/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.test.tsx b/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.test.tsx new file mode 100644 index 00000000000..2e4b7712c5f --- /dev/null +++ b/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.test.tsx @@ -0,0 +1,101 @@ +import { describe, it, expect, vi } from "vitest"; +import { render, screen } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import OptionalPreCallChecksSelector from "./OptionalPreCallChecksSelector"; + +vi.mock("antd", async (importOriginal) => { + const actual = await importOriginal(); + return { + ...actual, + Select: ({ value, onChange, options, "data-testid": testId }: any) => ( + + ), + }; +}); + +const baseMetadata = { + optional_pre_call_checks: { + ui_field_name: "Optional Pre-call Checks", + field_description: "Extra checks the router runs before picking a deployment", + link: null, + }, +}; + +const options = ["prompt_caching", "router_budget_limiting", "session_affinity"]; + +describe("OptionalPreCallChecksSelector", () => { + it("should render one option per entry in options", () => { + render( + , + ); + const select = screen.getByTestId("optional-pre-call-checks-select") as HTMLSelectElement; + expect(Array.from(select.options).map((o) => o.value)).toEqual(options); + }); + + it("should display default label when no metadata is provided", () => { + render( + , + ); + expect(screen.getByText("Optional Pre-call Checks")).toBeInTheDocument(); + }); + + it("should display the label and description from metadata when provided", () => { + render( + , + ); + expect(screen.getByText("Extra checks the router runs before picking a deployment")).toBeInTheDocument(); + }); + + it("should render a Learn more link when metadata provides one", () => { + const metadata = { + optional_pre_call_checks: { ...baseMetadata.optional_pre_call_checks, link: "https://docs.example.com/checks" }, + }; + render( + , + ); + const link = screen.getByRole("link", { name: /learn more/i }); + expect(link).toHaveAttribute("href", "https://docs.example.com/checks"); + }); + + it("should call onChange with the selected checks", async () => { + const onChange = vi.fn(); + const user = userEvent.setup(); + render( + , + ); + + await user.selectOptions(screen.getByTestId("optional-pre-call-checks-select"), "prompt_caching"); + + expect(onChange).toHaveBeenCalledWith(["prompt_caching"]); + }); + + it("should reflect an already-selected value", () => { + render( + , + ); + const select = screen.getByTestId("optional-pre-call-checks-select") as HTMLSelectElement; + const selected = Array.from(select.selectedOptions).map((o) => o.value); + expect(selected).toEqual(["router_budget_limiting"]); + }); +}); diff --git a/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.tsx b/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.tsx new file mode 100644 index 00000000000..ab52bad644d --- /dev/null +++ b/ui/litellm-dashboard/src/components/router_settings/OptionalPreCallChecksSelector.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import { Select } from "antd"; + +interface OptionalPreCallChecksSelectorProps { + value: string[]; + options: string[]; + routerFieldsMetadata: { [key: string]: any }; + onChange: (value: string[]) => void; +} + +const OptionalPreCallChecksSelector: React.FC = ({ + value, + options, + routerFieldsMetadata, + onChange, +}) => { + const meta = routerFieldsMetadata["optional_pre_call_checks"]; + + return ( +
+