Commit graph

4669 commits

Author SHA1 Message Date
mateo-berri
6918214266 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_fix_dotprompt_model_swap
# Conflicts:
#	tests/test_litellm/integrations/dotprompt/test_prompt_manager.py
2026-08-26 15:13:57 -07:00
mateo-berri
f824ca7433 fix(responses): run prompt hook before provider credential resolution in sync responses() 2026-08-26 15:08:23 -07:00
Mateo Wang
632a007967
Merge pull request #38406 from BerriAI/litellm_fix_db_router_settings_overwrite
fix(proxy): stop empty DB router_settings lists from clobbering yaml fallbacks
2026-08-26 15:06:26 -07:00
mateo-berri
cd9dcb55b4 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_regenerate_lazy_openapi_snapshot 2026-08-26 15:04:13 -07:00
mateo-berri
b687fe2b50 fix(prompts): propagate PATCHed prompt templates to every worker and pod 2026-08-26 15:03:32 -07:00
Yuneng Jiang
3576c773eb
fix(proxy): serialize the search tool router refresh
reload_search_tools_from_db is a read-modify-write of the shared llm_router
global: it reads the whole table, merges the config tools in, and replaces
router.search_tools wholesale. Two of those interleaving lets the older
snapshot's assignment land last and put back a tool the newer one deleted, so a
revoked tool keeps serving on the provider key it carried until the next reload.

Take MODEL_RECONCILE_LOCK, which add_deployment already uses to serialize the
same shape of work on the same global. It has to go on this entry point rather
than in _init_search_tools_in_db, because _init_non_llm_objects_in_db calls that
while already holding the lock and asyncio.Lock is not reentrant.

A separate search-tools-only lock would not close the race: the periodic
reconcile reaches _init_search_tools_in_db under MODEL_RECONCILE_LOCK, so only
that same lock orders an endpoint refresh against a cron tick.

Ordering across workers is unchanged and still reconciles on the next tick.
2026-08-26 15:02:19 -07:00
Mateo Wang
16e9efccaf
Merge pull request #38404 from BerriAI/litellm_fix_prompt_data_double_nest
fix(prompts): reject keyed prompt_data with prompt_id and populate prompt version
2026-08-26 14:47:59 -07:00
mateo-berri
898ff74673 refactor(proxy): type the snapshot fragments and wrap a long test line 2026-08-26 14:39:51 -07:00
mateo-berri
3b9f6ee2aa fix(proxy): apply empty DB router_settings lists only where yaml sets no value 2026-08-26 14:37:29 -07:00
mateo-berri
afe5a240e5 fix(proxy): regenerate lazy OpenAPI snapshot and guard it in CI
The committed snapshot behind /openapi.json for unloaded lazy features had drifted on 30 of 31 fragments and never had one for a2a_registration or gemini_agents, so those routes showed as placeholder GET stubs or old docstrings until traffic loaded them. Regenerate the snapshot and schema.d.ts, make the check-ui-api-types job and make check regenerate the snapshot and fail on drift, and make the generator refuse to write a snapshot when any feature fails to import so a broken import cannot silently drop fragments.
2026-08-26 14:32:04 -07:00
mateo-berri
43b8ed0fd9 fix(prompts): validate only the litellm_params a PATCH sends 2026-08-26 14:20:26 -07:00
mateo-berri
dbc819dc77 fix(prompts): apply prompt templates before routing on /v1/responses and honor ignore_prompt_manager_model
On /v1/responses the prompt template ran inside litellm.aresponses, after the
router had already resolved a deployment and injected its api_key/api_base, so a
prompt whose metadata.model pointed at another provider sent the old
deployment's credentials cross-provider (401). The proxy now runs the prompt
template for aresponses in the pre-call hook, before routing, so the router
picks the deployment that matches the swapped model. As a backstop, the SDK
refuses a cross-provider swap when explicit credentials are already present
instead of forwarding them.

