Commit graph

47522 commits

Author SHA1 Message Date
Yuneng Jiang
e03c7ccbab
ci: remove main branch source guard 2026-09-07 15:58:25 -07:00
yuneng-jiang
1646901170
Merge pull request #40041 from BerriAI/litellm_presidio_ui_user_story_e2e
test(e2e/ui): automate the RC checklist's Presidio guardrail walk
2026-09-07 15:41:33 -07:00
yuneng-jiang
41e4f1a8c8
Merge pull request #40038 from BerriAI/litellm_/guardrail-automation-testing-3ecd3d
test(guardrails): pin the presidio spend-log record and the UI's masked-entity persistence
2026-09-07 15:39:51 -07:00
ryan-crabbe-berri
38683643e0
Merge pull request #40170 from BerriAI/litellm_chatgpt_add_model_provider
feat(ui): list the ChatGPT subscription provider in the Add Model form
2026-09-07 15:21:58 -07:00
Mateo Wang
058d260509
Merge pull request #38914 from BerriAI/litellm_fix_skills_hook_import_side_effect
fix(proxy): register SkillsInjectionHook at proxy startup instead of import time
2026-09-07 15:18:54 -07:00
Mateo Wang
0e9e2c01f3
Merge pull request #38806 from BerriAI/litellm_fix_mcp_test_connection_oauth_bearer
fix(mcp): forward staged credentials on /mcp-rest/test/connection like /test/tools/list
2026-09-07 15:18:35 -07:00
Mateo Wang
d0dd3ce2d8
Merge pull request #38869 from BerriAI/litellm_fix_guardrail_route_call_types
fix(guardrails): resolve generateContent routes and async-first passthrough call types
2026-09-07 15:15:51 -07:00
Mateo Wang
9eaf15bcf9
Merge pull request #38842 from BerriAI/litellm_fix_responses_reasoning_drop_params
fix(responses): drop unsupported reasoning param for openai non-reasoning models
2026-09-07 15:14:13 -07:00
ryan-crabbe-berri
bb2db2d3f8 test(proxy): drop docstrings from the Add Model provider tests
Move the only guidance worth keeping into the parity assertion message so a
failing run tells the contributor to add a catalog entry instead of growing
the frozen unlisted set.

Claude-Session: https://claude.ai/code/session_011Tn3657NkV6ojLqewL64Kb
2026-09-07 15:12:41 -07:00
ryan-crabbe-berri
8e5a12057a feat(ui): list the ChatGPT subscription provider in the Add Model form
The Add Model provider dropdown is driven entirely by provider_create_fields.json,
and chatgpt had no entry there, so the documented ChatGPT subscription setup was
unreachable from the Admin UI. Add the entry plus the dashboard enum, slug, logo and
placeholder mappings so the provider can be selected and its cost-map models listed.

The entry carries no credential fields on purpose: the chatgpt backend ignores
api_key and api_base and signs in through the device-code auth file on the proxy
host, so any field here would be inert.

Add a parity test that every LlmProviders value is either listed for Add Model or
frozen in an explicit unlisted set, so a new backend provider cannot silently miss
the dropdown again.

Claude-Session: https://claude.ai/code/session_011Tn3657NkV6ojLqewL64Kb
2026-09-07 14:55:43 -07:00
tin-berri
c5ec2eedc1
fix(spend): price caching savings on the billed request basis (#40160)
Resolves LIT-7137

Co-authored-by: Claude Code <noreply@anthropic.com>
2026-09-07 21:41:05 +00:00
devin-ai-integration[bot]
038025ba5e
fix(guardrails): accept on_violation block and alert for mcp_security (#40155)
* fix(guardrails): accept on_violation block and alert for mcp_security

The MCP Security policy template sends on_violation: "block", but the shared
LitellmParams model only allowed the /v1/realtime values "warn" and
"end_session", so POST /guardrails returned 422 before the MCP guardrail was
initialized. Widen the literal to include the MCP actions, map every non-alert
value to MCP's default "block" at init, and regenerate the lazy OpenAPI
snapshot and dashboard API types

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

* fix(guardrails): restrict on_violation block/alert to mcp_security and keep legacy MCP mapping

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

* fix(guardrails): return 422 when PATCH sets an mcp_security-only on_violation on another guardrail

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-07 14:33:02 -07:00
Jean-Rémi Larcelet-Prost
f896df1b06
docs: fix stale file paths in ARCHITECTURE.md (#40157)
Several file references under proxy/management_helpers/ and other
paths no longer exist; the code moved to proxy/common_utils/,
proxy/db/db_transaction_queue/, litellm_enterprise/proxy/common_utils/,
proxy/hooks/litellm_skills/, and litellm_core_utils/.
2026-09-07 14:19:46 -07:00
tin-berri
7c1745cc71
feat(ui): make automatic auto-router setup discoverable and show what it configured (#40146)
* fix(ui): expand Detailed Configuration after automatic auto-router setup

* feat(ui): promote automatic auto-router setup to a callout banner

* test(ui): read tier chips through testing-library queries to stay in lint budget

* style(ui): drop explanatory comments per repo convention

* test(ui): reject unexpected automatic tier models
2026-09-07 13:55:27 -07:00
devin-ai-integration[bot]
b618c7ad86
fix(proxy): let authorized internal users open vector store details (#40150)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-07 13:10:09 -07:00
yuneng-jiang
6be7a1cbe0
Merge pull request #40149 from BerriAI/litellm_prime_main_gha
ci: prepare workflows for main default branch
2026-09-07 13:00:47 -07:00
yucheng-berri
e04e5d7113
fix(router): keep provider response headers on streaming chat completions (#40091)
* fix(router): keep provider response headers on streaming chat completions

The Router re-wraps a deployment's CustomStreamWrapper in FallbackStreamWrapper
(and its sync twin) so a mid-stream failure can fail over. Neither wrapper
forwarded `_response_headers`, so every streaming chat completion handed the
proxy's callbacks and its response-header builder a wrapper with no provider
headers, and a successful mid-stream fallback still published the failed
deployment's identity, `x-request-id` and rate limit counters.

Forward `_response_headers` into both wrappers, repoint the wrapper at the
deployment that served the stream once a fallback takes over, and rebuild the
proxy's response headers from that deployment while `create_response` still has
the first chunk buffered.

* fix(router): follow a nested fallback to the deployment that served the stream

A fallback the router picks is itself a fallback-aware wrapper, and it only
repoints at its own fallback once it yields, so reading its hidden params at
selection time named a deployment that produced no output. Re-read them when
the first fallback item arrives, which is still before the proxy commits
response headers.

Also addresses review feedback: the streaming header builder reads self.data
instead of taking a coarse request_data parameter, and the new test recorder
local is Final.

* test(router): cover the fallback header adoption helper directly

The router_code_coverage gate wants every router.py function named in a
router test, and this also pins the weak-reference behavior: a wrapper
collected mid-stream must not break the generator still draining it.

* refactor(proxy): take a read-only mapping for the model-id lookup

_get_model_id_from_response only reads its request payload, so a Mapping
says what it needs and the two metadata hops are narrowed instead of
assumed to be dicts.

* test: drop mutable recorder locals and routine comments from the new tests

An AsyncMock await_count and an asyncio.Event say the same thing as a
list and a dict that the test mutates.

* chore(router): justify the two rebinds in the fallback loops

Both are the one-shot re-read that follows a nested fallback, so they get
the repo's rebind-ok note like the rest of the file.
2026-09-07 12:59:57 -07:00
ryan-crabbe-berri
11702ae4e1
Merge pull request #38204 from davida-ps/litellm_prompt_security_file_modify_block
fix(guardrails): block Prompt Security file modifications
2026-09-07 12:53:57 -07:00
Yuneng Jiang
edeb93e727
ci: prepare workflows for main default branch 2026-09-07 12:50:17 -07:00
devin-ai-integration[bot]
6908318c16
feat(keys): allow editing soft budget on existing keys (#39002)
* feat(keys): allow editing soft budget on existing keys

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

* refactor(ui): extract KeyBudgetNumberField to keep key_edit_view under max-lines

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

* style(ui): format keyEditFormValues with prettier

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

* test(keys): cover soft budget validation and update adapter

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

* fix(ui): reject non-finite soft budget values instead of clearing

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

* test(keys): assert soft budget validation returns None for valid values

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

* fix(keys): write soft budget and key row in one transaction

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>
Co-authored-by: yassin <yassin@berri.ai>
2026-09-07 19:37:44 +00:00
devin-ai-integration[bot]
e11a8c59ff
fix(ui): show inherited MCP servers on the internal user editor and flag access groups with no members (#40036)
* fix(ui): show inherited MCP servers on the internal-user editor and flag access groups with no members

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

* fix(ui): consult the unfiltered access group registry before calling a group empty

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-07 19:34:43 +00:00
Yassin Kortam
192e38fa7b
feat(skills): semantic search over the LiteLLM-hosted skill registry (#39401)
* feat(skills): semantic search over the LiteLLM-hosted skill registry

Adds GET /v1/skills?query= (custom_llm_provider=litellm_proxy) and a
skill_search MCP virtual tool, ranking the caller's accessible skills by
semantic similarity, mirroring the A2A agent registry search (LIT-6309).

Also fixes a pre-existing bug where create_skill() dropped description and
instructions for the litellm_proxy provider, which left every LiteLLM-hosted
skill with no searchable text.

* fix(mcp): coerce skill_search top_k instead of raising 500 on malformed input

The MCP-REST skill_search dispatch validated raw tool arguments through a
pydantic model directly, so a non-numeric top_k raised a ValidationError
that the endpoint's catch-all turned into an HTTP 500. Mirrors the
agent_search branch's tolerant coerce_top_k handling instead.

* fix(skills): enforce key limits on search embeddings and bound the semantic index

Semantic search embeddings now run the same pre_call_hook the /embeddings
route runs, so key rate limits, budgets and guardrails apply before the
embedding model is called. The shared SemanticTextIndex caps cached vectors
and evicts the least recently searched entries, and each skill's embedded
text is capped so one skill cannot inflate the embedding batch

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

* fix(skills): surface proxy 429s from search embeddings instead of a 503

ProxyRateLimitError is also an OpenAIError, so the search engine was folding
a key rate limit into skill_search_unavailable. Proxy HTTPExceptions now
propagate so the caller gets the same 429 the /embeddings route returns

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

* fix(skills): import assert_never from typing_extensions for Python 3.10

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

* fix(skills): embed the request as the pre-call hooks returned it, not the original text

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

* refactor(skills): keep the litellm_proxy provider check for GET /v1/skills?query= inside llms/

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

* test(skills): move the GET /v1/skills?query= endpoint tests under tests/test_litellm/proxy

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-07 12:28:38 -07:00
devin-ai-integration[bot]
c949843157
fix(ui): send empty vector_stores when the last team vector store is removed (#40144)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-07 12:24:04 -07:00
devin-ai-integration[bot]
cc287a7d8f
fix(ui): hide the Create Vector Store flow from non proxy admins (#40148)
* fix(ui): hide the Create Vector Store flow from non proxy admins

The vector stores page rendered the Create Vector Store tab, the
+ Add Vector Store button and a GET /credentials call for every role,
while the proxy only lets proxy admins call POST /vector_store/new and
GET /credentials. Internal users landed on the create form and got an
Only proxy admin error toast. Gate all three on isProxyAdminRole and
default everyone else to the Manage tab, matching the Indexes tab and
the Add Model gating.

Resolves LIT-7131

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

* fix(ui): exclude view-only admin sessions from the vector store create flow

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-07 12:23:47 -07:00
tin-berri
eea4c860f7
feat(ui): add key-scoped auto-router usage tab (#39999)
* feat(ui): add key-scoped auto-router usage tab

GET /auto_router/benchmarks takes an optional api_key filter, applied in the
rollup aggregate on the primary key's leading column. Proxy admins get a
separate Auto-router usage tab on key detail pages with spend, baseline,
savings, tier routing, cache metrics and the existing router selector

* fix(ui): share key analytics date range
2026-09-07 12:12:22 -07:00
Mateo Wang
e0c5bb990a
Merge pull request #39835 from BerriAI/litellm_cost_map_guard
feat(ci): add the cost map guard check
2026-09-07 12:11:41 -07:00
Mateo Wang
2cfe106f9f
Merge pull request #39660 from BerriAI/litellm_bedrock_passthrough_model_access
fix(proxy): enforce key and team model access on Bedrock passthrough routes (internal copy of #34244)
2026-09-07 12:11:15 -07:00
tin-berri
1ae3216120
fix(router): preserve default heuristic updates (#40007) 2026-09-07 12:05:43 -07:00
Roman D
55fe4a7894
feat(proxy): resolve root_path per request from a configured prefix list (SERVER_ROOT_PATHS) (#35935)
* feat(proxy): resolve root_path per request from SERVER_ROOT_PATHS

One deployment can encode exactly one client-visible URL path prefix
today: SERVER_ROOT_PATH is a scalar stamped onto the app at startup, so
a pod fronting several ingress prefixes 404s every prefix but one before
any handler runs, and MCP OAuth discovery can emit only one prefix's
URLs (RFC 9728 section 3 exact-match fails for the rest).

Add an opt-in outermost ASGI middleware that matches the request path
against a configured prefix list (SERVER_ROOT_PATHS, comma-separated) on
a segment boundary and sets scope["root_path"] for that request only.
Everything downstream is stock Starlette: route matching strips
root_path so routes stay registered root-relative, and request.base_url
re-includes it, so the discovery documents' resource and the 401
challenges' resource_metadata land under the prefix the client actually
called — with no discovery-builder changes.

LazyFeatureMiddleware now strips the scope root_path (falling back to
the cached SERVER_ROOT_PATH scalar) before feature prefix matching, so
lazily-registered routers — the MCP OAuth discovery router among them —
load under per-request prefixes.

Follow-up to the routing discussion on #35226; composes with, but does
not depend on, #35576.

* fix(proxy): import Sequence from collections.abc (ruff UP035 strict-budget gate)

* review(greptile): trim implementation commentary; fixture-own MCP registry state in tests

Addresses both P2s from the first Greptile pass:
- per_request_root_path_middleware.py (and the related _lazy_features /
  proxy_server comments) cut down to the constraints the code cannot
  express, per repo comment guidance
- the new discovery tests no longer clear/repopulate the shared MCP
  registry inline; a fixture snapshots it, hands the test an empty
  registry, and restores it afterwards so no state leaks between cases

* fix(lint): mutable-ok marker on the prefix accumulator (LIT002 type-discipline gate)

* fix(proxy): tie 401 challenges and get_custom_url to the per-request root_path

The per-request root_path middleware sets scope["root_path"] to the
prefix the client actually called, but the OAuth 401 challenges
(raise_user_oauth_challenge / raise_token_exchange_challenge) still
built their resource_metadata from SERVER_ROOT_PATH. On a pod fronting
several prefixes, the challenge advertised a discovery URL under a
different prefix than the discovery document served — the two
disagreed on where the resource metadata lives, and a strict RFC 9728
client refused the challenge. Route the challenges through a small
ContextVar the middleware populates so they read the same effective
root_path Starlette resolves the request under.

The same accessor fixes get_custom_url: when a request lives under a
SERVER_ROOT_PATHS-matched prefix, request.base_url already carries it,
so appending the SERVER_ROOT_PATH scalar on top produced e.g.
/tenant-a/legacy/sso/callback — a path that does not exist. Reading
the per-request prefix instead (and relying on join_paths's tail-dedup)
keeps SSO login/callback URLs under one prefix — the one the request
actually arrived on.

Fallback: outside a request (module-load-time UI URL builders,
background tasks) the ContextVar is unset and the accessor reads
SERVER_ROOT_PATH, matching get_server_root_path() so scalar-only
deployments are byte-identical.

* fix(mcp): challenge URL under per-request prefix must route, and mock parity

Two follow-ups to the review fix that made the 401 challenge use the
per-request root_path:

1. oauth_protected_resource_path must pick the URL structure that
   actually routes for the mechanism in use:
   - The scalar SERVER_ROOT_PATH deployment registers the well-known
     routes with the prefix INSERTED (via well_known_root_suffix at
     import time), matching RFC 8414 §3. The challenge URL must use the
     same insertion or a client fetching it 404s.
   - The per-request SERVER_ROOT_PATHS deployment can't register routes
     per prefix; PerRequestRootPathMiddleware strips the prefix from
     scope["path"] and the router matches the un-inserted route. The
     URL must place the prefix BEFORE .well-known so the strip leaves a
     matching path.
   The previous fix used the insertion form for both, which 404'd the
   discovery fetch on the per-request path — the discovery doc and the
   challenge would then disagree on where the resource metadata lives,
   the very failure the review flagged. End-to-end verified: the URL
   the challenge advertises routes and the doc's `resource` field
   equals the URL the client originally called (RFC 9728 §3).

2. get_request_root_path now delegates its fallback through
   get_server_root_path() instead of reading the env directly, so every
   existing `monkeypatch.setattr("litellm.proxy.utils.get_server_root_path"`
   test override keeps working. This unstubbed the mock on the /v2/login
   test that failed on the last CI run.

Plus the lint budget: annotate the local accumulator Final, tag the
scope["root_path"] rewrite as an intentional ASGI-contract mutation,
tag the reused `path`/`root_path` rebinds in LazyFeatureMiddleware, and
add reason strings to the two new PLC0415 lazy-import noqas.

* test(mcp): pin the reviewer's expected end-state — challenge URL routes, resource matches called URL

End-to-end regression test that mounts the discoverable router + the
per-request root_path middleware, hits an MCP endpoint that raises
raise_user_oauth_challenge, fetches the resource_metadata URL the
challenge advertises, and checks the returned document's `resource`
equals the URL the client originally called (RFC 9728 §3 exact match).

Covers /tenant-a, /tenant-b, and the unprefixed path on the same app so
a regression on any prefix — challenge URL 404s, or doc emits a
different prefix than the client called — fails at this test rather
than in a strict MCP client's discovery.

---------

Co-authored-by: gym-cmd <186399764+gym-cmd@users.noreply.github.com>
2026-09-07 11:54:59 -07:00
Yuneng Jiang
9c48373bcb
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/guardrail-automation-testing-3ecd3d 2026-09-07 11:47:54 -07:00
Yuneng Jiang
a88002c034
test(guardrails): document audit prompt storage prerequisite 2026-09-07 11:43:32 -07:00
Yuneng Jiang
4044cd2f0c
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/guardrail-automation-testing-3ecd3d 2026-09-07 11:38:59 -07:00
devin-ai-integration[bot]
96c698030b
fix(spend_logs): keep partition DDL transactions alive for their statement timeout (#40098)
* fix(spend_logs): keep partition DDL transactions alive for their statement timeout

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

* style: ruff format changed files

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

* fix(lint): avoid dict-literal kwargs and keep cast-ok on the cast line

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

* fix(lint): cast at the call site instead of widening PrismaClient.tx

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

* test(spend_logs): require partition tx timeout to strictly exceed statement bound

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

---------

Co-authored-by: jesus <jesus@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-07 11:38:53 -07:00
yuneng-jiang
4b3355bdc6
test(e2e): prove the virtual key lifecycle on every gateway replica (#40023)
* test(e2e): prove the virtual key lifecycle on every replica

Walks one virtual key through create, read, partial update, clear, enforce
and delete against a live proxy and database, reading every write back on
every gateway replica.

The management suite already had single write-then-read tests for keys, but
none of them proved that a partial /key/update leaves the untouched fields
alone, that an explicit null clears a field, or that a write is visible on
more than the one gateway that took it.

Adds read_back_everywhere to the shared ProxyClient: it polls a GET path on
every URL in PROXY_REPLICA_URLS until each replica's parsed body satisfies
the caller's predicate, and fails naming the replica that never converged.
The CLEAR sentinel in the e2e models makes an explicit JSON null expressible
in a body the transport otherwise strips of None fields.

Documents /key/update's merge patch semantics on the endpoint docstring.

* test(e2e): prove key revocation and field preservation on every replica

Applies the findings from an adversarial review of the first commit.

The delete step only checked that chat was refused on the gateway that took
the write, so it would have passed while a sibling gateway kept serving the
deleted key. It now serves one call from every replica first, so each has the
key cached and the delete has something to revoke everywhere, then polls every
replica for the refusal.

The file also carried its own poll loop that tested the deadline before
attempting, so it gave up one attempt early and skipped the attempt landing
exactly on the deadline. It now shares the harness helper, which is generic
over the polled value rather than over a parsed body, so the same loop covers
both the info read-back and the chat refusal.

The model the enforcement step registers now carries a unique marker in its
alias, matching every other deployment this suite creates, so concurrent runs
never share one model group.

The docstring sentence claimed an explicit null clears any field. It does not:
the metadata-backed fields merge into stored metadata, where a null is a silent
no-op, and only the key's own columns clear. Regenerating the dashboard types
picks up the corrected text.

* fix(e2e): delete a deployment that never becomes servable

Registering a model posts /model/new and then waits for every replica to list
it. When that wait timed out the deployment already existed in the database but
its id had never been returned, so no caller could delete it and the row
outlived the run. It is now deleted before the failure propagates.

Found by review on the key lifecycle suite, whose module fixture registers a
deployment this way, but every caller of the shared helper had the same
exposure.

* docs(e2e): drop the duplicated notes from the lifecycle docstrings

The delete method restated what the warm-up helper already explains, and the
module restated the merge patch rule that the endpoint and the request model
both document.
2026-09-07 11:30:46 -07:00
yujonglee
5f2b4d27d7
test(ocr): add SDK callback E2E parity (#40061)
* test(ocr): cover SDK callback parity

* test(ocr): compare callback kwargs
2026-09-07 11:23:12 -07:00
yuneng-jiang
9acc01efce
test(e2e/ui): cover member role and budget edits, member permission delegation, and team guardrail removal (#40042)
* test(e2e/ui): cover member role and budget edits, member permission delegation, and team guardrail removal

Three Playwright specs for the Teams flows enterprise customers hit most, each
owning its fixtures and proving the mutation through a read-back rather than a
toast.

- teamMemberEdit: an admin edits a member's team role and per-member budget,
  and both survive a reload of the Members table
- memberPermissions: a plain member is refused /key/generate for their team,
  a team admin grants it on the Member Permissions tab, and the member then
  creates a team key that serves a real completion
- teamGuardrailRemoval: clearing a team's only guardrail on the Settings tab
  really clears it, and traffic the guardrail refused starts serving again

* test(e2e/ui): make the new team specs safe to run in parallel

Fixture ids came from Date.now(), so two repeats starting in the same
millisecond minted the same user id: one got a 409 and the loser's teardown
deleted the user the other was still signed in as. Ids now carry a random
suffix.

Also move the member-permissions setup inside the cleanup-protected block so a
half-finished setup cannot leak a team, and close both browser contexts the
test opens.
2026-09-07 11:18:16 -07:00
yuneng-jiang
6dfcc46c9e
Merge pull request #40026 from BerriAI/litellm_fix_migrated_pages_sidebar_test
test(ui): make navigation smoke resilient to router refactors
2026-09-07 11:17:32 -07:00
yucheng-berri
2700ffe8c9
fix: capture provider request id in failure logging payloads (#40045)
* fix: capture provider request id in failure logging payloads

* fix: include common provider request id headers

* test: remove accidental formatter churn

* test: type provider request id cases

* test: cover azure and google request id headers

* refactor: share provider request id headers from constants

* chore: remove redundant request header comment

* test: cover provider header lookup failures
2026-09-07 11:12:34 -07:00
Mateo Wang
9275cf42ed
Merge pull request #40015 from BerriAI/litellm_fix_check_run_name_collisions
fix(ci): stop the auto-close duplicates job colliding with the required test check
2026-09-07 10:55:34 -07:00
Mateo Wang
8e7f748e8a
Merge pull request #39870 from BerriAI/litellm_lit_6917_make_check_test_tree_ruff
fix(make check): lint the test tree on tests-only changes like CI does
2026-09-07 10:55:28 -07:00
Mateo Wang
c8ef043087
Merge pull request #39981 from BerriAI/litellm_lit_7079_bridge_preserve_provider_metadata
fix: keep provider id and metadata on Responses API bridged chat completions
2026-09-07 10:55:25 -07:00
Mateo Wang
3dac0ba79b
Merge pull request #39850 from BerriAI/litellm_fix_realtime_reasoning_double_bill
fix(cost): bill realtime reasoning tokens nested in text_tokens once
2026-09-07 10:55:20 -07:00
Mateo Wang
642a0f68ae
Merge pull request #39530 from BerriAI/litellm_fix_gateway_rustls_provider
fix(ai-gateway): dial upstream WebSockets over an explicit rustls provider
2026-09-07 10:55:15 -07:00
Mateo Wang
9700f666d0
Merge pull request #39839 from BerriAI/litellm_async_remote_image_fetch
fix(async): move remote image fetches off the event loop for Snowflake, Bedrock invoke Claude, Mantle and Gemini
2026-09-07 10:55:04 -07:00
Mateo Wang
a9556c7bad
Merge pull request #39965 from BerriAI/litellm_fix_oci_cohere_stream_tool_turn_dup
fix(oci): stream Cohere tool-calling answers once
2026-09-07 10:54:59 -07:00
Mateo Wang
a676f5eb6d
Merge pull request #39800 from BerriAI/litellm_claude_md_qa_screenshots
docs(claude): have runs embed their own QA screenshots on visual changes
2026-09-07 10:54:49 -07:00
yuneng-jiang
5930549bf8
Merge pull request #40140 from BerriAI/litellm_fix_autorouter_prisma_filter
fix(router): serialize heuristic tuning quota filters for Prisma
2026-09-07 10:52:38 -07:00
yujonglee
8da735410c
test(ocr): trace callback lifecycle parity (#40063) 2026-09-07 10:44:22 -07:00
yujonglee
217cb12623
refactor(rust): remove per-request enablement arguments (#39928)
* refactor(rust): remove per-request enablement arguments

* fix(rust): remove ignored transcription enablement

* refactor(rust): remove OCR-specific bridge controls
2026-09-07 10:43:45 -07:00
Yuneng Jiang
b61ef7c232
Merge branch 'litellm_/guardrail-automation-testing-3ecd3d' into litellm_presidio_ui_user_story_e2e 2026-09-07 10:08:30 -07:00