Commit graph

16299 commits

Author SHA1 Message Date
Yuneng Jiang
f44d5ef101
fix(proxy): preserve model budget update compatibility 2026-09-11 22:59:46 -07:00
Yuneng Jiang
f96af80a0c
fix(proxy): persist clearing user model budgets 2026-09-11 22:49:12 -07:00
Mateo Wang
98d46ee59d
Merge pull request #40765 from BerriAI/litellm_fix_health_scoped_results_and_serialization
fix(proxy): expand access groups in /health scoping and allowlist health display fields
2026-09-11 21:21:44 -07:00
yuneng-jiang
1be89d28b8
Merge pull request #39990 from BerriAI/litellm_e2e_jwt_harness
test(e2e): reusable JWT fixtures and management lifecycle coverage
2026-09-11 21:18:59 -07:00
Mateo Wang
7ad6c628de
Merge pull request #40773 from BerriAI/litellm_e2e_memory_regression_failing_requests
test(e2e): memory regression test for failing requests on the release gate
2026-09-11 20:46:33 -07:00
mateo-berri
5ab6e0858c fix(health): resolve a model name the way a request routes before matching the provider model string 2026-09-11 20:40:00 -07:00
Mateo Wang
99e14fc2e5
Merge pull request #40798 from BerriAI/litellm_lit7523_mantle_reasoning_summary
fix(bedrock_mantle): gate reasoning.summary on the OpenAI Responses path
2026-09-11 20:30:49 -07:00
joshua-berri
70cf348aa5
Merge pull request #40791 from BerriAI/litellm_fix_mcp_root_discovery_6634
fix(mcp): use gateway authentication for root discovery
2026-09-11 20:23:10 -07:00
joshua-berri
e86adf98ac
Merge pull request #40808 from BerriAI/litellm_fix_mcp_oauth_issuer_7078
fix(mcp): match per-server OAuth metadata issuers
2026-09-11 20:23:00 -07:00
joshua-berri
108cacdd2f
Merge pull request #40790 from BerriAI/litellm_fix_mcp_discovery_cache_6585
fix(mcp): cache upstream discovery lists
2026-09-11 20:16:36 -07:00
mateo-berri
eaf3d8ad3e fix(health): target a model name the way a request for it routes
A team's copies published under the name win, then deployments named that way, then a public name only another team's deployment carries (an admin reaches it, routing does too). The endpoint resolver and the live narrowing share one rule.
2026-09-11 20:12:39 -07:00
Mateo Wang
19c8553052
Merge pull request #40820 from BerriAI/litellm_sanitize_unknown_model_error_message
fix(proxy): keep the raw model string out of the unknown-model spend-log error message
2026-09-11 19:54:34 -07:00
mateo-berri
6209f0694b fix(health): keep team public names to the owning team and let model_id win over model
A public name a team publishes its own deployment copy under now targets that copy only for a caller from that team, so an admin or another team probing the shared name gets the global deployment alone

model_id wins when paired with model: a foreign id still gets the 403, and an id no deployment carries gets the 404 of the lone-id path, before any probe runs or a result is stored under it

