Commit graph

13250 commits

Author SHA1 Message Date
mateo-berri
5b2d1874b0 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_reasoning_effort_capability_v2
# Conflicts:
#	tests/test_litellm/test_router.py
2026-08-25 12:07:05 -07:00
Mateo Wang
c543461297
Merge pull request #38225 from BerriAI/litellm_fix_bedrock_mantle_gpt5_context_window
fix(model_prices): raise bedrock_mantle gpt-5.6 max_input_tokens to Mantle's enforced 1050000
2026-08-25 11:51:19 -07:00
Mateo Wang
76e1105f74
Merge pull request #38235 from BerriAI/litellm_router_api_base_resolution
fix(router): resolve provider from api_base in deployment validation and acompletion
2026-08-25 11:51:15 -07:00
Mateo Wang
18108ecc24
Merge pull request #38231 from BerriAI/litellm_fix_bedrock_mantle_passthrough_invoke
fix(bedrock_mantle): register a Bedrock runtime passthrough config so /bedrock/model/<deployment>/invoke works
2026-08-25 11:51:03 -07:00
Mateo Wang
41aa1caff1
Merge pull request #38233 from BerriAI/litellm_together_api_host
fix(together_ai): default endpoints to api.together.ai instead of api.together.xyz
2026-08-25 11:17:17 -07:00
mateo-berri
e8bdbcd1cf fix(bedrock_mantle): parse converse passthrough bodies with the converse shape config for logging 2026-08-25 10:56:55 -07:00
ryan-crabbe-berri
c3bcb6f64f
test(mcp): drain the logging worker after each test so queued callbacks cannot leak into the next test (#38228)
LoggingWorker now carries still-queued coroutines onto the next event loop (12a34a10d8). Under xdist,
a success-logging coroutine queued by test_acompletion_mcp_respects_manual_approval ran nine seconds
later inside test_mcp_tool_call_hook on the same worker, resolved litellm.callbacks at run time and
overwrote that test's captured payload with a gpt-4o-mini completion (assert 1.35e-05 == 1.42).

Run clear_queue() in the suite's autouse teardown so every coroutine a test enqueues finishes before the
next test registers its callbacks, and add a subprocess regression test that runs the real conftest
against a stopped worker with work still queued.
2026-08-25 10:50:35 -07:00
Mateo Wang
751976db8b
Merge pull request #38229 from BerriAI/litellm_vertex_ai_interactions
feat(vertex_ai): add native Vertex AI Interactions API support
2026-08-25 10:50:02 -07:00
mateo-berri
5e6b6c6281 fix(together_ai): let an explicit api_key beat the Together env key on api_base match 2026-08-25 10:39:10 -07:00
mateo-berri
367a6e5dc5 test(router): pin the guard that keeps a junk-typed operator effort value out of model group info 2026-08-25 10:37:48 -07:00
mateo-berri
0bd4d323da fix(router): resolve provider from api_base in deployment validation and acompletion
Router._add_deployment called get_llm_provider without the deployment's api_base, so a config entry with a bare model plus a known OpenAI-compatible endpoint failed startup validation with LLM Provider NOT provided and the proxy returned 400 no healthy deployments for that model group. acompletion had the same gap at request time: it forwarded only base_url into its get_llm_provider call, dropping the api_base kwarg the router passes. Both now forward api_base so endpoint matching resolves the provider the same way sync completion already does
2026-08-25 10:33:40 -07:00
mateo-berri
6be000f1f3 test(bedrock_mantle): type _repo_cost_map return instead of bare dict 2026-08-25 10:23:12 -07:00
mateo-berri
b46f17faf5 fix(together_ai): default endpoints to api.together.ai instead of api.together.xyz
Together AI moved its canonical API host from api.together.xyz to
api.together.ai. Default the provider api_base and the rerank handler to
the new host, make rerank honor api_base and TOGETHER_AI_API_BASE like
chat already does, map both hosts to together_ai when passed as
api_base, and delete the dead models/info fetch in factory.py.
2026-08-25 10:18:55 -07:00
mateo-berri
68ad575fc2 fix(bedrock_mantle): register a Bedrock runtime passthrough config so /bedrock/model/<deployment>/invoke works 2026-08-25 10:10:38 -07:00
Mateo Wang
92fe35854b
Merge pull request #38222 from BerriAI/litellm_fix_mantle_reasoning_effort_max
fix(completion_extras): forward reasoning_effort=max through the Responses API bridge
2026-08-25 10:06:08 -07:00
Mateo Wang
9dff9cdd9a
Merge pull request #37979 from BerriAI/litellm_lit5714_adaptive_thinking_display
fix(anthropic/bedrock): request summarized adaptive thinking for reasoning_effort and use provider thinking token counts
2026-08-25 09:58:03 -07:00
mateo-berri
530dab32b9 feat(vertex_ai): add native Vertex AI Interactions API support 2026-08-25 09:55:13 -07:00
mateo-berri
f583151a5b fix(model_prices): raise bedrock_mantle gpt-5.6 max_input_tokens to Mantle's enforced 1050000 2026-08-25 09:53:19 -07:00
Yassin Kortam
1d695a714b
fix(proxy): reset a stuck team member's budget (#37971)
* fix(proxy): reset a stuck team member's budget

A per-team-member budget check reads a cross-pod spend counter that
nothing ever invalidates. Once a member exceeds their per-member
budget, resetting the key's spend, raising the user's or the team's
own budget, or issuing a new key all leave the member stuck, because
none of them touch this counter or its cached membership object.

Add POST /team/{team_id}/member/{user_id}/reset_spend to reset a
member's tracked spend, and invalidate the same cached state from
/team/member_update when it raises a member's own budget, so that
path also takes effect immediately instead of waiting on the
membership cache's TTL. Name the entity in the check's error message
so a stuck member is diagnosable from the 429 body alone.

* fix(proxy): close reset-vs-floor-read race and surface double Redis write failure on member spend reset

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

* fix(proxy): broadcast spend reset as a SET so the handler's self-delivered message cannot erase the reset guard

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

* fix(proxy): omit null fields from the invalidation message so plain evictions keep the old wire format

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-08-25 09:50:09 -07:00
mateo-berri
a73f11ae9c fix(completion_extras): forward reasoning_effort=max through the Responses API bridge 2026-08-25 09:40:23 -07:00
mateo-berri
7dc5a1682d Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_reasoning_effort_capability_v2 2026-08-25 09:28:55 -07:00
Anmol Jaiswal
bb27bfd9a7
fix(http_handler): dispose aiohttp session when AsyncHTTPHandler is finalized without a running loop (#36670)
* fix(http_handler): dispose aiohttp session when finalized without a running loop

AsyncHTTPHandler.__del__ can only schedule an async close when a running
event loop exists at finalization time; in any other context (worker
threads whose loop has closed, sync contexts, interpreter shutdown) the
RuntimeError from get_running_loop() is swallowed and the underlying
aiohttp ClientSession is abandoned to GC, emitting 'Unclosed client
session' / 'Unclosed connector' warnings.

This is the disposal gap left after the recycle-time fix: clients created
for short-lived event loops (the loop-id-keyed LLM client cache mints one
handler per loop) are never recycled - they live and die with their loop,
and their finalization is precisely the loop-less case.

Fix:
- no running loop: fall back to the connector's synchronous teardown via
  LiteLLMAiohttpTransport._mark_connector_closed - the same finalizer-safe
  path used for dead-loop recycles - honoring _owns_session so a shared
  session is never closed.
- running loop: keep the async close, but hold a strong reference to the
  scheduled task until it completes (a bare create_task() result may be
  collected before running), mirroring _background_close_tasks.

Tests: loop-less finalization closes a dead-loop session; running-loop
finalization registers and drains the close task; the sync fallback
respects session ownership. All three fail without the fix.

* lint: conform new finalizer code to the type-discipline budget

Final on the five never-rebound locals (LIT010); the class-level task
registry keeps its mutable set with the sanctioned mutable-ok reason,
mirroring the aiohttp transport's registry (LIT001).

* lint: reasoned pyright ignore on the cross-class teardown call

The handler deliberately reuses the transport's finalizer-safe connector
teardown; no public seam exists and an async close can never run at
loop-less finalization. Clears the net-new reportPrivateUsage the
basedpyright budget gate flagged once the LIT stage passed.

* fix(http_handler): retrieve exceptions from finalizer close tasks

A bare discard done-callback dropped the task without consuming its
exception, so a failing aclose() emitted "Task exception was never
retrieved" at GC, the same noise class this path exists to remove.
Mirror the transport's _on_close_task_done: discard, early-return on
cancellation, retrieve and debug-log the exception.

* fix(http_handler): dispose foreign-loop sessions instead of scheduling aclose on the live loop

GC on a live loop (e.g. the app's) of a handler whose session belongs to
another, possibly dead, loop scheduled aclose() on the current loop, the
cross-loop path the transport refuses. Route both that case and the
loop-less case through the transport's lifecycle-aware
_close_recycled_session, which picks async close on the session's own
loop, threadsafe handoff, or the synchronous connector teardown.

Regression test: a dead-loop session collected while another loop runs
is disposed without scheduling anything on that loop.

* chore: retrigger CI (test_mcp_logging payload-order flake, also failed on litellm_spendlogs_fallback_metadata minutes earlier)

* test(mcp): select the MCP tool-call payload instead of the last-delivered one

TestMCPLogger kept a single last-writer slot; an async success event from
another call (a mocked acompletion whose log task lands late) races the
MCP event for it, so the cost assertions intermittently read the wrong
payload. This PR's finalizer change shifts task interleaving on the loop
and tips that latent race over (also seen on an unrelated PR minutes
earlier). Collect call_type=call_mcp_tool payloads in their own list and
assert on those.

* test(mcp): MCPLoggerHook inherits the order-independent payload capture

It duplicated TestMCPLogger's init and success handler verbatim; the
hook test reads the same MCP payload selection, so subclass instead.
2026-08-25 08:12:10 -07:00
tin-berri
31a67561ab
feat(complexity_router): bound the classifier context block, not each turn in it (#38145)
The LLM classifier capped every prior turn at 200 characters independently, so a
785 character turn was cut even when the whole block it belonged to was 353
characters. A character budget now bounds the block: turns are taken newest first
and quoted whole while they fit, older turns are dropped whole once it runs out,
and only the turn straddling the boundary is cut. The per-turn cap stays as an
optional clamp for operators who set it deliberately, defaulting to unset.
2026-08-24 22:56:00 -07:00
devin-ai-integration[bot]
a9c7b848f2
fix(logging): skip parsing redacted tool call arguments (#38169)
Some checks failed
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 DB Operations / proxy-utils (push) Blocked by required conditions
Unit Tests / caching-local (push) Waiting to run
Unit Tests / core-utils (push) Waiting to run
Unit Tests / enterprise-package (push) Waiting to run
Unit Tests / enterprise-routing (push) Waiting to run
Unit Tests / integrations (push) Waiting to run
Unit Tests / All Other Providers (push) Waiting to run
Unit Tests / Vertex AI (push) Waiting to run
Unit Tests / misc (push) Waiting to run
Unit Tests / proxy-auth (push) Waiting to run
Unit Tests / proxy-endpoints (push) Waiting to run
Unit Tests / proxy-extras (push) Waiting to run
Unit Tests / proxy-infra (push) Waiting to run
Unit Tests / proxy-server (push) Waiting to run
Unit Tests / responses-caching-types (push) Waiting to run
GitHub Actions Security Analysis / zizmor (push) Waiting to run
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 / 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 / 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
Terraform Provider / gofmt, vet, build, test (push) Has been cancelled
Terraform Provider / Provider endpoints vs proxy OpenAPI schema (push) Has been cancelled
* fix(logging): skip parsing redacted tool call arguments

Co-authored-by: hansu650 <hansu650@users.noreply.github.com>

* test: annotate parser-warning test locals with Final

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

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: hansu650 <hansu650@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-24 20:59:57 -07:00
Mateo Wang
53c9d48bd2
ci(e2e): record the e2e suite weekly and replay it on weekdays with zero egress (#38163)
Adds a scheduled GitHub Actions lane on top of the merged record/replay
transport. A Saturday cron records the `replayable` e2e tests against the
real providers and publishes the fixture bundle as a private
`e2e-fixtures-bundle` artifact with a SHA-256 sidecar. Weekday crons pull
that artifact by its pinned digest, verify the checksum before extracting,
and replay it with provider credentials set to bogus values, so a run that
ever reached a real provider fails instead of passing.

An egress sentinel pins the provider hostnames to a local sink for the whole
replay job and counts every connection that reaches them; the job asserts
that count is zero, so hermeticity is proven by measurement. A red Saturday
publishes no bundle, so the next weekday finds nothing fresh and fails loudly
rather than replaying a week-old recording, and the transport's seven-day
freshness gate hard-fails any bundle that has drifted too far. The lane also
runs on demand from the Actions tab with a record/replay `mode` input.

Tests join the lane with `@pytest.mark.replayable`. The streaming Anthropic
test now counts to twenty so its recorded response banks several content
deltas, matching the assertion that the stream arrives incrementally.
2026-08-24 23:49:03 -04:00
yucheng-berri
ee68813530
fix(langsmith): keep root-run ids self-consistent so batch ingest stops rejecting header-tagged requests (#38116)
A request carrying a session/trace header fans the header value into
litellm metadata as both trace_id and session_id. LangSmith then rejected
the whole ingest batch: a root run's trace_id must equal the run id
embedded in dotted_order (400), and a run-body session_id must reference
an existing tracer session (404/422). Override caller trace_id on runs
that post as roots and drop session_id only when it mirrors trace_id,
so deliberate child-run and valid tracer-session fields still pass through.
2026-08-24 19:47:12 -07:00
Mateo Wang
539ba9f939
Merge pull request #37899 from BerriAI/litellm_ban_data_migrations
ci: ban row-rewriting DML from prisma migrations
2026-08-24 19:44:34 -07:00
Mateo Wang
da91d4b6c9
Merge pull request #38119 from BerriAI/litellm_bing_grounding_search_provider
feat(search): add Grounding with Bing Search (bing_grounding) as a search provider
2026-08-24 19:33:23 -07:00
ryan-crabbe-berri
891b23d680
Merge pull request #38156 from BerriAI/litellm_caching_error_drilldown
feat(ui): add error-code drilldown for failed requests on caching page
2026-08-24 18:30:41 -07:00
devin-ai-integration[bot]
8f6de53c92
fix(s3_v2): percent-encode object keys once so signed and sent URLs match (#38005)
Co-authored-by: yucheng <yucheng@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-24 18:16:17 -07:00
Mateo Wang
82b0069f83
Merge pull request #38155 from BerriAI/litellm_forward_video_edit_source_file
fix(videos): forward uploaded source file on /v1/videos/edits to the provider
2026-08-24 18:00:29 -07:00
Mateo Wang
a28f075f45
Merge pull request #29832 from hclsys/fix/files-decode-encoded-id-in-chat-and-responses
fix(files): decode x-litellm-model encoded file_id in chat + responses
2026-08-24 17:29:00 -07:00
mateo-berri
a527275d05 fix: keep a schema-qualified call inside an index expression from reading as a relation
A quoted routine call qualified by a schema and sitting inside a CREATE INDEX
expression, ON "Foo" (public."f"(col)), walked its qualifier read-through back
across the opening paren to the ON that introduces the indexed table, so the call
was misread as a relation and dropped from the call set, leaving a rewrite in that
routine unscanned. A word now only introduces the name when nothing but whitespace
and qualifier dots lies between them, so a paren in that gap keeps ON (and any
relation-introducing keyword) from reaching across it and the call stays a call.
2026-08-24 16:04:38 -07:00
Akshay Sasi
fde307539e
fix: tolerate stream chunks without a choices key in stream_chunk_builder (#34382)
The Responses-API to /chat/completions bridge yields ModelResponseStream
chunks that carry choices followed by a trailing event object that has no
choices key. stream_chunk_builder assumed every chunk was subscriptable at
"choices", so assembling those chunks raised KeyError('choices') and was
re-wrapped as a 500 APIError building the streaming usage.

Guard each choices access with .get("choices") so choices-less chunks are
skipped instead of crashing. Behavior is unchanged for chunks that do carry
choices, since .get("choices") is truthy only for a non-empty choices list.

Adds a regression test that assembles content across chunks followed by a
trailing chunk with no choices key.

Co-authored-by: mubashir1osmani <mubashir.osmani777@gmail.com>
2026-08-24 18:53:30 -04:00
ryan-crabbe-berri
0de0e1cef6 feat(ui): add error-code drilldown for failed requests on caching page
/global/activity/cache_hits now returns an error_breakdown: failed spend
logs bucketed per call_type by error code and error class, read from
metadata->error_information. Clicking a red failed-requests segment on
the cache activity chart opens a per-code bar chart; hovering a bar
lists the error classes behind that code.
2026-08-24 15:45:45 -07:00
mateo-berri
7d0df4a062 fix(videos): forward uploaded source file on /v1/videos/edits to the provider
The video edit endpoint parsed the multipart body but dropped the uploaded
source video, only normalizing it to an id. When a raw file is uploaded it now
flows through videos.main -> the http handler -> the provider transform, which
emits multipart/form-data with the source video as a file part, matching the
official OpenAI SDK's videos.edit wire format. Edit-by-id still egresses JSON.
2026-08-24 15:34:21 -07:00
mateo-berri
c9d1b94828 fix: read through a spaced schema qualifier when telling a table from a routine call 2026-08-24 15:07:01 -07:00
Mateo Wang
25ec6827b7
Merge pull request #38136 from BerriAI/litellm_lit_5742_streaming_replay
feat(e2e): record and replay streamed provider responses chunk-for-chunk
2026-08-24 14:55:27 -07:00
Mateo Wang
fbb46b3ac6
Merge pull request #38133 from BerriAI/litellm_harden_retry_breadcrumb_credentials
fix(router): stop copying forwarded credentials into retry breadcrumbs
2026-08-24 14:55:04 -07:00
Mateo Wang
46c2328641
Merge pull request #38114 from BerriAI/litellm_fix_5997_vertex_pt_key_leak
fix(passthrough): stop leaking the caller's virtual key on credential-less Vertex passthrough
2026-08-24 14:54:53 -07:00
Mateo Wang
ccb03f567f
Merge pull request #38149 from BerriAI/litellm_fix_recursive_detector_form_flatteners
fix(ci): ignore-list recursive form-field flatteners in recursive_detector
2026-08-24 14:54:43 -07:00
mateo-berri
90a3101a45 fix: read through a schema qualifier when telling a table from a routine call 2026-08-24 14:52:55 -07:00
tin-berri
40246f43d7
fix(complexity_router): keep both ends of a clipped classifier context turn (#38141)
The LLM classifier's conversation context cut each prior turn head-only, so a turn
opening with an incident report and closing with the actual request reached the
classifier as the incident report alone. Keeping head and tail costs the same
budget and is what the truncation literature measures as best for classifying
long text.
2026-08-24 14:51:13 -07:00
mateo-berri
16a81c9ceb fix(vertex-passthrough): cover the mapped-route litellm_user_api_key header
On mapped pass-through routes, of which /vertex_ai is one,
user_api_key_auth accepts the caller key from a header literally named
litellm_user_api_key and applies it last, so it overrides every other source.
The credential-less filter neither dropped it nor resolved the caller key from
it, so a virtual key there reached Google past a real x-goog-api-key, and a
bring-your-own Authorization could be stripped when auth actually came from that
header. Drop it by name and resolve it at highest precedence.
2026-08-24 14:30:44 -07:00
Mateo Wang
0f596a5145
Merge pull request #38129 from BerriAI/litellm_autorouter_dropdown_registry
fix(auto-router): list configured auto-routers in the usage picker before they have traffic
2026-08-24 14:23:09 -07:00
mateo-berri
e018b9ce74 fix: don't read a quoted table's column list as a routine call site 2026-08-24 14:21:53 -07:00
mateo-berri
5d34b1232e fix(ci): ignore-list recursive form-field flatteners in recursive_detector
The recursive_detector code-quality gate fails on litellm_internal_staging
because _flatten_form_field and _flatten_form_data_field in
llm_request_utils.py are recursive but absent from IGNORE_FUNCTIONS. Both are
bounded structural recursion over an already-parsed JSON-shaped request body
(a finite tree, no cycles possible), matching the existing ignored walkers, so
add them to the ignore list with a justification comment.
2026-08-24 14:17:18 -07:00
ryan-crabbe-berri
380338c0b4
refactor(utils)!: delete prompt_token_calculator (#38132)
Follow-up to #38130. The function has no callers in the repo or the docs and is
not exported from `litellm/__init__.py`, and `token_counter` already does the same
job better, so keeping a second entry point only preserves a trap.

That trap is real: Greptile flagged on #38130 that `token_counter` picks the claude
tokenizer only for bare ids. `claude-sonnet-4-5` resolves to huggingface_tokenizer,
while `claude-3-opus-20240229` and `anthropic/claude-sonnet-4-5` fall back to the
OpenAI one, 24 tokens against 27 on the same string. Deleting the wrapper removes
the surface rather than papering over it; the selection gap in `token_counter`
itself is worth its own fix.

BREAKING CHANGE: `from litellm.utils import prompt_token_calculator` no longer
resolves. Use `litellm.token_counter(model=..., text=...)`.
2026-08-24 14:14:25 -07:00
Mateo Wang
463261d21d
Merge pull request #38117 from BerriAI/litellm_lit5902_managed_files_e2e
test(e2e): pin require_managed_files enforcement behind a marker-gated stack phase
2026-08-24 14:04:33 -07:00
Mateo Wang
1e9cecd05f
Merge pull request #38135 from BerriAI/litellm_lit_5704_vectorstore_upload_controls
feat(proxy): enforce vector-store upload security controls on /v1/rag/ingest
2026-08-24 14:04:22 -07:00