Commit Graph

35355 Commits

Author SHA1 Message Date
milan-berri d29287c1c3 fix: normalize content_filtered finish_reason (#23564)
Map provider finish_reason "content_filtered" to the OpenAI-compatible "content_filter" and extend core_helpers tests to cover this case.

Made-with: Cursor
2026-03-14 10:50:33 -07:00
milan-berri b793eee245 fix: tiktoken cache nonroot offline (#23498)
* fix: restore offline tiktoken cache for non-root envs

Made-with: Cursor

* chore: mkdir for custom tiktoken cache dir

Made-with: Cursor

* test: patch tiktoken.get_encoding in custom-dir test to avoid network

Made-with: Cursor

* test: clear CUSTOM_TIKTOKEN_CACHE_DIR in helper for test isolation

Made-with: Cursor

* test: restore default_encoding module state after custom-dir test

Made-with: Cursor
2026-03-14 10:48:36 -07:00
Ishaan Jaff b87d1f8dad [Feat] - Ishaan main merge branch (#23596)
* fix(bedrock): respect s3_region_name for batch file uploads (#23569)

* fix(bedrock): respect s3_region_name for batch file uploads (GovCloud fix)

* fix: s3_region_name always wins over aws_region_name for S3 signing (Greptile feedback)

* fix: _filter_headers_for_aws_signature - Bedrock KB (#23571)

* fix: _filter_headers_for_aws_signature

* fix: filter None header values in all post-signing re-merge paths

Addresses Greptile feedback: None-valued headers were being filtered
during SigV4 signing but re-merged back into the final headers dict
afterward, which would cause downstream HTTP client failures.

Made-with: Cursor

* feat(router): tag_regex routing — route by User-Agent regex without per-developer tag config (#23594)

* feat(router): add tag_regex support for header-based routing

Adds a new `tag_regex` field to litellm_params that lets operators route
requests based on regex patterns matched against request headers — primarily
User-Agent — without requiring per-developer tag configuration.

Use case: route all Claude Code traffic (User-Agent: claude-code/x.y.z) to
a dedicated deployment by setting:

  tag_regex:
    - "^User-Agent: claude-code\\/"

in the deployment's litellm_params. Works alongside existing `tags` routing;
exact tag match takes precedence over regex match. Unmatched requests fall
through to deployments tagged `default`.

The matched deployment, pattern, and user_agent are recorded in
`metadata["tag_routing"]` so they flow through to SpendLogs automatically.

* fix(tag_regex): address backwards-compat, metadata overwrite, and warning noise

Three issues from code review:

1. Backwards-compat: `has_tag_filter` was widened to activate on any non-empty
   User-Agent, which would raise ValueError for existing deployments using plain
   tags without a `default` fallback. Fix: only activate header-based regex
   filtering when at least one candidate deployment has `tag_regex` configured.

2. Metadata overwrite: `metadata["tag_routing"]` was overwritten for every
   matching deployment in the loop, leaving inaccurate provenance when multiple
   deployments match. Fix: write only for the first match.

3. Warning noise: an invalid regex pattern logged one warning per header string
   rather than once per pattern. Fix: compile first (catching re.error once),
   then iterate over header strings.

Also adds two new tests covering these cases, and adds docs page for
tag_regex routing with a Claude Code walk-through.

* refactor(tag_regex): remove unnecessary _healthy_list copy

* docs: merge tag_regex section into tag_routing.md, remove standalone page

- Add ## Regex-based tag routing (tag_regex) section to existing
  tag_routing.md instead of a separate page
- Remove tag_regex_routing.md standalone doc (odd UX to have a separate
  page for a sub-feature)
- Remove proxy/tag_regex_routing from sidebars.js
- Add match_any=False debug warning in tag_based_routing.py when regex
  routing fires under strict mode (regex always uses OR semantics)

* fix(tag_regex): address greptile review - security docs, strict-mode enforcement, validation order

- Strengthen security note in tag_routing.md: explicitly state User-Agent
  is client-supplied and can be set to any value; frame tag_regex as a
  traffic classification hint, not an access-control mechanism
- Move tag_regex startup validation before _add_deployment() so an invalid
  pattern never leaves partial router state
- Enforce match_any=False strict-tag policy: when a deployment has both
  tags and tag_regex and the strict tag check fails, skip the regex fallback
  rather than silently bypassing the operator's intent
- Extract per-deployment match logic into _match_deployment() helper to
  keep get_deployments_for_tag() readable
- Add two new tests: strict-mode blocks regex fallback, regex-only
  deployment still matches under match_any=False

* fix(ci): apply Black formatting to 14 files and stabilize flaky caplog tests

- Run Black formatter on 14 files that were failing the lint check
- Replace caplog-based assertions in TestAliasConflicts with
  unittest.mock.patch on verbose_logger.warning for xdist compatibility
- The caplog fixture can produce empty text in pytest-xdist workers
  in certain CI environments, causing flaky test failures

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-14 09:40:00 -07:00
Joe Reyna 25ee2fb3f9 fix(security): bump tar to 7.5.11 and tornado to 6.5.5 (#23602)
* fix(security): bump tar to 7.5.11 and tornado to 6.5.5

- tar >=7.5.11: fixes CVE-2026-31802 (HIGH) in node-pkg
- tornado >=6.5.5: fixes CVE-2026-31958 (HIGH) and GHSA-78cv-mqj4-43f7 (MEDIUM) in python-pkg

Addresses vulnerabilities found in ghcr.io/berriai/litellm:main-v1.82.0-stable Trivy scan.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix: document tar override is enforced via Dockerfile, not npm

* fix: revert invalid JSON comment in package.json tar override

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-13 23:08:14 -07:00
xianzongxie-stripe 81474c17fe Handle response.failed, response.incomplete, and response.cancelled (#23492)
* Handle response.failed, response.incomplete, and response.cancelled terminal events in background streaming

Previously the background streaming task only handled response.completed and
hardcoded the final status to "completed". This missed three other terminal
event types from the OpenAI streaming spec, causing failed/incomplete/cancelled
responses to be incorrectly marked as completed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

* Remove unused terminal_response_data variable

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

* Address code review: derive fallback status from event type, rewrite tests as integration tests

1. Replace hardcoded "completed" fallback in response_data.get("status")
   with _event_to_status lookup so that response.incomplete and
   response.cancelled events get the correct fallback if the response
   body ever omits the status field.

2. Replace duplicated-logic unit tests with integration tests that
   exercise background_streaming_task directly using mocked streaming
   responses and assert on the final update_state call arguments.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

* Remove dead mock_processor and unused mock_response parameter from test helper

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

* Remove FastAPI and UserAPIKeyAuth imports from test file

These types were only used as Mock(spec=...) arguments. Drop the spec
constraints and remove the top-level imports to avoid pulling FastAPI
into test files outside litellm/proxy/.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

* Log warning when streaming response has no body_iterator

If base_process_llm_request returns a non-streaming response (no
body_iterator), log a warning since this likely indicates a
misconfiguration or provider error rather than a successful completion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Committed-By-Agent: claude

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 23:02:09 -07:00
Pradyumna Yadav a94b961c18 fix: auto-fill reasoning_content for moonshot kimi reasoning models in multi-turn tool calling (#23580) 2026-03-13 22:48:45 -07:00
Awais Qureshi c7ba7948bc PR #22867 added _remove_scope_from_cache_control for Bedrock and Azur… (#23183)
* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

---------

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-13 22:41:25 -07:00
Ethan T. 7bb2d78394 fix: add getPopupContainer to Select components in fallback modal to fix z-index issue (#23516)
The model dropdown menus in the Add Fallbacks modal were rendering behind
the modal overlay because Ant Design portals Select dropdowns to document.body
by default. By setting getPopupContainer to attach the dropdown to its parent
element, the dropdown inherits the modal's stacking context and renders above
the modal.

Fixes #17895
2026-03-13 21:58:58 -07:00
RoomWithOutRoof a0a951b34f fix: forward extra_headers to HuggingFace embedding calls (#23525)
Fixes #23502

The huggingface_embed.embedding() call was not receiving the headers
parameter, causing extra_headers (e.g., X-HF-Bill-To) to be silently
dropped. Other providers (openrouter, vercel_ai_gateway, bedrock) already
pass headers correctly. This fix adds headers=headers to match the
behavior of other providers.

Co-authored-by: Jah-yee <sparklab@outlook.com>
2026-03-13 21:54:43 -07:00
Shivam Rawat 2405e0d400 Merge pull request #23592 from BerriAI/docs_per_model_tpm_rpm_for_teams
added doc
2026-03-13 17:35:43 -07:00
shivam 546ecfb084 added doc 2026-03-13 17:24:15 -07:00
yuneng-jiang 6549b4583f Merge pull request #23591 from BerriAI/litellm_internal_dev_03_12_2026
[Infra] Merge internal dev branch to main
2026-03-13 16:43:35 -07:00
yuneng-jiang 811ce13ad4 Merge pull request #23590 from BerriAI/litellm_refactor_update_key_fn
[Refactor] Extract validation from update_key_fn to fix PLR0915 lint
2026-03-13 16:33:34 -07:00
yuneng-jiang 1d403e9bd8 refactor(key_management): extract validation logic from update_key_fn to fix PLR0915
Extract permission checks and constraint validation from update_key_fn
into _validate_update_key_data helper to reduce statement count below
the 50-statement limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:29:28 -07:00
yuneng-jiang 85e5ef45d3 Merge pull request #23589 from BerriAI/litellm_fix_responses_background_cost_tests
[Fix] Update Outdated test_responses_background_cost Assertions
2026-03-13 16:23:44 -07:00
yuneng-jiang 3aeca22031 fix(test): update test_responses_background_cost assertions for pagination and stale cleanup
Tests were outdated after #23472 added pagination (take/order) to find_many
and stale-row cleanup via update_many. Updated assertions to match new call
signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:18:15 -07:00
yuneng-jiang dca231e3f6 Merge pull request #23557 from BerriAI/litellm_ui_key_org-2
[Feature] Allow Setting organization_id on Key Update
2026-03-13 16:10:35 -07:00
yuneng-jiang 818c097ca9 Fix self-exclusion hash mismatch and missing throughput field checks
The self-exclusion filter compared raw key strings against SHA-256
hashed tokens from the DB, so keys were never excluded and
double-counting persisted. Now hash data.key before comparison.

Also add tpm_limit_type/rpm_limit_type to _throughput_fields_changed
guard, fall back to existing_key_row.team_id for team limit checks
(matching the org pattern), and add team self-exclusion test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:59:23 -07:00
yuneng-jiang 1038a119ce Skip org limit check when non-throughput fields are updated
Only run org validation (get_org_object + _check_org_key_limits) when
the update actually touches throughput-related fields (tpm_limit,
rpm_limit, or organization_id). Previously, any update to a key
belonging to an org would trigger the check, which would fail with a
400 if the org had been deleted — blocking unrelated field changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:38:42 -07:00
yuneng-jiang 133471f882 Fix double-counting bug in org/team key limit checks on update
When updating a key, _check_org_key_limits and _check_team_key_limits
would include the key being updated in the find_many results, causing
its current limits to be counted twice (once from the DB query, once
from the new requested limits). This caused false 400 errors on valid
limit adjustments.

Fix: exclude the key being updated (by matching token) from the
allocated totals before checking limits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:27:56 -07:00
yuneng-jiang 0b3dc00440 Merge remote-tracking branch 'origin' into litellm_internal_dev_03_12_2026 2026-03-13 15:11:49 -07:00
yuneng-jiang 0e44c460b5 Merge pull request #23584 from BerriAI/litellm_release_day_03_12_2026
[Infra] Merge Release Day Branch with Main
2026-03-13 14:31:27 -07:00
yuneng-jiang f351bbdb36 [Fix] Derive SPEND_PER_REQUEST dynamically in spend accuracy tests
Instead of hardcoding SPEND_PER_REQUEST (which broke when the model
changed from gpt-3.5-turbo-0301 to gpt-3.5-turbo), make a single
calibration request first, poll for its spend, and use that as the
per-request cost. Fails fast with pytest.fail() after 5 retries if
calibration cannot determine the cost.

Also fixes a bug in test_basic_spend_accuracy where the user spend
assertion error message referenced user_info['info'] instead of
user_info['user_info'].

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
v1.82.2-nightly
2026-03-13 13:27:06 -07:00
yuneng-jiang f5662eeb8a [Fix] Update otel and spend tracking test configs to use gpt-3.5-turbo
Same deprecated model fix as proxy_server_config.yaml — these two CI
configs also referenced gpt-3.5-turbo-0301 which has no pricing data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 13:08:36 -07:00
yuneng-jiang 3ec7c2a81e [Fix] Fail fast when team member spend not flushed in time
Increase wait timeout to 90s and pytest.fail() instead of silently
continuing, so the failure message points at the real cause.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:40:17 -07:00
yuneng-jiang e2779639c0 [Fix] Fix test_users_in_team_budget using model with no pricing data
gpt-3.5-turbo-0301 was removed from the model cost map, so every call
had response_cost=0 and team member spend never increased. The wait
helper also returned True after 3s regardless of whether spend updated.

- Switch fake-openai-endpoint to gpt-3.5-turbo (has pricing in cost map)
- Remove premature early-return in wait_for_team_member_spend_update

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:35:20 -07:00
yuneng-jiang 4e70254d56 [Fix] Increase _delete_file retry budget to reduce flakiness
Increase max_retries from 6 to 9 and retry_delay from 10s to 20s
(180s total wait, up from 60s) to give batch cost tracking more time
to finish before cleanup attempts file deletion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:32:55 -07:00
yuneng-jiang 57865ec96e Revert "[Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path"
This reverts commit ca2033036f.
2026-03-13 12:21:39 -07:00
yuneng-jiang ca2033036f [Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path
The terminal-state DB shortcut in retrieve_batch returned a LiteLLMBatch
with empty _hidden_params, causing the managed_files hook to skip encoding
output_file_id into a unified ID. This adds the same model_id extraction
from unified_batch_id that the non-terminal path already has.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:14:58 -07:00
yuneng-jiang 5b755db329 [Fix] Correct mypy fixes for realtime_api and presidio
- realtime_api/main.py: Revert param types to Dict, explicitly construct
  RealtimeSessionConfig/RealtimeExpiresAfter before passing to
  RealtimeClientSecretRequest
- presidio.py: Move type:ignore[override] to def line where mypy reports it

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:10:27 -07:00
yuneng-jiang 1f71578de2 [Fix] Add flaky reruns to test_e2e_managed_batch
The test_e2e_managed_batch test intermittently fails during cleanup
when deleting the input file — the batch cost tracking hasn't finished
processing yet (batch_processed=true not set), causing a 400 error.
This is a timing race condition unrelated to batch retrieval logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:57:22 -07:00
yuneng-jiang e40ebf262a Revert "[Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path"
This reverts commit 1642a2f7ac.
2026-03-13 11:57:22 -07:00
yuneng-jiang 25e161a0fa fix(tests): remove test_completion_bedrock_claude_sts_oidc_auth and test_completion_bedrock_httpx_command_r_sts_oidc_auth that depend on external infra
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:53:53 -07:00
yuneng-jiang efe6ddfc68 Merge pull request #23577 from Sameerlite/litellm_gpt54-tools-reasoning-routing
feat(openai): route gpt-5.4+ tools+reasoning to Responses API
2026-03-13 11:49:46 -07:00
Sameer Kankute 7dce61ce48 fix(tests): update TestGPT5ReasoningEffortPreservation for dict normalization
Made-with: Cursor
2026-03-14 00:13:16 +05:30
yuneng-jiang a6ab172db0 [Fix] Use type:ignore instead of Union return type for realtime endpoint
The Union[RealtimeClientSecretResponse, Response] annotation breaks
FastAPI's response model generation. Revert to the original annotation
and suppress mypy on the error-path return instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:42:26 -07:00
yuneng-jiang 57397e0d26 Merge pull request #23576 from Sameerlite/litellm_gpt54-tools-reasoning-routing
Litellm gpt54 tools reasoning routing
2026-03-13 11:38:50 -07:00
yuneng-jiang 1642a2f7ac [Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path
The terminal-state DB shortcut in retrieve_batch returned a LiteLLMBatch
with empty _hidden_params, causing the managed_files hook to skip encoding
output_file_id into a unified ID. This adds the same model_id extraction
from unified_batch_id that the non-terminal path already has.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:38:09 -07:00
Sameer Kankute 408b717cb9 Fix gpt 5 transformation tests 2026-03-14 00:00:02 +05:30
Sameer Kankute 30645d683f Reserve reasoning for responses via chat completion 2026-03-13 23:59:57 +05:30
Sameer Kankute 7abbe2dc06 Fix routing of tool call + reasoning effor for gpt-5.4 2026-03-13 23:59:53 +05:30
Sameer Kankute 3596464d11 Revert "feat(openai): drop reasoning_effort for gpt-5.4 when tools present"
This reverts commit 14b52b1318.
2026-03-13 23:59:48 +05:30
yuneng-jiang e88ee338bd [Fix] Resolve 7 mypy linting errors across 5 files
- realtime_api/main.py: Widen param types to accept both Dict and Pydantic models
- proxy/realtime_endpoints/endpoints.py: Widen return type to Union[..., Response]
- proxy/guardrails/guardrail_hooks/presidio.py: Add type:ignore[override] for bytes in streaming return
- proxy/_experimental/mcp_server/rest_endpoints.py: Annotate _oauth2_flow with Literal type
- proxy/management_endpoints/ui_sso.py: Add httpx import under TYPE_CHECKING, remove invalid timeout kwarg from AsyncHTTPHandler.get()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:21:49 -07:00
yuneng-jiang 6a90596377 updating Dockerfile to tar 7.5.11 2026-03-13 11:16:17 -07:00
Ishaan Jaff 1b96064600 fix(proxy): prevent OOM/Prisma connection loss from unbounded managed-object poll (#23472)
* fix(proxy): cap managed-object poll size + expire stale rows + kill-switch flag to prevent OOM/Prisma connection loss

* fix(constants): simplify PROXY_BATCH_POLLING_ENABLED readability

* docs+test: document new polling env vars, add pagination+stale-cleanup tests

* fix: exclude stale_expired from batch poll queries; fix update_many assertions in tests

* fix: scope stale cleanup to file_purpose, fix file_object mocks, add CheckBatchCost tests

* fix: avoid duplicate cost logging in fallback path; guard integer constants against zero/negative values

* fix: cache _has_batch_processed_column; guard cleanup from aborting poll; narrow fallback except

* fix: add complete/completed to primary query not_in; fix vacuous test assertion

- Primary find_many was missing "complete" and "completed" in its not_in
  filter, creating asymmetry with the fallback query. A job whose status
  was set to "complete" but whose batch_processed flag update failed would
  be silently re-fetched and re-processed every cycle, emitting duplicate
  cost logs.

- test_fallback_completion_update_omits_batch_processed patched
  _is_base64_encoded_unified_file_id to return None, causing an immediate
  continue — so update() was never called and the assertion looped over an
  empty list (vacuously true). Rewrote the test to mock the full
  completion pipeline, verify update() is called exactly once, and assert
  batch_processed is absent from the update data.

- Added symmetric test (primary path) proving batch_processed IS included
  when the column exists.

Made-with: Cursor
2026-03-13 11:01:40 -07:00
yuneng-jiang 488a4d2b63 bumping tar for security 2026-03-13 10:43:16 -07:00
yuneng-jiang 0fbfb8e772 fix(tests): remove test_oidc_circle_v1_with_amazon_fips that depends on external infra
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:33:52 -07:00
yuneng-jiang 9ad2223531 [Fix] Convert _has_attribute_error_in_chain from recursive to iterative
The recursive implementation was flagged by the recursive function detector
lint check. Converted to an iterative approach using an explicit stack and
seen set, with depth capped at DEFAULT_MAX_RECURSE_DEPTH.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:24:01 -07:00
yuneng-jiang 4c3a4e6c38 Merge pull request #23566 from BerriAI/revert-23535-litellm_improve_qa-5.4
Revert "QA:  improve gpt-5.4 code/bugs"
2026-03-13 10:16:34 -07:00
yuneng-jiang 2b71b0fb25 Revert "QA: improve gpt-5.4 code/bugs" 2026-03-13 10:15:47 -07:00