Commit graph

9968 commits

Author SHA1 Message Date
tin-berri
df73c623b2
feat(router): limit heuristic_v2 auto-routers to one without the auto_router license feature (#39468)
Without the auto_router feature in the signed enterprise license a proxy may hold
one complexity router with classifier_type heuristic_v2 across config.yaml and the
DB; with it the limit is lifted. The ceiling is derived once from LicenseCheck and
handed to the Router, which refuses the extra router at registration. config.yaml
over the limit refuses to start, and /model/new, /model/update and
PATCH /model/{id}/update refuse the write with a 403 before touching the DB.
Expiry follows the existing max_users/max_teams pattern: judged when the
license is verified, not on every call, and a verify that rejects the license
(expired or unreadable) leaves no signed payload behind. The rollback after a
failed upsert re-admits state that was already serving, so it is exempt from the
ceiling: an edit that fails, including one refused by a ceiling that has since
tightened, leaves the router serving its previous configuration.
A write that leaves a row on heuristic_v2 under a limited license runs in one
transaction that takes a Postgres advisory lock before counting the DB rows plus
this proxy's config.yaml routers, so concurrent writes on any pod cannot both
claim the sole slot and no surplus row is ever persisted.
Only the row insert runs under that lock: the team model bookkeeping, which
needs a second pool connection, runs after the transaction has committed.
PATCH /model/{id}/update follows the same order as create: the row is written
through the slot first and the team's model list is updated only afterwards, so
a refused write leaves the team as it was.
The slot transaction bypasses the repository's publish-on-write, so it
publishes the config change once after commit, as delete_team_models does.
2026-09-03 13:39:58 -07:00
Mateo Wang
828d561fcc
Merge pull request #39622 from BerriAI/litellm_gpt_6_astra
feat(models): add gpt-6-astra pricing and metadata
2026-09-03 13:18:34 -07:00
devin-ai-integration[bot]
1f20b38115
fix(vector_stores): only list vector stores the caller was granted (#39612)
* fix(vector_stores): only list vector stores the caller was granted

/vector_store/list returned every managed vector store with no team_id to any
key, and let a dashboard session see stores created from the dashboard because
every session shares the litellm-dashboard team id. Non-admin listings now show
a store only when the key or one of the caller's real teams is allowlisted for
it via object_permission.vector_stores, or the team owns it

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

* fix(vector_stores): keep a dashboard session key's own grants when the user has no teams

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 13:17:48 -07:00
Mateo Wang
e4b8caeb36
Merge pull request #38975 from BerriAI/litellm_fix_azure_ai_reclassify
fix(azure_ai): don't reclassify Foundry deployments as azure provider
2026-09-03 13:15:40 -07:00
Mateo Wang
cff2fd4f80
Merge pull request #39610 from BerriAI/litellm_bedrock_mantle_web_search_cost
fix(cost): bill bedrock_mantle web search at $12 per 1k queries using Bedrock's reported count
2026-09-03 13:14:20 -07:00
Mateo Wang
c137828a92
Merge pull request #39594 from BerriAI/litellm_lit6867_jwt_deployment_affinity
fix(router): pin JWT-authenticated callers by user id in deployment_affinity
2026-09-03 13:14:17 -07:00
Mateo Wang
0eed564ee3
Merge pull request #39587 from BerriAI/litellm_fix_responses_bridge_privatelink_api_base
fix(openai): bridge gpt-5.4+ tool calls to /v1/responses on every api.openai.com host
2026-09-03 13:13:27 -07:00
Mateo Wang
80250807db
Merge pull request #38808 from BerriAI/litellm_headroom_ccr_streaming_responses
fix(headroom): resolve CCR retrieval on streaming /v1/responses
2026-09-03 13:13:18 -07:00
Mateo Wang
8cf3bc87a2
Merge pull request #39597 from BerriAI/litellm_lit6642_vertex_count_tokens_anthropic_beta
fix(proxy): drop anthropic-beta on the Vertex passthrough count-tokens route
2026-09-03 13:13:11 -07:00
Mateo Wang
1e2d6abc18
Merge pull request #39614 from BerriAI/litellm_fix_stream_usage_default_openai_hosts
fix(openai): default stream usage on PrivateLink and regional api.openai.com hosts
2026-09-03 13:13:00 -07:00
Mateo Wang
7d6b7dcca0
Merge pull request #39592 from BerriAI/litellm_lit6782_dashscope_off_peak_pricing
fix(cost): apply off_peak_pricing in the dashscope cost calculator
2026-09-03 13:12:55 -07:00
mateo-berri
f40f14ae39 fix(tests): fold the local price map into the provider model sets
CI unit shards load the price map from main at import, so a model that only
exists on the branch never reaches open_ai_chat_completion_models and
cost_per_token cannot infer its provider. Refresh the sets after swapping in
the local map so the tier pricing cases resolve gpt-6-astra before merge
2026-09-03 13:09:46 -07:00
ryan-crabbe-berri
1c14ded0e4
Merge pull request #39598 from BerriAI/litellm_lit_4929_session_token_aggregation
fix(ui): aggregate session token usage in the logs table
2026-09-03 12:57:27 -07:00
moe-berri
f5f78fbb97
Merge pull request #39619 from BerriAI/litellm_fix_39451_model_mode
fix(proxy): expose configured mode for auto-router models
2026-09-03 12:56:44 -07:00
ryan-crabbe-berri
f173a6baf1
Merge pull request #39215 from BerriAI/litellm_lit_6592_team_overview_inherited_mcp_agents
fix(ui): show MCP servers and agents inherited from access groups on team overview
2026-09-03 12:53:27 -07:00
mateo-berri
4991d0bf3e fix(models): match gpt-6-astra reasoning effort levels to OpenAI docs
OpenAI documents low, medium, high, xhigh, and max for gpt-6-astra, with no none level, so the entry stops advertising none and starts advertising max.
2026-09-03 12:47:25 -07:00
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
moe-berri
425e3069b9 fix(proxy): expose configured model mode 2026-09-03 12:40:22 -07:00
mateo-berri
1e75668a25 fix(openai): default stream usage on PrivateLink and regional api.openai.com hosts 2026-09-03 12:37:17 -07:00
mateo-berri
339da4183d test(cost): type the web search cost helpers and cover OpenAI-shaped tool_usage 2026-09-03 12:34:54 -07:00
mateo-berri
51d821ae45 fix(cost): bill bedrock_mantle web search at $12 per 1k queries using Bedrock's reported count 2026-09-03 12:21:54 -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
mateo-berri
9c7c7a05ac test(router): type the deployment affinity JWT test helpers 2026-09-03 11:58:25 -07: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
ryan-crabbe-berri
b3325750ae fix(ui): aggregate session token usage in the logs table
The logs table already rolled up cost per session but the Tokens column only showed the representative call's usage. The per-session aggregate query now also sums prompt, completion and total tokens, and the Tokens cell switches to those sums for multi-call sessions the same way the Cost cell does.

Claude-Session: https://claude.ai/code/session_01CNasFqyjnLN3Rqman25vde
2026-09-03 11:09:44 -07:00
mateo-berri
aaef5d219a fix(proxy): drop anthropic-beta on the Vertex passthrough count-tokens route 2026-09-03 11:07:29 -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
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
mateo-berri
68ffa1db23 fix(router): pin JWT-authenticated callers by user id in deployment_affinity 2026-09-03 10:43:41 -07:00
mateo-berri
b9e030ddd6 fix(cost): apply off_peak_pricing in the dashscope cost calculator 2026-09-03 10:38:25 -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
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
ryan-crabbe-berri
2fd6e19051 fix(ui): name the granting access group on hover instead of an Inherited tag
`/team/info` access_group_details now carries mcp_server_ids and agent_ids per
group next to models, so the dashboard can say which group granted a server or
agent. The Object Permissions rows drop the Inherited badge and the row tooltip
reads "Granted via access group <name>. Full ID: <id>", listing every group
when more than one grants the same id and falling back to "an access group"
when the proxy did not say.

Claude-Session: https://claude.ai/code/session_01QvQzYztinxj8ZuD5YxbVdL
2026-09-03 10:20:10 -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
mateo-berri
7a5e4b9ba4 fix(openai): bridge gpt-5.4+ tool calls to /v1/responses on every api.openai.com host
The auto-bridge that moves gpt-5.4+ requests carrying function tools and no
reasoning_effort onto /v1/responses only fired when the resolved api_base was
the literal https://api.openai.com/v1, so a deployment pointed at an OpenAI
PrivateLink hostname (<region>.privatelink.api.openai.com) or a port-qualified
or trailing-slash default stayed on Chat Completions and got OpenAI's 400 back.
Gate on the resolved URL's hostname instead: api.openai.com or any subdomain of
it bridges, every other custom base still stays on chat
2026-09-03 10:04:18 -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
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
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-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