From f4a217d0056576822608aed7089f812cdaa2a667 Mon Sep 17 00:00:00 2001 From: "devin-ai-integration[bot]" <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 28 Sep 2026 17:59:47 -0700 Subject: [PATCH] fix(ui): rename All Models tab to Deployed Models and model filters to All Proxy Models (#43638) * fix(ui): rename All Models tab to Deployed Models and view filter to All Proxy Models Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix(ui): use All Proxy Models label for the public model name filter Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> * test(e2e): rename ALL_MODELS_VIEW constant to ALL_PROXY_MODELS_VIEW Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: kerry Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- .../tests/internal-user/modelsByTeam.spec.ts | 8 ++++---- tests/e2e/ui/tests/modelsPage/addModel.spec.ts | 14 +++++++------- .../components/AllModelsTab.test.tsx | 13 ++++++++++++- .../components/AllModelsTable.tsx | 5 +++-- .../AutoRouters/AutoRoutersPanel.tsx | 2 +- .../models-and-endpoints/page.test.tsx | 18 +++++++++--------- .../(dashboard)/models-and-endpoints/page.tsx | 2 +- 7 files changed, 37 insertions(+), 25 deletions(-) diff --git a/tests/e2e/ui/tests/internal-user/modelsByTeam.spec.ts b/tests/e2e/ui/tests/internal-user/modelsByTeam.spec.ts index 736c352e3ee..22740d185c0 100644 --- a/tests/e2e/ui/tests/internal-user/modelsByTeam.spec.ts +++ b/tests/e2e/ui/tests/internal-user/modelsByTeam.spec.ts @@ -17,7 +17,7 @@ import { CHAT_MODEL_A, CHAT_MODEL_B, masterKey } from "../../helpers/traffic"; const MOCK_LLM_BASE = `http://127.0.0.1:${process.env.MOCK_LLM_PORT ?? "8090"}/v1`; const CURRENT_TEAM_VIEW = "Current Team Models"; -const ALL_MODELS_VIEW = "All Available Models"; +const ALL_PROXY_MODELS_VIEW = "All Proxy Models"; const PERSONAL_TEAM = "Personal"; const teamSelector = (page: PlaywrightPage): Locator => @@ -174,10 +174,10 @@ test.describe("Models and Endpoints for an internal user", () => { `${ungrantedModelName} is granted to no team and must not leak into ${E2E_TEAM_ORG_ALIAS}`, ).toHaveCount(0); - await chooseOption(page, viewSelector(page), ALL_MODELS_VIEW); + await chooseOption(page, viewSelector(page), ALL_PROXY_MODELS_VIEW); await expect( modelRow(page, CHAT_MODEL_A), - `switching to ${ALL_MODELS_VIEW} leaves the table populated rather than blanking it`, + `switching to ${ALL_PROXY_MODELS_VIEW} leaves the table populated rather than blanking it`, ).toHaveCount(1, { timeout: 15_000 }); await expect(page).toHaveURL((url) => @@ -192,7 +192,7 @@ test.describe("Models and Endpoints for an internal user", () => { await expect( viewSelector(page), "the selected view is restored from the URL after a reload", - ).toContainText(ALL_MODELS_VIEW, { timeout: 15_000 }); + ).toContainText(ALL_PROXY_MODELS_VIEW, { timeout: 15_000 }); await expect(modelRow(page, CHAT_MODEL_A)).toHaveCount(1, { timeout: 15_000 }); await expect(page.getByTestId("pagination-range")).toHaveText("Showing 1-1 of 1"); await expect(modelRow(page, CHAT_MODEL_B)).toHaveCount(0); diff --git a/tests/e2e/ui/tests/modelsPage/addModel.spec.ts b/tests/e2e/ui/tests/modelsPage/addModel.spec.ts index de25ec1aac5..a99fb937b83 100644 --- a/tests/e2e/ui/tests/modelsPage/addModel.spec.ts +++ b/tests/e2e/ui/tests/modelsPage/addModel.spec.ts @@ -362,7 +362,7 @@ test.describe("Add Model", () => { await expect(page.getByText(/Connection to .* failed/)).toBeVisible({ timeout: 30_000 }); }); - test("Add specific model and verify it appears in All Models", async ({ page }) => { + test("Add specific model and verify it appears in Deployed Models", async ({ page }) => { await navigateToPage(page, Page.Models); await page.getByRole("tab", { name: "Add Model" }).click(); @@ -389,8 +389,8 @@ test.describe("Add Model", () => { // Wait for success notification await expect(page.getByText("created successfully")).toBeVisible({ timeout: 15_000 }); - // Navigate to All Models tab - await page.getByRole("tab", { name: "All Models" }).click(); + // Navigate to Deployed Models tab + await page.getByRole("tab", { name: "Deployed Models" }).click(); await page.waitForLoadState("networkidle"); // Search for the model we just added @@ -469,7 +469,7 @@ test.describe("Add Model", () => { }); // The Models table renders team-scoped models with the team id in the row. - await page.getByRole("tab", { name: "All Models" }).click(); + await page.getByRole("tab", { name: "Deployed Models" }).click(); await page.waitForLoadState("networkidle"); await page.getByPlaceholder("Search model names").fill("cohere"); @@ -488,7 +488,7 @@ test.describe("Add Model", () => { } }); - test("Add wildcard route and verify it appears in All Models", async ({ page }) => { + test("Add wildcard route and verify it appears in Deployed Models", async ({ page }) => { await navigateToPage(page, Page.Models); await page.getByRole("tab", { name: "Add Model" }).click(); @@ -513,8 +513,8 @@ test.describe("Add Model", () => { // Wait for success notification await expect(page.getByText("created successfully")).toBeVisible({ timeout: 15_000 }); - // Navigate to All Models tab - await page.getByRole("tab", { name: "All Models" }).click(); + // Navigate to Deployed Models tab + await page.getByRole("tab", { name: "Deployed Models" }).click(); await page.waitForLoadState("networkidle"); // Search for the wildcard model diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.test.tsx index a5eb149e1f0..0c93bb234a5 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.test.tsx @@ -403,6 +403,17 @@ describe("AllModelsTab", () => { }); }); + it("uses All Proxy Models as the public model name filter default", async () => { + const user = userEvent.setup(); + renderWithProviders(); + + await user.click(screen.getByTestId("datatable-filters-trigger")); + await user.click(await screen.findByPlaceholderText("Filter by Public Model Name")); + + expect(await screen.findByRole("option", { name: "All Proxy Models" })).toBeInTheDocument(); + expect(screen.queryByRole("option", { name: "All Models" })).not.toBeInTheDocument(); + }); + it("renders every row the server returned for the selected model group so rows match the footer total", () => { setModelsInfo([makeRow(), { ...makeRow({ model_info: { id: "model-2" } }), model_name: "claude-opus" }], 2); renderWithProviders(); @@ -567,7 +578,7 @@ describe("AllModelsTab", () => { renderWithProviders(); await user.click(screen.getByTestId("models-view-select")); - await user.click(await screen.findByRole("option", { name: "All Available Models" })); + await user.click(await screen.findByRole("option", { name: "All Proxy Models" })); await waitFor(() => { expect(screen.queryByText(/create a Virtual Key/i)).not.toBeInTheDocument(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx index f46130d2386..2a52bdfb46e 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTable.tsx @@ -31,6 +31,7 @@ export const ALL_MODEL_GROUPS_VALUE = "all"; export const WILDCARD_MODEL_GROUP_VALUE = "wildcard"; const MODEL_TABLE_BODY_HEIGHT = 600; +const ALL_PROXY_MODELS_LABEL = "All Proxy Models"; const FILTER_LABELS: Record = { [MODEL_NAME_COLUMN_ID]: "Public Model Name", @@ -39,7 +40,7 @@ const FILTER_LABELS: Record = { const VIEW_MODE_LABELS: Record = { current_team: "Current Team Models", - all: "All Available Models", + all: ALL_PROXY_MODELS_LABEL, }; export interface ModelsTableTeamOption { @@ -146,7 +147,7 @@ export function AllModelsTable({ const modelGroupOptions = useMemo( () => [ - { label: "All Models", value: ALL_MODEL_GROUPS_VALUE }, + { label: ALL_PROXY_MODELS_LABEL, value: ALL_MODEL_GROUPS_VALUE }, { label: "Wildcard Models (*)", value: WILDCARD_MODEL_GROUP_VALUE }, ...availableModelGroups.map((group) => ({ label: group, value: group })), ], diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.tsx index 1625e0cbfb8..607b676d304 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.tsx @@ -38,7 +38,7 @@ export function AutoRoutersPanel({ const canCreate = createScope !== "forbidden"; const { data: deployments, isLoading } = useAutoRouters(); const invalidateAutoRouters = useInvalidateAutoRouters(); - // Clicking a router opens the same ?model= drill-in the All Models table uses, so an auto + // Clicking a router opens the same ?model= drill-in the Deployed Models table uses, so an auto // router gets the full ModelInfoView: Model Settings, Edit Settings, Edit Auto Router and // Delete. A separate detail view here would be a worse copy of it. const { openModel } = useModelDetailRouting(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.test.tsx index 652a3e804db..41f71a3bf12 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.test.tsx @@ -81,9 +81,9 @@ describe("ModelsAndEndpointsPage", () => { }; }); - it("renders the admin tab bar and the All Models panel by default", () => { + it("renders the admin tab bar and the Deployed Models panel by default", () => { renderPage(); - expect(screen.getByRole("tab", { name: "All Models" })).toBeInTheDocument(); + expect(screen.getByRole("tab", { name: "Deployed Models" })).toBeInTheDocument(); expect(screen.getByRole("tab", { name: "LLM Credentials" })).toBeInTheDocument(); expect(screen.getByRole("tab", { name: "Health Status" })).toBeInTheDocument(); expect(screen.getByTestId("panel-all-models")).toBeInTheDocument(); @@ -101,7 +101,7 @@ describe("ModelsAndEndpointsPage", () => { detailState.modelId = "abc-123"; renderPage(); expect(screen.getByTestId("model-info")).toHaveTextContent("model:abc-123"); - expect(screen.queryByRole("tab", { name: "All Models" })).not.toBeInTheDocument(); + expect(screen.queryByRole("tab", { name: "Deployed Models" })).not.toBeInTheDocument(); }); it("renders the team detail overlay from the ?team drill-in with admin edit rights", () => { @@ -138,7 +138,7 @@ describe("ModelsAndEndpointsPage", () => { it("keeps the full admin tab order for a real admin", () => { renderPage(); expect(screen.getAllByRole("tab").map((tab) => tab.textContent)).toEqual([ - "All Models", + "Deployed Models", "Add Model", "Auto-Routers Beta", "LLM Credentials", @@ -154,7 +154,7 @@ describe("ModelsAndEndpointsPage", () => { it("hides the admin write-form tabs from a view-only admin, keeping the read views", () => { mockUseAuthorized.mockReturnValue(VIEW_ONLY_ADMIN); renderPage(); - expect(screen.getByRole("tab", { name: "All Models" })).toBeInTheDocument(); + expect(screen.getByRole("tab", { name: "Deployed Models" })).toBeInTheDocument(); expect(screen.getByRole("tab", { name: "Health Status" })).toBeInTheDocument(); expect(screen.queryByRole("tab", { name: "LLM Credentials" })).not.toBeInTheDocument(); expect(screen.queryByRole("tab", { name: "Pass-Through Endpoints" })).not.toBeInTheDocument(); @@ -169,7 +169,7 @@ describe("ModelsAndEndpointsPage", () => { mockUseAuthorized.mockReturnValue(VIEW_ONLY_ADMIN); renderPage(); expect(screen.queryByRole("tab", { name: "Add Model" })).not.toBeInTheDocument(); - expect(screen.getByRole("tab", { name: "All Models" })).toBeInTheDocument(); + expect(screen.getByRole("tab", { name: "Deployed Models" })).toBeInTheDocument(); }); // Read parity: the Auto-Routers list stays reachable for a view-only admin; only the @@ -180,14 +180,14 @@ describe("ModelsAndEndpointsPage", () => { expect(screen.getByRole("tab", { name: /Auto-Routers/ })).toBeInTheDocument(); }); - // Auto-routers are excluded from the All Models table, so this tab is their home: the only + // Auto-routers are excluded from the Deployed Models table, so this tab is their home: the only // place in the product to list, create, edit or delete one. describe("Auto-Routers tab", () => { - it("sits third, after All Models and Add Model", () => { + it("sits third, after Deployed Models and Add Model", () => { renderPage(); const tabs = screen.getAllByRole("tab").map((tab) => tab.textContent); - expect(tabs[0]).toContain("All Models"); + expect(tabs[0]).toContain("Deployed Models"); expect(tabs[1]).toBe("Add Model"); expect(tabs[2]).toContain("Auto-Routers"); // Badged Beta while the tab settles; BetaBadge renders the label text. diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx index d8952b88545..a4e5afe0533 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/page.tsx @@ -123,7 +123,7 @@ export default function ModelsAndEndpointsPage() { [canCreate, canViewAutoRouters, isAdmin, isViewOnly], ); - const allModelsLabel = isAdmin ? "All Models" : "Your Models"; + const allModelsLabel = isAdmin ? "Deployed Models" : "Your Models"; const tabLabel = (slug: "" | ModelTabSlug): React.ReactNode => { if (!slug) return allModelsLabel; if (slug === "auto-routers" || slug === "access-group-budgets") {