mirror of
https://github.com/BerriAI/litellm.git
synced 2026-10-05 02:41:56 +00:00
fix(anthropic): strip safeguards on the adapter path and type it on streaming chunks
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
parent
3ebd5add32
commit
b59028d525
4 changed files with 16 additions and 7 deletions
|
|
@ -35,7 +35,7 @@ if TYPE_CHECKING:
|
|||
from litellm.router import Router
|
||||
|
||||
# Anthropic-only keys already mapped by the translator; strip on extra_kwargs re-merge.
|
||||
ANTHROPIC_ONLY_REQUEST_KEYS: Final[frozenset[str]] = frozenset({"output_config"})
|
||||
ANTHROPIC_ONLY_REQUEST_KEYS: Final[frozenset[str]] = frozenset({"output_config", "safeguards"})
|
||||
|
||||
_AnthropicMessages: TypeAlias = "list[dict[str, object]]"
|
||||
_AnthropicSystem: TypeAlias = "str | list[dict[str, object]] | None"
|
||||
|
|
|
|||
|
|
@ -531,6 +531,7 @@ class AnthropicStopDetails(TypedDict, total=False):
|
|||
class MessageDelta(TypedDict, total=False):
|
||||
stop_reason: str | None
|
||||
stop_details: ReadOnly[AnthropicStopDetails]
|
||||
safeguard_results: ReadOnly[dict[str, object]]
|
||||
|
||||
|
||||
class ServerToolUsage(TypedDict, total=False):
|
||||
|
|
@ -601,6 +602,7 @@ class MessageChunk(TypedDict, total=False):
|
|||
stop_reason: str | None
|
||||
stop_sequence: str | None
|
||||
usage: UsageDelta
|
||||
safeguard_results: ReadOnly[dict[str, object]]
|
||||
|
||||
|
||||
class MessageStartBlock(TypedDict):
|
||||
|
|
|
|||
|
|
@ -110,6 +110,19 @@ class TestOutputConfigStrippedFromCompletionKwargs:
|
|||
"reject it with 400 'Extra inputs are not permitted'"
|
||||
)
|
||||
|
||||
def test_safeguards_is_stripped_for_non_anthropic_target(self):
|
||||
extra_kwargs = {
|
||||
"custom_llm_provider": "azure",
|
||||
"safeguards": {"auto_mode": {"enabled": True, "version": "2026-09-01"}},
|
||||
}
|
||||
|
||||
result = _call_prepare(extra_kwargs=extra_kwargs)
|
||||
|
||||
completion_kwargs = result[0] if isinstance(result, tuple) else result
|
||||
assert "safeguards" not in completion_kwargs, (
|
||||
"safeguards is an Anthropic-only field; OpenAI-format backends reject it with 400"
|
||||
)
|
||||
|
||||
def test_output_config_format_translated_to_response_format(self):
|
||||
"""When ``output_config`` carries structured-output ``format``, the
|
||||
translator now maps it to OpenAI's ``response_format`` so non-Anthropic
|
||||
|
|
|
|||
|
|
@ -1442,9 +1442,6 @@ async def test_anthropic_messages_leaves_non_provider_failures_unmapped():
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_anthropic_messages_forwards_safeguards_and_unknown_beta_to_anthropic():
|
||||
"""Regression test for LIT-8232. Claude Code auto mode sends a `safeguards` body
|
||||
field paired with a beta value the gateway has never seen. Both must reach
|
||||
api.anthropic.com unchanged or the session falls back to billed classifier calls."""
|
||||
from litellm.llms.anthropic.experimental_pass_through.messages import handler
|
||||
|
||||
safeguards = {"auto_mode": {"enabled": True, "version": "2026-09-01"}}
|
||||
|
|
@ -1491,9 +1488,6 @@ async def test_anthropic_messages_forwards_safeguards_and_unknown_beta_to_anthro
|
|||
|
||||
@pytest.mark.asyncio
|
||||
async def test_anthropic_messages_streaming_forwards_safeguards_and_keeps_safeguard_results():
|
||||
"""Streaming sibling of the LIT-8232 regression: the request must still carry
|
||||
`safeguards` and the `safeguard_results` Anthropic emits on `message_start` and
|
||||
`message_delta` must reach the client byte for byte."""
|
||||
from litellm.llms.anthropic.experimental_pass_through.messages import handler
|
||||
|
||||
safeguards = {"auto_mode": {"enabled": True, "version": "2026-09-01"}}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue