Commit graph

43176 commits

Author SHA1 Message Date
abhi
1b8daea07c fix: fail closed when key context is absent (veria-ai finding)
Confirmed real. _canonical_target_is_allowed returned True when
user_api_key_dict was None, on the reasoning that no key context meant
non-proxy Router use. That reasoning was wrong: of the 12 route_request call
sites, only one (common_request_processing, the /chat/completions path)
forwards user_api_key_dict. Image generation, rerank, moderation, speech,
transcription, realtime, and the Responses WebSocket path are all
authenticated endpoints that call route_request without it, so the rewrite ran
with no target authorization at all on exactly those paths -- a key whose
allowlist held only the stale requested spelling could reach a canonical
target it was never granted.

Now returns False. Declining costs those endpoints only the convenience
rewrite: they behave exactly as they do today, resolution simply never
engages, and no request that works now breaks. The AND-on-target guarantee
becomes unconditional rather than depending on whether a given caller happens
to thread the key through.

Verified the primary path is unaffected: with key context present and
authorized, resolution still resolves -- that is the Claude Code 403 case this
PR exists to fix. Threading user_api_key_dict through the other call sites is
the follow-up that re-enables resolution for them; doing it here would touch
11 unrelated endpoints in a PR that should not be changing their signatures.

Updated test_no_auth_context_is_allowed -> test_absent_auth_context_fails_closed
with the reasoning recorded.

Gates: pytest 531 passed - ruff format/check clean - type-discipline all LIT
rules at base parity - basedpyright new module 0 errors.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 18:38:07 -07:00
abhi
9b1fdc1d8d fix: address three bugbot findings (team re-auth, provider override, proxy settings)
All three confirmed real and reproduced before fixing.

1. [High] Team allowlist bypassed AND-on-target. The rewrite re-auth called
   can_key_call_model, which checks only the key's own allowlist, so team,
   team-member, and project allowlists were never re-checked against the
   resolved target. An unrestricted key on a team whose allowlist held only a
   stale unserved name could ride the rewrite onto a deployment that team was
   never granted. Now calls can_key_call_resolved_model -- the helper every
   other post-resolution auth site already uses (model_group_alias rewrites,
   realtime endpoints, auto-router), which runs the full key/team/member/project
   chain.

2. [Medium] Index ignored the deployment's custom_llm_provider, canonicalizing
   only litellm_params.model. Reproduced: a deployment with
   model='claude-haiku-4-5' + custom_llm_provider='openrouter' was indexed under
   ('anthropic', ...), so an Anthropic-form request resolved onto OpenRouter
   credentials, quota, and billing -- precisely the cross-provider hop rule 2
   of the module docstring forbids. canonicalize() now takes the override and
   prefers it over the provider inferred from the model string.

3. [Medium] Operators could not select model_name_resolution: strict on the
   proxy. Both proxy Router construction sites passed a hardcoded
   RouterGeneralSettings(async_only_mode=True) as an explicit keyword alongside
   **router_params. Since router_general_settings IS an accepted config key,
   setting it raised TypeError: got multiple values for keyword argument at
   startup -- so the documented opt-out was unreachable either way. Added
   _proxy_router_general_settings(), which forces async_only_mode (a proxy
   runtime requirement) while preserving every other operator-set field, and
   copies rather than mutating the caller's object.

Added 10 regression tests. Verified the two re-auth tests actually fail against
the pre-fix code (2 failed / 1 passed) rather than passing vacuously.

Gates: pytest 531 passed - ruff format clean - ruff check clean - strict
BLE001/PERF401 at base parity (2957/22) - type-discipline all LIT rules at base
parity - basedpyright new module 0 errors - router_code_coverage 0.0% untested
- proxy_server imports cleanly.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 12:50:02 -07:00
abhi
5a677ca271 style: conform to repo type-discipline rules (LIT001/002/006/010/011)
The lint job has three independent gates; this is the third (type-discipline
budget, delta vs base). Rather than keep discovering them one CI round at a
time, ran scripts/check_type_discipline.py locally over the whole tree and
brought every LIT rule back to exact base parity.

Conformed rather than blanket-suppressed where the rule was right:
- build_canonical_index takes a read-only Sequence[Mapping[str, object]] and
  returns a MappingProxyType, so the index cannot be mutated by callers after
  construction. This also removed the cast() at the router call site (LIT006)
  and the now-stale reportUnnecessaryIsInstance suppressions -- with object
  values the runtime validation is genuinely necessary, not redundant.
