Commit graph

32819 commits

Author SHA1 Message Date
Ishaan Jaffer
70cb86befa emit status events during variation generation so UI shows progress 2026-02-18 20:19:24 -08:00
Ishaan Jaffer
0878c7f812 add refinement input for iterating on competitor list with AI 2026-02-18 20:15:55 -08:00
Ishaan Jaffer
00bc862030 add instruction and existingCompetitors params to streaming enrichment 2026-02-18 20:15:50 -08:00
Ishaan Jaffer
0a88980aa4 add refinement instruction support for competitor discovery 2026-02-18 20:15:40 -08:00
Ishaan Jaffer
2ccfa903ae validate competitors list size, cap variation prompt input 2026-02-18 20:04:20 -08:00
Ishaan Jaffer
175a33a4b1 use llm_router instead of litellm.acompletion, extract helpers, move constants 2026-02-18 20:01:29 -08:00
Ishaan Jaffer
96a02347a8 show discovered competitors as tags in guardrail selection modal 2026-02-18 19:56:18 -08:00
Ishaan Jaffer
3d86aa8d5c update policies panel to pass enrichment options and show discovered competitors 2026-02-18 19:56:14 -08:00
Ishaan Jaffer
46c592bb60 rewrite template parameter modal with streaming tags, AI/manual toggle, model selector 2026-02-18 19:56:10 -08:00
Ishaan Jaffer
3a004d05d6 add streaming enrichPolicyTemplate networking function 2026-02-18 19:56:06 -08:00
Ishaan Jaffer
0ebd0b12d7 add streaming enrichment endpoint, competitor variations, and model selection 2026-02-18 19:55:57 -08:00
Ishaan Jaffer
d6626893bd sync policy_templates_backup.json with policy_templates.json 2026-02-18 19:55:34 -08:00
Ishaan Jaffer
2eb89803d1 update policy templates with competitor pre/post guardrails and streaming enrichment 2026-02-18 19:55:30 -08:00
Ishaan Jaffer
76568b4dae fix airline brand protection filter: add identifier words, competitor/ops block words, tighten exceptions 2026-02-18 19:55:11 -08:00
Ishaan Jaffer
bd61f3e69d fix aviation safety topic filter: remove overly broad exceptions, add cockpit access block words 2026-02-18 19:55:11 -08:00
Sameer Kankute
4773838561
Merge pull request #21531 from BerriAI/litellm_cicd_190226
Litellm cicd 190226
2026-02-19 09:07:25 +05:30
Ishaan Jaff
0486161bea
feat(ui): add CSV dataset upload to compliance playground (#21526) 2026-02-19 03:33:18 +00:00
Sameer Kankute
0664604fda Fix:test_standard_logging_payload_stream_usage 2026-02-19 08:47:09 +05:30
Sameer Kankute
51146c4c94 Fix:test_anthropic_messages_with_all_beta_headers 2026-02-19 08:35:38 +05:30
Krish Dholakia
e00c181f0c
Mcp user permissions (#21462)
* feat(schema.prisma): add object permissions for end users

allows controlling if end user can call specific mcp servers

* feat: cleanup for customer_endpoints support of object permission id

* fix: cleanup str

* feat(customers/): enforce end user can only call allowed mcps - if configured

* docs: document customer/end user object permission usage

* feat: enforce end user permissions on MCP tool calls

This commit implements end user permission enforcement for MCP servers:

1. Always add server prefixes to MCP tool names
   - Removed conditional logic that only added prefixes when multiple servers existed
   - Now always adds server prefix for consistent tool naming across all scenarios
   - Updated 5 locations in server.py (list_tools, get_prompts, get_resources,
     get_resource_templates, get_prompt)

2. Created MCP End User Permission Guardrail Hook
   - New guardrail hook: litellm/proxy/guardrails/guardrail_hooks/mcp_end_user_permission.py
   - Runs on post_call to validate tool calls in LLM responses
   - Extracts MCP server name from tool names (splits on first '-')
   - Checks if end_user_id has permissions for the MCP server
   - Raises GuardrailRaisedException if end user lacks permission
   - Supports both streaming and non-streaming responses

3. Added comprehensive tests
   - Test file: tests/test_litellm/proxy/guardrails/guardrail_hooks/test_mcp_end_user_permission.py
   - Tests cover: authorized/unauthorized tools, non-MCP tools, no end_user scenarios
   - Tests permission checking logic and exception raising

The hook integrates with the existing MCPRequestHandler._get_allowed_mcp_servers_for_end_user
to fetch end user permissions and enforce access control at the response level.

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

* refactor: remove redundant add_prefix variable assignments

Simplified the code by removing intermediate `add_prefix` variable
assignments and passing `True` directly to function calls since
we now always add server prefixes.

Changes:
- Removed `add_prefix = True` variable assignments in 5 locations
- Changed `add_prefix=add_prefix` to `add_prefix=True` in function calls
- Added inline comments to clarify the behavior

This makes the code more concise and clearer in intent.

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

* feat(auth_utils.py): support safety_identifier as a valid way of passing the end user id for responses api

* feat(llms): ensure 'tools' is correctly updated for responses api

* fix: fix greptile feedback

* feat: transformation.py

proper responses api tool handling for guardrail translation layer

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-18 18:53:59 -08:00
Ishaan Jaffer
936e04e0e1 fix: add missing Field import in policy_endpoints.py
Co-Authored-By: Warp <agent@warp.dev>
2026-02-18 18:28:31 -08:00
Ishaan Jaff
91fd2b4621
Add aviation and UAE policy templates with tag-based filtering (#21518)
* add aviation and UAE regex patterns (PNR, Skywards, Emirates ID, UAE phone, flight number)

* add aviation safety topics category yaml

* add airline brand protection category yaml

* add UAE cultural sensitivity category yaml

* add UAE anti-discrimination category yaml

* add aviation, UAE, and competitor policy templates + migrate region/type to tags

* sync policy_templates_backup.json

* add /policy/templates/enrich endpoint for LLM competitor discovery

* add enrichPolicyTemplate networking call

* add TemplateParameterModal component

* handle parameterized templates and LLM enrichment in policies index

* replace region/type radio filters with tag sidebar checkboxes
2026-02-18 18:26:24 -08:00
Krish Dholakia
a385126a7c Litellm dev compliance UI (#21457)
* feat(ui/): initial commit adding a compliance testing playground

allow proxy admins to test policies and guardrails against datasets

* feat(ui/): make score more friendly

* feat(policy_endpoints.py): new helper function for testing policies

* feat(policy_endpoints.py): expose new endpoint for testing policies and guardrails

enables compliance playground to work as expected

* feat(complianceui.tsx): show returned text
2026-02-18 18:22:43 -08:00
Ishaan Jaff
323aed7211
fix: CI failures - missing env key doc + streaming test (#21510)
* docs: add DATABRICKS_API_KEY to environment settings reference

* fix: streaming test usage check on Pydantic model

* fix: mock litellm.proxy.proxy_server in test_skip_server_startup
2026-02-18 18:20:32 -08:00
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
jquinter
d75bb10c5f
Merge pull request #21506 from BerriAI/fix/enterprise-install-wrong-venv
fix(ci): install enterprise package into main project venv, not enterprise's own venv
2026-02-18 21:31:48 -03:00
Julio Quinteros Pro
24ead9b4e1 fix(ci): install enterprise package into main project venv, not enterprise's own venv
Running `cd enterprise && poetry run pip install -e .` causes poetry to
create a separate venv in `enterprise/.venv` (since enterprise/ has its
own pyproject.toml). The main project's tests run with `.venv/bin/python`,
so the enterprise package installed in `enterprise/.venv` is never seen.

Fix: run `poetry run pip install -e enterprise/` from the repo root so
poetry uses the main project's venv. This ensures litellm_enterprise is
importable when tests run.

This explains why enterprise tests kept failing with:
  AttributeError: '_PROXY_LiteLLMManagedFiles' object has no attribute
  '_check_file_deletion_allowed'
even after --force-reinstall was added — the reinstall was going to the
wrong virtual environment.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 21:24:06 -03: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
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
jquinter
d01adf58f5
Merge pull request #21484 from BerriAI/fix/mcp-test-isolation
fix(tests): resolve MCP test isolation failures in parallel execution
2026-02-18 19:06:59 -03:00
jquinter
b29ee632d8
Merge pull request #21481 from BerriAI/fix/enterprise-editable-install-ci
fix(ci): force-reinstall enterprise package to override PyPI version
2026-02-18 19:05:50 -03:00
yuneng-jiang
5625fc1537
Merge pull request #21495 from BerriAI/litellm_server_root_path_non_root
[Infra] Change Server Root Path GitHub action test to non root image
2026-02-18 13:56:08 -08:00
Julio Quinteros Pro
bbbac1ae0e fix(ci): apply --force-reinstall --no-deps to enterprise install in all CI configs
The same PyPI-override issue existed in test-litellm.yml, test-mcp.yml,
and .circleci/config.yml. Also adds --no-deps (enterprise has no runtime
deps) to avoid redundant dependency resolution on every forced reinstall.

Addresses greptile review comments on PR #21481.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 18:53:45 -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
jquinter
12f5d6409c
Merge pull request #21499 from BerriAI/fix/model-cost-test-contamination
fix(tests): restore litellm.model_cost after reload endpoint test
2026-02-18 18:49:11 -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
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
yuneng-jiang
d1961072e8 adjusting the server root path test to non root image 2026-02-18 11:56:10 -08:00
Sameer Kankute
69975217d2
Merge pull request #21485 from BerriAI/litellm_fix_Note
Add version in claude-code-beta-headers-incident
2026-02-18 22:55:01 +05:30
Sameer Kankute
fef26cfae2 Add version in claude-code-beta-headers-incident 2026-02-18 22:54:27 +05:30
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
yuneng-jiang
66a33d13a3
Merge pull request #21364 from BerriAI/litellm_ui_key_type_label
[Refactor] UI - Keys: Change Key Type Label
2026-02-18 08:54:41 -08:00
Sameer Kankute
a7da7b53f0
Merge pull request #19143 from emerzon/affinity_callback
Add deployment affinity routing callback
2026-02-18 22:21:02 +05:30
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
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
262c16adf5 fix(ci): force-reinstall enterprise package to override PyPI version
poetry install includes litellm-enterprise from PyPI, then the editable
install step runs. When the same version is already installed, pip may
skip the editable install leaving the PyPI build in place - which may
lack methods added after the latest PyPI release. Adding
--force-reinstall ensures the local editable version always wins.

Fixes enterprise tests failing with AttributeError on methods that exist
locally but not in the cached PyPI-installed package.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 12:02:11 -03:00