cache_health_check_results accepts the Mapping sequences perform_health_check returns
2026-09-11 19:49:37 -07:00
mateo-berri
9ba7ec2964 test(e2e): keep the memory regression case in a class and drop the helper docstrings 2026-09-11 19:46:06 -07:00
ryan-crabbe-berri
e65b7ff0b8
Merge pull request #40659 from BerriAI/litellm_team_member_table_search_sort_filter
feat(ui): search, sort and role filter for the team member table
2026-09-11 19:37:29 -07:00
devin-ai-integration[bot]
98f6c14a76
test(pgbouncer): stop the never-listens replacement test flaking under CI load (#40830) 2026-09-11 19:32:56 -07:00
mateo-berri
a8ffc852f2 test(e2e): trim the reliability helper docstrings to the cooldown rationale 2026-09-11 19:32:40 -07:00
mateo-berri
9375719feb Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_e2e_memory_regression_failing_requests
# Conflicts:
#	tests/e2e/CLAUDE.md
#	tests/e2e/models.py
2026-09-11 19:31:11 -07:00
mateo-berri
6a96a47e9f style(proxy): drop the docstring bullet and wrap the sanitizer test call 2026-09-11 19:29:53 -07:00
Mateo Wang
55c34951e3
Merge pull request #40609 from csoni-cweave/fix/guardrail-len-mismatch
fix(guardrails): fail closed with a named error when a Responses input rewrite cannot be applied
2026-09-11 19:22:53 -07:00
mateo-berri
3dafa7aac1 test(proxy): expect the sanitized unknown-model message in the spend-log error test 2026-09-11 19:18:10 -07:00
devin-ai-integration[bot]
b5bf09d22d
fix(db): carry DATABASE_SSLMODE/DATABASE_SSLROOTCERT into the assembled writer and reader URLs (#40815)
* fix(db): carry DATABASE_SSLMODE/DATABASE_SSLROOTCERT into the assembled writer and reader URLs

The componentized gateway supervisor starts the in-container PgBouncer from the
DATABASE_URL assembled out of the discrete DATABASE_* vars before config.yaml is
read, so an IAM URL had no way to request verified TLS: PgBouncer dialed the
server with server_tls_sslmode = prefer (no SNI, no verification) and public
RDS endpoints rejected the handshake. Two new env vars, exposed by the chart as
database.writer.sslMode / sslRootCert, are appended as libpq sslmode/sslrootcert
to every writer and reader URL the settings assemble (never to a pinned URL),
then translated for Prisma as before. Token refresh now also carries Prisma's
sslmode/sslcert/sslaccept over into the re-minted URL

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

* fix(db): keep TLS params on the CLI password URL and the initial IAM reader mint

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

* fix(db): treat DATABASE_SSLROOTCERT on its own as verify-full and cover collector and migrations TLS env

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

* test(db): type the reader mint TLS test double and drop its mutable capture

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@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-09-12 02:14:39 +00:00
devin-ai-integration[bot]
1fde15c1ec
fix(shadow-eval): skip hosted web search samples (#40827)
(cherry picked from commit a78cd2fe02)

Co-authored-by: Tin Chi Lo <tin@berri.ai>
2026-09-12 02:11:48 +00:00
devin-ai-integration[bot]
7057b2f6c4
fix(fireworks_ai): keep reasoning_content on replayed assistant messages (#40682)
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 18:47:37 -07:00
mateo-berri
e4030597d8 test(guardrails): prove the structured write-back lands CrowdStrike redactions on Responses instructions and tool items 2026-09-11 18:47:18 -07:00
Mateo Wang
eed11ba59b
Merge pull request #40812 from BerriAI/litellm_fireworks_deepseek_v4p1_flash
feat(model_prices): add DeepSeek V4.1 Flash on Fireworks
2026-09-11 18:43:00 -07:00
mateo-berri
832da2950f fix(proxy): keep the raw model string out of the unknown-model spend-log error message 2026-09-11 18:42:08 -07:00
Mateo Wang
44ce8bb1ef
Merge pull request #40769 from BerriAI/litellm_azure_realtime_ga_default
fix(realtime): dial Azure's GA realtime upstream for GA clients
2026-09-11 18:34:20 -07:00
devin-ai-integration[bot]
f84f986b4e
fix(guardrails): keep post_call guardrail info on streamed chat completions (#40806)
* fix(guardrails): sync logging_obj guardrail info on every record so post_call entries survive streamed chat completions

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

* test(guardrails): hoist regression test imports to module scope

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

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 18:16:33 -07:00
mateo-berri
105dc77109 fix(realtime): probe Azure's GA realtime upstream in health checks when no protocol is pinned 2026-09-11 18:14:21 -07:00
ryan-crabbe-berri
e72d1cfa8d
Merge pull request #40572 from dclarksymmetry/fix/spend-counter-reseed-double-count
fix(proxy): prevent spend counter double counting
2026-09-11 18:14:04 -07:00
Joshua Valluru
9d31de2f20 fix(mcp): bound discovery cache result bytes 2026-09-11 18:08:27 -07:00
ryan-crabbe-berri
50cd26cd9c
Merge pull request #40396 from jon-walton/litellm_user_budget_webhook_alerts
fix(proxy): emit internal user budget webhook alerts
2026-09-11 18:03:35 -07:00
mateo
6c07876dcf test(model_prices): use local cost map for Fireworks cost coverage
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-12 01:00:11 +00:00
Joshua Valluru
05d2c316f5 refactor(mcp): reuse in-memory discovery storage 2026-09-11 17:53:51 -07:00
mateo
115535c3ad test(model_prices): cover Fireworks DeepSeek V4.1 costs
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-12 00:49:26 +00:00
devin-ai-integration[bot]
bf146e2cac
fix(otel v2): name Langfuse traces from the langfuse_trace_name header or metadata.trace_name (#40793)
* fix(otel v2): name Langfuse traces from the langfuse_trace_name header or metadata.trace_name

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

* test(otel v2): type the named-request helper in the Langfuse logger tests

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

---------

Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 17:37:35 -07:00
mateo
6cffb31e5c feat(model_prices): add DeepSeek V4.1 Flash on Fireworks
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-12 00:36:20 +00:00
Joshua Valluru
0690520080 test(mcp): isolate static-prefix discovery UI assets 2026-09-11 17:26:35 -07:00
Yuneng Jiang
90bf2911dc
test(e2e): verify IdP readiness through real HTTP 2026-09-11 17:25:38 -07:00
devin-ai-integration[bot]
dab7f6a86a
feat(proxy): expose complexity routing headers (#40792)
(cherry picked from commit c817faec7a)

Co-authored-by: Tin <tin@berri.ai>
Co-authored-by: Claude Code <noreply@anthropic.com>
2026-09-11 17:14:40 -07:00
Yuneng Jiang
a706dbbb7d
chore: merge current staging into JWT E2E infrastructure 2026-09-11 17:13:52 -07:00
Joshua Valluru
f66239a50f test(mcp): cover static-prefix issuer discovery 2026-09-11 17:13:47 -07:00
Joshua Valluru
da61fa3564 fix(mcp): preserve existing relay discovery identifiers 2026-09-11 17:11:42 -07:00
Yuneng Jiang
77f406dc00
test(e2e): start persistent Keycloak in the changed-test runner 2026-09-11 17:09:35 -07:00
Joshua Valluru
17863fa5cf fix(mcp): match per-server OAuth metadata issuers 2026-09-11 17:05:35 -07:00
kerry-berri
8e4f2abb40
Merge pull request #40482 from BerriAI/litellm_e2e_redis_timeout
test(load): add a Redis timeout chaos load test
2026-09-11 16:58:52 -07:00
yucheng-berri
e4706fa409
fix(hide-secrets): restore credential coverage lost to the 4.5 entropy limit (#40190)
* fix(hide-secrets): restore credential coverage lost to the 4.5 entropy limit

Shannon entropy is bounded by log2(length), so the 4.5 limit #39879 shipped
cannot score any value shorter than 23 characters, and it catches a random
32-character base64 credential only about two thirds of the time. A line like
REDIS_PASSWORD=aB3dE6gH9jK2mN5p therefore reaches the provider in the clear.

Add a keyword plugin that yields the credential-shaped value assigned to a
credential-named key, reusing detect_secrets' own maintained denylist so
camelCase, snake_case and SCREAMING_CASE all work with no local word list, and
re-run the assignment-quoting transform detect_secrets skips once its first
pass has matched.

The entropy limits are untouched, so #39879's false-positive fix still holds.

* fix(hide-secrets): read the assignments in a prompt that is mostly prose

configparser aborts the whole parse on the first line it cannot read, so a
message like "Here is my config, can you review it?" followed by
REDIS_PASSWORD=... lost every assignment to that one prose line. Hand the
parser only the lines it can read, dedent the assignments inside a pasted
config, and keep each key distinct by line number so a config naming api_key
once per model keeps every value instead of only the last.

* fix(hide-secrets): drop the plugin docstrings and pin the block-scalar shapes

* fix(hide-secrets): keep a comment or an indented header from closing an open value

* fix(hide-secrets): drop the explanatory comments from the new scan helpers

* fix(hide-secrets): accept punctuation in a credential value

The value filter only allowed the URL-safe Base64 alphabet, so a password
such as hunter2!brahms or p@ssw0rd!2026 passed through unredacted while
the upstream keyword plugin had already matched it. The filter now rejects
only whitespace and brackets, which keeps function calls, subscripts and
sentences out while letting symbol-heavy passwords through.

* fix(hide-secrets): redact every credential on a line and skip timestamps and plain urls

replaces the inherited first-match scan with finditer over every keyword
match, drops iso 8601 timestamps and userinfo-free urls from credential
values, and threads the parser's open-option state through
itertools.accumulate instead of rebinding it

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

* fix(hide-secrets): scan the first token of an assignment and ignore surrounding punctuation

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

* refactor(hide-secrets): drop the unreachable configparser error fallback

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

* fix(hide-secrets): keep prose after a credential key out of the keyword detector

A bare value followed by ordinary words (secret_sauce: Worcestershire sauce)
is prose, so the synthetic assignment is only built when the value stands
alone or is followed by a shell operator, comment, or another assignment

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

* fix(hide-secrets): scan the first token of shell-style assignments regardless of what follows

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

* fix(hide-secrets): keep spaced assignments in scope when shell text follows the value

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

* test(hide-secrets): drop docstrings that restate the test names

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

* fix(hide-secrets): stop reading a comparison operator as a trailing assignment

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

* fix(hide-secrets): keep dashed flags as assignment trailers

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>
2026-09-11 16:49:48 -07:00
devin-ai-integration[bot]
359b7a8489
feat(rust): count tiktoken cl100k_base admission tokens in Rust (#40777)
* feat(rust): count tiktoken cl100k_base admission tokens in Rust

The Rust admission token counter only had the Anthropic tokenizer, so every
other model (OpenAI gpt-4 family, Azure, Gemini, Bedrock non-Claude, Mistral)
tokenized with tiktoken on the Python inference worker.

Add an exact cl100k_base counter to litellm-token-counter: the vendored rank
file (base64 token / rank lines, the bytes Python's tiktoken uses) is parsed
into a byte-level BPE model and the cl100k split pattern is a handwritten
scanner over the shared Unicode classes, so no regex engine runs per request.
Both tokenizers share the message, tool and reply-priming accounting.

The PyO3 TokenCounter gains a from_cl100k_ranks constructor; Python reads the
rank file and passes it in, the way claude_json_str already works. The bridge
selects the counter through the same predicates litellm.token_counter uses
(huggingface_tokenizer_kind, openai_tokenizer_encoding), declines o200k_base,
downloaded HuggingFace and custom tokenizers to Python, and budget reservation
counts once per distinct tokenizer a request names.

The legacy gpt-3.5-turbo-0301 message accounting (4 per message, -1 per name)
stays in Python: the selector declines it through the predicate token_counter
itself uses.

* feat(rust): count tiktoken o200k_base admission tokens in Rust (#40794)

Add a handwritten o200k_base split scanner and TokenCounter::from_o200k_ranks
next to the cl100k_base counter, sharing MergeRanks and the request
accounting. The Python bridge selects it when openai_tokenizer_encoding
names o200k_base, so gpt-4o, gpt-4.1, gpt-5, o1/o3/o4 and chatgpt-4o
requests stop tokenizing on the Python worker under LITELLM_RUST=true

Co-authored-by: yassin <yassin@berri.ai>

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-11 23:47:05 +00:00
Yuneng Jiang
4dd6af5722
chore: merge latest staging into JWT E2E foundation 2026-09-11 16:46:20 -07:00