Commit graph

41449 commits

Author SHA1 Message Date
Yuneng Jiang
5be4ed911e
fix: preserve trailing slash when joining pass-through paths
posixpath.normpath strips trailing slashes, which silently changed
endpoints like /v1/models/ to /v1/models. Track whether the original
input ended in a slash and re-append it after normalization.
2026-04-24 18:23:59 -07:00
Mateo Wang
0beec45c13
[Feat] Add azure/gpt-5.5 + azure/gpt-5.5-pro entries (+ dated variants) (#26361)
Some checks failed
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
CodSpeed Benchmarks / benchmarks (push) Has been cancelled
Helm unit test / unit-test (push) Has been cancelled
Read Version from pyproject.toml / read-version (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (auth-checks, tests/proxy_unit_tests/test_auth_checks.py tests/proxy_unit_tests/test_user_api_key_auth.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (key-generation, tests/proxy_unit_tests/test_key_generate_prisma.py, 30, 0) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (proxy-utils, tests/proxy_unit_tests/test_proxy_utils.py, 20, 8) (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-db (remaining, tests/proxy_unit_tests --ignore=tests/proxy_unit_tests/test_key_generate_prisma.py --ignore=tests/proxy_unit_tests/test_auth_checks.py --ignore=tests/proxy_unit_tests/test_user_api_key_auth.py --ignore=tests/proxy_unit_tests/test_p… (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
GitHub Actions Security Analysis / zizmor (push) Has been cancelled
* feat(azure): add azure/gpt-5.5 + azure/gpt-5.5-pro entries (+ dated variants)

Azure variants of OpenAI's GPT-5.5 family. Microsoft has not yet
shipped GPT-5.5 on Azure OpenAI (latest GA on the Foundry models page
is GPT-5.4 as of 2026-04-24), but adding the entries day-0 mirrors the
established precedent for azure/gpt-5.4* (which were in the cost map
before the Azure rollout) so cost tracking and capability flags work
the moment customers deploy.

Schema follows the existing azure/gpt-5.4* shape:
- Same base/long-context pricing as openai/gpt-5.5*: $5/$30 chat,
  $60/$360 pro per 1M, with priority tier 2x base
- Azure variants drop the flex/batches keys (Azure has no flex tier)
  but keep priority pricing, matching gpt-5.4* precedent
- mode=chat for the thinking model, mode=responses for pro

reasoning_effort capability flags mirror the OpenAI variants exactly
since Azure proxies the same API contract: minimal rejection on both
chat and pro, low/none rejection on pro. Once #26456 (which sets
supports_low_reasoning_effort + minimal=false on openai/gpt-5.5*)
lands, OpenAI and Azure flag profiles align.

Tests pin entry presence + pricing for all four Azure variants and
verify the live-API-derived reasoning_effort flags.

* test: register supports_low_reasoning_effort in cost-map JSON schema

azure/gpt-5.5-pro and azure/gpt-5.5-pro-2026-04-23 added in this branch
carry supports_low_reasoning_effort=false. The strict
'additionalProperties: false' schema in
test_aaamodel_prices_and_context_window_json_is_valid rejected the new
key. Register it alongside the other supports_*_reasoning_effort
entries.

Note: the runtime side of this flag (code that reads it) lands in
#26456. Until that PR merges the flag is inert for both Azure and
OpenAI pro entries, but having the schema accept it lets cost-map
tests pass on either merge order.
2026-04-24 18:10:21 -07:00
Yuneng Jiang
961672efa2
fix: harden pass-through target URL construction
Use posixpath-based joining when combining the operator-configured base
target with request subpaths and provider endpoint paths so any path
prefix on the base URL is preserved and '..' segments cannot climb out
of it. Adds a shared HttpPassThroughEndpointHelpers.join_base_and_endpoint_path
helper and routes the generic and provider pass-through handlers
(Anthropic, Gemini, Mistral, Cohere, Cursor, Milvus, OpenAI, etc.)
through it.
2026-04-24 18:09:49 -07:00
yuneng-jiang
9521b74e9a
Merge pull request #26464 from BerriAI/litellm_team_metadata_hardening
Some checks failed
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
[Fix] Harden team metadata handling in /team/new and /team/update
2026-04-24 17:57:15 -07:00
milan-berri
3c0d172d4e
fix(proxy): single-team DB fallback when JWT has no team_id (#26418)
* fix(proxy): infer team from DB when JWT has no team and user has one team

- When team_id is unset after JWT auth but the user row has exactly one
  team, set team_id, team_object, and team_membership from DB.
- Skip when zero or multiple teams (ambiguous).
- Add parametrized unit tests in test_handle_jwt.py.

Made-with: Cursor

* fix(proxy): JWT single-team DB fallback: catch errors, tests match get_team_object

- Wrap get_team_object + get_team_membership in one try/except; log and skip on failure (stale/missing team id no longer fails auth).
- Parametrize tests: HTTP 404/500, membership error; use side_effect not return_value=None for missing team row.

Made-with: Cursor

* refactor(jwt): extract single-team fallback into _resolve_single_team_fallback helper

Made-with: Cursor
2026-04-24 17:51:42 -07:00
harish-berri
f08a8534ab fix failing test
Some checks failed
Unit Tests: Caching (Redis) / caching-redis (push) Has been cancelled
Unit Tests: Proxy DB Operations / assert-shard-coverage (push) Has been cancelled
Unit Tests: Security / security (push) Has been cancelled
Unit Tests: Proxy DB Operations / custom-logging (push) Has been cancelled
Unit Tests: Proxy DB Operations / logging-misc (push) Has been cancelled
Unit Tests: Proxy DB Operations / auth-checks (push) Has been cancelled
Unit Tests: Proxy DB Operations / budgets (push) Has been cancelled
Unit Tests: Proxy DB Operations / db-and-spend (push) Has been cancelled
Unit Tests: Proxy DB Operations / endpoints-and-responses (push) Has been cancelled
Unit Tests: Proxy DB Operations / guardrails-hooks (push) Has been cancelled
Unit Tests: Proxy DB Operations / jwt-and-keys (push) Has been cancelled
Unit Tests: Proxy DB Operations / key-generation (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-runtime (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-server-core (push) Has been cancelled
Unit Tests: Proxy DB Operations / schema-migration (push) Has been cancelled
Unit Tests: Proxy DB Operations / proxy-utils (push) Has been cancelled
2026-04-25 00:44:59 +00:00
user
0a4640fbd0
fix(mcp): don't coerce ProxyException.code with int()
Greptile flagged a regression introduced in the previous commit's merged
exception handler: ``ProxyException.__init__`` normalizes ``code`` via
``str(code)``, so a ``code=None`` (valid per the type signature) becomes
the string ``"None"``. Coercing that with ``int(...)`` raises
``ValueError``, which propagates uncaught and rewrites the auth error as
an unhandled 500 — degrading security posture compared to the pre-merge
``str(e.code) in ("401", "403")`` shape.

Compare against both int and str forms of the auth-error codes instead
of coercing. Adds a regression test for the ``code=None`` case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 00:42:43 +00:00
yuneng-jiang
7723a54478
Merge pull request #25677 from BerriAI/litellm_migration_projects
[Refactor] Proxy: move projects management to enterprise package
2026-04-24 17:40:33 -07:00
yuneng-jiang
91d6626254
Merge pull request #25808 from BerriAI/litellm_sendInviteEmailToggle
[Feature] UI - Users: Add Send Invitation Email Toggle
2026-04-24 17:40:14 -07:00
harish-berri
b3c6566ee0 Merge origin/litellm_internal_staging into litellm_token_verification_query_opt
Conflicts resolved:
- docs/my-website/docs/proxy/config_settings.md: deleted (docs moved to litellm-docs repo)
- litellm/proxy/auth/handle_jwt.py: kept both CacheCodec import (our branch) and RouteChecks import (staging)

Made-with: Cursor
2026-04-25 00:34:43 +00:00
Yuneng Jiang
0a729388f1
fix: harden team metadata handling in /team/new and /team/update
Restrict caller-supplied metadata so server-owned keys can only be set by
the code paths that manage the underlying rows.
2026-04-24 17:27:17 -07:00
harish-berri
77847752fa feat(auth): add Prometheus metrics for combined_view SQL queries
- Introduced `litellm_auth_combined_view_queries_total` metric to track the number of combined_view SQL queries issued for virtual-key authentication.
- Added `AuthMetrics` class to encapsulate metric incrementing logic.
- Updated relevant code to increment the new metric on database lookups, aiding in the validation of Redis cache effectiveness.
- Updated Prometheus metric definitions to include the new auth diagnostic metrics.
2026-04-25 00:21:33 +00:00
yuneng-jiang
fdac444956
Merge pull request #26390 from BerriAI/litellm_guardrail_param_masking
[Fix] Guardrail param handling in list and submission endpoints
2026-04-24 17:20:07 -07:00
user
73869f0faf
fix(mcp): tighten public-route detection and OAuth2 fallback gating
Two related issues in `MCPRequestHandler.process_mcp_request`:

1. Public-route detection used `".well-known" in str(request.url)`, a
   substring match against the full URL. Attackers could smuggle the
   marker via the query string, hostname, or a deeper path segment to
   bypass authentication on any MCP route. Replaced with an exact path
   prefix on `request.url.path` (`startswith("/.well-known/")`).

2. The OAuth2 passthrough fallback (added in #20602 to support
   `auth_type=oauth2` upstream MCP servers like Atlassian) caught any
   401/403 from `user_api_key_auth` and replaced the result with an
   anonymous `UserAPIKeyAuth()`. That fallback fired regardless of the
   target server's configured `auth_type`, so an attacker presenting a
   garbage `Authorization` header could exchange a failed LiteLLM auth
   for an anonymous session against any server. The fallback now runs
   only when EVERY MCP server the request targets is operator-configured
   for `auth_type=oauth2`. For any non-oauth2 server (api_key,
   bearer_token, basic, etc.), the auth error propagates as before.

Target resolution prefers the `x-mcp-servers` header when present
(including the explicitly-empty case, which fails closed) and otherwise
parses the standard `/mcp/{server_name}` and `/{server_name}/mcp`
transport URL patterns. Routes that don't match either form fail closed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 00:18:36 +00:00
ishaan-berri
8a9faa81b2
feat(guardrails): LLM-as-a-Judge guardrail (#26360)
* feat(guardrails): add LLM_AS_A_JUDGE to SupportedGuardrailIntegrations

* feat(types): add EvalVerdict, StandardLoggingEvalInformation; wire eval_information into SpendLogsMetadata

* feat(guardrails): add self-contained llm_as_a_judge guardrail hook

* fix(a2a): filter agent-only litellm_params from acompletion kwargs; pass agent_id into body

* feat(ui): add LLMJudgeFields criteria builder component

* feat(ui): wire LLM-as-a-Judge into add guardrail form

* feat(ui): update EvalViewer — title 'LLM Judge Results', weighted score column, summary row

* fix(ui): wire EvalViewer into LogDetailContent to show LLM judge results on logs page

* fix(guardrails-ui): route llm_as_a_judge to criteria builder step; rename to LiteLLM LLM as a Judge; add litellm logo

* fix(guardrail-viewer): stack lifecycle + eval details vertically to avoid badge overflow in narrow drawer

* fix(guardrail-create): surface config validation errors on create instead of silently orphaning guardrail in DB

* fix(guardrail-registry): hardcode llm_as_a_judge in initializer registry so it loads regardless of package install path

* fix(llm-as-a-judge): fix P1 code quality issues - validate weights/on_failure, guard pre_call, handle multimodal, move imports to module level, fix spurious finally logging

* fix(guardrail_endpoints): use correct PK field in rollback delete and log rollback failure

* fix(llm_as_a_judge): support Pydantic object in _get_litellm_param fallback chain

* fix(LLMJudgeFields): replace @tremor/react Button with antd Button

* fix(llm_as_a_judge): remove dead registry dicts, fix KeyError in prompt builder, set correct status on judge failure

* test(llm_as_a_judge): add unit tests for guardrail hook

* fix(llm_as_a_judge): remove @log_guardrail_information decorator to fix duplicate guardrail_information entries

The decorator and the manual finally block both called add_standard_logging_guardrail_information_to_request_data, producing two entries per request. The decorator also misclassified HTTPException(422) blocks as guardrail_failed_to_respond (it checks for 400). The finally block correctly tracks status throughout, so removing the decorator is sufficient.

* fix(test_gcs_pub_sub): ignore metadata.eval_information in comparison

* fix(test_spend_management): ignore metadata.eval_information in payload comparison

* fix(types/guardrails): add input_type and messages to ApplyGuardrailRequest

* fix(guardrail_endpoints): pass input_type and messages through apply_guardrail endpoint

* fix(guardrail_endpoints): auto-detect post_call guardrails and use input_type=response

* fix(a2a_endpoints): merge agent litellm_params guardrails into data before post_call hooks

* fix(llm_as_a_judge): use float sum with tolerance for weight validation

* fix(guardrail_registry): split long import line for black formatting

* fix(llm_as_a_judge): guard guardrail_name Optional for mypy

* fix(llm_as_a_judge): set guardrail_status=guardrail_intervened when score fails, regardless of on_failure mode

* fix(a2a_endpoints): use try/finally so deferred spend log fires even when guardrail blocks with 422

* fix(litellm_logging): declare _defer_async_logging and _enqueue_deferred_logging on Logging class for mypy

* fix(logging_worker): restore queue.join() in flush() to wait for in-flight callbacks
2026-04-24 17:15:32 -07:00
Yuneng Jiang
7a91d80f9a
fix(auth): exempt auth=false pass-through endpoints from centralized gate
User-configured pass-through endpoints with ``auth: false`` are
explicitly unauthenticated — the builder short-circuits at
check_api_key_for_custom_headers_or_pass_through_endpoints and returns
a fresh empty UserAPIKeyAuth() without an api_key, user_id, or role.
Pre-refactor, that empty token never reached common_checks. After the
centralization, it does — and common_checks rejects it as admin-only,
breaking every Langfuse / custom unauthenticated pass-through.

This is the same regression class as the public-routes one: a
builder fast-path whose return value cannot survive common_checks.
Honor the same contract here — when the matched endpoint config has
auth != True, skip the centralized gate. auth=True endpoints still
run the full gate (covered by a companion test).

No security regression: ``auth: false`` is the operator's explicit
opt-out from LiteLLM auth on this path. The original commit closed
seven authenticated bypasses; this exemption applies only to a path
the operator has already declared unauthenticated.
2026-04-24 17:04:37 -07:00
Milan
22439a119e
Handle cleanup delete races and accurate counts
Made-with: Cursor
2026-04-25 03:01:34 +03:00
Yuneng Jiang
3560823196
fix(passthrough): strip Server/Date/Connection from upstream response headers
The passthrough helper copied the upstream provider's Server: header
(e.g. "cloudflare" from Anthropic) onto the FastAPI response. uvicorn
then added its own Server: header on top, producing two Server: lines
in the wire response. Strict HTTP parsers (aiohttp's, used in CI's
passthrough tests) reject this with "Duplicate 'Server' header found"
and the request fails with a 400.

Same risk for Date, Content-Length, Connection, Keep-Alive: the ASGI
server writes its own copy at serialization time. Forwarding the
upstream's value either duplicates the header or lies about the
re-serialized body length.

Drop these from the forwarded set. Application/business headers
(content-type, x-request-id, anthropic-ratelimit-*, etc.) still pass
through unchanged.
2026-04-24 16:56:44 -07:00
Yuneng Jiang
06e3691bc3
fix(auth): exempt public routes and trust admin token role in centralized authz gate
Two regressions introduced by 3737d6a1f3 (centralized common_checks):

1. Public routes (e.g. /health/readiness, /metrics) are exempted by the
   builder fast-path but the wrapper then ran common_checks on the
   synthetic INTERNAL_USER_VIEW_ONLY token, which has no user_id, no
   team, no scopes — so common_checks rejected the request as admin-
   only. This broke every k8s readiness probe when master_key is set
   (helm chart job confirmed: pod never goes Ready, service has no
   endpoints).

2. The admin user_object synthesis only triggered when
   user_object is None. After any team-creation flow runs, the row
   for litellm_proxy_admin_name (default "default_user_id") exists
   in litellm_usertable with the default user_role=internal_user.
   get_user_object then returned that row, the synthesis was skipped,
   and master_key requests were demoted to internal_user — failing
   /team/update, /team/block, etc. The token's user_role is the
   source of truth for these paths (set inside the authenticated
   master_key / JWT-admin builders); a stale DB row must not override
   it.

Fix:
- Short-circuit _run_centralized_common_checks for routes already in
  LiteLLMRoutes.public_routes (or general_settings.public_routes).
  Same exemption surface the builder already trusts.
- When the token's user_role is PROXY_ADMIN, force the synthesized
  admin user_object regardless of what get_user_object returned.
  Preserves the spend value from the DB row.

Neither change reopens any of the seven bypasses the original commit
closed: OAuth2, JWT non-admin, DB-fallback, /user/auth, pass-through
headers, etc., still go through the gate. Only paths that were
already admin or already public skip it.

Adds two regression tests:
- test_centralized_common_checks_skips_public_routes
- test_centralized_common_checks_master_key_admin_overrides_db_user_role
2026-04-24 16:50:29 -07:00
harish-berri
ce087aa796 refactor(proxy): update documentation and code references for enable_redis_auth_cache
- Removed the deprecated enable_redis_auth_cache field from ConfigGeneralSettings.
- Updated references in proxy_server.py to use litellm_settings for enable_redis_auth_cache.
- Clarified documentation to reflect the new configuration structure and its impact on Redis integration for user_api_key_cache.
2026-04-24 23:44:57 +00:00
mateo-berri
68d4420233 fix(ci): strip trailing class segment from JUnit classnames before pytest
Pytest tests inside a class produce JUnit XML classnames like
'tests.local_testing.test_file_types.TestFileConsts' (module + class).
The previous awk preprocessor would convert this to
'tests/local_testing/test_file_types/TestFileConsts.py', which doesn't
exist, causing pytest to collect 0 items on rerun.

Strip a trailing '.<UppercaseSegment>' before the dot-to-slash
conversion. Module path segments are lowercase (test files start with
'test_'), and the class name is the only segment beginning with an
uppercase letter, so this is unambiguous.

Verified affected files in tests/local_testing/: test_file_types.py
(TestFileConsts), test_gcs_cache_unit_tests.py, test_disk_cache_unit_tests.py,
test_docker_no_network_on_deploy.py, test_sagemaker_nova_integration.py,
test_cache_preset_key.py.
2026-04-24 16:42:21 -07:00
Milan
69c5840e5f
Test cleanup of multiple expired UI session keys
Made-with: Cursor
2026-04-25 02:21:28 +03:00
Yuneng Jiang
ae9f12fb8a
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_yj_apr23 2026-04-24 16:13:52 -07:00
Milan
60f6a5dcfa
Tune expired UI session cleanup lock logging
Made-with: Cursor
2026-04-25 02:12:31 +03:00
yuneng-jiang
70a986e689
Merge pull request #26457 from BerriAI/litellm_enterpriseLicenseMetadata
[Infra] Declare proprietary license in litellm-enterprise metadata
2026-04-24 16:10:32 -07:00
ryan-crabbe-berri
c91a22a001
Merge pull request #26438 from BerriAI/litellm_fix-jwt-admin-bypass
fix(jwt-auth): apply team TPM/RPM + attribution for admins using x-litellm-team-id
2026-04-24 16:07:50 -07:00
ishaan-berri
7cf6a95b62
fix(vertex passthrough): log :embedContent and :batchEmbedContents responses (#26146)
* fix(vertex passthrough): log :embedContent and :batchEmbedContents responses

* test(vertex passthrough): add unit tests for :embedContent and :batchEmbedContents logging

* fix(vertex passthrough): extract input text from request body for embedContent token counting

* fix(vertex passthrough): add embedContent and batchEmbedContents to TRACKED_VERTEX_ROUTES

* fix(vertex passthrough): detect Google AI Studio URLs in embedContent handler

* test(vertex passthrough): add unit test for Google AI Studio URL embedContent provider detection

* style: black format vertex_passthrough_logging_handler
2026-04-24 16:07:11 -07:00
Milan
21cf42f568
Add expired UI session key cleanup job
Made-with: Cursor
2026-04-25 01:57:22 +03:00
Yuneng Jiang
ea5a34c59a
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_sendInviteEmailToggle 2026-04-24 15:34:34 -07:00
mateo-berri
c3338384c9 test: register supports_low_reasoning_effort in cost-map JSON schema
The strict 'additionalProperties: false' schema in
test_aaamodel_prices_and_context_window_json_is_valid rejected the new
flag added in this PR's earlier commit. Register it alongside the other
supports_*_reasoning_effort entries so the schema validation passes.
2026-04-24 15:33:30 -07:00
mateo-berri
94f8f12a00 feat(openai): add supports_low_reasoning_effort flag; reject low on gpt-5.5-pro
gpt-5.5-pro only accepts reasoning_effort in {medium, high, xhigh}
(verified live against OpenAI's API on 2026-04-24). LiteLLM previously
had no way to express this constraint — the existing JSON schema
covered none/minimal/xhigh but not low. Result: drop_params=true users
saw an avoidable 400 from OpenAI.

Add supports_low_reasoning_effort following the existing opt-out
pattern (default-allow, explicit false to block). Mirror the minimal
branch in OpenAIGPT5Config.map_openai_params so 'low' goes through the
same _is_reasoning_effort_level_explicitly_disabled gate.

Set the flag to false on gpt-5.5-pro and gpt-5.5-pro-2026-04-23 in
both model_prices JSON files (kept in sync). Other models leave the
key absent so behavior is unchanged.

Tests cover: rejection on pro variants (no drop_params), drop on pro
with drop_params=True, passthrough on gpt-5.5 chat, passthrough on
unknown models, and the helper-level _is_reasoning_effort_level_explicitly_disabled
contract.
2026-04-24 15:05:43 -07:00
Yuneng Jiang
5d8ef97fa1
chore(packaging): declare proprietary license in litellm-enterprise metadata
The enterprise package ships under the BerriAI Enterprise License defined
in enterprise/LICENSE.md, which is not an SPDX-listed license. Declare it
via PEP 639's LicenseRef-Proprietary expression so metadata-reading tools
(PyPI classifiers, Nexus IQ, pip-licenses) resolve it instead of reporting
License-None. The existing license-files entry already ships the full terms.
2026-04-24 14:56:28 -07:00
shin-berri
082a8faf46
Merge pull request #26454 from BerriAI/litellm_remove_docs_repo_moved
[Infra] Remove docs/my-website, point contributors to litellm-docs repo
2026-04-24 14:54:35 -07:00
Ryan Crabbe
a0bba43cea
fix(jwt-auth): soft-fail unresolvable x-litellm-team-id for admins
Previously, an admin JWT sending a stale/typo'd/missing x-litellm-team-id
on an LLM API route received a hard 404 from get_team_object, blocking the
request. Restore pre-PR admin behavior: if the header can't be resolved,
skip team attribution and proceed with admin access, logging a warning
with the header value and route so the misconfigured caller is diagnosable.
2026-04-24 14:31:36 -07:00
mateo-berri
34c93645e9 fix(openai): gpt-5.5 does not support reasoning_effort=minimal
Verified against OpenAI's live Chat Completions API on 2026-04-24:

  POST /v1/chat/completions
  {"model": "gpt-5.5", "reasoning_effort": "minimal", ...}
  -> 400 Unsupported value: 'reasoning_effort' does not support 'minimal'
     with this model. Supported values are: 'none', 'low', 'medium',
     'high', and 'xhigh'.

  POST /v1/chat/completions
  {"model": "gpt-5.5-pro", "reasoning_effort": "minimal", ...}
  -> 400 Unsupported value: 'minimal' is not supported with the
     'gpt-5.5-pro' model. Supported values are: 'medium', 'high', and
     'xhigh'.

Set supports_minimal_reasoning_effort=false on all four entries
(gpt-5.5, gpt-5.5-2026-04-23, gpt-5.5-pro, gpt-5.5-pro-2026-04-23) so
OpenAIGPT5Config._is_reasoning_effort_level_explicitly_disabled fires
and LiteLLM either drops the param (drop_params=True) or raises a
local UnsupportedParamsError, instead of round-tripping to OpenAI for
a 400.

Adds a parametrized test_gpt55_reasoning_effort_flags_match_live_openai_api
test that pins supports_{none,minimal,xhigh}_reasoning_effort on each
entry to OpenAI's actual API contract.

Note: gpt-5.5-pro additionally rejects 'none' and 'low'. 'none' is
already handled (supports_none_reasoning_effort=false). 'low' is not
representable in the current JSON schema (no supports_low flag);
filing separately.
2026-04-24 14:30:41 -07:00
Yuneng Jiang
d42281338e ci: check out litellm-docs directly into docs/my-website
Replaces the rm-and-symlink hack with a plain actions/checkout
using path: docs/my-website. The previous approach failed on this
branch because docs/my-website no longer exists in the repo (its
parent docs/ directory was also removed), so ln -s had nowhere
to create the symlink.

Also adds the same checkout step to test-unit-documentation.yml,
which was silently relying on docs/my-website existing in-tree
for test_env_keys.py and test_router_settings.py.
2026-04-24 14:21:18 -07:00
Yuneng Jiang
c35f3a50ae docs: remove docs/my-website, point contributors to litellm-docs
The documentation source has moved to a separate repository,
BerriAI/litellm-docs, served at docs.litellm.ai. This PR removes
docs/my-website/ from this repo and updates README.md, AGENTS.md,
and CLAUDE.md to direct doc contributions to the new repo.

Also fixes a broken relative link in
litellm/integrations/levo/README.md.

The existing CI symlink in .github/workflows/test-code-quality.yml
(which clones litellm-docs and symlinks docs/my-website to it for
tests/documentation_tests/*) continues to work without change.
2026-04-24 14:17:46 -07:00
Mateo Wang
d21e90f683
[Feat] Day-0 support for GPT-5.5 and GPT-5.5 Pro (#26449)
* feat(openai): day-0 support for GPT-5.5 and GPT-5.5 Pro

Add pricing + capability entries for the new GPT-5.5 family launched by
OpenAI on 2026-04-24:

- gpt-5.5 / gpt-5.5-2026-04-23 (chat): $5/$30/$0.50 per 1M
  input/output/cached input
- gpt-5.5-pro / gpt-5.5-pro-2026-04-23 (responses-only): $60/$360/$6
  per 1M input/output/cached input

Other fees (long-context >272k, flex, batches, priority, cache
discounts) follow the same ratios as GPT-5.4, with context window
retained at 1.05M input / 128K output.

No transformation / classifier code changes are required:
OpenAIGPT5Config.is_model_gpt_5_4_plus_model() already matches 5.5+ via
numeric version parsing, and model registration is driven from the
JSON. The existing responses-API bridge for tools + reasoning_effort
(litellm/main.py:970) already covers gpt-5.5-pro.

Tests:
- GPT5_MODELS regression list now covers gpt-5.5-pro and dated variants
- New test_generic_cost_per_token_gpt55_pro cost-calc test
- Updated test_generic_cost_per_token_gpt55 for long-context fields

* fix(openai): mirror reasoning_effort flags onto gpt-5.5 dated variants

gpt-5.5-2026-04-23 and gpt-5.5-pro-2026-04-23 were missing the
supports_none_reasoning_effort, supports_xhigh_reasoning_effort, and
supports_minimal_reasoning_effort flags that their non-dated
counterparts define. Reasoning-effort routing in OpenAIGPT5Config is
fully capability-driven from these JSON flags — since an absent flag
is treated as False for opt-in levels (xhigh), users pinning to a
dated snapshot would silently lose xhigh support and diverge from the
base alias on logprobs + flexible temperature handling.

Copy the flags onto both dated variants so every dated snapshot
inherits the base model's reasoning-effort capability profile.

Adds a parametrized regression test that asserts
supports_{none,minimal,xhigh}_reasoning_effort parity between each
dated variant and its non-dated counterpart, preventing future drift
when new snapshots are added.
2026-04-24 14:10:42 -07:00
Yuneng Jiang
b300dc3e54
Preserve UISettings docstring on effective class for GET schema
create_model does not inherit the base class docstring, so once an
extension registered a field the effective class had no description.
The UI renders schema.description as a header paragraph — losing it
broke the 'Configuration for UI-specific flags' text. Pass __doc__
through explicitly and add a regression test.
2026-04-24 13:56:59 -07:00
mateo-berri
ed0a965208 fix(ci): convert dot-notation test paths to file paths for CircleCI rerun
CircleCI's 'Rerun failed tests' feature passes test identifiers from the
JUnit XML classname attribute (dot notation, e.g.
'tests.local_testing.test_router') via stdin. pytest receives these paths
and collects 0 items, causing the rerun to exit 123 with no tests run.

Add an awk preprocessor before xargs that detects dot-notation module
paths and converts them to file paths (tests/local_testing/test_router.py).
File paths already containing '.py' are passed through unchanged.

Applied to all three jobs using the 'circleci tests run' + 'xargs pytest'
pattern: local_testing_part1, local_testing_part2, and the router test job.
2026-04-24 13:40:02 -07:00
Ryan Crabbe
e1bb542556
chore: fix linting (ruff PLR0915, black) on admin team-header fix
Extract the admin team-header attachment into a helper so
auth_builder stays under the 50-statement lint threshold; apply
black formatting to the two files flagged on the prior commit.
No behavior change.
2026-04-24 13:38:28 -07:00
Yuneng Jiang
85b6cae508
Type _get_effective_ui_settings_class as Type[UISettings] for mypy 2026-04-24 13:19:02 -07:00
Yuneng Jiang
32d4ae79f6
Validate UI settings PATCH body against effective class
GET /get/ui_settings returns a schema built from the effective UISettings
class (base + enterprise-registered fields), but PATCH /update/ui_settings
declared its body as the base UISettings. Enterprise fields still worked
via extra="allow", but the OpenAPI schema was asymmetric between GET and
PATCH.

Accept the body as a dict and validate with the effective class so both
sides are in sync and enterprise-registered fields are type-checked.
2026-04-24 13:09:16 -07:00
yuneng-jiang
51d4c6c2f2
Merge pull request #26274 from stuxf/fix/mcp-byok-oauth-auth
fix(mcp): harden OAuth authorize/token endpoints (BYOK + discoverable)
2026-04-24 13:05:44 -07:00
yuneng-jiang
29ca1dc1f9
Merge pull request #26279 from stuxf/fix/post-auth-enforcement
fix(auth): centralize common_checks to close authorization bypass
2026-04-24 13:04:29 -07:00
yuneng-jiang
1a3db6dfa4
Merge pull request #26365 from stuxf/fix/deps-security-bumps
chore(deps): bump vulnerable dependencies
2026-04-24 13:02:58 -07:00
yuneng-jiang
3c3ef7ec9f
Merge pull request #26369 from stuxf/fix/license-metadata
chore(packaging): declare MIT license in litellm-proxy-extras metadata
2026-04-24 13:01:52 -07:00
Yuneng Jiang
e7f4e77af0
Bound _get_masked_values recursion depth
Add _depth/_max_depth guards (default 20) so the nested dict masking
cannot run away, and allowlist the function in the recursive_detector
CI check alongside the other bounded recursive helpers.
2026-04-24 13:00:33 -07:00
Yuneng Jiang
d747e4c248
Remove stale test_project_endpoints_prisma.py path from proxy-db workflow
The file was moved to tests/enterprise/litellm_enterprise/proxy/management_endpoints/
and is covered by the CircleCI litellm_mapped_enterprise_tests job. The stale path
was causing pytest to error with 'file or directory not found'.
2026-04-24 12:52:51 -07:00
Yuneng Jiang
000ce70127
Merge remote-tracking branch 'origin/litellm_internal_staging' into litellm_migration_projects
# Conflicts:
#	litellm/proxy/ui_crud_endpoints/proxy_setting_endpoints.py
#	uv.lock
2026-04-24 12:52:10 -07:00