diff --git a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTable.test.tsx b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTable.test.tsx
index 040fa463f9c..af3f98b746b 100644
--- a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTable.test.tsx
+++ b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTable.test.tsx
@@ -89,6 +89,65 @@ describe("PassThroughEndpointsTable", () => {
expect(onDeleteClick).toHaveBeenCalledWith("ep-1");
});
+ it("should disable edit and delete for config-defined endpoints", async () => {
+ const user = userEvent.setup();
+ const onEndpointClick = vi.fn();
+ const onDeleteClick = vi.fn();
+ const configEndpoint: passThroughItem = {
+ id: "ep-config",
+ path: "/from-config",
+ target: "https://config.example.com",
+ headers: {},
+ is_from_config: true,
+ };
+ render(
+ ,
+ );
+
+ await user.click(screen.getByTestId("endpoint-actions-ep-config"));
+ const editItem = await screen.findByTestId("endpoint-action-edit");
+ const deleteItem = await screen.findByTestId("endpoint-action-delete");
+
+ expect(editItem).toHaveAttribute("data-disabled");
+ expect(deleteItem).toHaveAttribute("data-disabled");
+ expect(screen.getByTestId("endpoint-config-hint")).toHaveTextContent(
+ "This endpoint is defined in the config file and cannot be edited or deleted on the dashboard.",
+ );
+
+ await user.click(editItem);
+ await user.click(deleteItem);
+
+ expect(onEndpointClick).not.toHaveBeenCalled();
+ expect(onDeleteClick).not.toHaveBeenCalled();
+ });
+
+ it("should not show the config hint for DB endpoints", async () => {
+ const user = userEvent.setup();
+ render();
+
+ await user.click(screen.getByTestId("endpoint-actions-ep-1"));
+ await screen.findByTestId("endpoint-action-delete");
+ expect(screen.queryByTestId("endpoint-config-hint")).not.toBeInTheDocument();
+ });
+
+ it("should label endpoint source as Config or DB", () => {
+ const configEndpoint: passThroughItem = {
+ id: "ep-config",
+ path: "/from-config",
+ target: "https://config.example.com",
+ headers: {},
+ is_from_config: true,
+ };
+ render();
+ expect(screen.getByText("Config")).toBeInTheDocument();
+ expect(screen.getAllByText("DB")).toHaveLength(2);
+ });
+
it("should disable edit and delete for endpoints without an id", async () => {
const user = userEvent.setup();
const onEndpointClick = vi.fn();
diff --git a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTableColumns.tsx b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTableColumns.tsx
index d22b274861a..5b18685a140 100644
--- a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTableColumns.tsx
+++ b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughEndpointsTableColumns.tsx
@@ -18,6 +18,9 @@ import { cn } from "@/lib/cva.config";
import type { passThroughItem } from "./PassThroughSettings";
+const CONFIG_ENDPOINT_HINT =
+ "This endpoint is defined in the config file and cannot be edited or deleted on the dashboard.";
+
function HeaderWithTooltip({ title, tooltip }: { title: string; tooltip: string }) {
return (
@@ -73,6 +76,7 @@ interface EndpointRowActionsProps {
function EndpointRowActions({ endpoint, onEndpointClick, onDeleteClick }: EndpointRowActionsProps) {
const endpointId = endpoint.id;
+ const isFromConfig = endpoint.is_from_config ?? false;
return (
endpointId && onEndpointClick(endpointId)}
+ disabled={isFromConfig || !endpointId}
+ onClick={() => !isFromConfig && endpointId && onEndpointClick(endpointId)}
>
Edit
@@ -95,12 +99,17 @@ function EndpointRowActions({ endpoint, onEndpointClick, onDeleteClick }: Endpoi
endpointId && onDeleteClick(endpointId)}
+ disabled={isFromConfig || !endpointId}
+ onClick={() => !isFromConfig && endpointId && onDeleteClick(endpointId)}
>
Delete
+ {isFromConfig && (
+
+ {CONFIG_ENDPOINT_HINT}
+
+ )}
);
@@ -124,7 +133,9 @@ export const getPassThroughEndpointsTableColumns = ({
enableSorting: false,
cell: ({ row }) => {
const endpointId = row.original.id;
- if (!endpointId) return
—;
+ if (!endpointId || row.original.is_from_config) {
+ return
—;
+ }
return (
{
+ const isFromConfig = row.original.is_from_config ?? false;
+ return ;
+ },
+ },
{
id: "path",
accessorKey: "path",
diff --git a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughSettings.tsx b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughSettings.tsx
index 2dc6fdbd32c..8ef2766d412 100644
--- a/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughSettings.tsx
+++ b/ui/litellm-dashboard/src/components/PassThroughSettings/PassThroughSettings.tsx
@@ -1,4 +1,13 @@
import React, { useState, useEffect } from "react";
+import {
+ AlertDialog,
+ AlertDialogCancel,
+ AlertDialogContent,
+ AlertDialogDescription,
+ AlertDialogFooter,
+ AlertDialogHeader,
+ AlertDialogTitle,
+} from "@/components/ui/alert-dialog";
import { Button } from "@/components/ui/button";
import { deletePassThroughEndpointsCall, getPassThroughEndpointsCall } from "../networking";
import AddPassThroughEndpoint from "../add_pass_through";
@@ -25,6 +34,7 @@ export interface passThroughItem {
methods?: string[];
guardrails?: Record;
default_query_params?: Record;
+ is_from_config?: boolean;
}
const PassThroughSettings: React.FC = ({ accessToken, userRole, userID, premiumUser }) => {
@@ -133,42 +143,22 @@ const PassThroughSettings: React.FC = ({ accessToken,
onDeleteClick={handleDelete}
/>
- {isDeleteModalOpen && (
-
-
-
-
-
-
-
-
-
-
-
-
-
Delete Pass-Through Endpoint
-
-
- Are you sure you want to delete this pass-through endpoint? This action cannot be undone.
-
-
-
-
-
-
-
-
-
-
-
-
- )}
+ !open && cancelDelete()}>
+
+
+ Delete Pass-Through Endpoint
+
+ Are you sure you want to delete this pass-through endpoint? This action cannot be undone.
+
+
+
+ Cancel
+
+
+
+
);
};