diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index bf010c7f249..c6d9e28226f 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -12087,8 +12087,9 @@ async def model_info_v2( False, description=( "Omit auto-router deployments (litellm model prefixed `auto_router/`). " - "They are routing constructs rather than deployments, and are managed on the " - "Router Settings page. Defaults to false, so existing callers are unaffected" + "They select among deployments rather than being deployments themselves, so a " + "caller rendering a deployment list can leave them out. Defaults to false, so " + "existing callers are unaffected" ), ), ): diff --git a/ui/litellm-dashboard/eslint-suppressions.json b/ui/litellm-dashboard/eslint-suppressions.json index c0d24d3a1e6..6819b2851f5 100644 --- a/ui/litellm-dashboard/eslint-suppressions.json +++ b/ui/litellm-dashboard/eslint-suppressions.json @@ -151,14 +151,11 @@ "no-restricted-imports": { "count": 1 }, - "prefer-const": { - "count": 1 - }, "react-hooks/purity": { "count": 1 }, "react-hooks/set-state-in-effect": { - "count": 2 + "count": 1 } }, "src/app/(dashboard)/caching/_components/cache_health.tsx": { @@ -3320,7 +3317,7 @@ "count": 5 }, "no-restricted-syntax": { - "count": 153 + "count": 152 }, "prefer-const": { "count": 32 diff --git a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx index 9c2d0b20b56..f6593e80999 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/cost-optimization/_components/CostOptimizationView.tsx @@ -45,7 +45,7 @@ const CostOptimizationView: React.FC = ({ accessToken

Track and configure the mechanisms that save you money: prompt compression and prompt caching. Auto routers - live on the Router Settings page + live under Models + Endpoints, on the Auto-Routers tab

diff --git a/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts b/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts index 88c4836f112..52459d69b9a 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts +++ b/ui/litellm-dashboard/src/app/(dashboard)/hooks/models/useModels.ts @@ -104,6 +104,7 @@ export interface AutoRouterDeployment extends AutoRouterCandidateDeployment { created_at?: string | null; updated_at?: string | null; team_id?: string | null; + created_by?: string | null; } | null; } 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 1a65109eac8..1d206f81030 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 @@ -104,8 +104,8 @@ const AllModelsTab = ({ teamIdForQuery, sortBy, sortOrder, - // Auto-routers are routing constructs, not deployments; they are listed and managed on - // the Router Settings page. Excluded server-side so total_count stays honest. + // Auto-routers are routing constructs, not deployments; the sibling Auto-Routers tab + // lists and manages them. Excluded server-side so total_count stays honest. true, ); const isLoading = isLoadingModelsInfo || isLoadingModelCostMap; diff --git a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.test.tsx b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.test.tsx index 7d026f067fb..9ec551bc227 100644 --- a/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.test.tsx +++ b/ui/litellm-dashboard/src/app/(dashboard)/models-and-endpoints/components/AutoRouters/AutoRoutersPanel.test.tsx @@ -108,7 +108,15 @@ const mockDeploymentsPage = () => { }; const renderPanel = (canModify = true) => - renderWithProviders(); + renderWithProviders( + , + ); describe("AutoRoutersPanel", () => { beforeEach(() => { 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 3fbce1bd4a0..f27c1e1c44a 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 @@ -11,6 +11,8 @@ import NotificationsManager from "@/components/molecules/notifications_manager"; import { modelDeleteCall } from "@/components/networking"; import { Button } from "@/components/ui/button"; import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import { type ModelWriteScope } from "@/utils/modelPermissions"; +import { Team } from "@/components/networking"; import { AutoRoutersTable } from "./AutoRoutersTable"; import { AutoRouterRow, toAutoRouterRows } from "./autoRouterRows"; @@ -18,11 +20,14 @@ import { AutoRouterRow, toAutoRouterRows } from "./autoRouterRows"; interface AutoRoutersPanelProps { accessToken: string; userRole: string; - /** Owned by the page, which knows whether the caller may write. */ - canModify: boolean; + userID: string | null; + teams: Team[] | null; + /** Owned by the page, which knows how this caller must scope what they create. */ + createScope: ModelWriteScope; } -export function AutoRoutersPanel({ accessToken, userRole, canModify }: AutoRoutersPanelProps) { +export function AutoRoutersPanel({ accessToken, userRole, userID, teams, createScope }: AutoRoutersPanelProps) { + 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 @@ -33,7 +38,10 @@ export function AutoRoutersPanel({ accessToken, userRole, canModify }: AutoRoute const [deletingRouter, setDeletingRouter] = useState(null); const [isDeleting, setIsDeleting] = useState(false); - const routers = useMemo(() => toAutoRouterRows(deployments ?? []), [deployments]); + const routers = useMemo( + () => toAutoRouterRows(deployments ?? [], { userRole, userID }, teams), + [deployments, userRole, userID, teams], + ); const handleCreated = () => { setIsCreating(false); @@ -65,7 +73,7 @@ export function AutoRoutersPanel({ accessToken, userRole, canModify }: AutoRoute so clients keep using a single model name.

- {canModify && ( + {canCreate && (