Merge remote-tracking branch 'origin/litellm_passthrough_auth_guardrails' into litellm_lakera_v2_gemini_contents

This commit is contained in:
yucheng 2026-11-05 01:41:16 -08:00
commit c0bb0c336f
2 changed files with 16 additions and 5 deletions

View file

@ -968,7 +968,7 @@ async def _inherit_auth_guardrails(
runs_guardrails: Final = bool(entries) or bool((as_str_mapping(metadata) or {}).get("_guardrail_pipelines"))
if entries and isinstance(metadata, dict):
metadata["guardrails"] = entries
elif isinstance(merged, list) and isinstance(metadata, dict):
elif isinstance(merged, (list, dict)) and isinstance(metadata, dict):
_restore_unmerged_guardrail_fields(
parsed_body,
cast("dict[str, object]", metadata), # cast-ok: the request body's JSON metadata object
@ -1025,8 +1025,8 @@ def _restore_unmerged_guardrail_fields(
client_body_guardrails: Mapping[str, object],
client_metadata_guardrails: Mapping[str, object],
) -> None:
"""Put back the client's ``guardrails`` and ``metadata.guardrails`` when the merge found no guardrail to run, so
the body keeps main's shape"""
"""Put back the client's ``guardrails`` and ``metadata.guardrails`` when the merge produced no list of guardrails,
such as an empty list or the client's object form on a plain key, so the body keeps main's shape"""
metadata.pop("guardrails", None)
metadata.update(client_metadata_guardrails)
parsed_body.update(client_body_guardrails)

View file

@ -13380,10 +13380,21 @@ class TestInheritAuthGuardrails:
{"guardrails": [], "metadata": {"user": "u"}},
{"guardrails": [], "metadata": {"guardrails": []}},
{"metadata": {"guardrails": []}},
{"guardrails": {"g": {}}},
{"guardrails": {"g": {}}, "metadata": {"headers": 5}},
{"guardrails": {"g": {}}, "metadata": {"guardrails": {"h": {}}}},
],
ids=[
"guardrails",
"with-metadata",
"with-metadata-guardrails",
"metadata-guardrails-only",
"object-form",
"object-form-with-metadata",
"object-form-with-metadata-object-form",
],
ids=["guardrails", "with-metadata", "with-metadata-guardrails", "metadata-guardrails-only"],
)
async def test_an_empty_guardrails_list_on_a_plain_key_keeps_the_body_as_sent(self, extra: dict[str, object]):
async def test_guardrails_that_merge_to_no_list_on_a_plain_key_keep_the_body_as_sent(self, extra: dict[str, object]):
body: Final[dict[str, object]] = self._chat_body(**extra)
assert await _inherit_auth_guardrails(body, UserAPIKeyAuth(api_key="sk-test"), None, True) is None