Search tools
{searchTools.length === 0 ? ( -- No restriction — all configured search tools are allowed for this team. -
+{searchToolCopy.emptyState}
) : ({searchTools.join(", ")}
)} diff --git a/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.test.ts b/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.test.ts new file mode 100644 index 00000000000..46bd633a90c --- /dev/null +++ b/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.test.ts @@ -0,0 +1,29 @@ +import { describe, expect, it } from "vitest"; +import { searchToolPermissionCopy } from "./searchToolPermissionCopy"; + +describe("searchToolPermissionCopy", () => { + it("says an empty list allows every search tool when default deny is off", () => { + const copy = searchToolPermissionCopy(false); + expect(copy.hint).toContain("Leave empty to allow all search tools"); + expect(copy.placeholder).toBe("Select search tools (optional, empty = all allowed)"); + expect(copy.emptyState).toContain("all configured search tools are allowed"); + }); + + it("says an empty list denies every search tool when default deny is on", () => { + const copy = searchToolPermissionCopy(true); + expect(copy.hint).toContain("leaving this empty denies every search tool"); + expect(copy.placeholder).toBe("Select search tools (empty = none allowed)"); + expect(copy.emptyState).toContain("no search tool is allowed"); + expect(Object.values(copy).join(" ")).not.toContain("all allowed"); + }); + + it("describes an empty key-level list as deferring to the team or user grant", () => { + expect(searchToolPermissionCopy(true, "key").emptyState).toBe( + "No key-level search tools. Default search list deny is on, so this key can use only the search tools granted to its team or user.", + ); + expect(searchToolPermissionCopy(false, "key").emptyState).toBe( + "No key-level restriction: this key can use any search tool its team or user allows.", + ); + expect(searchToolPermissionCopy(true, "key").hint).toBe(searchToolPermissionCopy(true).hint); + }); +}); diff --git a/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.ts b/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.ts new file mode 100644 index 00000000000..f914917acb5 --- /dev/null +++ b/ui/litellm-dashboard/src/components/search_tools/searchToolPermissionCopy.ts @@ -0,0 +1,30 @@ +export interface SearchToolPermissionCopy { + hint: string; + placeholder: string; + emptyState: string; +} + +export type SearchToolPermissionScope = "team" | "key"; + +const keyEmptyState = (defaultSearchListDeny: boolean): string => + defaultSearchListDeny + ? "No key-level search tools. Default search list deny is on, so this key can use only the search tools granted to its team or user." + : "No key-level restriction: this key can use any search tool its team or user allows."; + +export const searchToolPermissionCopy = ( + defaultSearchListDeny: boolean, + scope: SearchToolPermissionScope = "team", +): SearchToolPermissionCopy => { + const copy = defaultSearchListDeny + ? { + hint: "Select which search tools this team can access. Default search list deny is on, so leaving this empty denies every search tool.", + placeholder: "Select search tools (empty = none allowed)", + emptyState: "No search tools granted. Default search list deny is on, so no search tool is allowed.", + } + : { + hint: "Select which search tools this team can access. Leave empty to allow all search tools.", + placeholder: "Select search tools (optional, empty = all allowed)", + emptyState: "No restriction: all configured search tools are allowed for this team.", + }; + return scope === "key" ? { ...copy, emptyState: keyEmptyState(defaultSearchListDeny) } : copy; +}; diff --git a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx index 5dfcf1d8e35..c51e25fc578 100644 --- a/ui/litellm-dashboard/src/components/team/TeamInfo.tsx +++ b/ui/litellm-dashboard/src/components/team/TeamInfo.tsx @@ -106,6 +106,8 @@ import ObjectPermissionsView from "../object_permissions_view"; import NumericalInput from "../shared/numerical_input"; import VectorStoreSelector from "../vector_store_management/VectorStoreSelector"; import SearchToolSelector from "../search_tools/SearchToolSelector"; +import { searchToolPermissionCopy } from "../search_tools/searchToolPermissionCopy"; +import { useDefaultSearchListDeny } from "@/app/(dashboard)/hooks/uiSettings/useDefaultSearchListDeny"; import SkillSelector from "../skills/SkillSelector"; import EditLoggingSettings from "./EditLoggingSettings"; import RouterSettingsAccordion, { RouterSettingsAccordionRef } from "../common_components/RouterSettingsAccordion"; @@ -578,6 +580,7 @@ const TeamInfoView: React.FC