Commit graph

46560 commits

Author SHA1 Message Date
mateo-berri
897fba08c8 feat(models): add gpt-6-astra pricing and metadata
Adds the OpenAI gpt-6-astra entry to both price files with standard, flex, priority (fast mode), batch, and above-272K long-context rates, and regression tests covering each tier and the batch rates.
2026-09-03 12:47:25 -07:00
devin-ai-integration[bot]
92122086ec
fix: stop a cleared Organization field from failing key creation (#39316)
* fix: stop a cleared Organization field from failing key creation

Clearing the Organization combobox in the Create Key modal left organization_id set to an empty string, so /key/generate looked up an organization named "" and failed with "Organization doesn't exist in db. Organization=".

OrganizationDropdown now emits null on clear, and GenerateKeyRequest normalizes an empty organization_id or project_id to None the same way it already does for team_id.

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

* test: drop customer-specific docstring from key request normalization test

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-03 19:12:11 +00:00
devin-ai-integration[bot]
e046aee3d5
fix(spend_tracking): add missing_session_id: omit to leave SpendLogs.session_id null without a client session (#39458)
* fix(spend_tracking): leave SpendLogs.session_id null when no client session id was established

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

* chore(lint): ratchet basedpyright budget after session_id fix

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

* fix(spend_tracking): ignore trace ids as session ids

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

* fix(spend_tracking): gate null SpendLogs.session_id behind missing_session_id: omit

Unset, generate and reject keep the legacy trace id fallback. omit records only
metadata.session_id, the key Langfuse reads, so a trace id copied into
litellm_session_id by get_litellm_params never becomes a session.

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

* fix(spend_tracking): stamp the omit decision on the request so a config reload cannot fabricate a session

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

* fix(spend_tracking): keep omit covering requests the pre-call stamp never reaches

Router-model provider pass-through calls allm_passthrough_route directly and
skips add_litellm_data_to_request, so those requests never run the pre-call
helper and carry no omit stamp. Reading only the stamp made POST
/anthropic/v1/messages write a fabricated uuid into SpendLogs.session_id under
missing_session_id: omit while its Langfuse trace had no session, the exact
divergence the policy exists to remove.

The stamp now only pins omit on, and an unstamped request falls back to the
configured policy, so a config reload still cannot fabricate a session for a
request that was decided pre-call.

* fix(spend_tracking): make the session-omission marker proxy-owned so clients cannot forge it

* fix(spend_tracking): strip the client-sent omission marker from both metadata buckets before they merge

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

* fix(spend_tracking): strip the session-omission marker from both metadata buckets

The pre-call policy ran before litellm_metadata is merged into metadata, so a
client that planted the marker in litellm_metadata had it copied back into the
route's own bucket after the strip and still got a null SpendLogs.session_id.

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
2026-09-03 11:57:56 -07:00
devin-ai-integration[bot]
c2265b0ef3
fix(proxy): return persisted team memberships from /user/new so first CLI login gets the default team (#39545)
* fix(proxy): return persisted team memberships from /user/new

new_user attached default teams after building its response from the
pre-membership snapshot, so NewUserResponse.teams was always empty for
users created with default_internal_user_params.teams. The CLI SSO flow
reads that response on a user's first login and minted a teamless JWT,
which skipped the default team's model allowlist.

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

* fix(proxy): return team ids as a tuple to satisfy LIT001

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-03 11:55:59 -07:00
Mateo Wang
4b1e24eae9
Merge pull request #39525 from BerriAI/litellm_fix_gpt_image_background_dropped
fix(images): forward gpt-image supported params like background to OpenAI and Azure
2026-09-03 11:32:05 -07:00
mateo-berri
ec2e35b679 fix(image_gen): keep the provider's echoed size, quality, and output_format on gpt-image responses 2026-09-03 11:07:08 -07:00
yuneng-jiang
fa533f709b
Merge pull request #39595 from BerriAI/litellm_/release-version-bump-be1c60
chore: bump litellm-enterprise 0.1.63 -> 0.1.64, litellm-proxy-extras 0.4.92 -> 0.4.93
2026-09-03 11:03:31 -07:00
Yuneng Jiang
ba9bb75298
bump: litellm-enterprise 0.1.63 -> 0.1.64, litellm-proxy-extras 0.4.92 -> 0.4.93 2026-09-03 10:53:50 -07:00
mateo-berri
4d3c1998af fix(image_gen): report the requested output_format on gpt-image responses 2026-09-03 10:50:23 -07:00
Mateo Wang
7d6781fe6a
Merge pull request #35987 from BerriAI/litellm_bedrock_mantle_web_search
fix(bedrock_mantle): stop dropping the web_search tool on /v1/responses
2026-09-03 10:45:28 -07:00
yujonglee
bb7d787425
Merge pull request #39571 from BerriAI/codex/team-id-empty-field
fix(team): generate team IDs for blank input
2026-09-03 10:35:01 -07:00
tin-berri
7256bd307a
fix(mcp): scope allow-all servers to virtual keys (#39531) 2026-09-03 10:32:03 -07:00
Mateo Wang
27274f65e4
Merge pull request #39554 from BerriAI/litellm_fix_flaky_model_hub_e2e
fix(agents): keep the published agent in public_agent_groups
2026-09-03 10:29:41 -07:00
devin-ai-integration[bot]
a0f44af838
fix(proxy/db): translate libpq sslrootcert and verify-* into Prisma's strict TLS params (#39563)
* fix(proxy/db): translate libpq sslrootcert and verify-* into Prisma's strict TLS params

Prisma silently drops sslrootcert and treats sslmode=verify-ca/verify-full as
prefer, so a DATABASE_URL copied from the RDS docs connected over TLS without
checking the server certificate. The URL handed to Prisma (writer, DIRECT_URL,
read replica, componentized entrypoints) now carries sslmode=require,
sslcert=<bundle> and sslaccept=strict instead.

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

* style(proxy/db): ruff format translate_libpq_ssl_params

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-03 10:27:46 -07:00
devin-ai-integration[bot]
29c37141c3
feat(ui): keyset-paginate request logs by session trace (#38794)
* feat(ui): keyset-paginate request logs by session trace

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

* fix(proxy): keep session grouping within type discipline budget

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

* style(proxy): ruff format session grouping helpers

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

* fix(proxy): only group sessions when group_by_session is an explicit true

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

* fix(ui): reset session cursor on custom range and live tail toggles

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

* test(ui): cover cursor reset on custom range toggle

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

* fix(ui): ignore next page clicks while the grouped page is still fetching

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

* fix(ui): only block next page while grouped placeholder data is shown

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-03 17:27:05 +00:00
yujonglee
6f5bf0dab8
Merge pull request #39425 from BerriAI/litellm_ocr_fixture_generation
test(ocr): record provider fixtures in the migration harness
2026-09-03 10:26:39 -07:00
Mateo Wang
3fd74dfbb4
Merge pull request #39409 from BerriAI/litellm_databricks_strip_thinking_blocks
fix(databricks): strip thinking_blocks and reasoning_content from outbound messages
2026-09-03 10:22:48 -07:00
Yujong Lee
8c180afd4b test(ocr): record provider fixtures in the migration harness 2026-09-03 10:16:40 -07:00
yujonglee
2c30fe16b0
Merge pull request #38765 from BerriAI/litellm_ocr_sdk_parity_tests
test(harness): add OCR parity with migration strategy runners
2026-09-03 10:16:35 -07:00
mateo-berri
8713ba8a52 test(bedrock_mantle): capture the drop warning with caplog instead of patching the logger 2026-09-03 10:07:52 -07:00
yuneng-jiang
bd9de39349
Merge pull request #39583 from BerriAI/litellm_deterministic_timeout_tests
test(timeout): time out against the local fake endpoint instead of api.openai.com
2026-09-03 10:04:02 -07:00
Yuneng Jiang
c70e4857fa
test(timeout): time out against the local fake endpoint instead of api.openai.com
test_router_timeout, test_timeout_streaming and test_openai_embedding_timeouts
asked api.openai.com for a response in 10 to 100 microseconds and asserted the
resulting exception was a timeout. No connect can finish in that window, so
socket.create_connection always walked the whole address list, and because it
re-raises only the LAST address's error, the assertion was decided by the order
getaddrinfo happened to return.

api.openai.com is dual-stack and the CI container has no usable IPv6, so a
trailing AAAA record made the last attempt fail with an OSError. httpcore maps
socket.timeout to ConnectTimeout but OSError to ConnectError, so the expected
APITimeoutError arrived as APIConnectionError and the job went red. The three
tests were really measuring DNS ordering, not litellm.

Point them at the fake OpenAI endpoint the suite already runs, ask for the
slow-endpoint model it already delays on, and give them a timeout comfortably
under that delay. The embeddings route did not honour slow-endpoint yet, so it
now delays the same way chat and text completions already do.

Each test also gained a failure on the success path. Without it a request that
returned instead of timing out fell out of the try block and the test passed on
a result it was written to reject.
2026-09-03 09:53:30 -07:00
mateo-berri
a1e58aabe7 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_bedrock_mantle_web_search 2026-09-03 09:50:42 -07:00
yuneng-jiang
342e4470c4
fix(ui): replace the key detail URL entry when a virtual key is rotated (#39471)
Regenerating a key repointed ?key= at the rotated hash with a pushed history
entry, so pressing the browser Back button landed on the hash that had just
been revoked. /key/info answers 404 for it and the page shows "Key not found
in database".

The rotated hash now replaces the current entry instead of pushing a new one,
so Back from a just-regenerated key returns to the key list. Opening a key
from the table still pushes, so Back from a normally opened key is unchanged.
2026-09-03 09:47:45 -07:00
moe-berri
4990f06acc
feat(auto-router): support classifier reasoning effort (#39372)
* feat(auto-router): support classifier reasoning effort

* fix(auto-router): harden classifier reasoning effort

* fix(ui): satisfy classifier config lint limits

* refactor(auto-router): simplify classifier effort support

* fix(auto-router): clear frontend-lint and type-discipline gates, trim LOC

---------

Co-authored-by: Tin Chi Lo <tin@berri.ai>
2026-09-03 08:59:04 -07:00
Mateo Wang
34d4f7f8ae
fix: 1.99.0-rc2 UI bug batch (empty org on key create, session pagination, access group rename/delete) (#39436)
* fix(ui): clearing the organization picker no longer sends organization_id="" on key create

* fix(proxy): paginate Request Logs by conversation and aggregate session type counts and models server-side

* fix(proxy): keep access groups in sync when a model is renamed or deleted

* fix(proxy): cap the Request Logs conversation total like the row total

* fix(proxy): judge access group backing by the database for db models

A worker whose router has not polled the database yet still lists a sibling under its old
name, so a delete or rename handled there kept the stale name in every access group. Only
config-sourced deployments count as router backing now; db models are counted in the table.

* fix(ui): keep the conversation badge when an MCP call represents a conversation

A conversation that straddles the bounded page window can be represented by one of its MCP
rows, which showed a plain MCP badge and hid the session counts. The badge now reads the
server aggregates whenever the conversation has more than one call.

* fix(proxy): list every model of a conversation in Request Logs and keep the conversation badge for MCP representatives

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

* fix(proxy): type session spend aggregates

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

* fix(ui): satisfy request logs lint budget

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

* fix(proxy): cap per-session model aggregation in request logs

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

* chore: ratchet type-discipline budget after staging merge

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

* fix(ui): send an explicit null when the key edit form clears the organization

Clearing the Organization picker in the key edit form wrote undefined into
the form value, and JSON.stringify drops undefined-valued keys, so
/key/update never saw the field and the key kept its old organization.
Writing null instead survives serialization, and the backend's
model_dump(exclude_unset=True) preserves it, so the column is set to NULL.

---------

Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-03 08:58:48 -07:00
Rakesh
1de960bce7
fix(docker): bump nginx runtime to 1.31.5-alpine3.24 and pin digest to resolve critical CVEs (#39561) 2026-09-03 08:46:07 -07:00
devin-ai-integration[bot]
e80e78d3ef
feat(cli): enable Claude Code gateway model discovery by default in lite claude (#39445)
* feat(cli): enable Claude Code gateway model discovery by default in lite claude

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

* refactor(cli): build agent env declaratively and document discovery key for lite up

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

* fix(cli): keep build_agent_env within LIT002 type-discipline budget

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-03 08:38:25 -07:00
Mateo Wang
45495e1ab5
Merge pull request #39506 from BerriAI/litellm_fix_v2_migration_resolver_attempt_accounting
fix(proxy-extras): only spend a migrate-deploy attempt when a pass made no progress
2026-09-03 08:36:31 -07:00
Mateo Wang
11a02b9581
Merge pull request #36260 from eeshsaxena/fix-credential-endpoints-raise-not-return
fix(proxy): 404 a credential delete that matched nothing, and raise instead of return
2026-09-03 06:17:56 -07:00
mateo-berri
f83b6029e3 Merge branch 'litellm_internal_staging' into fix-credential-endpoints-raise-not-return 2026-09-03 05:36:50 -07:00
mateo-berri
418d0e79ba fix(proxy): answer 404 when deleting a credential that was never stored
prisma's `delete` returns None when the `where` clause matched no row
instead of raising, and the handler never looked at the return value. It
went straight on to filter an in-memory list that never held the name and
answered 200 "Credential deleted successfully", so an operator scripting
credential cleanup could not tell a real deletion from a typo.

Look at what the repository returned and answer 404 with the name, the
same rejection PATCH /credentials/{credential_name} already gives. A
credential that only exists in the config yaml is never written to the
table, so it now answers 404 too, which is honest: reporting success for
it is the same lie, since it comes back on the next proxy boot.

Adds regression tests for the delete 404, the still-working delete, the
config-yaml-only credential, and for the raise-not-return fix on both
DELETE /credentials/{credential_name} and GET /credentials, which
serialized a rejection as the 200 response body.
2026-09-03 05:30:28 -07:00
mateo-berri
15e956db33 test(agents): make the make_public regression tests fail without the fix
The config stub shared one list object between save_config and get_config, so the
DB overlay handed the endpoint back the very list it had just appended to and both
tests passed with the product fix reverted. Store the settings as JSON the way the
litellm_config row does, and check the duplicate guard against a list that only
ever existed in the DB.
2026-09-03 05:21:42 -07:00
mateo-berri
b1695e9090 test(agents): type the public-agent regression tests fully 2026-09-03 04:33:55 -07:00
mateo-berri
9d862a6583 style: drop explanatory comments from the agent publish fix 2026-09-03 04:27:43 -07:00
mateo-berri
ccbd3e495c fix(agents): keep the published agent in public_agent_groups
`POST /v1/agents/{id}/make_public` appended the agent id to
`litellm.public_agent_groups` and only then called `get_config()`, which
re-applies the DB's `litellm_settings` over the module globals and threw the
append away. The config it saved was therefore a no-op: the endpoint answered
200 with an empty `public_agent_groups`, the agent never reached
`GET /public/agent_hub`, and re-publishing never hit the "already public" 400.
Read the config first, derive the new list from the refreshed globals, save it,
then update the global

Also fixes the e2e model hub spec, which is flaky for a second reason: the
"Make Models Public" modal preselects the groups that are already public, so a
blind click on "Select All" cleared them and left "Next" disabled for the full
15s action timeout. Check the box instead of toggling it, and wait for "Next"
to be enabled before clicking
2026-09-03 04:24:09 -07:00
Devin AI
e1b2d9de3c fix(images): forward gpt-image supported params like background to OpenAI and Azure
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-09-03 08:45:23 +00:00
yuneng-jiang
658f50663d
fix(ui): keep Virtual Keys list state in the URL so it survives leaving the page (#39481)
* fix(ui): keep Virtual Keys list state in the URL so it survives leaving the page

The search term, sort, pagination and drawer filters lived in component
state, so navigating away from Virtual Keys and back reset the table to an
unfiltered first page. Move them into query state alongside the existing
?key= deep link, which also makes a filtered view shareable.

* fix(ui): namespace the Virtual Keys filter params and bound page inputs

The unprefixed team_id filter hijacked the /api-keys create-key deep link,
which already takes team_id as a prefill, so ?create=true&team_id=X silently
filtered the list underneath the modal. Prefix the four drawer filters.

Now that page and page_size come from the address bar, clamp them to what
/key/list accepts instead of forwarding 0, negatives or an int64-overflowing
page straight through, and trim filter values arriving from a URL the same
way the drawer already trims them.

* fix(ui): fall back to a sortable column when the URL names an unknown one

A hand-edited or stale sort_by reached /key/list, which 400s it, leaving the
Virtual Keys page on its loading skeleton with no error. Validate it against
the fields the table's own headers can produce, and clear sort_by rather than
blanking it when a sort is reset so the URL stays clean.

Also replaces a default-state URL assertion that ran before any query-state
write could land, so it could not fail for the regression it named.

* fix(ui): use TanStack's functionalUpdate instead of a hand-rolled updater resolver

The local helper narrowed typeof updater === "function" against an
unconstrained T, which TypeScript cannot do because T itself may be a function
type, so next build failed to type check. table-core already exports the same
helper.
2026-09-03 00:35:32 -07:00
Mateo Wang
066d5f0694
Merge pull request #39502 from BerriAI/litellm_/triage-slack-message-4bd4e6
fix(test): drop the duplicate embedding_executor arg in the Bedrock KB fake handler
2026-09-03 00:26:08 -07:00
mateo-berri
8572544b44 refactor(proxy-extras): pull the migrate deploy recovery branches into a budget helper
_setup_database_v2 decided the next attempt budget inline in eight
branches, each rebinding budget before continuing. The branches now live
in _budget_after_deploy_failure, which returns the budget the next pass
runs under, and the two identical idempotent-recovery blocks share
_mark_migration_applied. The loop backs off whenever a pass spent an
attempt, which is the same set of paths that slept before.
2026-09-03 00:20:46 -07:00
yucheng-berri
ecabfbd5af
fix(guardrail): hide-secrets playground redaction and guardrail telemetry (#39398)
* Fix hide-secrets guardrail: playground redaction, UI dropdown entry, spend-log telemetry

The hide-secrets guardrail never implemented apply_guardrail, so the UI test
playground echoed secrets verbatim; it was missing from the Add Guardrail
dropdown; and it recorded no guardrail_information, so Spend Logs could not
distinguish a redacted request from a clean one.

- implement apply_guardrail (unified interface) with use_native_lifecycle_hooks
  so proxied traffic stays on async_pre_call_hook (per-key opt-out and
  data["prompt"] handling live only there)
- record standard_logging_guardrail_information (allow/mask + masked_entity_count)
  via _process_response/_process_error; opted-out keys and legacy nameless
  callback instances record nothing
- advertise hide-secrets in /guardrails/ui/add_guardrail_settings (pre_call only)
  and /guardrails/ui/provider_specific_params with a config model

Resolves LIT-3548

* Fix hide-secrets passthrough telemetry and JSON config input

* fix(guardrails): validate hide-secrets object config before submit

- apply_guardrail treats empty-string-only texts as no input, so no
  false allow is recorded
- the UI object field keeps raw text while editing and blocks submission
  until it parses to a JSON object, instead of posting a string to an
  object-only API
- supported_modes_by_provider keeps its dict[str, list[str]] value type

* fix(guardrails): record no hide-secrets telemetry when nothing was inspected

walk_user_text and the prompt redaction now report how many non-empty
strings they visited; when neither inspected anything (image-only
content, empty strings), the run records no guardrail entry instead of
an 'allow' row that counts a check which never saw any text.
2026-09-03 00:01:03 -07:00
mateo-berri
7b8cc0319e fix(proxy-extras): only spend a migrate-deploy attempt when a pass made no progress
The v2 migration resolver gave `prisma migrate deploy` four attempts, and
every recovery path ended in a bare `continue`, so each one burned an attempt.
A database first brought up with `--use_prisma_db_push` has a full schema and
no migrations ledger, so the baseline spent attempt one and the first three
migrations whose objects already existed spent the rest. The proxy then exited
before binding its port, and that database could never be moved onto the
resolver.

The retry budget now counts only attempts that got nowhere. Creating the
baseline, and each migration newly marked applied, leaves the budget alone, so
a push-created database works through its pre-existing objects one pass at a
time. Timeouts, deadlock rollbacks, advisory-lock waits, and a repeat of a
recovery that already ran still spend an attempt, so a run that stops making
progress gives up exactly as before.
2026-09-02 23:56:09 -07:00
Yuneng Jiang
47611fa207
fix(test): drop the duplicate embedding_executor arg in the Bedrock KB fake handler
Two branches independently added embedding_executor to the same fake
search handler in this file, #39472 in the middle of the signature and
#39474 at the end. Neither conflicted with the other, so both edits
merged and the function ended up declaring the parameter twice.

Python rejects that at compile time, so the whole module fails to
import and every test in the file is uncollectable, taking the
logging_testing job down on staging.

Keep the earlier of the two, which sits where the real handler declares
the parameter.
2026-09-02 23:22:40 -07:00
yuneng-jiang
3cac5e5cd4
fix(sso): resolve multi-valued role claims to the highest privilege role (#39480)
* fix(sso): resolve multi-valued role claims to the highest privilege role

A role claim carrying several roles used to resolve to whichever one the IdP
listed first, so a user holding both proxy_admin_viewer and internal_user lost
org-level spend visibility depending on claim ordering alone.

get_litellm_user_role now picks the highest privilege role out of a list-valued
claim, and the Entra app_roles path shares that same resolution instead of
keeping its own copy of the hierarchy. SAML assertions carrying several role
values go through the same path rather than taking the first value.

* test(sso): lock ranked-over-unranked role resolution for mixed claims

org_admin, team and customer sit outside the privilege ladder. Pin the
resolution for a claim that mixes one of them with a ranked role so the
asymmetry is covered rather than implicit.

* fix(sso): label the claim-sequence cast for the type-discipline gate

* fix(sso): resolve claim entries without recursing

The repo's recursive-function gate rejects self-recursion here, and a role
claim is flat anyway. Pull the single-value lookup into its own helper so the
list branch maps over it instead of calling back into itself.
2026-09-02 22:44:17 -07:00
Mateo Wang
62ed7e1942
Merge pull request #39478 from BerriAI/litellm_ui_presets_mock_build_ctx
fix(ui): read the preset catalog at runtime in the dashboard tests
2026-09-02 22:38:59 -07:00
yuneng-jiang
c841a56e9a
fix(ui): stop the create team form resetting organization and models (#39476)
* fix(ui): stop the create team form resetting organization and models

The organization preselect ran in an effect keyed on the organizations
query, so any refetch of that list while the Create Team modal was open
overwrote the user's organization pick, which in turn cleared their
models pick. The models field was also cleared whenever the available
models fetch resolved.

Preselect the organization when the modal opens instead, and clear the
models only when the user picks a different organization. An org admin
whose admin orgs narrow to one while the form is open can still pick,
rather than facing a locked empty field.

* fix(ui): block team create when the picked organization is no longer available

An organization picked in the Create Team form now survives a refetch of
the organization list, so it can outlive the admin's access to it. Refuse
the create with a message on the field rather than letting the request
fail authorization at the proxy.

* fix(ui): keep the team create organization field usable when the pick goes stale

Locking the field on a single admin organization also locked it while it
held a rejected organization, so an admin who lost access could not pick
the one organization left. Lock it only while it holds that organization.

* test(ui): hoist the created team fixture out of the mock call

The inline object pushed the repo past its no-large-inline-object-arg
lint budget, which has no headroom.
2026-09-02 22:34:15 -07:00
tin-berri
534003da03
feat(ui): add 1M context auto-router preset (#39490)
* feat(ui): add 1M context auto-router preset

* feat(ui): use heuristic v2 for 1M preset

* fix(ui): keep 1M preset test within lint budget
2026-09-02 22:33:14 -07:00
Mateo Wang
99da04a1b0
Merge pull request #39441 from BerriAI/litellm_internal_copy_36281
fix(xai): bill from the cost xAI reports instead of recomputing it (internal copy of #36281)
2026-09-02 22:23:50 -07:00
Mateo Wang
66a3d24b3f
Merge pull request #39474 from BerriAI/litellm_s3_vectors_query_embedding_executor
refactor(s3_vectors): embed search queries through the shared vector store executor
2026-09-02 22:23:44 -07:00
mateo-berri
f62e87d28c fix(ui): read the preset catalog through the shared mock in the lib test 2026-09-02 21:42:47 -07:00