Commit graph

48834 commits

Author SHA1 Message Date
devin-ai-integration[bot]
4df284e16d
fix(guardrails): record guardrail information for undecorated custom apply_guardrail overrides (#39727)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 11:39:24 -07:00
moe-berri
a0b07b4791 docs(auto-router compression): cut the explanatory comments back
The module, its routing hook and its tests carried long prose rationale where the
repository allows only concise comments for genuinely complex logic. Trimmed to the
non-obvious reasons and dropped the rest; no logic or test behaviour changes.
2026-09-05 11:33:21 -07:00
moe-berri
723bc2140f refactor(auto-router compression): resolve the policy without a loop-local rebind
The marker walk rebound a loop-local on each iteration, which is the mutation the
repository's convention exists to discourage, but a `: Final` cannot express that
inside a loop body: basedpyright rejects it outright with 'A Final variable cannot
be assigned within a loop'. A lazy generator binds the name once per item and never
rebinds it, so the first marker carrying a policy still wins and the rest are never
read.
2026-09-05 11:19:39 -07:00
moe-berri
ff942c3a74 fix(auto-router compression): surface a stored model-only policy in the edit form
The backend treats either compression key on its own as an authoritative policy, but
hydrate returned the untouched inherit state whenever the routing key was absent. A
config carrying only auto_router_model_compression was therefore invisible in the
form, and picking a routing value then overwrote the stored model hop. Only neither
key set now reads as untouched, and an absent key on either hop hydrates as no
compression for that hop rather than same-as-the-other.
2026-09-05 11:05:50 -07:00
Yuneng Jiang
88c46fb1de
test(e2e): cover Anthropic and OpenAI prompt caching, Cohere embeddings, and costed /openai chat passthrough
Four registry cells that had no e2e test. The cache_control suite gains a direct
Anthropic case (the same cache_control prefix the Bedrock and Vertex rows send)
and an OpenAI case, where caching is automatic so the prefix goes out as a plain
system string with a prompt_cache_key; both assert the second identical call
reports cache-read tokens. The shared second-call helper now takes the send
callable so the OpenAI shape fits without a second copy of the retry loop.

The embeddings suite gains a cohere/embed-v4.0 deployment that must return a
non-zero vector, and the passthrough suite gains an OpenAI-format chat through
the raw /openai/v1/chat/completions prefix that must relay a real completion and
log a costed pass_through_endpoint row whose token counts match the usage the
caller was served.
2026-09-05 10:52:46 -07:00
Yuneng Jiang
df544fcc53
test(e2e): cover key spend reset, regenerate grace period, and the llm_api_routes grant
Three deterministic proxy-only cells from the coverage registry that had no e2e
test. A key over its max_budget is reset to 0 through /key/{key}/reset_spend and
must both read back 0 on /key/info and serve traffic again. /key/regenerate with
grace_period keeps the old key valid until the period elapses and rejects it 401
afterwards. A key whose allowed_routes is the llm_api_routes group must reach
/chat/completions and /embeddings while /model/new stays 403.

KeyRegenerateBody gains grace_period and the management client gains
reset_key_spend so the tests stay on the shared typed transport.
2026-09-05 10:46:05 -07:00
Yuneng Jiang
98784360e8
test(e2e): cover Anthropic /chat/completions streaming and tool calls
Adds TestAnthropicChatCompletions to the chat completions regression suite,
registering a claude-haiku-4-5 deployment via /model/new and asserting the
streamed call delivers real content deltas and a tool-forced call returns a
well-formed get_weather tool_call on both the non-streamed and streamed paths.
Covers three P0 registry cells that had no e2e test.
2026-09-05 10:37:14 -07:00
moe-berri
1c16a5910b fix(tests): undo a stray whole-file reformat and arm a real guardrail
test_router.py is not ruff-formatted on staging and CI's format check only scopes
litellm/*.py, so running ruff format over the whole file rewrote ~900 lines of
unrelated code. That reflow split long single-line patch() calls into multi-line
form, which the test-quality gate counts individually, pushing TQ008 four over its
ceiling. The file is back to staging's formatting with only the compression test
class added.

test_common_request_processing.py armed a model-side guardrail name with no such
guardrail registered, which stopped working once both hops began requiring the name
to resolve to an active compression guardrail.
2026-09-05 10:31:56 -07:00
yuneng-jiang
7672399c26
Merge pull request #39804 from BerriAI/litellm_/e2e-wildcard-probe-and-embedding-allowlist
test(e2e): repair the wildcard readiness probe and the semantic auto-router spend assertion
2026-09-05 10:27:31 -07:00
yuneng-jiang
f753dacbbb
Merge pull request #39912 from BerriAI/litellm_/release-version-bump-d7c975
chore: bump litellm-enterprise 0.1.64 -> 0.1.65, litellm-proxy-extras 0.4.93 -> 0.4.94
2026-09-05 10:26:12 -07:00
moe-berri
d143b1954e Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_auto_router_compression_split 2026-09-05 10:19:48 -07:00
ryan-crabbe-berri
f0618394c1
Merge pull request #39680 from BerriAI/litellm_lit_4738_table_pagination
fix(ui): make Admin UI table pagination honor the selected page size
2026-09-05 10:16:56 -07:00
ryan-crabbe-berri
d885104125 chore: merge litellm_internal_staging into litellm_lit_4738_table_pagination
per_user_usage.tsx conflicted with the server pagination that already landed on
staging (default 50 rows, stale-response guard, tag and page-size resets). Took
the staging version and dropped this PR's now-redundant 25-row test for it

Claude-Session: https://claude.ai/code/session_01HkaXiD6gssHnx3kqu1rR8C
2026-09-05 10:08:11 -07:00
moe-berri
f4329d5491 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_auto_router_compression_split
# Conflicts:
#	ui/litellm-dashboard/src/components/edit_auto_router/edit_auto_router_modal.test.tsx
2026-09-05 10:06:01 -07:00
ryan-crabbe-berri
a5a846dd0c
Merge pull request #39672 from BerriAI/litellm_expose_v2_organization_patch_openapi
feat(organization): expose PATCH /v2/organization/{organization_id} in the OpenAPI spec
2026-09-05 10:05:09 -07:00
moe-berri
7bfbdf39a0
Merge pull request #39817 from BerriAI/litellm_shadow_eval_judge_output_cap
fix(shadow_eval): size the judge output cap for a judge that reasons
2026-09-05 09:59:45 -07:00
Yuneng Jiang
88985d00e2
bump: litellm-enterprise 0.1.64 -> 0.1.65, litellm-proxy-extras 0.4.93 -> 0.4.94 2026-09-05 09:58:44 -07:00
moe-berri
8284208af2 fix(auto-router compression): restrict both hops to real compression guardrails
The two policy fields are operator-supplied names and nothing else constrained them.
The routing hop calls apply_guardrail directly, which hands the guardrail the
conversation and POSTs it to whatever service backs that guardrail, and the model hop
is added to metadata["guardrails"], which runs it even when it is not default_on. So
naming an ordinary guardrail turned either hop into a way to invoke it and ship prompt
content to it. Both hops now refuse a name that does not resolve to an active
compression guardrail, and say so in the log rather than failing quietly.
2026-09-05 09:51:51 -07:00
tin-berri
d0d09e5343
feat(router): meter auto-router tier and prompt customization against the auto_router license feature (#39674)
Generalizes the heuristic_v2 ceiling from #39468 into a capability table whose
records own their in-process predicate, SQL spelling and refusal wording. The
existing heuristic_v2 capability keeps its own one-router ceiling. A single
customization capability combines operator-defined tier definitions with every
operator-written part of the classifier prompt. The prompt half only applies to
classifier types that call an LLM. The shipped default prompt, classification
rubric presets, tier-label renames and tier model choices remain ungated.

Scope every enforcement point to actual complexity routers. A model-less PATCH
or legacy update now decrypts the stored model before accepting strategy-router
settings, so a regular model cannot acquire a router config or spend a license
slot. Under the existing advisory lock, the cross-pod candidate query returns
only model scalars and the count decrypts and classifies them in process; old
non-router rows carrying a capability-shaped config no longer block a real
complexity router. The signed auto_router license feature makes both ceilings
unlimited.
2026-09-05 09:51:23 -07:00
Mateo Wang
74ebe2974c
Merge pull request #39851 from BerriAI/litellm_fix_realtime_backend_close_hang
fix(realtime): relay the upstream websocket close to the client instead of hanging
2026-09-05 09:51:15 -07:00
moe-berri
0b3687ec56 fix(shadow_eval): import Final for the test helper's annotation 2026-09-05 09:49:00 -07:00
Mateo Wang
275484fb09
Merge pull request #39856 from BerriAI/litellm_ui_lint_inline_object_budget
fix(ui): bring the inline-object lint budget back under its ceiling
2026-09-05 09:42:30 -07:00
moe-berri
00b49ccc8b fix(auto-router compression): honor the policy on the SDK path and on re-save
The router reused the model hop's compression for routing whenever both hops named
the same guardrail, on the premise that arm_pre_call had already run it. Only the
proxy calls arm_pre_call, so through the SDK nothing armed the guardrail and nothing
had compressed anything: the shortcut skipped routing compression too and served the
request with no compression on either hop. The reuse is now conditional on the model
hop actually having been armed.

The Admin UI hydrated an absent auto_router_model_compression as same-as-routing,
while the backend reads it as no model-hop compression. Opening a router configured
with only auto_router_routing_compression and saving any unrelated edit wrote the
routing guardrail onto the model hop, silently starting to compress the model call.

Both carry a regression test that fails when the fix is reverted.
2026-09-05 09:31:18 -07:00
moe-berri
03da725ee4
Apply suggestion from @greptile-apps[bot]
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-09-05 09:30:42 -07:00
mateo
528f3ae016 test(bedrock_mantle): cover gpt-oss-safeguard-20b input and output rates
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 13:46:46 +00:00
mateo
bbf51146ca fix(pricing): correct Vertex Haiku 4.5 output limit, Bedrock Mantle gpt-oss rates, add Scaleway deprecation dates
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 13:29:38 +00:00
mateo
3b191384d1 chore: merge litellm_internal_staging into rolling registry PR
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 13:28:17 +00:00
mateo-berri
344b992bed fix(ui): withhold model row actions and team edit rights from view-only admins 2026-09-05 04:05:30 -07:00
mateo-berri
2dabac186a fix(anthropic): clear the placeholder cost once and let logging price recovered tokens
Drop the second pricing pass on interrupted /v1/messages streams: clearing
the stale usage.cost and hidden response_cost is enough for the existing
success and failure logging to price the recovered usage. Add an iterator
test for the upstream-close path the proxy takes on a client disconnect.
2026-09-05 03:53:40 -07:00
mateo-berri
4706acef95 fix(passthrough): charge remote high-detail images at the high-detail upper bound 2026-09-05 03:48:06 -07:00
mateo
8a7dc64ab4 test: assert LangSmith periodic flush by observing a batch send
Replace the coroutine __qualname__ check with a functional check: queue one event, run with a short flush interval, and wait for async_send_batch to be awaited by the task init scheduled

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 10:36:15 +00:00
mateo
bd5f066c67 test: deflake two tests whose shared-state leaks failed once and passed on CI rerun
The Redis semantic cache tests wrapped the first import of litellm.caching.redis_semantic_cache in patch.dict("sys.modules", ...), which snapshots and restores all of sys.modules on exit. Every module first imported inside the block, including litellm.proxy.proxy_server, was dropped from sys.modules while staying cached as an attribute on the litellm.proxy package. The next test that patched litellm.proxy.proxy_server.<attr> hit the stale attribute while production code re-imported a fresh module, so the patch never reached it. Replace the whole-dict patch with MonkeyPatch.setitem on the two redisvl keys only

The LangSmith init test globally patched asyncio.get_running_loop while constructing the logger. Any orphaned AsyncHTTPHandler finalized by the cyclic GC during that window also called loop.create_task on the mock, tripping assert_called_once. Run the test under a real event loop and assert on the real task instead of patching asyncio

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-05 10:27:01 +00:00
mateo-berri
d992937900 fix(responses): read reasoning support from the cost map instead of model-name rules 2026-09-05 03:17:11 -07:00
mateo-berri
eb9beced71 fix(anthropic): price recovered tokens when a /v1/messages client disconnects mid-stream 2026-09-05 02:49:09 -07:00
mateo-berri
832a05458b Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_responses_reasoning_drop_params 2026-09-05 02:40:00 -07:00
mateo-berri
37722eba68 fix(realtime): close a rejected client before releasing its budget reservation
A slow or unreachable counter store made a pre-relay rejection wait behind
the reservation release before the client saw the error event and the close.
Close first and release in finally, mirroring the relay's own failure path,
so a client that already hung up still gets its reservation released.
2026-09-05 02:35:26 -07:00
mateo-berri
5a35e6d41f fix(realtime): release the budget reservation when a session is rejected before the relay starts
The three pre-relay exits of realtime_websocket_endpoint (missing model,
key/model access denied, pre-call rejection such as a rate limit or a
guardrail) returned before the finally that releases the auth-time budget
reservation, so a rejected session pinned the key at the reserved amount
until the counter TTL expired and its next requests got budget_exceeded
while /key/info showed spend 0. A single _reject_realtime_session helper
now releases the reservation before sending the error event and closing,
and release_or_invalidate_budget_reservation shields the release from a
second cancellation and logs, rather than raises, a failing invalidate
fallback so it can never mask the session's own outcome.
2026-09-05 02:18:33 -07:00
mateo-berri
6ed72693dc Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_lit_7022_azure_ai_passthrough_config 2026-09-05 02:10:00 -07:00
mateo-berri
2f981d14e4 refactor(passthrough): inject the streaming prompt-token counter instead of a default-image flag 2026-09-05 02:09:26 -07:00
mateo-berri
df6fb9e5d9 fix(azure_ai): relay from the Foundry root and log non-chat relays for spend tracking 2026-09-05 02:09:26 -07:00
mateo-berri
3f695846b3 fix(router): rewrite the passthrough model group as a whole path segment 2026-09-05 02:09:25 -07:00
mateo-berri
952f082e3e fix(test-quality-gate): keep a termination signal the parent already ignores ignored
The SIGTERM/SIGHUP teardown handlers were installed unconditionally, so a base scan started
under nohup (SIGHUP inherited as SIG_IGN) would start dying on hangups it was told to ignore.
Install them only where the disposition is still the default, and cover the ignored case with a
regression test that hangs up a scan started with SIGHUP ignored and expects it to finish.
2026-09-05 02:07:14 -07:00
mateo-berri
95d721ffe6 refactor(batches): drop docstrings restating the org fallbacks 2026-09-05 02:06:40 -07:00
Mateo Wang
c52b53706e
Merge pull request #39841 from BerriAI/litellm_gate_openai_ws_passthrough
fix(proxy): gate the OpenAI websocket passthrough behind an explicit opt-in
2026-09-05 01:51:14 -07:00
mateo-berri
2d2b5dabf2 fix(test-quality-gate): tear the base worktree down on SIGTERM and SIGHUP 2026-09-05 01:44:16 -07:00
mateo-berri
814c151b02 fix(batches): mask api base credentials on batch cost rows 2026-09-05 01:35:09 -07:00
mateo-berri
5c80e308cd Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_gate_openai_ws_passthrough 2026-09-05 01:26:47 -07:00
mateo-berri
aca1c54391 refactor(proxy): build the OpenAI websocket refusal frame from a TypedDict
The two dict literals behind the refusal event counted against the LIT002 ceiling once the base branch used up its headroom, so the frame is now a ReadOnly TypedDict built in one shot. Importing Literal explicitly also makes the UP037 suppression on the Vertex discovery signature unnecessary, so it goes.
2026-09-05 01:26:36 -07:00
mateo-berri
1fe87e8e25 fix(realtime): settle the budget reservation only for sessions the success log does not own
The blanket finally release from the previous commit also zeroed the reservation
of successful sessions. Success settlement is enqueued on the logging worker, not
awaited, so the endpoint's finally ran first and released the reservation the cost
callback still had to reconcile, dropping the real spend from the key/team/user
counters.

The relay now stamps a synchronous marker (REALTIME_SESSION_SUCCESS_LOGGED_KEY) on
the shared logging object at the single success-dispatch site, and the endpoint
releases the reservation only when that marker is absent. Refused or failed
sessions, which never log success, still release; successful sessions leave the
reservation for the cost callback to settle to actual spend. Exactly one settler
touches each reservation, so the idempotent reconcile never double-adjusts.
2026-09-05 01:11:24 -07:00
mateo-berri
05c4e16b48 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_ui_lint_inline_object_budget
# Conflicts:
#	ui/litellm-dashboard/src/components/add_model/build_complexity_router_config.test.ts
2026-09-05 00:44:04 -07:00