diff --git a/litellm/proxy/litellm_pre_call_utils.py b/litellm/proxy/litellm_pre_call_utils.py index 14d941ff62c..27540c24bc5 100644 --- a/litellm/proxy/litellm_pre_call_utils.py +++ b/litellm/proxy/litellm_pre_call_utils.py @@ -377,6 +377,8 @@ LITELLM_METADATA_ROUTES: Final = ( "responses", "files", "interactions", + "/decisions", + "/systemone", ) LITELLM_TRACE_CONTROL_METADATA_FIELDS: Final = frozenset( diff --git a/tests/unit/proxy/decisions_endpoints/test_endpoints.py b/tests/unit/proxy/decisions_endpoints/test_endpoints.py index c67d1012475..7903c9300a0 100644 --- a/tests/unit/proxy/decisions_endpoints/test_endpoints.py +++ b/tests/unit/proxy/decisions_endpoints/test_endpoints.py @@ -577,6 +577,53 @@ _OPENAI_FORMAT_ANSWERS: Final = [ ] +@pytest.mark.parametrize( + ("endpoint", "request_body"), + ( + ("/v1/decisions", _OPENAI_FORMAT_REQUEST), + ("/decisions", _OPENAI_FORMAT_REQUEST), + ("/v1/systemone", _REQUEST), + ("/systemone", _REQUEST), + ), +) +def test_proxy_decisions_routes_apply_tag_routing( + client: TestClient, + monkeypatch: pytest.MonkeyPatch, + respx_mock: respx.MockRouter, + endpoint: str, + request_body: Mapping[str, object], +) -> None: + monkeypatch.setattr( + litellm.proxy.proxy_server, + "llm_router", + litellm.Router( + model_list=[ + { + "model_name": "decider", + "litellm_params": { + "model": "perplexity/pplx-decider-v1-27b", + "api_key": "test-key", + "tags": ["provider:perplexity"], + }, + } + ], + enable_tag_filtering=True, + ), + ) + upstream: Final = respx_mock.post("https://api.perplexity.ai/v1/decisions").respond(json=_RESPONSE) + + rejected: Final = client.post(endpoint, json=request_body, headers={"x-litellm-tags": "&inference:bedrock"}) + + assert rejected.status_code == 401, rejected.text + assert "Not allowed to access model due to tags configuration" in rejected.text + assert not upstream.called + + accepted: Final = client.post(endpoint, json=request_body, headers={"x-litellm-tags": "provider:perplexity"}) + + assert accepted.status_code == 200, accepted.text + assert upstream.called + + @pytest.mark.parametrize("endpoint", ("/v1/decisions", "/decisions")) def test_openai_format_decisions_translate_through_systemone( client: TestClient, diff --git a/tests/unit/proxy/test_litellm_pre_call_utils.py b/tests/unit/proxy/test_litellm_pre_call_utils.py index 81a196af676..cc8f5a733f2 100644 --- a/tests/unit/proxy/test_litellm_pre_call_utils.py +++ b/tests/unit/proxy/test_litellm_pre_call_utils.py @@ -116,6 +116,11 @@ class TestGetMetadataVariableName: request = self._make_request(path) assert get_metadata_variable_name(request) == "litellm_metadata" + @pytest.mark.parametrize("path", ["/v1/decisions", "/decisions", "/v1/systemone", "/systemone"]) + def test_returns_litellm_metadata_for_decisions_routes(self, path): + request = self._make_request(path) + assert get_metadata_variable_name(request) == "litellm_metadata" + def test_returns_metadata_for_chat_completions(self): request = self._make_request("/chat/completions") assert get_metadata_variable_name(request) == "metadata"