Commit graph

47406 commits

Author SHA1 Message Date
mateo-berri
63f5de12ae chore(techdebt): ratchet lint budgets to the merged tree 2026-09-02 16:25:58 -07:00
mateo-berri
683fc34044 fix(azure_ai): let the caller's output_config from extra_body win over the legacy thinking upgrade 2026-09-02 16:23:52 -07:00
mateo-berri
81481bea95 chore(lint): ratchet down Any and strict-typing budgets 2026-09-02 23:21:19 +00:00
mateo-berri
8c646a916c feat(cli): pre-fill the SSO verification code in the browser when the proxy allows it 2026-09-02 16:19:17 -07:00
moe-berri
f5721ff6f0 test(router): cover Claude session multi-hop fallbacks 2026-09-02 16:17:35 -07:00
mateo-berri
ddc2582374 fix(vector-store): build the Router executor from the router kwarg and gate the SDK fallback on explicit config 2026-09-02 16:15:20 -07:00
Mateo Wang
3c6b0705b2
Merge pull request #39420 from BerriAI/litellm_bedrock_kb_fake_router_kwarg
test(bedrock): accept the router kwarg in the knowledge base search fake
2026-09-02 16:13:47 -07:00
mateo-berri
1a1d459701 fix(xai): keep streamed and custom-priced billing inside the cost calculator
Restate xAI's usage.cost_in_usd_ticks as usage.cost on chat and responses
replies, streamed ones included, then let the cost calculator own the
figure: a deployment with its own input_cost_per_token and
output_cost_per_token keeps that price, cost margins apply on chat streams
as they already did on non-streamed calls, and only OpenRouter's usage
cost becomes the llm_provider-x-litellm-response-cost header, so xAI
streams no longer skip the calculator through the header or the
stream_chunk_builder hidden response_cost.
2026-09-02 16:13:31 -07:00
mateo-berri
459858829e refactor(typing): replace Any with proven types in 89 more backend files 2026-09-02 23:08:42 +00:00
Yassin Kortam
bc2370f3fd
test(proxy): verify NO_DOCS/NO_REDOC/NO_OPENAPI restrict every doc surface (#39378)
* test(proxy): verify NO_DOCS/NO_REDOC/NO_OPENAPI gate every doc surface

Confirms /docs, /redoc and /openapi.json are reachable by default and
each 404 with no schema in the body when NO_DOCS/NO_REDOC/NO_OPENAPI are
set, and that disabling them does not affect other routes.

* test(proxy): pin the production docs_url construction to the real helpers

Addresses Greptile 4/5 feedback: the disabled-path tests built a fresh
FastAPI() app, which could miss drift in the actual
FastAPI(docs_url=..., ...) call in proxy_server.py. This pins that
exact call site against _get_docs_url/_get_redoc_url/_get_openapi_url.
2026-09-02 16:06:04 -07:00
mateo-berri
fe34124610 feat(azure_ai): add grok-4.6 to the model cost map 2026-09-02 16:03:45 -07:00
mateo-berri
8e26d13fa0 test(bedrock): type the router parameter on the knowledge base search fake 2026-09-02 16:03:39 -07:00
moe-berri
1306a4505a fix(router): preserve bound router fallbacks for subagents 2026-09-02 16:01:15 -07:00
mateo-berri
b327437d47 Merge branch 'litellm_internal_staging' of https://github.com/BerriAI/litellm into litellm_fix_guardrail_event_hook_resync
# Conflicts:
#	litellm/proxy/guardrails/guardrail_registry.py
2026-09-02 15:55:04 -07:00
Yuneng Jiang
2bce27cfa6
docs(e2e): describe the dedicated, least-privilege, capped credentials behind the pull request check 2026-09-02 15:52:42 -07:00
ishaan-berri
4c51ca72d6
test: add interactive Rust Python parity harness (#39419)
* test: add interactive Rust Python parity harness

* test: simplify Rust Python parity harness structure

* test: show parity confidence by SDK section

---------

Co-authored-by: yuneng-jiang <yuneng@berri.ai>
2026-09-02 15:51:08 -07:00
Yuneng Jiang
c62643f0cf
ci(e2e): drop trailing newlines from fetched secret values before writing the env 2026-09-02 15:39:21 -07:00
moe-berri
ed0d3f9442 fix(router): fail open on session binding reads 2026-09-02 15:38:32 -07:00
Devin AI
6265437592 chore(techdebt): avoid new mutable literal in gigachat tool conversion
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 22:35:02 +00:00
Devin AI
0ff6f566ec Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_techdebt_20260901
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 22:34:53 +00:00
mateo-berri
979c3cb1aa fix(proxy-extras): retry when the advisory lock wait times out behind a concurrent migrate deploy 2026-09-02 15:29:10 -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
b6b5b31ce4 test(bedrock): accept the router kwarg in the knowledge base search fake 2026-09-02 15:25:05 -07:00
mateo-berri
7cbc74399d fix(responses): accept pydantic tool objects returned by guardrails 2026-09-02 15:24:43 -07:00
mateo-berri
61ae06d4d9 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_vector_store_request_embedding_resolution 2026-09-02 15:24:21 -07:00
Yassin Kortam
6c5fb0ef6f
fix(proxy): build coordination Redis from REDIS_* env vars unconditionally (#39410)
Coordination Redis (spend counters, budget-window enforcement, and the
reset_spend cache-eviction broadcast) previously only attached when a
deployment set general_settings.coordination_redis or
litellm_settings.cache. Bare REDIS_HOST/REDIS_PORT env vars alone did
nothing, so a multi-replica proxy with no cache block got no cross-pod
coordination at all: a key reset on one pod never cleared another
pod's stale budget enforcement.

The inferred Redis is pinged before being adopted, and a malformed
REDIS_CLUSTER_NODES/REDIS_SENTINEL_NODES value is tolerated too: env
vars can be set for an unrelated reason with nothing reachable there,
and guessing wrong must not turn a previously harmless in-memory-only
proxy into one that fails to boot or raises on its next cache write.
2026-09-02 15:21:15 -07:00
yujonglee
0c0b432cf1
refactor(rust): move audio transcription into core (#39126) 2026-09-02 15:20:54 -07:00
Mateo Wang
2d3e4d6eff
Merge pull request #39417 from BerriAI/litellm_muse_spark_1_3
feat(model_prices): add meta/muse-spark-1.3 and its contributor tier
2026-09-02 15:18:05 -07:00
Devin AI
e3f61ce134 chore(techdebt): refresh lint budgets after staging merge
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 22:13:23 +00:00
yucheng-berri
b4f5b6aa94
fix(logging): redact credential query params from the uvicorn access log (#39293)
* fix(logging): redact credential query params from the uvicorn access log

Raw virtual keys reached container stdout two ways:

- `GET /key/info?key=sk-...`, `/global/spend/report?api_key=sk-...`,
  `/key/spend/report`, `/spend/logs`, `/user/daily/activity` and the Gemini
  passthrough routes all put the credential in the request target, and
  `uvicorn.access` had no redaction filter (only `uvicorn.error` did).
- the key budget error interpolates `LiteLLM_VerificationToken.key_name`,
  a column with no enforced shape, into a message that is both logged and
  returned to the caller.

`SecretRedactionFilter` cannot be reused on an access logger: it collapses the
record into `record.msg` and clears `record.args`, and uvicorn's AccessFormatter
unpacks those args at emit time, so every access line would raise TypeError.
`AccessLogRedactionFilter` scrubs the positional args in place instead.

An access line is the one input to the secret regex an unauthenticated caller
controls end to end, so two bounds go with it. The request target is cut back to
a whole query parameter under 512 characters before it is scanned, since a half
parameter is too short to match its own pattern and would be logged raw, and the
dropped tail is not logged at all. The connection-string pattern is bounded too,
because its user half could previously re-scan the rest of the string from every
`://`: a 16 KB URL of `a://` pairs took 314s and now takes 0.12s, with the caps
set high enough that an RDS IAM auth token used as a DSN password still redacts.

Credential query params are terminated by `&` like the existing `key=` and
`sig=` patterns, so redacting one param no longer swallows the rest of the
request line, and a second credential in the same query string is now redacted
on its own instead of surviving once the first one stops the span. `key_name` is
echoed into the budget error only when it still has the masked `sk-...abcd`
shape `abbreviate_api_key` writes, so a value put there by a direct DB write or
a migration falls back to the key alias.

Also point the `/key/info` and spend-report examples at the sha256 hash both
endpoints already accept, so callers stop putting raw keys in URLs that
third-party access logs record.

Resolves LIT-5909

* test(logging): assert on emitted access lines instead of filter registration

The two registration tests checked that an AccessLogRedactionFilter instance
sits in uvicorn.access.filters, which is the shape of the code rather than its
behavior. Handing the logger a real access record and reading what a handler
wrote covers the same wiring and still fails when the registration is removed.

* fix(logging): redact percent-encoded credentials from access logs

?k%65y=sk%2D... is a working credential once the request parser decodes it,
but the redaction patterns match literal text and never see it. Decode the
request target as a detector and drop the query when decoding reveals a
secret. The decoded text is never logged back, so a %0A cannot forge a
following log line

Also accept any four non-space characters in the masked key_name check, since
abbreviate_api_key copies the last four characters of a custom key verbatim
and those can be punctuation or non-ASCII

* fix(auth): keep control codes out of the masked key label

/key/generate accepts a custom key ending in an escape sequence, and
abbreviate_api_key copies those four characters into key_name verbatim, so
the over-budget message carried them to a terminal and a log viewer. Bar
whitespace and C0/C1 control codes from the four, and keep everything else
2026-09-02 15:10:36 -07:00
devin-ai-integration[bot]
a76cb6feaf
feat(mcp): semantic tool search for the native MCP Gateway (#39404)
The mcp_tool_search virtual tool only did substring token matching, so a native MCP client asking for "FX" could not find a tool described as "foreign exchange rates" even though the same catalog is ranked by embeddings on /responses and /chat/completions.

Adds litellm_settings.mcp_tool_search (embedding_model, top_k, similarity_threshold, core_tools). With an embedding model the caller's authorized catalog from _list_mcp_tools is ranked by cosine similarity of name plus description; configured core tools the caller can reach come first and do not consume top_k. Without an embedding model the keyword fallback keeps the old behavior. Settings are hot-reloadable from the DB, exposed on /get and /update mcp_tool_search_settings, and editable from the Admin UI under MCP Servers > Tool Search. The embedding index is shared with agent_search via a new SemanticTextIndex.

Resolves LIT-6751

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 15:09:44 -07:00
Devin AI
6ca4e1c681 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_techdebt_20260901
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 22:09:07 +00:00
devin-ai-integration[bot]
a701effbad
refactor(utils): remove the dead get_api_key provider-key resolver (#39260)
get_api_key had no callers. main.py imported it without using it, and
because main.py declares no __all__, the star import in __init__.py
published it as litellm.get_api_key. It duplicated key resolution that
get_llm_provider_logic already performs, which is how a misspelled env
var survived in it unnoticed until #35985. Drop the definition, the
unused import, the test that pinned the ai21 branch, and ratchet the
lint budgets down by the violations it carried.

Resolves LIT-5245

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 15:06:36 -07:00
devin-ai-integration[bot]
748c2026d7
fix(proxy): word database 503s by whether the fault is transient (#39256)
Permanent Prisma/query-engine faults keep the 503 status and no_db_connection type but stop claiming the database is temporarily unreachable. A permanent fault anywhere in the exception chain outranks the transport error that surfaced it. MCP bridge and DCR flows gain a faulted resolution state with matching wording. Resolves LIT-5208

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 15:05:55 -07:00
devin-ai-integration[bot]
346813b374
fix(proxy/db): keep prisma predicates from raising TypeError under a mocked prisma module (#39253)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 15:05:37 -07:00
mateo
6fa02887c4 feat(model_prices): add meta/muse-spark-1.3 and its contributor tier
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 22:05:17 +00:00
Mateo Wang
eac2c54141
Merge pull request #39241 from BerriAI/litellm_fix_gateway_injection_scope
fix(spend): keep every-deployment scope on gateway cache-injection marks
2026-09-02 15:02:47 -07:00
Yujong Lee
1988dfc4cc fix: qualify list annotations for Python 3.14 runtime inspection 2026-09-02 15:02:04 -07:00
Yuneng Jiang
743f94f82a
ci(e2e): fail when nothing collects and ignore lanes with their own checks in the smoke trigger 2026-09-02 14:59:15 -07:00
mateo-berri
cdf8383d9e Merge branch 'litellm_internal_staging' of https://github.com/BerriAI/litellm into litellm_fix_mcp_oauth_tool_fetch_auth
# Conflicts:
#	litellm/proxy/_experimental/mcp_server/rest_endpoints.py
2026-09-02 14:58:08 -07:00
mateo-berri
52f34ff553 fix(guardrails): rebuild the serving worker guardrail on PUT instead of patching it in place
update_in_memory_guardrail now goes through reinitialize_guardrail, the same
delete-and-construct path the DB poller and PATCH already use, whenever the
row name or litellm_params changed. Patching raw DB values over constructor
derived state clobbered normalized URLs, derived api_base values, and resolved
secrets, which 500d the serving worker in the earlier revision. An unchanged
config only refreshes the cached row, and a row the constructor rejects keeps
the previous instance enforcing and raises
2026-09-02 14:58:01 -07:00
Yuneng Jiang
b348ed7f09
ci(e2e): only tail stack logs when the stack actually booted 2026-09-02 14:56:52 -07:00
Yuneng Jiang
cfe247ebfe
fix(vector_stores): translate the two MongoDB driver errors that still reached callers as 500s
A connection string whose password holds an unescaped '/' makes pymongo's URI
parser raise a plain ValueError, not a PyMongoError, and a URI with no
credentials at all makes Atlas close the connection, which surfaces as
AutoReconnect. Neither was handled, so both fell through to litellm's generic
wrapper and were served as 500s with a traceback for what are routine typos.
Both now return a 400 naming the cause. The ConnectionFailure branch sits after
the ServerSelectionTimeoutError and NetworkTimeout branches, which subclass it,
and two ordering tests pin that.
2026-09-02 14:55:13 -07:00
mateo-berri
856cce636a Merge branch 'litellm_internal_staging' of https://github.com/BerriAI/litellm into litellm_fix_gateway_injection_scope
# Conflicts:
#	tests/e2e/test_junit_properties.py
2026-09-02 14:54:30 -07:00
Yuneng Jiang
4a646dd9a0
ci(e2e): run a PR's changed e2e tests three times behind a human-approved environment
Adds a required-check candidate that selects the tests/e2e test files a PR added or
modified, boots a stage-mirror stack on the runner (migrations, backend, two gateway
processes behind nginx, Postgres, Jaeger, TLS cluster Valkey), and runs those files
three times with retries off. The run job sits behind the e2e-changed GitHub
environment, so a reviewer approves each run before the OIDC token that reads the
provider keys from AWS Secrets Manager exists. Supersedes #34981
2026-09-02 14:53:40 -07:00
mateo-berri
b16b2a8691 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_converse_legacy_thinking_adaptive 2026-09-02 14:49:56 -07:00
Devin AI
1d40202a4e fix(databricks): keep new helpers within the type discipline budget
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 21:48:25 +00:00
Yujong Lee
cfb0b59e34 fix: use typing backport in general upload validation 2026-09-02 14:44:13 -07:00
Devin AI
518506834a fix(databricks): drop assistant turns left empty after stripping thinking_blocks
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-02 21:43:22 +00:00
Mateo Wang
86ca146ea2
Merge pull request #39271 from BerriAI/litellm_fix_presidio_sibling_callback_leak
fix(guardrails): track and tear down presidio sibling callbacks on delete and update
2026-09-02 14:39:47 -07:00