- spellings is built functionally (two generator-fed tuples) instead of
  seed-then-append.
- The AND-on-target auth re-check moved into a small _canonical_target_is_allowed
  helper, which removes a rebound flag and makes the AND-on-target contract
  documented in one place.
- Genuine cases carry the house-style justification comments: mutable-ok for
  the grow-only log-dedup ledger and the local accumulators (frozen on return),
  rebind-ok for the in-place  rewrites route_request already performs on
  every other route, and for per-iteration loop variables (where Final is
  illegal).

Verified locally against every gate this time, not just the ones CI had
surfaced: pytest 522 passed · ruff format clean · ruff check clean ·
ruff-strict BLE001/PERF401 at base parity (2957/22) · type-discipline all LIT
rules at base parity · basedpyright new module 0 errors · router_code_coverage
0.0% untested.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 11:51:50 -07:00
abhi
646bde17af style: apply ruff format to canonical resolution changes
The lint job's 'Check ruff format' step (separate from the strict-rule budget
step that failed earlier) flagged two files. Both diffs are confined to lines
added by this PR -- the multi-line isinstance/and condition in
_can_object_call_model, and the build_canonical_index call in
_get_canonical_model_index -- so no unrelated formatting is swept in.
Cosmetic only, no semantic change.

ruff format --check: clean. ruff check: clean. basedpyright (new module): 0
errors. strict-rule budgets BLE001/PERF401: unchanged at base parity. Tests:
32 passed.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 11:24:57 -07:00
abhi
84e2d4e23c fix: address review findings (team-scoping leak, sentinel collision, log dedup)
Three issues flagged by automated PR review (greptile-apps, veria-ai), all confirmed real and reproduced before fixing:

1. [High/Security] Team-owned deployments entered the global canonical index
   unconditionally. A no-team (unrestricted) key could request an unclaimed
   spelling of a model (e.g. the dated Anthropic ID) whose only server was a
   team's private deployment, resolve onto it, and use that team's
   credentials/quota -- target-authorization passes for unrestricted keys and
   doesn't itself re-derive team ownership. Fixed by excluding any deployment
   with model_info.team_id set from the index entirely: a team boundary is an
   access/billing boundary exactly like the cross-provider boundary this
   module already respects, and team-scoped models remain reachable exactly as
   before, via team_public_model_name through the existing team-route
   machinery this module never touches.

2. [P1] Sentinel collision defeated the ambiguity guard: index.get(key,
   '__absent__') treated a model group literally named '__absent__' as a
   missing entry, so a second group with the same identity would silently
   overwrite it instead of triggering the ambiguity decline. Fixed with a
   proper 'in' check.

3. [P2] Log deduplication was keyed on target alone, so a second distinct
   requested spelling resolving to an already-logged target never got its own
   log line -- undercounting the (requested, target) cardinality that's the
   whole point of the observability story (sizing follow-up-resolution
   demand). Now keyed on the (requested, target) pair.

Added 5 regression tests reproducing each bug pre-fix and asserting the fixed
behavior. Full affected suite: 522 passed. router_code_coverage: 0.0% untested.
ruff-strict BLE001/PERF401: unchanged at base parity. basedpyright: new module
0 errors.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 11:18:57 -07:00
abhi
6df125ff6d fix: address CI failures on canonical model resolution
Three CI gates failed on the initial push; all three were real:

1. lint (strict-rule budget): BLE001 +5, PERF401 +1 over base. The defensive
   'except Exception' catches are intentional (an unplaceable name or a
   malformed deployment must never fail a request or brick a router), so they
   now carry '# noqa: BLE001' with justifications, matching the convention
   already used in router.py and common_request_processing.py. The candidate
   -spelling loop becomes a generator passed to list.extend (PERF401).
   Both rules are now back at base parity.

2. code-quality (router_code_coverage): the checker only scans test files whose
   filename contains 'router', so tests/.../test_canonical_model_resolution.py
   was invisible to it and both new Router methods read as untested. Renamed to
   test_router_canonical_model_resolution.py and added direct coverage for
   _get_canonical_model_index (memoization + fenced build failure). Checker now
   reports untested_perc: 0.0.

