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 0c93bb234a5..b105349c867 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 @@ -250,6 +250,39 @@ describe("AllModelsTab", () => { expect(lastModelsInfoCall().page).toBe(1); }); + it("drops the team filter and the page when switching to all proxy models", async () => { + // "All Proxy Models" promises every model the user can reach, so the team + // must stop narrowing the query -- and the page has to go back to 1 like it + // does for every other control that changes the result set. + const user = userEvent.setup(); + setModelsInfo([makeRow()], 200); + const onUrlUpdate = vi.fn(); + renderWithProviders(, { + searchParams: { page: "3", filter_team: "team-1" }, + onUrlUpdate, + }); + + await waitFor(() => { + expect(lastModelsInfoCall().teamId).toBe("team-1"); + }); + expect(lastModelsInfoCall().page).toBe(3); + + await user.click(screen.getByTestId("models-view-select")); + await user.click(await screen.findByRole("option", { name: "All Proxy Models" })); + + await waitFor(() => { + expect(lastModelsInfoCall().teamId).toBeUndefined(); + }); + expect(lastUrlParams(onUrlUpdate)?.get("page")).toBeNull(); + + await user.click(screen.getByTestId("models-view-select")); + await user.click(await screen.findByRole("option", { name: "Current Team Models" })); + + await waitFor(() => { + expect(lastModelsInfoCall().teamId).toBe("team-1"); + }); + }); + it("debounces the model name search into the server query", async () => { renderWithProviders(); diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx index 2217bca0fa0..dd68052a9e2 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AllModelsTab.tsx @@ -101,7 +101,11 @@ const AllModelsTab = ({ const [deleteLoading, setDeleteLoading] = useState(false); const [pausingModelId, setPausingModelId] = useState(null); - const teamIdForQuery = selectedTeamValue === PERSONAL_TEAM_VALUE ? undefined : selectedTeamValue; + // Scoped by the view mode, not just by the team picker: in "all available + // models" the team must not narrow the query, or the tab shows the current + // team's models under a heading that promises every model the user can reach. + const teamIdForQuery = + modelViewMode === "current_team" && selectedTeamValue !== PERSONAL_TEAM_VALUE ? selectedTeamValue : undefined; const isConcreteModelGroup = Boolean(selectedModelGroup) && selectedModelGroup !== ALL_MODEL_GROUPS_VALUE && @@ -210,7 +214,10 @@ const AllModelsTab = ({ }; const handleViewModeChange = (value: ModelViewMode) => { - void setTableState({ view_mode: value }); + // `page: null` like every other handler that changes the result set -- + // without it, switching view while past page 1 keeps the old page number + // against a different, usually shorter, list. + void setTableState({ view_mode: value, page: null }); }; const resetFilters = () => {