ignore_prompt_manager_model and ignore_prompt_manager_optional_params saved on
a prompt were only read by the generic manager, so dotprompt prompts ignored
them on every endpoint. PromptManagementBase now merges the prompt spec's flags
with the per-request ones for every manager, and the generic manager no longer
drops caller flags when no spec is present.
2026-08-26 14:12:28 -07:00
mateo-berri
465ebb1bdd fix(mcp): join discovery for a clientless DCR bridge still missing its registration endpoint 2026-08-26 14:08:09 -07:00
ryan-crabbe-berri
870328f8cc test(team): fake the budget table instead of patching new_budget and update_budget
The three member-budget tests patched litellm internals and asserted only on
the mock, which tripped the TQ002 and TQ008 test-quality ratchet. Fake the
prisma budget table on the shared client and assert on the row that reaches
the database plus the returned team payload.
2026-08-26 14:00:45 -07:00
mateo-berri
6d1b295dae fix(proxy): stop empty DB router_settings lists from clobbering yaml fallbacks 2026-08-26 13:58:00 -07:00
mateo-berri
6fa5164d86 fix(prompts): reject keyed prompt_data with prompt_id and populate prompt version
POST /prompts silently stored an empty template when litellm_params.prompt_id
was combined with prompt_data keyed by template name, because the loader
wrapped the already-keyed dict under prompt_id a second time. The loader now
wraps only a flat template (a dict carrying a content key), and create,
update, and patch reject the ambiguous keyed+prompt_id combination with a 400
that names both valid shapes. The API also returned version null on every
create and lost version, environment, and created_by on registry reload; both
now carry through. Versioned ids like my-prompt.v1, which the create API
itself returns, now resolve to their base template on the SDK prompt hooks,
and a flat DB prompt with no litellm_params.prompt_id registers under its base
API id instead of garbage.
2026-08-26 13:57:10 -07:00
milan
99d4741586 fix(team): allow no-reset default budgets for team members
The Default Budget Duration field in Team Member Settings only offered daily, weekly and monthly, so a team member budget could never be set to never reset. It now uses the shared BudgetDurationDropdown, and /team/update writes an explicitly null duration through to the member budget row along with its reset time.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-26 13:48:08 -07:00
yuneng-jiang
a5d8963616
Merge pull request #38308 from BerriAI/litellm_key-update-redis-evict
fix(proxy): stop cache eviction errors from failing /key/update
2026-08-26 13:44:20 -07:00
mateo-berri
19e6f03a3c fix(mcp): let root oauth routes defer discovery to the endpoint-gated flow join 2026-08-26 13:39:35 -07:00
ryan-crabbe-berri
968c96143f test(proxy): assert the rpm/tpm guard returns None on the passing paths
Satisfies the TQ001 zero-assert gate
2026-08-26 13:27:02 -07:00
ryan-crabbe-berri
a85036ec3e Merge branch 'litellm_internal_staging' into enforce-rpm-tpm-on-model-add
Drop the notifications_manager.tsx keyword tweak: staging replaced the
substring classifier with lib/toast.ts, which already titles
validation_error responses as Validation Error
2026-08-26 13:19:07 -07:00
Daniel Meismer
cc400502fa fix(mcp): canonicalize bearer scheme on bridge egress
Co-Authored-By: Codex
2026-08-26 16:09:21 -04:00
mateo-berri
8fcbc357e5 fix(mcp): gate deferred oauth discovery on the endpoint each flow needs and read the resolved server
The token exchange no longer joins deferred discovery when the token url is
already stored, so it cannot 503 over an unreachable issuer it needs nothing
from. After a request joins discovery, authorize and token now read the
resolved server for the DCR bridge relay decision and the rest of the flow,
so a registration endpoint resolved mid-request routes a front-door client
to its own redirect binding. The encrypt seam in the issuer-yield authorize
test now uses a real salt key instead of patching an SDK internal.
2026-08-26 12:45:25 -07:00
Mateo Wang
43ae3507e0
Merge pull request #37090 from Siraj637909/fix/gh-36898-health-leak-extra-headers
fix(health): strip credential fields from GET /health output
2026-08-26 12:35:43 -07:00
Mateo Wang
99789733fb
Merge pull request #38378 from BerriAI/litellm_anthropic_fast_mode_cache_and_response_speed
fix(anthropic): scale cache costs by fast mode and trust served speed
2026-08-26 12:18:44 -07:00
mateo-berri
41192ef085 feat(ui): toggle internal health check visibility in request logs 2026-08-26 12:16:24 -07:00
Yuneng Jiang
291484a5e2
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_/search-tools-sync-issue-e522a2 2026-08-26 12:11:06 -07:00
KnyazSh
736411bd67 Merge branch 'litellm_internal_staging' into feature/improve-gigachat-provider 2026-08-26 19:10:57 +00:00
mateo-berri
ece187ea24 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_anthropic_fast_mode_cache_and_response_speed
# Conflicts:
#	tests/test_litellm/test_cost_calculator.py
2026-08-26 12:10:33 -07:00
yuneng-jiang
da528e455c
Merge pull request #38307 from BerriAI/litellm_proxy_types_validator_contracts
test(proxy): pin the request-validation contracts in proxy/_types.py
2026-08-26 12:09:53 -07:00
Mateo Wang
ace28fd97a
Merge pull request #37384 from daniel-meismer-zocdoc/litellm_mcp_dcr_bridge_complete_challenges
fix(mcp): complete DCR bridge OAuth challenges
2026-08-26 12:07:54 -07:00
Mateo Wang
c7b9060fb1
Merge pull request #38291 from BerriAI/devin_ai_lit6160_health_check_image_edit_mode
fix(health): support `mode: image_edit` in health checks
2026-08-26 12:04:53 -07:00
mateo-berri
50f69a3a81 fix(health): strip client_secret, azure_ad_token, and other credential fields from /health output 2026-08-26 12:00:13 -07:00
mateo-berri
8a2fc2cc9f Merge remote-tracking branch 'origin/litellm_internal_staging' into fix/gh-36898-health-leak-extra-headers 2026-08-26 11:57:55 -07:00
Yuneng Jiang
91e7eb115d
fix(proxy): sync search tools into the router on management writes
Creating a search tool through the UI only wrote the row; the router was updated
solely by the add_deployment job, so the tool was unusable for up to
PROXY_CONFIG_RELOAD_INTERVAL_SECONDS (30s by default) even on the worker that
served the write. Tools declared in config.yaml load straight into the router at
startup, which is why they never showed the delay.