3. proxy-infra (test_route_non_a2a_model_raises_error_if_not_in_router): a real
   regression. The test drives route_request with a Mock() router, so
   resolve_canonical_model_name returned a truthy Mock and the hook treated it
   as a resolved target instead of raising. Both hooks (routing and auth) now
   require an actual non-empty str before acting on a resolution -- correct
   hardening independent of the test: a stub or partially-initialised router
   must never be read as a grant.

Full affected suite: 517 passed. basedpyright: new module 0 errors.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 11:09:14 -07:00
abhi
d952e5e87e chore: type-discipline cleanup for canonical model resolution
basedpyright: new module at 0 errors; modified files back to baseline
(+1 structural 'Return type is Any' on the new route return, matching the
file's existing pattern on every route return). ruff clean.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 08:36:36 -07:00
Abhimanyu Kapur
55c499100e feat: same-provider canonical model-name resolution
Implement Feature A: when a request names a model using one spelling (e.g.
dated 'claude-haiku-4-5-20251001') that the gateway serves under a different
spelling (e.g. 'anthropic/claude-haiku-4-5'), route the request to the serving
deployment instead of failing with a 403/400. Resolution only fires after all
existing routes (exact name, alias, wildcard, default_deployment, team routes)
have declined, so a request that succeeds today is never re-pointed (I1).

Identity is enforced strictly: same provider (never cross-provider like Bedrock
to Vertex), same model per cost-map attestation (never family/version hops like
claude-sonnet-4-5 to claude-sonnet-5) (I2).

Auth is AND-on-target: the caller must be allowed to call the resolved target
group; the requested spelling's presence in an allowlist alone grants nothing,
preventing privilege escalation via stale spellings (I3).

Observability: requested name preserved in request metadata, resolution logged
at INFO per (requested, target) pair, Prometheus counter for cardinality.

Changes:
- litellm/router_utils/canonical_model_resolution.py: new module with
  canonicalize, build index, lookup functions.
- litellm/router.py: Router.resolve_canonical_model_name(), index caching +
  invalidation, config flag model_name_resolution.
- litellm/types/router.py: RouterGeneralSettings.model_name_resolution field.
- litellm/proxy/route_llm_request.py: resolve hook before 400, re-auth on
  target, metadata stamping.
- litellm/proxy/auth/auth_checks.py: canonical lookup in _can_object_call_model
  with AND-on-target semantics.
- tests/test_litellm/router_utils/test_canonical_model_resolution.py: 23
  property tests covering I1–I4, cross-provider block, ambiguity fail-closed,
  auth semantics.

Defaults to 'canonical' (on); users can set model_name_resolution: strict in
router_settings to opt out entirely.

Fixes the Claude Code case: dated Haiku requests now resolve across harness
versions without client-side env vars.

Follow-up: once operator data shows a single provider deployment of all
Anthropic models, Feature B (cross-deployment resolution when only 1 provider
exists) becomes safe to implement under similar guards.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-08-15 08:13:19 -07:00
Mateo Wang
d70cc14981
Merge pull request #35092 from BerriAI/litellm_vertex_batch_embeddings_translation
fix(vertex_ai): translate /v1/embeddings batch rows to the Gemini embedding shape
2026-08-14 21:52:32 -07:00
Mateo Wang
89f233a15d
Merge pull request #36720 from BerriAI/litellm_tiered_pricing_cache_creation
fix(cost): tiered pricing supports cache creation cost and is all-or-nothing
2026-08-14 21:51:54 -07:00
mateo-berri
18752c860c fix(cost): honor explicit zero tier rates and skip synthesized backend output rates 2026-08-14 21:05:22 -07:00
devin-ai-integration[bot]
6e7984e537
fix(proxy): requeue spend logs when the DB write fails with a transport error (#36716)
* fix(proxy): requeue spend logs when the DB write fails with a transport error

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): hardcode the spend log queue cap and drop the stale re-export

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* refactor(proxy): keep the spend log requeue within the type discipline budget

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): apply the spend log queue cap to producer appends too

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): lower the spend log queue cap to 1k and make it env configurable

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): bound the spend log queue by bytes instead of row count

A row cap cannot bound memory: a row carries the whole prompt under store_prompts_in_spend_logs, so a cap that rides out an outage of counter-only rows is an OOM once prompts are stored. Every enqueue and dequeue now goes through one pair that tracks what the queue costs and drops the oldest rows past a 64 MB budget.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): make the spend log queue byte budget env configurable

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): use a string default for the spend log queue byte budget env read

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(proxy): make the spend log queue byte total a public attribute

