Commit graph

8121 commits

Author SHA1 Message Date
yuneng-jiang
2c6095bdf2
Merge pull request #21511 from BerriAI/litellm_store_model_in_db_from_database
[Feature] Allow store_model_in_db to be set via database
2026-02-18 17:43:56 -08:00
yuneng-jiang
64fe3a502e
Merge pull request #21503 from BerriAI/litellm_sso_role_map
fix(sso): preserve SSO role regardless of role_mappings config
2026-02-18 17:31:49 -08:00
yuneng-jiang
6356db560d [Feature] Allow store_model_in_db to be set via database
Users had to set store_model_in_db in the config YAML and restart the proxy,
causing service downtime. This change allows the value to be written to the
LiteLLM_Config table and read from the database at runtime, with DB values
overriding config file values.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-18 17:25:39 -08:00
Shivam Rawat
9ceaa2cbb0
tests and route permissions (#21508) 2026-02-18 16:58:38 -08:00
Ishaan Jaff
6486db3646
fix: improve streaming proxy throughput by fixing middleware and logging bottlenecks (#21501)
* fix(middleware): replace BaseHTTPMiddleware with pure ASGI middleware

BaseHTTPMiddleware wraps streaming responses with receive_or_disconnect
per chunk, blocking the event loop and causing severe throughput
degradation under concurrent streaming load (53% of CPU in profiling).

Converts PrometheusAuthMiddleware to a pure ASGI middleware using the
__call__(scope, receive, send) protocol.

* fix(streaming): remove expensive debug logging and optimize usage stripping

- Remove print_verbose calls that format chunk/response Pydantic objects,
  triggering millions of __repr__ calls (8% of CPU in profiling)
- Guard remaining verbose_logger.debug with isEnabledFor(DEBUG) and use
  lazy %s formatting instead of f-strings
- Replace usage stripping round-trip (model_dump + delete + reconstruct)
  with a _usage_stripped flag, deferring exclusion to serialization time

* fix(proxy): remove per-chunk debug log and use _usage_stripped flag

- Remove verbose_proxy_logger.debug that formatted every streaming chunk
- Honor _usage_stripped flag from streaming handler to exclude usage
  during model_dump_json serialization instead of reconstructing objects

* fix(proxy): remove per-chunk debug log in async_data_generator

Remove verbose_proxy_logger.debug that formatted every streaming chunk,
which triggered expensive Pydantic serialization on the hot path.

* fix indentation and add clarifying comment for usage stripping

* fix: guard calculate_total_usage against None usage in chunks

* fix: store chunk copy to preserve usage for calculate_total_usage
2026-02-18 16:16:49 -08:00
yuneng-jiang
e445694a40 fix(sso): preserve SSO role regardless of role_mappings configuration
When `default_internal_user_params` was set, `insert_sso_user()` only
preserved SSO-provided roles if `role_mappings` was explicitly configured.
Roles from other valid SSO sources (Microsoft app_roles,
GENERIC_USER_ROLE_ATTRIBUTE, custom SSO handlers) were silently
overwritten with the default "internal_user" role, causing admin users
to be downgraded on first login or after user deletion.

Replace the `role_mappings_configured` gate with `_should_use_role_from_sso_response()`
which validates the role is a recognized LitellmUserRoles value regardless
of origin. Also removes an unnecessary DB round-trip to litellm_ssoconfig
on every new SSO user creation.

Fixes: admin users seeing internal-user UI after SSO login
Fixes: test_get_redirect_url_for_sso flaking due to local env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-02-18 15:24:18 -08:00
Julio Quinteros Pro
db615cd721 chore: resolve merge conflict with main
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 19:10:36 -03:00
Julio Quinteros Pro
5fe1dd3ec8 fix(tests): restore initialized_langfuse_clients counter after test
Save and restore litellm.initialized_langfuse_clients around
test_max_langfuse_clients_limit to prevent ordering-dependent failures
in other tests that rely on the counter's value.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 19:09:35 -03:00
jquinter
a9058bb584
Merge pull request #21483 from BerriAI/fix/test-delattr-default-internal-user-params
fix(tests): restore default_internal_user_params instead of delattr-ing it
2026-02-18 19:07:47 -03:00
Julio Quinteros Pro
7b6ffbb52a fix(tests): wrap callbacks cleanup in try/finally and resolve merge conflict
- test_litellm_pre_call_utils.py: wrap test body in try/finally so
  litellm.callbacks is always restored even when an assertion fails,
  addressing greptile review comment
- test_langfuse_otel.py: resolve trivial merge conflict in comment
  ("unpatched" vs "unpatch-ed"), keeping correct spelling

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 18:50:17 -03:00
Julio Quinteros Pro
1c0f4302f8 fix(tests): restore litellm.model_cost after reload endpoint test
test_reload_model_cost_map_admin_access calls the /reload/model_cost_map
HTTP endpoint with get_model_cost_map mocked to return a single-entry
dict. The endpoint handler does a direct module-level assignment
(litellm.model_cost = new_model_cost_map) which persists after the
patch context manager exits, stripping all models except gpt-3.5-turbo
from the in-memory cost map and causing subsequent tests that rely on
models like gemini-1.5-flash, multimodalembedding@001, and gpt-4o to
fail with "model not mapped" errors or zero-cost spend payloads.

Fix: save litellm.model_cost before the test and restore it (along with
invalidating the case-insensitive lookup cache) in a finally block.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 18:20:48 -03:00
Chesars
0ebbec4d0e fix(chatgpt): normalize streaming tool_call indices and deduplicate closing chunks
The ChatGPT backend API sends non-spec-compliant streaming tool call chunks
where index is always 0 for parallel tool calls and id/name get repeated in
duplicate closing chunks. Add ChatGPTToolCallNormalizer to fix indices and
filter duplicates before they reach the consumer.

Fixes #21482
2026-02-18 18:02:36 -03:00
Ishaan Jaff
e8ab773ac4
fix: guard against None metadata in prometheus metrics (#21489)
* fix: guard against None metadata in prometheus metrics

Use get_litellm_metadata_from_kwargs and get_metadata_variable_name_from_kwargs
helpers to properly resolve metadata from both 'metadata' and 'litellm_metadata'
keys, with None safety.

* test: add test for None metadata in prometheus metrics
2026-02-18 12:40:45 -08:00
SolitudePy
7fc29dc9f1 fix: allow github aliases to reuse upstream model metadata
Update provider matching so github/<model> aliases can resolve capabilities from existing upstream model metadata, including OpenAI and Anthropic entries. Add regression tests for known github aliases and unknown-model fallback behavior.
2026-02-18 22:29:15 +02:00
Chesars
fd4dc028bc fix(anthropic): remove hardcoded reasoning summary in adapter
The adapter was injecting `summary: "detailed"` into the reasoning config
when routing Anthropic thinking requests to OpenAI's Responses API.
Per the OpenAI spec, reasoning.summary is opt-in — it should not be
added unless the user explicitly requests it.
2026-02-18 16:52:58 -03:00
Shivam Rawat
7f655be191
Merge branch 'main' into litellm_budget_tier_enforcement_for_keys 2026-02-18 11:24:24 -08:00
Ryan Crabbe
f0a542c55d fix: add .copy() to create_request_copy and tests for header caching
Protect cached headers from mutation in create_request_copy sites and
add unit tests for _safe_get_request_headers caching behavior.
2026-02-18 09:44:35 -08:00
Julio Quinteros Pro
2e0a8b3cf8 fix(tests): resolve MCP test isolation failures in parallel execution
Three test isolation issues fixed:

1. test_mcp_debug.py: Replace deprecated asyncio.get_event_loop().run_until_complete()
   with asyncio.run() in TestWrapSendWithDebugHeaders. In Python 3.10+,
   get_event_loop() raises RuntimeError when no event loop is set in the
   current thread, causing test_injects_headers and test_body_messages_unchanged
   to fail in isolation.

2. test_mcp_server_manager.py: After _reload_mcp_manager_module() creates a new
   global_mcp_server_manager instance, server.py still holds a stale reference
   to the old instance. Tests in test_mcp_server.py that populate the new
   manager's registry and then call server.py functions (e.g. _get_tools_from_mcp_servers)
   get empty results because server.py reads from the old manager. Fix: update
   server.py's module-level reference after each reload.

3. test_litellm_pre_call_utils.py: test_add_litellm_metadata_from_request_headers
   sets litellm.callbacks without restoring it afterward. Add cleanup to restore
   original callbacks after the test to prevent state leaking to subsequent tests.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 14:08:48 -03:00
Julio Quinteros Pro
f542f92026 fix(tests): restore default_internal_user_params instead of delattr-ing it
Four finally blocks in test_internal_user_endpoints.py and one in
test_ui_sso.py used the pattern:

    if original_default_params is not None:
        litellm.default_internal_user_params = original_default_params
    else:
        delattr(litellm, "default_internal_user_params")

Since the attribute is defined in litellm/__init__.py with a default of
None, `getattr(litellm, "default_internal_user_params", None)` returns
None. The else branch then calls delattr(), permanently removing the
attribute from the module for the rest of the process.

Subsequent tests in the same pytest-xdist worker (e.g.
test_add_new_member_* in test_management_helpers_utils.py) then fail
with: AttributeError: module 'litellm' has no attribute
'default_internal_user_params'

Fix: replace all five flawed finally blocks with a simple assignment:
    litellm.default_internal_user_params = original_default_params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 13:33:53 -03:00
Harshit Jain
3949aac2d7
fix identation error by greplite 2026-02-18 21:55:56 +05:30
Emerson Gomes
3dd55a7b61 Merge main into affinity_callback and address deployment affinity review feedback 2026-02-18 10:01:11 -06:00
Julio Quinteros Pro
aa9d97b23d fix(tests): use record.getMessage() instead of record.message for LogRecord
LogRecord objects do not have a .message attribute by default — it is
only populated after the record has been formatted by a Formatter.
The correct way to retrieve the formatted log message is getMessage().

This fixes AttributeError: 'LogRecord' object has no attribute 'message'
in test_cost_calculation_uses_debug_level and
test_batch_cost_calculation_uses_debug_level.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 11:46:32 -03:00
jquinter
45d3d1adfd
Merge pull request #21477 from BerriAI/fix/schema-inference-geo-property
fix(tests): add inference_geo to model prices JSON schema validator
2026-02-18 11:46:03 -03:00
jquinter
63783dbfb2
Merge pull request #21478 from BerriAI/fix/vertex-rerank-merge-conflict
fix(tests): resolve merge conflict in test_vertex_ai_rerank_transformation.py
2026-02-18 11:44:53 -03:00
Harshit Jain
c760318c79
Merge pull request #21449 from Harshit28j/litellm_feat_dataDog_tags
feat(datadog): add 'team' tag to logs, metrics, and cost management
2026-02-18 20:05:32 +05:30
Julio Quinteros Pro
419151dce8 fix(tests): resolve merge conflict in test_vertex_ai_rerank_transformation.py
The file had two unresolved git merge conflict markers from a merge of
litellm_oss_staging_02_17_2026 into main, causing a SyntaxError when
pytest tried to collect the test module.

Kept the instance-level mocking approach (from litellm_oss_staging) for
test_get_complete_url and test_validate_environment, which is consistent
with the rest of the file and avoids class-reference issues caused by
importlib.reload(litellm) in conftest.py.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 11:31:56 -03:00
Julio Quinteros Pro
d4755c8284 fix(tests): add inference_geo to model prices JSON schema
The model_prices_and_context_window_backup.json file has 'inference_geo'
fields (e.g. on 'us/claude-sonnet-4-6') for geo-prefixed Anthropic models
used in cost calculation, but the JSON schema validator in test_utils.py
did not include 'inference_geo' as an allowed property.

This caused test_aaamodel_prices_and_context_window_json_is_valid to fail
with: Additional properties are not allowed ('inference_geo' was unexpected)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 11:29:31 -03:00
jquinter
34f06c4242
Merge pull request #21473 from BerriAI/fix/test-proxy-admin-expired-key-cleanup
fix(tests): restore proxy_server module attrs after test_proxy_admin_expired_key_from_cache
2026-02-18 11:22:03 -03:00
jquinter
0d11720586
Update tests/test_litellm/proxy/auth/test_user_api_key_auth.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-02-18 11:21:53 -03:00
Sameer Kankute
a358b7a488
Merge pull request #21475 from BerriAI/litellm_fix_mock_test
Fix mock test
2026-02-18 19:41:15 +05:30
Sameer Kankute
610bf00768 Fix:test_get_key_object_loads_object_permission 2026-02-18 19:18:15 +05:30
Sameer Kankute
3e0a72307c
Merge pull request #21474 from BerriAI/litellm_incident_report_vllm
Incident Report: vLLM Embeddings Broken by encoding_format Parameter
2026-02-18 18:43:11 +05:30
Sameer Kankute
6f82a3ec00
Merge pull request #21456 from BerriAI/litellm_fix_delete_file_managed_access
Add File deletion criteria with batch references
2026-02-18 18:39:45 +05:30
Sameer Kankute
ee3ad3aec4
Merge pull request #21464 from BerriAI/litellm_sanitise_anthropic_mesages_2
Litellm sanitise anthropic mesages 2
2026-02-18 18:39:11 +05:30
Sameer Kankute
d7401965cb
Merge pull request #21468 from BerriAI/litellm_vllm_streaming
Add 'reasoning' field to 'reasoning_content' field in delta
2026-02-18 18:35:28 +05:30
Sameer Kankute
421b4e05b3
Merge pull request #21465 from BerriAI/litellm_map_anthropi_web_search_to_chat
Add mapping for websearch from v1/messages to chat/completions
2026-02-18 18:22:28 +05:30
Sameer Kankute
a9b7320b53 Incident Report: vLLM Embeddings Broken by encoding_format Parameter 2026-02-18 18:19:02 +05:30
Julio Quinteros Pro
30d4f344ae fix(tests): restore proxy_server module attrs in test_proxy_admin_expired_key_from_cache
The test was using setattr() to set module-level attributes (including
proxy_logging_obj = MagicMock()) on the real litellm.proxy.proxy_server
module, but the finally block only had `pass` — no cleanup.

This left proxy_logging_obj as a MagicMock in subsequent tests running
in the same pytest-xdist worker, causing TypeError when log_db_metrics
decorator called asyncio.create_task(proxy_logging_obj.service_logging_obj
.async_service_success_hook(...)) — a MagicMock is not a coroutine.

Fix: save original attribute values before the test and restore them in
the finally block to ensure test isolation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 09:33:11 -03:00
Sameer Kankute
aa255c7e63
Merge pull request #21361 from BerriAI/litellm_oss_staging_02_17_2026
Litellm oss staging 02 17 2026
2026-02-18 17:48:15 +05:30
Sameer Kankute
bd0c80406f
Merge pull request #21326 from BerriAI/litellm_oss_staging_02_16_2026
Litellm oss staging 02 16 2026
2026-02-18 17:47:57 +05:30
Sameer Kankute
4bbd15fe41 Fix test_async_post_call_success_hook_includes_client_ip_user_agent 2026-02-18 17:37:23 +05:30
Sameer Kankute
6a42e997ec
Merge pull request #21469 from BerriAI/revert-21226-fix/pod-lock-atomic-release-delete
Revert "fix: make PodLockManager.release_lock atomic compare-and-delete"
2026-02-18 17:26:43 +05:30
Sameer Kankute
eb8b991260
Merge branch 'main' into litellm_oss_staging_02_17_2026 2026-02-18 17:26:33 +05:30
Sameer Kankute
0e79326c81 Fix cicd tests 2026-02-18 17:25:28 +05:30
Sameer Kankute
53dcebc37a
Revert "fix(pod-lock): make release lock compare-and-delete atomic (#21226)"
This reverts commit f162371b93.
2026-02-18 17:24:34 +05:30
Julio Quinteros Pro
d44d52f1e3 fix(test): correct assertion order in test_case_a_orphaned_tool_call_multiple
The implementation correctly preserves tool_call order: existing results first
(call_1), then dummy results for missing ones (call_2). The test was asserting
the reverse order with incorrect comments. Fix the assertions to match the
actual correct behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 08:25:33 -03:00
Julio Quinteros Pro
dc003e2a94 fix: prevent sys.modules["langfuse"] import failures in langfuse unit tests
Three test failures caused by the real langfuse SDK import being triggered
at test time:

1. test_langfuse_prompt_management.py: Both tests create LangfusePromptManagement()
   which calls `import langfuse`. Since earlier TestLangfuseUsageDetails tests
   remove sys.modules["langfuse"] via patch.dict teardown, the real langfuse
   import runs and fails on Python 3.14 (pydantic v1 incompatibility).
   Fix: add setup_method/teardown_method to mock sys.modules["langfuse"].

2. test_langfuse.py::test_max_langfuse_clients_limit: Same root cause — creates
   LangFuseLogger() without mocking sys.modules["langfuse"].
   Fix: wrap test body with patch.dict("sys.modules", {"langfuse": mock}).

3. test_langfuse_otel.py::test_extract_langfuse_metadata_with_header_enrichment:
   Replaces sys.modules["litellm.integrations.langfuse.langfuse"] with a stub
   without restoring it, causing patch() in later tests to target the stub
   instead of the real module.
   Fix: use monkeypatch.setitem() which auto-restores after the test.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 08:22:23 -03:00
Julio Quinteros Pro
77d1f6932e fix(test): restore default_internal_user_params to None instead of delattr
test_role_mappings_override_default_internal_user_params was calling
delattr(litellm, 'default_internal_user_params') in its finally block
when the original value was None. This removes the attribute entirely from
the module, causing subsequent tests in the same xdist worker to get
AttributeError when accessing litellm.default_internal_user_params (because
litellm.__getattr__ has no handler for this name).

Fix: always restore the attribute by assignment (litellm.default_internal_user_params = original_default_params)
rather than deleting it.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 08:18:13 -03:00
Sameer Kankute
9678c723b0 Add reasoning' field to 'reasoning_content' field in delta 2026-02-18 16:47:05 +05:30
Harshit Jain
78e6080ed7
Merge branch 'main' of https://github.com/BerriAI/litellm into litellm_feat_dataDog_tags 2026-02-18 16:29:01 +05:30