fix: let operators allowlist web search interception settings

Peer pods gate the settings poll on general_settings.supported_db_objects,
which validates against SupportedDBObjectType. Without a member for this
name an operator could not opt in, so a configured allowlist left every
pod but the one that served the write on stale settings.

Also types the dashboard's settings payload off the generated schema
instead of Record<string, any>.
This commit is contained in:
Yuneng Jiang 2026-09-19 13:00:00 -07:00
parent d15ceab174
commit d5ae810ea9
No known key found for this signature in database
7 changed files with 34 additions and 10 deletions

View file

@ -123,6 +123,7 @@ class SupportedDBObjectType(str, enum.Enum):
MODEL_COST_MAP = "model_cost_map"
TOOLS = "tools"
CONFIG_OVERRIDES = "config_overrides"
WEBSEARCH_INTERCEPTION_SETTINGS = "websearch_interception_settings"
def __str__(self):
return str(self.value)

View file

@ -7714,7 +7714,7 @@ class ProxyConfig:
if self._should_load_db_object(object_type="semantic_filter_settings"):
await self._init_semantic_filter_settings_in_db(prisma_client=prisma_client)
if self._should_load_db_object(object_type="websearch_interception_settings"):
if self._should_load_db_object(object_type=SupportedDBObjectType.WEBSEARCH_INTERCEPTION_SETTINGS):
await self.init_websearch_interception_settings_in_db(prisma_client=prisma_client)
if self._should_load_db_object(object_type="config_overrides"):

View file

@ -4700,3 +4700,17 @@ def test_init_websearch_interception_honors_enabled_providers(monkeypatch):
registered = [cb for cb in litellm.callbacks if isinstance(cb, logger_cls)]
assert len(registered) == 1
assert registered[0].enabled_providers == ["bedrock", "vertex_ai"]
def test_websearch_interception_settings_can_be_named_in_supported_db_objects(monkeypatch):
from litellm.proxy import proxy_server
from litellm.proxy._types import ConfigGeneralSettings
allowlist = ConfigGeneralSettings(supported_db_objects=["websearch_interception_settings"]).supported_db_objects
assert allowlist
monkeypatch.setattr(proxy_server, "general_settings", {"supported_db_objects": allowlist})
assert proxy_server.should_load_db_object(object_type="websearch_interception_settings") is True
monkeypatch.setattr(proxy_server, "general_settings", {"supported_db_objects": ["models"]})
assert proxy_server.should_load_db_object(object_type="websearch_interception_settings") is False

View file

@ -1,4 +1,4 @@
import { updateWebSearchInterceptionSettings } from "@/components/networking";
import { updateWebSearchInterceptionSettings, type WebSearchInterceptionSettings } from "@/components/networking";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
@ -8,7 +8,7 @@ export const useUpdateWebSearchInterceptionSettings = (accessToken: string) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (settings: Record<string, any>) => {
mutationFn: async (settings: WebSearchInterceptionSettings) => {
if (!accessToken) {
throw new Error("Access token is required");
}

View file

@ -1,4 +1,4 @@
import { getWebSearchInterceptionSettings } from "@/components/networking";
import { getWebSearchInterceptionSettings, type WebSearchInterceptionSettingsResponse } from "@/components/networking";
import { useQuery } from "@tanstack/react-query";
import { createQueryKeys } from "../common/queryKeysFactory";
import useAuthorized from "../useAuthorized";
@ -7,7 +7,7 @@ const webSearchInterceptionSettingsKeys = createQueryKeys("webSearchInterception
export const useWebSearchInterceptionSettings = () => {
const { accessToken } = useAuthorized();
return useQuery<Record<string, any>>({
return useQuery<WebSearchInterceptionSettingsResponse>({
queryKey: webSearchInterceptionSettingsKeys.list({}),
queryFn: async () => await getWebSearchInterceptionSettings(accessToken),
enabled: !!accessToken,

View file

@ -3667,17 +3667,26 @@ export const updateMCPSemanticFilterSettings = async (accessToken: string, setti
}
};
export const getWebSearchInterceptionSettings = async (accessToken: string) => {
export type WebSearchInterceptionSettings = components["schemas"]["WebSearchInterceptionSettings"];
export type WebSearchInterceptionSettingsResponse = components["schemas"]["WebSearchInterceptionSettingsResponse"];
export const getWebSearchInterceptionSettings = async (
accessToken: string,
): Promise<WebSearchInterceptionSettingsResponse> => {
try {
const data = await apiClient.get(`/get/websearch_interception_settings`, { accessToken });
return data;
return await apiClient.get<WebSearchInterceptionSettingsResponse>(`/get/websearch_interception_settings`, {
accessToken,
});
} catch (error) {
console.error("Failed to get web search interception settings:", error);
throw error;
}
};
export const updateWebSearchInterceptionSettings = async (accessToken: string, settings: Record<string, any>) => {
export const updateWebSearchInterceptionSettings = async (
accessToken: string,
settings: WebSearchInterceptionSettings,
) => {
try {
return await apiClient.patch(`/update/websearch_interception_settings`, { accessToken, body: settings });
} catch (error) {

View file

@ -38068,7 +38068,7 @@ export interface components {
* Use in general_settings.supported_db_objects to specify which objects to load from DB.
* @enum {string}
*/
SupportedDBObjectType: "models" | "mcp" | "guardrails" | "policies" | "vector_stores" | "pass_through_endpoints" | "prompts" | "model_cost_map" | "tools" | "config_overrides";
SupportedDBObjectType: "models" | "mcp" | "guardrails" | "policies" | "vector_stores" | "pass_through_endpoints" | "prompts" | "model_cost_map" | "tools" | "config_overrides" | "websearch_interception_settings";
/** SupportedEndpoint */
SupportedEndpoint: {
/** Endpoint */