Commit graph

167 commits

Author SHA1 Message Date
Mateo Wang
ff71808671
Merge pull request #35967 from BerriAI/litellm_bedrock_strip_client_metadata
fix(bedrock): strip client_metadata from converse additionalModelRequestFields
2026-09-02 16:46:48 -07:00
mateo-berri
277cb3a938 Merge branch 'litellm_bedrock_converse_legacy_thinking_adaptive' of https://github.com/BerriAI/litellm into litellm_bedrock_converse_legacy_thinking_adaptive
# Conflicts:
#	litellm/llms/bedrock/chat/invoke_transformations/anthropic_claude3_transformation.py
#	tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py
2026-09-02 15:29:00 -07:00
mateo-berri
fd4b15fae6 fix(anthropic): upgrade legacy thinking after the Bedrock Invoke and Vertex structured-output stub swap 2026-09-02 13:37:14 -07:00
Devin AI
0346bb2659 fix(bedrock): upgrade legacy thinking after the invoke response_format stub model swap
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 19:58:05 +00:00
mateo-berri
1801fbb1a8 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_converse_legacy_thinking_adaptive 2026-09-02 11:03:02 -07:00
mateo-berri
53da9bca8e fix(bedrock): drop client_metadata for every converse model 2026-09-02 10:29:44 -07:00
mateo-berri
c05aef159f Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_strip_client_metadata 2026-09-02 09:44:14 -07:00
mateo-berri
863199c09b Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_bearer_token_converse_crash 2026-09-01 19:07:43 -07:00
mateo-berri
0e7a05d878 test(bedrock): read the sent bearer header off the mock instead of a hand-rolled recorder 2026-09-01 18:46:41 -07:00
tin-berri
48dd06e841
fix(bedrock): gate Converse cachePoint emission on model prompt caching support (#39210)
Bedrock rejects requests carrying cachePoint blocks for models whose entry in the cost map does not declare supports_prompt_caching (403 "You invoked an unsupported model or your request did not allow prompt caching"). Clients like Claude Code attach cache_control to every request, so any such model behind the gateway failed on every call. The new bedrock_model_accepts_cache_points predicate drops cachePoint emission for map-known non-caching models at all three emission funnels, keeps emitting for unmapped ids (application inference profile ARNs), and skips the gateway injection credit when the tool_config point is not placed.
2026-09-01 18:00:31 -07:00
mateo
d568bbe58d fix(bedrock): use tool fallback without forced tool_choice for claude-fable-5-1 structured output
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 20:19:46 +00:00
mateo
3e3e4d6970 fix(anthropic): use native structured output for claude-fable-5-1 on Vertex AI and Bedrock Invoke
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 20:01:03 +00:00
mateo
bba951c5eb fix(bedrock): drop client_metadata for ARNs that hide the model family
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 19:26:19 +00:00
mateo
d6005a1876 merge: resolve conflict with litellm_internal_staging in anthropic transformation tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 19:23:47 +00:00
mateo-berri
f8298fa35c fix(bedrock): stop Converse crashing on bearer-token auth without SigV4 credentials
Since the Rust core handoff in #37241, BedrockConverseLLM.completion read
access_key, secret_key and token off the boto3 credentials before asking
the Rust gate whether it wanted the call. On a deployment that only sets
AWS_BEARER_TOKEN_BEDROCK boto3 resolves no credentials, so every Converse
call through /v1/chat/completions and /v1/responses failed with
"'NoneType' object has no attribute 'access_key'", with or without the
Rust opt-in

Bearer auth resolves no SigV4 principal at all, and both the Python and
the Rust path read the bearer token themselves, so only hand the
principal keys down when boto3 actually resolved one

get_request_headers now accepts credentials=None and raises botocore's
NoCredentialsError when neither a bearer token nor a principal exists
instead of handing SigV4Auth a None

Fixes #38579

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BFDpYC45u9p8eKd4aBATnS
2026-09-01 12:22:15 -07:00
mateo
d816b75dd4 feat(bedrock): gate forced tool_choice on supports_forced_tool_use in converse
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 19:05:03 +00:00
milan
ed4343a026 fix(bedrock): scope client_metadata drop to anthropic converse models
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 19:04:32 +00:00
Devin AI
2063c29f5d fix(anthropic): upgrade legacy thinking to adaptive on adaptive-only models for chat and Bedrock Converse
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 18:45:26 +00:00
milan
ab11613441 fix(bedrock): strip client_metadata from converse additionalModelRequestFields
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 16:50:24 +00:00
Tin Chi Lo
a27e12367e fix(bedrock): forward native structured outputs on Invoke instead of silently inlining the schema 2026-08-31 23:19:22 -07:00
mateo-berri
cf1b431d58 fix(bedrock): stop duplicating Converse config blocks inside inferenceConfig 2026-08-31 11:50:45 -07:00
tin-berri
ca0b951a43
feat(spend): report prompt caching savings as total and gateway-attributed (#38134)
* feat(spend): report prompt caching savings as total and gateway-attributed

`prompt_caching_savings_spend` credited every cached request, including caching a
client asked for with its own `cache_control` and caching a provider does implicitly,
so the number overstated what the gateway had any hand in.

Gating that column in place would have fixed the overstatement by changing what the
column means, leaving rows written before the change saying "all caching savings" and
rows after saying "gateway-injected only" with nothing to tell them apart, and forcing
a decision about rewriting history. It also breaks the cache-leakage estimate on the
dashboard, whose numerator would be gated while its denominator, the cached token
counts, would not, so the rate it extrapolates from would be quietly diluted.

Report both instead. `prompt_caching_savings_spend` keeps meaning every net dollar
caching saved, which is what a customer means by "what did caching save me", and the
new `gateway_injected_caching_savings_spend` carries the subset litellm caused by
injecting the breakpoints itself. Both are derived from the same marker, so this
changes what is done with it rather than how it is obtained.

The attributed figure is normally the smaller of the two, being a subset of the same
requests, but not always: a request that writes cache it never reads has negative net
savings, and excluding such a request can lift the attributed figure above the total.

Also stops the marker riding into a fallback leg. The fallback rebuild spread the
failed attempt's metadata forward, so a deployment that injected nothing inherited the
marker and was credited anyway, which silently restored the very overstatement this
separates out.

* fix(bedrock): credit gateway caching where the tool cachePoint is placed (#38478)

The savings marker records breakpoints litellm placed, and a tool_config
injection point becomes one only in the converse transform, and only when the
request carries tools. The prompt hook cannot see either condition, so marking
on the point's presence credited request shapes that cached nothing, while
Bedrock tool caching the gateway did cause went uncredited.

Record it at the placement site instead. The marker's reader also resolves its
bucket by value now: litellm_params declares litellm_metadata as None on every
request, so asking the shared name resolver named a bucket that was not there
and the mark was dropped.
2026-08-28 00:19:06 -07:00
mateo-berri
ca177f9cbc Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_pr36762_bedrock_cache_details
# Conflicts:
#	litellm/llms/bedrock/chat/converse_transformation.py
2026-08-26 12:45:15 -07:00
Matthew Lapointe
9cc276a96e fix(bedrock): never forward Anthropic thinking for OpenAI GPT-5.x Converse
Stop advertising thinking/output_config as supported for OpenAI GPT-5.x and
skip the thinking mapping for these models, so a request combining thinking
with reasoning_effort can no longer leak a thinking block into
additionalModelRequestFields regardless of parameter order, which Bedrock
rejects with unknown_parameter.
2026-08-25 19:32:54 -04:00
Matthew Lapointe
74e86d3c0d fix(bedrock): route reasoning_effort to reasoning.effort for OpenAI GPT-5.x on Converse
OpenAI GPT-5.x models on Bedrock Converse expect reasoning effort under
additionalModelRequestFields as {"reasoning": {"effort": ...}}. They were
falling into the Anthropic branch and emitting a `thinking` block, which
Converse rejects with unknown_parameter.

The bedrock_converse gpt-5.6 entries were also missing supports_reasoning,
so reasoning_effort was dropped before mapping. Setting the flag lets the
existing config-driven supported-params path accept it, rather than adding
another model-name branch.
2026-08-25 19:20:00 -04:00
Mateo Wang
9dff9cdd9a
Merge pull request #37979 from BerriAI/litellm_lit5714_adaptive_thinking_display
fix(anthropic/bedrock): request summarized adaptive thinking for reasoning_effort and use provider thinking token counts
2026-08-25 09:58:03 -07:00
mateo-berri
e0511e9384 Merge branch 'litellm_internal_staging' into litellm_bedrock_converse_no_trailing_empty_chunk
Resolves the test-file conflict by keeping both sides, extends the
finish-reason gate to trace-bearing metadata events so guardrail trace
chunks keep their pre-regression delta shape, parametrizes the
regression test over tool-call, mixed, and reasoning streams, and
repairs the one ant-design icon usage the lucide-react migration left
behind in skill_detail.tsx (semantic conflict on the base branch)
2026-08-24 10:37:32 -07:00
Devin AI
418e8ca5e8 fix(bedrock): build response field paths as an immutable sequence to satisfy the type discipline gate
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-23 00:00:21 +00:00
Devin AI
20e92d1e68 fix(anthropic/bedrock): request summarized adaptive thinking for reasoning_effort and use provider thinking token counts
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-22 23:10:42 +00:00
yuneng-jiang
6a0d03914c
test: drop the cwd-relative sys.path.insert calls from the test suite (#37802)
* test: drop the cwd-relative sys.path.insert calls from the test suite

TQ003 stands at 1,077 across 1,058 files, and 1,015 of them are the same shape:
sys.path.insert(0, os.path.abspath("../..")) and its deeper siblings. The
argument resolves against the working directory rather than the file, so from
the repo root, where every job runs pytest, it inserts the directory two levels
above the checkout. It has never pointed at litellm. The package is installed
into the environment anyway, which is what actually makes the import work, and
what the rule's message has said all along.

Removing them leaves 1,634 imports of sys and os with no remaining reference,
and those go too, except where another test module imports the name back out of
the file. The rest of TQ003 is 62 call sites that resolve against __file__ or a
variable, which are a different question and are left alone.

Collection is identical either way: 45,871 tests and the same 51 pre-existing
collection errors before and after, and ruff reports no new undefined name.

* test: drop the duplicate imports the sys.path sweep exposed to F811

* test(pre-call-utils): restore the os import the new bedrock tests need
2026-08-22 09:25:58 -07:00
yuneng-jiang
693797420d
test: unwind environment writes in tests/test_litellm with monkeypatch (#37806)
* test: use monkeypatch.setenv for env writes in tests/test_litellm

`os.environ["X"] = v` inside a test leaks the value into every test that runs
after it in the same worker, so ordering decides the result. 262 of those
writes across 40 files now go through pytest's `monkeypatch` fixture, which
restores the previous value at teardown.

The rewrite skips any test that a mock.patch-family decorator wraps, any test
with defaulted positional parameters, any test whose own name is called
directly elsewhere, and rebinds nothing inside nested defs, because in each of
those cases appending a fixture parameter changes what pytest or mock binds.

Ratchets the TQ004 ceiling from 768 to 506.

* fix(test): delete the key through monkeypatch instead of popping it first

Five tests popped a key straight out of `os.environ`, ran, then restored it with
`monkeypatch.setenv`. By the time monkeypatch saw the name it was already gone,
so it recorded "absent" as the value to go back to and deleted the key at
teardown. On a worker that inherited a real `RESEND_API_KEY`, `SENDGRID_API_KEY`,
`UI_PASSWORD`, `LITELLM_SALT_KEY` or `OPENAI_API_KEY`, every test after the first
one ran without it.

`monkeypatch.delenv(..., raising=False)` removes the key and restores whatever
was there, so the try/finally the manual restore needed goes with it.

* chore(test): leave the two cost-calc files to the PR that rewrites them fully

Both files are also in #37815, which converts the module-global writes as well
as the env writes and folds them into one fixture. Two PRs rewriting the same
lines differently is a conflict nobody benefits from resolving, so this one
drops back to staging on those two and keeps the other 39.

TQ004 clears 200 here instead of 275; the rest moves with #37815.
2026-08-21 20:28:37 -07:00
ryan-crabbe-berri
5ed230701a test: escape the literal match= patterns PT017 minted 2026-08-21 16:22:51 -07:00
ryan-crabbe-berri
243ed4393d test: reject assertions on a caught error inside except (ruff PT017)
A test that asserts on the error inside its own except block passes when the
call stops raising, because nothing runs the handler. That is the exact case
the test exists to catch, so the regression lands green.

Rewrites all 111 such blocks into pytest.raises, which fails when the call
succeeds, and selects PT017 in ruff-tests.toml so no new one lands.
2026-08-21 13:35:08 -07:00
tin-berri
4307b34aca
fix: omit thinking.type=disabled for always-on thinking Claude models (#37510) 2026-08-21 10:27:26 -07:00
Devin AI
8a40aff1d2 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_forward_bedrock_response_headers 2026-08-21 02:49:56 +00:00
Yassin Kortam
bf59b7e23d
feat(rust): route /chat/completions through the Rust core for anthropic and bedrock (#37241)
Adds a chat_completions route module to litellm-core, mirroring the messages
route, plus Anthropic Messages and Bedrock Converse provider configs. The
per-model `rust: true` opt-in now covers /chat/completions for both providers.

The core accepts an allowlisted subset (text conversations, non-streaming) and
returns CoreError::Unsupported for anything else, so tool calls, multimodal
content and streaming fall back to the Python path transparently.

Resolves LIT-5698
2026-08-20 16:15:24 -07:00
ryan-crabbe-berri
21e9632713
test: add six ruff rules that catch tests which cannot fail (#37709)
`assert False` inside a `try:` raises AssertionError, which the `except
Exception` right below it catches, so several tests reported green no matter
what the code did. `pytest.fail` raises Failed, a BaseException, and escapes.

A bare `a == b` statement is evaluated and discarded. Nine of those sat in
tests, and one was comparing against a model name the router never produces.

Selects B011, B015, B018, PT015, PLR0133 and PLW0127 in ruff-tests.toml
alongside F821, with all 50 existing violations fixed, so no budget file or
ratchet is needed. CI already runs this config over tests/.
2026-08-20 14:21:26 -07:00
mateo-berri
46a4eda19e Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_bedrock_adaptive_thinking_token_accounting
# Conflicts:
#	litellm/llms/bedrock/chat/invoke_handler.py
#	litellm/responses/litellm_completion_transformation/transformation.py
#	tests/test_litellm/llms/bedrock/chat/test_converse_transformation.py
#	tests/test_litellm/responses/litellm_completion_transformation/test_reasoning_content_transformation.py
2026-08-19 14:10:53 -07:00
mateo-berri
54cc988a9e test: drop restating comment and wrap long call in thinking tests 2026-08-18 19:55:22 -07:00
mateo-berri
138c77023a fix: accept bool thinking param instead of crashing with AttributeError
litellm.completion(thinking=True) crashed pre-network in is_thinking_enabled
with a retryable APIConnectionError ('bool' object has no attribute 'get'),
so the router burned retries on a deterministic failure and proxy clients got
a traceback instead of a usable response.

validate_and_fix_thinking_param now coerces thinking=True to the enabled dict
with the default medium budget and drops thinking=False, and the remaining
dict-assuming thinking accessors (base config, bedrock converse, deepseek)
guard with isinstance so raw bools can never crash a transform.
2026-08-18 19:44:31 -07:00
Marty Sullivan
5fe7793a14 refactor(bedrock): own the Converse batch usage shape in the provider layer
Shape detection and block normalization sat in the generic batch layer, which
let batch and live parsing of the same wire format drift apart. Both now live on
AmazonConverseConfig as is_converse_usage_shape and usage_from_batch_output, so
batch_utils asks the provider adapter rather than knowing Bedrock's field names.

Adds direct coverage for the shape predicate, the completion of an incomplete
block, cache-count inflation, and the streaming usage event that shares the
public transform. Drops the narrative banner from the batch tests.
2026-08-16 22:32:56 -04:00
Marty Sullivan
7dbf2d57c5 fix(bedrock): read batch usage by payload shape, not by provider name
Every bedrock batch output line went through the Anthropic usage parser, which
reads snake_case input_tokens/output_tokens. Converse-family models (Nova and
friends) report camelCase inputTokens/outputTokens, so their usage came back
0/0/0 and the batch billed $0 despite real token consumption.

Usage is now selected by the shape of the payload: a Converse-shaped block goes
through the same transform the live Converse path uses, so a batch and an
equivalent non-batch call agree on tokens, including cache reads and writes.
Anthropic-shaped bedrock output is unchanged.

A shape neither parser understands (an InvokeModel-native payload from Titan,
Cohere, or Llama, which name their counts differently again) still reads zero,
but now warns with the keys it saw instead of silently billing $0.

Exposes the Converse usage transform as public, since batch parsing is a second
legitimate caller; that also removes the private-member access invoke_handler
was already making.
2026-08-16 04:18:22 -04:00
Devin AI
726db1a4c1 test(bedrock): cover async header forwarding for converse and invoke
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 03:07:14 +00:00
Devin AI
9c922f4aa4 fix(bedrock): forward provider response headers on chat completions
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 02:49:10 +00:00
mateo
3db1759d04 fix(bedrock): stop emitting an empty assistant delta after the finish_reason chunk
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-13 19:45:32 +00:00
Daniel Vainshtein
42a2b5f057 fix(bedrock): guard cache-detail split against partial/unrecognized ttl entries
Address review feedback on #36762:
- Only use the parsed 5m/1h split when it fully accounts for
  cacheWriteInputTokens; an unrecognized ttl or missing entry now falls
  back to the aggregate (previous behavior) instead of silently
  understating cost.
- Mark TypedDict fields ReadOnly (AWS response data, never constructed
  by us) to satisfy the repo's type-discipline lint gate.
- Trim comments and add Final to locals per repo style.

Co-Authored-By: pi (Claude/GPT via @earendil-works/pi-coding-agent) <noreply@earendil.works>
2026-08-13 14:06:22 +03:00
Daniel Vainshtein
97290b4e0e fix(bedrock): parse cacheDetails for Converse 1h/5m cache write cost split
AmazonConverseConfig._transform_usage only read the aggregate
cacheWriteInputTokens field, so cache_creation_token_details was always
unset for Bedrock Converse responses. calculate_cache_writing_cost bills
the whole cache-write count at the 5m rate whenever that field is None,
so 1-hour TTL cache writes on the standard Bedrock chat path were always
undercounted, even though Bedrock returns the 5m/1h split in
usage.cacheDetails.

Parse cacheDetails (when present) into CacheCreationTokenDetails so the
correct rate applies to each portion. No cacheDetails in the response
(older models/regions) keeps the previous behavior.

Fixes #36760

Co-Authored-By: pi (Claude/GPT via @earendil-works/pi-coding-agent) <noreply@earendil.works>
2026-08-13 13:44:15 +03:00
mateo-berri
0f41365c34 fix(bedrock): forward output_config effort for application inference profile ARNs 2026-08-11 09:11:22 +00:00
mateo-berri
929ee52b87 fix(bedrock): preserve adaptive thinking effort through the /v1/messages bridge
Claude Code drives Opus 4.7 with thinking {"type": "adaptive"} plus
output_config {"effort": "max"}. The anthropic-to-openai adapter
forwarded thinking verbatim for Claude models but dropped output_config,
and Bedrock Converse streams zero reasoningContent blocks for adaptive
thinking without an effort tier. Forward the effort subset of
output_config for Bedrock targets, accept it in the converse supported
params, and map it with the model's effort ceiling applied. Re-enable
the skipped e2e compat cell that catches this
2026-08-11 03:23:16 +00:00
Alex Shtof
280c95ccb0
fix(bedrock): enable native structured output for GLM 5 and DeepSeek V3.2 (#35669)
* fix(bedrock): enable native structured output for GLM 5 and DeepSeek V3.2

* ci: empty commit

---------

Co-authored-by: Alexander Shtoff <alexander.shtoff@tii.ae>
2026-08-10 10:18:13 -07:00