The create, update and delete endpoints now refresh the router inline, matching
what the MCP server endpoints already do. The refresh is best-effort: the row is
already committed, so a failure must not surface as a 500 and push the caller
into a retry that creates duplicates.

Two related gaps go with it. _init_search_tools_in_db skipped the router update
whenever the merged list came back empty, so deleting the last search tool left
it live in memory forever. And in store_model_in_db-off deployments the
add_deployment job is never scheduled, so DB-backed search tools never reached
the router at all; that branch now loads them at startup and keeps them fresh on
its own interval, the same way MCP servers already do.
2026-08-26 11:46:54 -07:00
yuneng-jiang
7bc80994b7
Merge pull request #38305 from BerriAI/litellm_/testing-strategy-audit-c39e33
fix(ci): let the mutation workflow find covered lines so it generates mutants
2026-08-26 11:34:08 -07:00
yuneng-jiang
b03e913ccf
Merge pull request #38315 from BerriAI/litellm_cost_estimate_pricing_edges
test(cost-estimate): pin the prices and period totals /cost/estimate returns
2026-08-26 11:32:22 -07:00
mateo-berri
229e136783 fix(mcp): honor admin-entered OAuth URLs on authorize after issuer yield
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 11:26:54 -07:00
Mateo Wang
ca6387fae7
Merge pull request #38271 from daniel-meismer-zocdoc/litellm_mcp_bridge_provider_token_lifetime
fix(mcp): preserve provider access token lifetime
2026-08-26 11:25:55 -07:00
Mateo Wang
def5ca6d68
Merge pull request #38299 from BerriAI/litellm_fix_vertex_pt_custom_auth_google_token
fix(proxy): keep the caller's Google token on credential-less Vertex passthrough under custom auth
2026-08-26 11:24:56 -07:00
yuneng-jiang
309da5e70e
Merge branch 'litellm_internal_staging' into litellm_/testing-strategy-audit-c39e33 2026-08-26 11:24:55 -07:00
mateo-berri
a0d1fef89d fix(anthropic): scale cache costs by fast mode and trust served speed 2026-08-26 11:24:12 -07:00
mateo-berri
8ff832901b fix(health): accept image_edit mode on /health/test_connection 2026-08-26 11:18:50 -07:00
Devin AI
f3c1e2e2a7 fix(guardrails): forward aws_external_id when the bedrock guardrail assumes a role
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-26 18:12:15 +00:00
Mateo Wang
d46bcde2b5
Merge pull request #37922 from BerriAI/litellm_techdebt_20260822
chore(typing): roll up the daily tech debt cleanups from Aug 20 to Aug 26
2026-08-26 10:54:50 -07:00
mateo-berri
764048750e fix(mcp): name invalid_token challenges by the caller's requested spelling 2026-08-26 10:52:28 -07:00
mateo-berri
a3f654719e fix(proxy): strip the JWT that authenticated on credential-less Vertex passthrough 2026-08-26 10:43:04 -07:00
devin-ai-integration[bot]
c11c654b8e
fix(proxy): honor DATABASE_DISABLE_PREPARED_STATEMENTS in componentized entrypoints (#38363)
Co-authored-by: yassin <yassin@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-08-26 10:39:04 -07:00
mateo-berri
0bfc733278 Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_techdebt_20260822 2026-08-26 10:35:55 -07:00
Yuneng Jiang
3fdeb79737
fix(test): keep the mutmut sentinel out of the cleared environment
test_google_login_only_threads_user_code_when_enabled cleared the whole
process environment for the duration of the call. mutmut's trampoline reads
os.environ['MUTANT_UNDER_TEST'] with a bare subscript, so the first
trampolined callee inside the block, _get_cli_sso_flow_or_raise, raised
KeyError. The bare `except Exception: pass` swallowed it and the assertion
then read call_args on a mock that was never called, which is where
"'NoneType' object has no attribute 'kwargs'" came from.

The test only needs the SSO provider variables unset, so it now preserves the
rest of the environment instead of clearing everything. google_login does not
raise here, so the try/except is gone and any future exception propagates; the
added assert turns a silent early return into a readable failure instead of an
AttributeError.

Root cause measured in a trampolined copy of the mutated folder with
MUTANT_UNDER_TEST=stats: the old test fails there with
KeyError: 'MUTANT_UNDER_TEST' inside _mutmut_trampoline, the new one passes.
That was the only test the mutation run could not execute, so the --deselect
comes back out and it counts toward the score again.
2026-08-26 08:19:56 -07:00