Commit graph

14297 commits

Author SHA1 Message Date
Mateo Wang
435433fa07
Merge pull request #39149 from BerriAI/litellm_qwencloud_provider_aliases
feat(dashscope): add QwenCloud and Qwen AI Platform provider aliases
2026-09-01 12:18:05 -07:00
yuneng-jiang
33004d2f0c
test(e2e/ui): cover the Budgets page create, edit and delete flows (#39052)
* test(e2e/ui): cover the Budgets page create, edit and delete flows

The Budgets page had no browser coverage at all, so an admin creating or
editing a spend cap through the UI was only exercised by hand at RC time.

Each test reads the budget back from /budget/list, a different route from
the one the table renders, so a row that only exists in the table's cache
does not pass. The edit test pins the rate limits an unrelated spend-cap
edit has no business touching.

* test(e2e/ui): trim comments that restate the test steps

Review flagged the explanatory comments as restating ordinary setup rather
than explaining anything. Keeps the two that carry the regression rationale
for an assertion and drops the rest.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-09-01 12:17:02 -07:00
Mateo Wang
f3dbd253be
Merge pull request #38106 from Timik232/bugfix/streaming-stable-response-id
fix(streaming): keep response id stable across streamed chunks
2026-09-01 12:11:32 -07:00
yuneng-jiang
2b1bd20834
Merge pull request #31125 from BerriAI/litellm_/stoic-jones-7de871
feat(proxy): default to the v2 migration resolver, keep v1 as an opt-out
2026-09-01 11:46:13 -07:00
Mateo Wang
caeb5d181e
Merge pull request #39074 from BerriAI/litellm_fix_websearch_tool_selection_test
test(websearch): register configured search tool in pre-request hook test
2026-09-01 11:45:29 -07:00
mateo-berri
24393be4a6 Merge branch 'litellm_internal_staging' into bugfix/streaming-stable-response-id 2026-09-01 11:45:27 -07:00
mateo-berri
f3792fb700 feat(dashscope): add qwencloud and qwen_ai_platform provider aliases 2026-09-01 11:20:36 -07:00
Yuneng Jiang
201f60d19c
revert: restore search tool fallback when no router is configured
This reverts commit 65a46a5f32 (#38113)

That change made two edits that combine into a hard failure for SDK
users. It dropped the null-router guard in
_select_search_tool_from_router, so a missing router now yields an empty
search_tools list instead of returning early, and it turned the no-match
case in _select_search_tool_from_list from a debug-logged fallback into
a raised ValueError. It also added a call site in
async_pre_call_deployment_hook that invokes the selection purely for the
side effect of raising, discarding the return value

Used together, any SDK caller that sets search_tool_name and sends a web
search tool now raises "Configured search tool '<name>' was not found"
on every request. There is no way to satisfy the check off the proxy,
because search_tools is only ever populated from the proxy router, so
the SDK path cannot register one

tests/pass_through_unit_tests/test_websearch_interception_e2e.py caught
this, but #38113 only updated the handler unit tests, so the break
landed on staging

Reverting restores the previous behavior while we work out a fix that
keeps the stricter validation on the proxy path, where a silently
substituted search provider is the real problem worth rejecting, without
turning the SDK path into an unconditional error
2026-09-01 11:16:23 -07:00
Mateo Wang
ef7a984fbb
Merge pull request #38990 from BerriAI/devin_ai_1788201394-veo31-pricing-tiers
fix(registry): veo 3.1 pricing tiers + roll up open registry PRs (glm-5.2, Qwen3.8-Flash, gemma-4-31b, scribe_v2, fireworks/databricks deepseek v4) + deprecation dates
2026-09-01 10:32:59 -07:00
Mateo Wang
25b11301b2
Merge pull request #38891 from BerriAI/litellm_deflake_20260830
test: deflake MCP registry state, savings cost map, and MCP identity env reload tests
2026-09-01 10:15:29 -07:00
mateo-berri
06d4521fc0 fix(registry): add vertex veo 3.1 resolution tier pricing per vertex pricing page 2026-09-01 10:15:18 -07:00
Mateo Wang
6661e915a5
Merge pull request #38774 from BerriAI/litellm_fix_openai_embedding_encoding_format_omit
fix(embeddings): omit encoding_format when the client omits it on OpenAI-compatible calls
2026-09-01 10:13:38 -07:00
Mateo Wang
cfd9d27be2
Merge pull request #39038 from BerriAI/litellm_fix_pipeline_guardrail_list_clobber
fix(policy_engine): restore request guardrails list after pipeline allow
2026-09-01 10:13:30 -07:00
Mateo Wang
b86791b4b9
Merge pull request #38985 from BerriAI/litellm_fix_ocr_annotation_page_cost
fix(cost): bill OCR annotation pages via annotation_cost_per_page
2026-09-01 10:13:01 -07:00
Mateo Wang
30bf592aaf
Merge pull request #35417 from BerriAI/litellm_fix_responses_bridge_tool_call_arguments_json
fix(responses): json-encode object tool call arguments in the chat completions bridge
2026-09-01 10:08:12 -07:00
ryan-crabbe-berri
190b8c7d8e test(e2e): drop coverage registry cell for the alias-grant test 2026-09-01 09:03:47 -07:00
ryan-crabbe-berri
4118db5a50 test: drop litellm-internal patches from the cross-region alias test (TQ008)
The pure helpers express the same regression: the save-side drop must
leave the alias in place, and two registries must expand it to their
own ids. The full validate path is already covered by the
persists-verbatim test and the live e2e test.
2026-09-01 08:23:26 -07:00
ryan-crabbe-berri
7a761ccf5a test(e2e): cover alias MCP grant persisting verbatim on key generate
A single-instance run cannot reproduce the two-region setup, but the
regression is fully visible in one: the alias must survive to /key/info
unrewritten, and the alias-granted key must still list the server's
tools. The broken write path stored the resolved server id instead.
2026-09-01 08:10:41 -07:00
ryan-crabbe-berri
0d7035989c fix(mcp): persist alias MCP grants verbatim instead of rewriting to local server ids
Since PR #29128, key create/update/regenerate resolved every
object_permission.mcp_servers entry against the saving instance's
DB + config registry and persisted the resolved server ids. For
config-loaded servers the id is derived from a hash of the regional
URL, so in a shared-database multi-region deployment the rewrite baked
one region's ids into the row and every other region denied the key.
Grants written before v1.88.0 kept the raw alias and kept working,
which is why only newly provisioned keys broke.

Keep the validation and the stale-entry drop (the LIT-3278 fix), but
persist the caller's original identifiers for everything that resolves.
Read-time expand_permission_list already maps a name to each region's
local server id.
2026-09-01 08:10:36 -07:00
Devin AI
9a1aebc146 fix(registry): declare databricks deepseek cache-write rate at the input rate per repo convention
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 13:50:21 +00:00
Devin AI
7bfa0d7fb4 Registry audit: Fireworks DeepSeek V4 Flash 0731 pricing, Databricks DeepSeek V4 entries, provider deprecation dates
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 13:15:22 +00:00
Devin AI
5f44bdd1c1 test: trim mcp fixture docstring and reload comment
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 11:06:08 +00:00
Devin AI
95c7ca8801 fix(tests): restore module attributes after reload in mcp identity env tests
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 10:59:08 +00:00
Devin AI
2019c309ea merge: absorb litellm_internal_staging; drop python duplicate-issues closer fix superseded by ts rewrite
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-01 09:18:31 +00:00
Mateo Wang
ec3f8183c3
Merge pull request #39066 from BerriAI/litellm_aws_external_id_files_batches
fix(bedrock): forward aws_external_id in files and batches credential loading
2026-08-31 23:31:29 -07:00
Mateo Wang
9f6024bf97
Merge pull request #39044 from BerriAI/litellm_fix_bedrock_guardrail_token_log
fix(bedrock): mask signed request headers in guardrail debug log
2026-08-31 23:30:14 -07:00
Yassin Kortam
b11f0bcb92
fix(proxy): include litellm_model_table in GET /v2/team/list (#39045)
* fix(proxy): include litellm_model_table in GET /v2/team/list

GET /v2/team/list built its find_many queries without joining the
LiteLLM_ModelTable relation, so litellm_model_table (and the
model_aliases it carries) always read back as null there, same bug
class as GH #26312 which PR #33047 fixed on /team/info and /team/list
but never touched this endpoint.

* fix(test): assert observable output, not mock calls, in v2 team list test

The test-quality gate flagged the regression test for asserting on
find_many's call args instead of what the caller gets back. Rewritten
so the fake find_many only attaches litellm_model_table when its own
include kwarg asks for it, so the assertions are on the response.

* fix(proxy): drop invalid litellm_model_table include on deleted-team query

Greptile caught that LiteLLM_DeletedTeamTable has no litellm_model_table
relation in the Prisma schema, so passing that include on the deleted-team
find_many raised UnknownRelationalFieldError against a real database on
every GET /v2/team/list?status=deleted call. Confirmed live against
Postgres. Scope the fix to the active-team branch only, where the relation
exists; update the test to reflect that and assert the deleted branch no
longer requests it.
2026-08-31 23:19:45 -07:00
yuneng-jiang
635a8ad308
Merge pull request #39073 from BerriAI/litellm_e2e_stored_credential_poll
test(e2e-ui): poll credential availability before Test Connect to deflake multi-instance runs
2026-08-31 23:07:34 -07:00
Mateo Wang
d83d9645fe
Merge pull request #39065 from BerriAI/litellm_fix_openai_alias_reasoning_effort
fix(openai): forward reasoning_effort for unknown model aliases instead of failing closed
2026-08-31 22:56:38 -07:00
Mateo Wang
b35aa7d2d9
Merge pull request #38796 from BerriAI/litellm_decrease_anys_opus5_r2
chore(typing): clear 1.1k basedpyright Any errors across 53 backend files
2026-08-31 22:56:35 -07:00
Yuneng Jiang
a48953a0a8
test(e2e-ui): require consecutive credential probe successes to cover multi-replica routing 2026-08-31 22:37:35 -07:00
mateo-berri
f65bee6d74 test(websearch): carry a reasoned test-quality suppression on the router patch 2026-08-31 22:32:05 -07:00
yuneng-jiang
c78f405473
Merge pull request #39051 from BerriAI/litellm_/non-admin-key-type-change-e76bec
fix(key_management): allow non-admin key_type preset transitions on /key/update
2026-08-31 22:24:29 -07:00
mateo-berri
191313e756 test(websearch): register configured search tool in pre-request hook test
PR #38113 made a configured search_tool_name fail fast when the router
does not carry a matching search tool, which broke
test_pre_request_hook_modifies_request_body: it names test-search-tool
but never registers it. Stub the proxy router with that tool so the test
exercises the conversion path again.
2026-08-31 22:22:05 -07:00
Yuneng Jiang
fae5aabc5c
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/jovial-archimedes-1d743b 2026-08-31 22:21:35 -07:00
Yuneng Jiang
88501a074d
test(e2e-ui): poll credential availability before Test Connect to deflake multi-instance runs 2026-08-31 22:20:36 -07:00
yuneng-jiang
174acf90c1
Merge pull request #39025 from BerriAI/litellm_/jovial-archimedes-1d743b
test(e2e/ui): automate 8 manual QA checklist flows
2026-08-31 22:13:07 -07:00
Yuneng Jiang
81c48f810e
fix(key_management): keep read-only keys read-only in non-admin preset transitions
A non-admin could widen a read-only (info_routes) key to llm_api or full
access through the preset carve-out. Read-only keys now stay read-only
unless a proxy admin widens them; the other preset transitions, including
the LIT-4891 llm_api to full access switch, still work. Also converts the
transition tests to assert on a returned outcome so the no-403 cases
carry real assertions.
2026-08-31 22:09:21 -07:00
yuneng-jiang
aabfbd6e37
Merge pull request #39055 from BerriAI/litellm_e2e_drop_unsafe_mgmt_registry_cells
test(e2e): drop the two mgmt registry cells no shared-proxy test can cover
2026-08-31 21:48:27 -07:00
mateo-berri
0a9676bd4f fix(openai): scope unknown-model reasoning_effort forwarding to the plain openai provider 2026-08-31 21:42:31 -07:00
Mateo Wang
d22a3e847d
Merge pull request #38868 from BerriAI/litellm_fix_gemini_tts_container
fix(speech): honor pcm/wav response_format for Gemini TTS and reject unsupported containers
2026-08-31 21:31:34 -07:00
tin-berri
bfea8a8c19
feat(shadow_eval): compare several auto-routers on one job's sampled traffic (#39028) 2026-08-31 21:31:08 -07:00
George Pickett
65a46a5f32
fix(websearch): reject invalid explicit search tool selections (#38113)
* fix(websearch): reject invalid explicit search tool selections

* refactor(websearch): simplify explicit search tool validation
2026-09-01 00:28:45 -04:00
mateo-berri
60b24abd3e test(bedrock): capture s3 client kwargs from the boto3 mock instead of a mutable dict 2026-08-31 21:26:10 -07:00
ryan-crabbe-berri
fa720be1f4
Merge pull request #37044 from Thijmen/key-budget-window-usage
feat(key management): show budget window usage on /key/info
2026-08-31 21:18:46 -07:00
mateo-berri
76839ca9d8 fix(bedrock): forward aws_external_id in files and batches credential loading 2026-08-31 21:18:36 -07:00
mateo-berri
a03378f6d1 fix(openai): forward reasoning_effort for unknown model aliases instead of failing closed 2026-08-31 21:14:54 -07:00
ryan-crabbe-berri
760b864e43 refactor(key): trim budget_limits_usage entries to current_spend
max_budget and reset_at already live on the matching budget_limits entry, so
repeating them (as budget_limit and reset_at) only invited confusion about which
copy is authoritative.
2026-08-31 21:11:15 -07:00
mateo-berri
be84f0d7e5 Merge branch 'litellm_internal_staging' of https://github.com/BerriAI/litellm into litellm_fix_gemini_tts_container 2026-08-31 21:02:56 -07:00
Kolade Fajimi
d1320404fe
fix(redis): coerce env var string types and fix param discovery through decorator wrappers (#30644)
* fix(redis): coerce env var string types and fix param discovery through decorator wrappers

inspect.getfullargspec doesn't work on redis.Redis/redis.RedisCluster because
their __init__ is wrapped by @deprecated_args, which replaces the explicit
signature with *args/**kwargs internally. getfullargspec returns an empty arg
list, so _get_redis_kwargs and _get_redis_cluster_kwargs silently dropped every
real constructor parameter not in their hand-picked include_args set --
cluster_error_retry_attempts and connection_error_retry_attempts among them, so
an operator's configured retry bound never reached the Redis Cluster client and
it fell back to redis-py's own default instead.

Rebased onto litellm_internal_staging, which had independently added
_init_arg_names (MRO-walking, inspect.unwrap-based) for the same class of bug
in _get_redis_url_kwargs. Reused that pattern (as _unwrapped_init_args, without
the MRO walk: redis.Redis/RedisCluster declare every real parameter directly on
their own __init__, and MRO-walking breaks the tests here that mock the class
with autospec=True, since inspect.getmro needs a real __mro__) rather than
introducing a second, differently-shaped fix for the same problem.
_get_redis_cluster_kwargs now also honors its own client argument instead of
ignoring it, so the async cluster client's own extra constructor kwargs
(cluster_error_retry_attempts, connection_error_retry_attempts,
decode_responses, ...) are no longer filtered out by introspecting the sync
class regardless of which client is actually built.

Also fixes environment variables and Helm --set values always arriving as
strings: redis-py 8.x changed health_check_interval's arithmetic to require a
real number, so a stringified value raised TypeError on every Redis operation
instead of connecting. _coerce_redis_kwargs_types coerces to each parameter's
declared type at the end of _get_redis_client_logic, with an explicit type
table for max_connections/socket_timeout/socket_connect_timeout since redis-py
8.x changed the timeout defaults from None to int 5, which would otherwise
make a fractional value fail int() and get dropped.

Co-authored-by: mangabits <1457532+mangabits@users.noreply.github.com>

* ci: verify redis-py client version compatibility across a version matrix

* test(redis): assert an async-only cluster kwarg every matrix version declares

connection_error_retry_attempts is on the async cluster constructor in redis-py
5.x only; 6.0 removed it in favor of retry. The 6.4.0, 7.4.1 and 8.0.1 legs were
failing on that missing parameter name rather than on the behavior under test,
while the allow-list itself was doing the right thing on all four versions.

decode_responses is async-cluster-only on every version the matrix covers, so it
stands in for the same property: the sync cluster class takes it through **kwargs
and never names it in its signature. Reverting _get_redis_cluster_kwargs to ignore
its client argument still fails both tests on 5.3.1 and 8.0.1.

test_async_cluster_passes_async_only_kwargs now builds the real async cluster
client and reads connection_kwargs off it, so it no longer needs a patched class
factory; the constructor does no I/O. The retry-attempts test keeps its patch,
since redis-py >= 6 stores no cluster_error_retry_attempts attribute on the built
client and the constructor call is the only place the forwarded value shows up.

The _get_redis_cluster_kwargs docstring cited the same two parameters as its
examples of async-only kwargs, which is what made the test look reasonable;
cluster_error_retry_attempts is on both classes and connection_error_retry_attempts
is gone from 6.0 on, so it now names decode_responses instead.

* test(redis): drop internal patches from the kwarg coercion tests

The test-quality gate flagged the new patch() calls on litellm internals these
tests added. Three of them faked litellm._redis.inspect.signature with a MagicMock
to hand _coerce_redis_kwargs_types a synthetic parameter; that function already
takes a client argument, so they pass stub functions instead, matching the
_redis_signature_8x idiom the file uses elsewhere. The fourth patched
_redis_kwargs_from_environment to {} to prove _get_redis_client_logic raises
without a host or url, which clearing the real env keys through
_get_redis_env_kwarg_mapping does without pinning the test to that call.

Both files now sit one TQ008 below the merge base rather than six above it.

* fix(redis): keep the sync client construction inside the basedpyright budget

_get_redis_client_logic now returns dict[str, object] rather than an untyped
dict, which is the honest type for operator-supplied config, but it turns the
33 reportUnknownArgumentType errors at redis.Redis(**redis_kwargs) into 33
reportArgumentType errors plus one reportCallIssue, both over their budget.
No static type fits: redis-py's constructor declares 40-odd differently typed
parameters and the values arrive from config and env, so the allow-list and
coercion above are derived from that same signature and redis-py validates each
value itself at runtime.

The two suppressions name their exact rule and carry that reason. The file ends
up 42 basedpyright errors below the merge base, with reportArgumentType and
reportCallIssue back at the base counts of 3 and 0.

* fix(redis): coerce cluster-only and None-default bool kwargs

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

---------

Co-authored-by: mangabits <1457532+mangabits@users.noreply.github.com>
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-31 20:51:31 -07:00