The queue it accounts for is already public, and a private name only bought reportPrivateUsage errors at every call site.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: shivam <shivam@berri.ai>
2026-08-14 20:49:45 -07:00
mateo
e46f2ca62f fix(dashscope): honor the model reasoning rate when a tier omits output rates
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 03:42:23 +00:00
mateo-berri
34918d34f9 fix(cost): inherit the backend output rate when a deployment's tiers omit one 2026-08-14 20:37:18 -07:00
Mateo Wang
6c2dcb801b
Merge pull request #36907 from guptaishaan/fix/issue-36880-8933
fix: report real token usage on guardrail-blocked /v1/responses replies
2026-08-14 20:16:25 -07:00
mateo
c3e38a0b52 fix(cost): fall back to the model output rate when a tier omits one
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 03:05:13 +00:00
Mateo Wang
1a183efaa1
Merge pull request #36159 from daleselaji-dev/codex/bedrock-alias-36156
Some checks are pending
CodSpeed Benchmarks / benchmarks (push) Waiting to run
Publish basedpyright base counts / publish (push) Waiting to run
Code Quality Checks / code-quality (push) Waiting to run
UI Unit Tests / ui-unit-tests (push) Waiting to run
Unit Tests: Core Utilities / core-utils (push) Waiting to run
Unit Tests: Documentation Validation / documentation (push) Waiting to run
Unit Tests: Enterprise, Google GenAI & Routing / enterprise-routing (push) Waiting to run
Unit Tests: Integrations (Callbacks & Logging) / integrations (push) Waiting to run
Unit Tests: LLM Provider Transformations / Vertex AI (push) Waiting to run
Unit Tests: LLM Provider Transformations / All Other Providers (push) Waiting to run
Unit Tests: MCP, Secrets, Containers & Misc / misc (push) Waiting to run
Unit Tests: Proxy Auth & Key Management / proxy-auth (push) Waiting to run
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Waiting to run
Unit Tests: Proxy DB Operations / auth-checks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / budgets (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / custom-logging (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / db-and-spend (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / key-generation (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / logging-misc (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-runtime (push) Blocked by required conditions
Unit Tests: Proxy DB Operations / proxy-server-core (push) Blocked by required conditions
Unit Tests: Proxy API Endpoints / proxy-endpoints (push) Waiting to run
Unit Tests: Proxy API Endpoints / proxy-server (push) Waiting to run
Unit Tests: Proxy Infrastructure / proxy-infra (push) Waiting to run
Unit Tests: Responses, Caching & Types / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
fix(bedrock): resolve aliases in batch file records
2026-08-14 18:20:21 -07:00
Mateo Wang
70d51a196f
Merge pull request #35286 from BerriAI/devin_ai_lit_5013_web_search_cost
fix(cost): track OpenAI/Azure web search tool cost per call
2026-08-14 18:16:59 -07:00
Mateo Wang
cba2beaf42
Merge pull request #36965 from erensh27/feat/per-component-cost-headers
feat(proxy): per-component response cost headers
2026-08-14 18:15:23 -07:00
mateo
3f64cbe41b fix(ptu): empty a PTU deployment's tiered_pricing instead of dropping it
Dropping it falls back to the public cost map's tier table, whose rates outrank the
zeros written beside them, so a PTU deployment on a tiered model keeps billing its
traffic per token. Stored empty, the tiers no longer apply and the zeros win
2026-08-15 01:14:14 +00:00
yuneng-jiang
a4aab2e9f3
Merge pull request #36995 from BerriAI/litellm_/playground-config-select-25ad99
fix(ui): anchor chips-combobox popups to the field instead of the inner input
2026-08-14 18:11:38 -07:00
mateo
9079844fa2 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_tiered_pricing_cache_creation 2026-08-15 01:05:01 +00:00
yuneng-jiang
491e2ffb1b
Merge pull request #36993 from BerriAI/litellm_/scrollable-tabs-layout-6aa9f7
fix(ui): stop the models tab strip from scrolling vertically
2026-08-14 18:04:42 -07:00
mateo-berri
5970754a85 fix(ptu): clear a PTU deployment's tiered_pricing instead of zeroing it
tiered_pricing is a list, so the 0.0 the flat-rate zeroing stores does not
even validate. Supplying tiers alongside PTU config gets the same 400 as a
flat rate; tiers already stored are dropped from both blobs
2026-08-14 18:04:01 -07:00
mateo-berri
0176e4b3f6 refactor(cost): make the shared token-details parsers public
parse_prompt_tokens_details and parse_completion_tokens_details are imported
by four modules, so the leading underscore made every import a
reportPrivateUsage violation
2026-08-14 18:04:01 -07:00
Yuneng Jiang
c7084c04c0
test(ui): assert which element the chips-combobox popup anchors to
The previous assertion read data-chips, which is derived from the anchor prop
being truthy, so it stayed true even when the ref never reached the DOM and the
popup was still anchored to the inner input.

Stub distinct widths on the chips container and the input, then read the width
the positioner resolved. Reverting the anchor wiring now reports the input's
width instead of the field's, which is the actual bug.
2026-08-14 18:03:34 -07:00
Yuneng Jiang
6e38e9490d
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/playground-config-select-25ad99 2026-08-14 17:57:27 -07:00
Yuneng Jiang
654fab224a
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/scrollable-tabs-layout-6aa9f7 2026-08-14 17:55:49 -07:00
Yuneng Jiang
a0e5c7e818
fix(ui): anchor chips-combobox popups to the field instead of the inner input
Base UI positions a combobox popup against the Combobox.Input by default. In
chips mode the visible field is the ComboboxChips wrapper and the input is a
smaller box nested inside it, so every chips-combobox in the dashboard opened
its popup 11px right of the field and 17px past its right edge.

shadcn ships the wiring for this and their combobox-multiple example uses it:
useComboboxAnchor on the chips container, passed to ComboboxContent as anchor.
The anchor prop also drives data-chips, which cancels the extra min-width an
ordinary combobox wants. Every chips site in the dashboard omitted it.

The anchor is attached through Base UI's render prop rather than a plain ref,
because React 18 drops refs on function components and ComboboxChips is one.

Adds MultiSelect's first test, covering the anchor wiring plus selection,
chip rendering and custom values.
2026-08-14 17:51:54 -07:00
Mateo Wang
40a418440c
Merge pull request #35969 from milesadkins/fireworks_nim_vllm_compat
feat(fireworks_ai): translate NIM/vLLM extra params to Fireworks-native args
2026-08-14 17:47:47 -07:00
Ahmed N
691c7fd4d6
fix(anthropic_messages): make tool_result images visible to OpenAI-compatible providers (#34462)
Images nested inside an Anthropic `tool_result` block were dropped when the
request was adapted for an OpenAI-compatible provider, because the OpenAI tool
message shape only carried text. Hoist those images out of the tool result and
into a following user message so the model can still see them, and widen the
tool message content type to accept image parts.
2026-08-14 17:47:38 -07:00
mateo-berri
2c6409c7e6 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_tiered_pricing_cache_creation 2026-08-14 17:44:39 -07:00
Yuneng Jiang
5219658b8f
fix(ui): stop the models tab strip from scrolling vertically
The tab strip carried overflow-x-auto directly on the TabsList. CSS forces
overflow-y from visible to auto once overflow-x is not visible, and the line
variant's active-tab underline is an absolutely positioned ::after that hangs
5px below its trigger, so the strip picked up a pixel of vertical scroll on top
of the horizontal scroll it actually wants.

The scroll container now lives on a wrapper whose bottom padding leaves room for
the underline, offset by a matching negative margin so the row keeps its exact
geometry.
2026-08-14 17:44:00 -07:00
mateo-berri
de77711cf9 test(vertex_ai): cover duplicated fan-out rows in embeddings batch reassembly
Some checks failed
Terraform Modules / fmt, validate, test (aws) (push) Has been cancelled
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
Also ruff-formats the batch transformation test file, which the formatter
gate flags once the file is touched.
2026-08-14 17:37:07 -07:00
Mateo Wang
118523ede6
Merge pull request #34581 from BerriAI/litellm_anthropic_messages_response_cache
fix(caching): cache anthropic /v1/messages responses, including streaming
2026-08-14 17:34:08 -07:00
Mateo Wang
dc92749c07
Merge pull request #35360 from BerriAI/devin_ai_fix_batch_cost_completed_no_output
fix(batches): mark terminal batch with no output file as processed in CheckBatchCost
2026-08-14 17:33:07 -07:00
mateo-berri
05beb7abb5 fix(proxy): emit uncached input cost so component headers sum to the total 2026-08-14 17:30:50 -07:00
mateo-berri
7e539405ed fix(cost-tracking): price web search on dated search-preview map entries 2026-08-14 17:29:56 -07:00
milan
0d0c712df7 fix(vertex_ai): fail an embeddings batch entry whose fan-out came back incomplete
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-15 00:29:35 +00:00
yuneng-jiang
0f2566e823
Merge pull request #36984 from BerriAI/litellm_/key-info-badge-styling-b293cc
fix(ui): match the MCP servers count badge to its sibling permission badges
2026-08-14 17:26:31 -07:00
mateo-berri
688575e5bf fix(cost): bill reasoning tokens at the selected tier's reasoning rate 2026-08-14 17:26:29 -07:00
Mateo Wang
a5038661c9
Merge pull request #34850 from BerriAI/litellm_lit_4866_anthropic_geo_cache_uplift
fix(anthropic cost): apply regional geo uplift to cached tokens
2026-08-14 17:26:17 -07:00
Mateo Wang
b9d70b5ef5
Merge pull request #34860 from BerriAI/litellm_lit_4868_cache_write_split
fix(anthropic): aggregate 5m/1h cache-write split across iterations path
2026-08-14 17:25:20 -07:00
mateo-berri
7562445273 test(proxy): assert production nesting semantics for component cost headers 2026-08-14 17:24:10 -07:00
Mateo Wang
d74cb6de1b
Merge pull request #36798 from BerriAI/litellm_azure_ai_docs_index_write_grant_rc
fix(azure_ai): recognize real Search doc endpoints so teams can read/write via passthrough
2026-08-14 17:24:06 -07:00
mateo-berri
c9685b2a6d fix(router): honor tiered_pricing set in a deployment's litellm_params 2026-08-14 17:21:15 -07:00
yucheng-berri
f9f5c03884
fix(mcp): drop caller host and configured upstream headers from logged metadata (#36901)
* fix(mcp): drop caller host and configured upstream headers from logged metadata

The synthetic request that carries MCP client headers into
add_litellm_data_to_request forwarded the caller's Host header, and
Request.url is built from it, so a caller chose the proxy_server_request
url and the metadata endpoint that every logging callback records.

_upstream_credential_headers also only knew the configured client side
auth header and the x-mcp- prefix family, so a header name declared in
mcp_servers.<name>.extra_headers reached logging metadata in cleartext.
Those names are admin chosen, so no prefix rule can recognize them; read
them off the server registry instead. The header is still forwarded
upstream, which is what extra_headers is for. authorization is left out
because clean_headers already strips it and claiming it here would move
authenticated_with_header on the oauth passthrough config.

The Responses bridge tests stub the server manager, so their fakes gain
the registry accessor the sanitizer now reads.

* fix(mcp): drop caller host from the sanitized header mapping too

The synthetic request stopped forwarding host, but the parallel sanitizer
did not, so a forged hostname still reached the guardrail payload and the
list_tools spend row. Drop it there as well.

Exempt the configured identity headers from the upstream credential set.
get_user_from_headers resolves end user attribution off the same request
this module reconstructs, and it only fills end_user_id when auth left it
unset, so claiming user_header_name or a user_header_mappings name would
lose attribution on the MCP paths that authenticate upstream.

Drop the isinstance guard on extra_headers entries: the field is typed
list[str], so the check is dead and basedpyright scores it.

* fix(mcp): accept a bare user_header_mappings entry when exempting identity headers

get_internal_user_header_from_mapping and get_customer_user_header_from_mapping
both normalize a single mapping to a one element list, and config_settings.md
documents the key as a dict. Iterating the bare form yields its keys instead,
so the exemption silently matched nothing and an identity header also named in
an MCP server's extra_headers was dropped after all.
2026-08-14 17:21:07 -07:00
mateo-berri
ff547be3e3 fix(cost-tracking): count dict-shaped web_search_call output items 2026-08-14 17:19:37 -07:00
mateo-berri
f2a10f6331 merge: litellm_internal_staging into litellm_vertex_batch_embeddings_translation 2026-08-14 17:17:16 -07:00
mateo-berri
e8c1fe8b11 fix(bedrock): fall back to the batch deployment model for unmapped record models 2026-08-14 17:11:24 -07:00