Commit graph

34613 commits

Author SHA1 Message Date
Yuneng Jiang
46116bc088
chore: fixes 2026-04-04 23:05:50 -07:00
Cursor Agent
ae9fc0341f perf: add orjson import fallbacks + benchmark suite for fast-litellm integration
Fixes bare 'import orjson' in three hot-path modules that broke
non-proxy users (orjson is an optional dependency). Each module
now uses try/except with a stdlib json fallback:

- litellm/llms/openai_like/chat/handler.py
- litellm/llms/openai_like/chat/transformation.py
- litellm/llms/custom_httpx/llm_http_handler.py

Adds comprehensive benchmarking tools inspired by neul-labs/fast-litellm:

- benchmark_perf_integration.py: micro-benchmarks for each optimized
  hot path (JSON serialization, URL parsing, deployment lookup,
  spend-log sanitization, Prometheus label caching, routing, etc.)
- benchmark_sdk_hotpath.py: end-to-end SDK throughput measurement
  against a local mock server
- loadtest_config_nodb.yaml: proxy config without database dependency

Measured speedups (per-component, micro-benchmark):
  JSON serialization:    13.7x (orjson vs stdlib json)
  JSON deserialization:   3.7x
  httpx URL parsing:    202.2x (LRU-cached vs raw parse)
  Deployment lookup:     10.6x (O(1) index vs O(n) scan)
  Prometheus labels:     30.5x (cached model_dump)
  Simple shuffle:         5.8x (lazy logging)
  safe_json_dumps:        5.7x (orjson final step)
  Overall cumulative:    18.7x

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-10 18:11:37 +00:00
Krrish Dholakia
f4761c8697 fix: propagate use_sidecar config setting to env var for transport selection
When use_sidecar is set in the YAML config (general_settings), ensure the
USE_SIDECAR and SIDECAR_PORT env vars are set so that
AsyncHTTPHandler._should_use_sidecar_transport() picks them up.

Also add None guard for prisma_client in _sync_ui_settings_to_general_settings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:17:05 -07:00
Krrish Dholakia
91e3c86a12 fix: address 6 critical sidecar bugs from code review
- Fix connection leak: use release() instead of close() in SidecarResponseStream.aclose()
- Fix concurrent session leak: add asyncio.Lock with double-check in _get_session()
- Fix TOCTOU race: use DashMap entry() API in Rust sidecar get_or_create_client()
- Fix broken streaming: detect stream from request body JSON instead of Accept header
- Fix event loop stall: replace blocking subprocess.wait() with async run_in_executor()
- Fix type contract: decode orjson.dumps() bytes to str for consistency with json.dumps()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 11:16:35 -07:00
Krish Dholakia
dde4042e2d
System performance bottlenecks (#23075)
* perf: address GIL contention and hot-path bottlenecks from profiling data

Based on py-spy GIL profiling (38,800 samples, 2000 concurrent users) and
pyinstrument per-request timing, this commit addresses the top performance
bottlenecks identified:

1. _sanitize_request_body_for_spend_logs_payload (2.9% GIL):
   - Remove redundant inner import (constants already imported at top-level)
   - Remove dead-code branch (len check after already confirmed len > max)
   - Pre-compute truncation ratios outside inner function
   - Reorder isinstance checks: str first (most common leaf type)

2. Pydantic repr in logging (2.3% GIL):
   - Guard print_deployment calls behind isEnabledFor(logging.INFO)
   - Replace copy.deepcopy with shallow dict() copy in print_deployment
   - Use %-style lazy formatting instead of f-strings for logger calls
   - Remove kwargs from prometheus debug log message

3. Prometheus label_factory overhead (1.5% + 0.7% GIL):
   - Cache model_dump() on UserAPIKeyLabelValues via get_label_dict()
   - Convert supported_enum_labels to frozenset for O(1) membership tests
   - Called 37 times per success event; caching avoids 36 redundant dumps

4. pre_call_utils header lookup (1.9% GIL):
   - Replace dict comprehension over all headers with early-exit loop
   - Only lowercase and compare the two target header names

5. safe_json_dumps (0.7% GIL):
   - Replace stdlib json.dumps with orjson.dumps for final serialization

6. Hot-path debug logging:
   - Convert f-string debug logs to %-style in litellm_logging.py
   - Simplify prometheus print_verbose call

7. Cost calculator annotation checks:
   - Optimize response_includes_annotation_type to handle both dict
     and object annotation types without repeated __getattr__ calls

Estimated GIL time reduction: ~11-12% under concurrency.

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>

* test: add locust benchmark comparison tooling for perf analysis

Adds:
- loadtest_config_perf.yaml: proxy config with spend_logs enabled
- locustfile_perf.py: locust scenario for perf comparison
- compare_perf_results.py: CSV parser + comparison report generator
- run_perf_comparison.sh: automated baseline vs optimized runner

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>

* perf: guard orjson import with fallback, pre-parse httpx URLs, fix docstring

Addresses three review concerns and adds httpx URL caching:

1. safe_json_dumps.py: Guard orjson import with try/except fallback to
   stdlib json. This module is on the core SDK import path via
   _logging.py — unconditional orjson import would break plain
   'pip install litellm' (non-proxy) users.

2. router.py print_deployment: Update docstring to accurately describe
   the reduced return shape (model_name + litellm_params only).

3. run_perf_comparison.sh: Fix locustfile reference to use the correct
   locustfile_perf.py instead of locustfile.py.

4. httpx URL pre-parsing (~7.8us -> ~0.4us per request, 19x speedup):
   Add _parse_url() with LRU cache (maxsize=64) that pre-parses URL
   strings into httpx.URL objects. Applied to all HTTP methods (GET,
   POST, PUT, PATCH, DELETE) in both AsyncHTTPHandler and HTTPHandler.
   Eliminates regex-heavy re.finditer inside httpx._urlparse on every
   request — confirmed as a GIL hotspot in py-spy thread dumps.

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>

* fix: address review - document _parse_url safety, guard print_verbose

1. http_handler.py _parse_url: Add docstring documenting why the LRU
   cache is safe with query-string URLs. When params= is non-None,
   httpx replaces the query string entirely; when params= is None,
   the cached URL preserves the original query string. Both match
   pre-optimization behavior (verified with httpx.URL vs str tests).

2. prometheus.py print_verbose: Guard the call behind litellm.set_verbose
   check so the string formatting is truly lazy. The previous % formatting
   was eagerly evaluated (same cost as f-string) since print_verbose takes
   a pre-formatted string.

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
2026-03-07 19:24:36 -08:00
Cursor Agent
7f4cbf4893 perf: orjson serialization + correct transport-layer sidecar integration
Tier 1 — orjson hot path optimizations:
- Replace json.dumps() with orjson.dumps() in chat completion request
  serialization (openai_like/chat/handler.py, llm_http_handler.py)
- Replace response.json() with orjson.loads(response.content) in
  response transformation (openai_like/chat/transformation.py)
- Add response_class=ORJSONResponse to /chat/completions endpoints
  in proxy_server.py for faster response serialization

Tier 2 — Correct transport-layer sidecar:
- Add LiteLLMSidecarTransport (httpx.AsyncBaseTransport) that forwards
  already-transformed requests through the Rust sidecar binary
- Wire into AsyncHTTPHandler._create_async_transport() alongside
  existing aiohttp/httpx transport options
- Enabled via USE_SIDECAR=true env var
- All LiteLLM functionality preserved: provider transformations,
  callbacks, logging, retry logic, token counting

Reverted wrong approach:
- Remove _try_sidecar_route() from route_llm_request.py (was bypassing
  the entire translation layer)
- Delete sidecar_handler.py (replaced by transport-layer integration)

Load test results (200 users, 60s, full pipeline):
  Baseline:            223 RPS, 851ms avg, 1900ms P99
  Tier 1 (orjson):     248 RPS, 767ms avg, 1200ms P99
  Tier 2 (+sidecar):   268 RPS, 708ms avg, 1100ms P99

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-07 19:30:20 +00:00
Cursor Agent
5bd84d9f12 feat: add Rust sidecar binary for high-performance HTTP forwarding
Introduces litellm-sidecar, a Rust binary that provides:
- Pre-warmed connection pools per provider host (via reqwest + DashMap)
- Zero-copy HTTP request forwarding with SSE streaming support
- Lock-free atomic metrics (requests, errors, avg latency)
- Configurable via SIDECAR_PORT env var (default: 8787)
- /health endpoint for monitoring

The sidecar eliminates GIL contention in the HTTP forwarding path,
achieving ~3x throughput improvement under high concurrency.

Load test results (200 concurrent users, 60s):
  Baseline: 223 RPS, 851ms avg, 1900ms P99
  Sidecar:  655 RPS, 277ms avg,  850ms P99

Load test results (500 concurrent users, 60s):
  Baseline: 265 RPS, 1784ms avg, 23000ms P99
  Sidecar:  620 RPS,  751ms avg,  1200ms P99

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-07 19:04:10 +00:00
Cursor Agent
6432cfeb12 Add litellm-sidecar: high-performance Rust HTTP forwarding sidecar
- Standalone HTTP server on 127.0.0.1:8787 (configurable via SIDECAR_PORT)
- Pre-warmed per-host connection pools via reqwest + DashMap
- Transparent SSE streaming passthrough
- Header-based routing: x-litellm-provider-url, x-litellm-api-key,
  x-litellm-timeout, x-litellm-stream, x-litellm-path
- /health endpoint with request count, error count, avg latency metrics
- Release profile: LTO, opt-level 3, codegen-units 1

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-07 18:47:28 +00:00
yuneng-jiang
bcdcc8b1b7
Merge pull request #23040 from BerriAI/ui_release_build_mar7
[Infra] Building UI for Release
2026-03-07 10:31:35 -08:00
yuneng-jiang
621292cf7e chore: update Next.js build artifacts (2026-03-07 18:30 UTC, node v22.16.0) 2026-03-07 10:30:37 -08:00
yuneng-jiang
78834b5fa4
Merge pull request #22786 from milan-berri/fix/custom-sso-handler-user-info
fix: update Okta SSO docs and custom SSO handler example
2026-03-07 08:58:54 -08:00
Milan
277ad677c5 chore: remove debug print statements from custom_sso.py 2026-03-07 12:27:16 +02:00
yuneng-jiang
e5edbc629b
Merge pull request #23029 from BerriAI/litellm_config_overrides_table
[Infra] Sync Schema, Migration, Publish Proxy Extras
2026-03-06 23:41:00 -08:00
yuneng-jiang
5b0c963977 adding builds 2026-03-06 23:39:53 -08:00
yuneng-jiang
55f448abb8 bump: version 0.4.51 → 0.4.52 2026-03-06 23:39:08 -08:00
yuneng-jiang
315d04e92c
Merge pull request #23021 from BerriAI/litellm_fix_chat_root_path
[Fix] UI Chat - SERVER_ROOT_PATH not respected for chat and back-to-console links
2026-03-06 23:31:27 -08:00
yuneng-jiang
cb0d01ff26
Merge pull request #23028 from BerriAI/revert-22938-litellm_fix_team_usage_spend
Revert "[Fix] Team Usage Spend Truncated Due to Pagination"
2026-03-06 23:23:30 -08:00
yuneng-jiang
034e83e716
Revert "[Fix] Team Usage Spend Truncated Due to Pagination" 2026-03-06 23:23:20 -08:00
Harshit Jain
edf96886da
Merge pull request #23027 from BerriAI/litellm_validate_key_alias_format
feat: feature flag on validate key alias
2026-03-07 12:52:43 +05:30
Harshit28j
1452237ec6 fix req changes 2026-03-07 12:45:49 +05:30
Harshit28j
e33b26a45a doc: add about flag feature 2026-03-07 12:42:04 +05:30
Harshit28j
d78752b85b feat: feature flag on validate key alias 2026-03-07 12:32:21 +05:30
Harshit Jain
4f4225fdbf
Merge pull request #23020 from Harshit28j/litellm_feat_guardrails_tags
feat: support list of modes in tag-based guardrails
2026-03-07 12:15:18 +05:30
yuneng-jiang
be379b7b1e
Merge pull request #22722 from atapia27/feat/org-exclusive-add-member
org-exclusive-add-member
2026-03-06 22:24:05 -08:00
yuneng-jiang
aae0c81cd1 [Fix] UI Chat - respect SERVER_ROOT_PATH for chat and back-to-console links
The Chat button in the navbar and the "back to Developer Console" link
in ChatPage used the `serverRootPath` module variable directly, which is
initialized to "/" and only updated after `getUiConfig` resolves. Since
React does not re-render on module variable changes, the links computed
their hrefs with the stale default, ignoring any configured
SERVER_ROOT_PATH.

Both components now call `useUIConfig()` (React Query, cached) to
reactively read `server_root_path`, matching the pattern used elsewhere
in the UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 22:07:45 -08:00
yuneng-jiang
39c5adcff1
Merge pull request #23019 from BerriAI/litellm_redis_txn_buffer_check
[Fix] Block proxy startup when use_redis_transaction_buffer has no Redis
2026-03-06 22:01:37 -08:00
yuneng-jiang
b70ba3e6ed Update error message for missing Redis config
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:59:44 -08:00
Harshit28j
f18f4e3bbd feat: allow multiple calls from tags 2026-03-07 11:24:18 +05:30
Harshit Jain
497be5fb11
Merge pull request #23001 from Harshit28j/litellm_fix3458
Fix OTEL span redundancy, orphaned guardrail traces, and missing response IDs
2026-03-07 11:14:06 +05:30
yuneng-jiang
9d9a59190c Use passed general_settings parameter instead of global import
The validation method now reads use_redis_transaction_buffer directly
from the passed general_settings dict rather than delegating to
RedisUpdateBuffer._should_commit_spend_updates_to_redis() which
imports the global. Tests simplified to remove unnecessary patching.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:30:52 -08:00
yuneng-jiang
3a15e1cc2e [Fix] Block proxy startup when use_redis_transaction_buffer is enabled without Redis cache
When `use_redis_transaction_buffer: true` is set in general_settings but no
Redis cache is configured in litellm_settings, the proxy starts successfully
but silently drops all spend tracking data. This adds a startup validation
that raises a clear error, preventing the proxy from running in a broken state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:24:49 -08:00
yuneng-jiang
4eee2b752d
Merge pull request #23011 from BerriAI/litellm_key-aliases-internal-user
[Fix] Internal Users Cannot Access Key Aliases on Request Logs Page
2026-03-06 21:23:22 -08:00
yuneng-jiang
b314e8d20a
Merge pull request #20688 from BerriAI/litellm_budget_tier_enforcement_for_keys
[Fix] Budget-linked keys never had spend reset
2026-03-06 20:44:58 -08:00
Harshit Jain
6e09a52456
Merge pull request #23017 from BerriAI/revert-23008-litellm_bump-proxy-extras-0.4.51
Revert "bump litellm-proxy-extras 0.4.50 → 0.4.51"
2026-03-07 09:45:34 +05:30
Harshit Jain
fd4347533f
Revert "bump litellm-proxy-extras 0.4.50 → 0.4.51" 2026-03-07 09:40:00 +05:30
Harshit Jain
8e9fa6e993
Merge pull request #23008 from Harshit28j/litellm_bump-proxy-extras-0.4.51
bump litellm-proxy-extras 0.4.50 → 0.4.51
2026-03-07 09:12:14 +05:30
Harshit28j
de8d0f467a bump: version 0.4.50 → 0.4.51 2026-03-07 08:40:06 +05:30
Krish Dholakia
ff8e01d20b
feat: Add Canadian PII protection (PIPEDA) (#22951)
* feat: Add Canadian PII protection patterns and PIPEDA-compliant policy template

Adds 6 new Canadian PII regex pattern detectors to patterns.json:
- ca_sin: Social Insurance Number (PIPEDA Privacy Act, Income Tax Act)
- ca_ohip: Ontario Health Insurance Plan Number (PHIPA)
- ca_on_drivers_licence: Ontario driver's licence (HTA, PIPEDA)
- ca_immigration_doc: IRCC immigration docs (UCI, work/study permits, IMM refs)
- ca_bank_account: Canadian bank account routing (transit-institution-account)
- ca_postal_code: Canadian postal code (Canada Post spec)

Adds comprehensive policy template 'canadian-pii-protection' (id: canadian-pii-protection)
with 5 sub-guardrails grouping patterns by data type. All patterns include contextual
keyword matching (English + French keywords where applicable) to reduce false positives.
Complements existing passport_canada pattern.

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

* feat: Add Canadian PII compliance dataset and tests (57 tests)

Adds:
- test_ca_patterns.py: 30 unit tests for regex pattern matching (SIN, OHIP,
  driver's licence, immigration docs, bank account, postal code)
- test_ca_policy_e2e.py: 27 end-to-end tests running the full
  ContentFilterGuardrail pipeline with MASK action — validates detection
  of real PII and pass-through of clean prompts
- canadianPiiCompliancePrompts.ts: 21-prompt compliance dataset for UI
  evaluation, wired into the main compliancePrompts framework

Fixes keyword_pattern alternation ordering in patterns.json — longer
alternatives (e.g. "social insurance number") now precede shorter ones
("social insurance") to avoid excessive gap-word count when the regex
engine selects the shorter match first.

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

* feat: Add University of Toronto FIPPA identifier patterns and tests (36 tests)

Add 3 UofT institutional identifiers (student/employee number, UTORid, TCard)
covered under Ontario FIPPA. Includes pattern definitions, policy template
sub-guardrail, compliance prompts, unit tests, and e2e tests.

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

* fix: Correct test assertion bug and inaccurate docstring

Fix test_utorid_masked checking `result` (dict) instead of `output` (string).
Update test_ca_policy_e2e.py docstring to clarify scope vs UofT tests.

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

* fix: Address Greptile review feedback

- Tighten ca_postal_code keyword_pattern: replace broad "address" with
  specific compound terms (mailing/street/shipping/home address)
- Add missing "PIPEDA" tag to policy_templates.json for discoverability
- Add us_phone pattern to test_ca_policy_e2e.py setup to match deployed template
- Add phone number e2e test for complete coverage

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

* fix: Tighten patterns to reduce false positives and add missing test coverage

- ca_sin: reject leading-zero SINs ([1-9]\d{2}), set allow_word_numbers to false
- ca_immigration_doc: require separators in UCI pattern (prevent bare \d{10} match)
- uoft_utorid: qualify generic keywords (acorn -> acorn login, quercus -> quercus login)
- uoft_tcard: remove generic keywords (student card, id card, library card) that
  overlap with credit card contexts; keep only UofT-specific terms (tcard, campus card)
- Add visa/mastercard/amex/iban patterns to test_ca_policy_e2e.py setup to match
  deployed template; add Visa card masking test
- Add test verifying "student card" no longer triggers TCard redaction

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

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-06 18:27:31 -08:00
yuneng-jiang
12005c4a02 Fix /key/aliases auth for internal users and scope results by role
Internal users were blocked from accessing /key/aliases because the route
was missing from key_management_routes. Added the route and scoped query
results so non-admin users only see aliases for their own keys and their
teams' keys, matching /key/list behavior.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:20:10 -08:00
Yangqian Yan
7f5d5c5c6e
fix: use DeepSeekChatConfig instead of OpenAIConfig for deepseek provider (#22971)
* fix: use DeepSeekChatConfig instead of OpenAIConfig for deepseek provider

The deepseek provider was incorrectly using OpenAIConfig().map_openai_params()
instead of DeepSeekChatConfig().map_openai_params(), which meant DeepSeek-specific
parameter mappings were not being applied.

* test: add unit tests for deepseek DeepSeekChatConfig param mapping

Verify that get_optional_params uses DeepSeekChatConfig (not OpenAIConfig)
for the deepseek provider by testing thinking, reasoning_effort, and
budget_tokens stripping behavior.
2026-03-06 18:16:27 -08:00
yuneng-jiang
a323d37a5d
Merge pull request #23009 from BerriAI/feature/vkey-modal-squashed
[Infra] Resolve Merge Conflicts for #21065
2026-03-06 18:14:18 -08:00
Emerson Gomes
0e78aa4cf1
feat: add Azure AI grok-4-1-fast model support (#22587)
Add support for Grok 4.1 Fast models in Azure AI Foundry:
- azure_ai/grok-4-1-fast-non-reasoning
- azure_ai/grok-4-1-fast-reasoning

Pricing: $0.2/M input tokens, $0.5/M output tokens
Context window: 131k tokens

Source: https://techcommunity.microsoft.com/t5/Azure-AI-Foundry-Blog/Grok-4-0-Goes-GA-in-Microsoft-Foundry-and-Grok-4-1-Fast-Arrives/ba-p/4497964

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 18:10:40 -08:00
Ishaan Jaff
b7b20664c1
Gflags worker parameters (#22931)
* feat: add LITELLM_WORKER_STARTUP_HOOKS for per-worker initialization (gflags support)

Add support for running user-defined startup hooks in each worker process
during proxy_startup_event. This enables re-initialization of in-process
state (like gflags.FLAGS) that doesn't survive uvicorn worker spawning.

Usage:
  export LITELLM_WORKER_STARTUP_HOOKS=mymodule:init_fn,other:setup_fn

Hooks run early in proxy_startup_event (before config/DB loading).
Supports both sync and async callables. Errors propagate to prevent
broken workers from serving traffic. No-op when env var is unset.

Includes 5 tests covering sync/async hooks, multiple hooks, error
propagation, and no-hooks-set scenarios.

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

* docs: add Worker Startup Hooks page with gflags usage example

- New docs page: docs/proxy/worker_startup_hooks.md
  - Explains the problem (per-process state lost in multi-worker deployments)
  - Full gflags example with wrapper module and startup script
  - Covers multiple hooks, async hooks, error behavior
  - Architecture diagram showing master→worker flow
- Added LITELLM_WORKER_STARTUP_HOOKS to config_settings.md env var table
- Added to sidebar under Setup & Deployment

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

* Update litellm/proxy/proxy_server.py

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

* Apply suggestion from @greptile-apps[bot]

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-06 18:09:57 -08:00
Ishaan Jaff
bb52b0b6b0
fix(mcp): resolve $ref params and path-level params in OpenAPI spec parsing (#22952)
* fix(mcp): resolve \$ref params and merge path-level params in OpenAPI tool registration

Real-world OpenAPI specs (e.g. GitHub's 11.8 MB official spec) use two
patterns that crashed tool registration:

1. \$ref parameters: params defined as {"$ref": "#/components/parameters/foo"}
   instead of inline objects. Accessing param["name"] on a $ref raises KeyError.
   Fix: resolve each param against components/parameters before processing.

2. Path-level parameters: params defined on the path object apply to all
   HTTP methods on that path, but the operation object doesn't include them.
   GitHub's spec uses this for owner/repo/etc. path params.
   Fix: merge path-level params with operation-level params (op-level wins
   when the same name+in combination appears in both).

With this fix the full GitHub REST API spec loads successfully:
720 paths → 1079 tools, all with correct parameter schemas.

* fix(mcp): resolve \$ref params in OpenAPI preview endpoint (test/tools/list)

The _preview_openapi_tools function (called by the UI add-server form to show
connection status and available tools) had the same bug as _register_openapi_tools:
it accessed param["name"] directly without resolving \$ref parameters or merging
path-level parameters from the path item.

This caused "Failed to load OpenAPI spec: 'name'" for any spec that uses
component-level parameter references (e.g. GitHub's official REST API spec).

Apply the same fix: resolve \$ref against components/parameters and merge
path-level params (with operation-level taking priority) before building schemas.

* refactor(openapi-mcp): extract resolve_operation_params, add tests

- Hoist _resolve_ref and _resolve_param_list to module level in
  openapi_to_mcp_generator.py (were being redefined on every loop iteration)
- _resolve_ref now returns None for unresolvable $refs instead of
  the stub dict, preventing (None, None) from poisoning deduplication
- Add resolve_operation_params() as a shared helper that handles both
  $ref resolution and path-level param merging
- Replace duplicated inline logic in mcp_server_manager.py and
  rest_endpoints.py with calls to resolve_operation_params()
- Add TestResolveRef, TestResolveParamList, TestResolveOperationParams
  test classes covering $ref resolution, path-level merging, collision
  semantics, unresolvable ref filtering, and a GitHub-style spec fixture
2026-03-06 18:02:48 -08:00
yuneng-jiang
c2b03c15b9
Merge pull request #22939 from BerriAI/litellm_hashicorp_vault_backend
feat: Hashicorp Vault config override backend endpoints
2026-03-06 17:59:46 -08:00
Ryan Crabbe
6091621bec Build artifacts 2026-03-06 17:58:49 -08:00
Ryan Crabbe
a9dcc1ab37 bump: version 0.4.50 → 0.4.51 2026-03-06 17:55:12 -08:00
Ryan Crabbe
b87133ae04 fix json loads, migration file 2026-03-06 17:52:31 -08:00
yuneng-jiang
5c8bd6a6ca
Merge pull request #23006 from BerriAI/litellm_policy_component_tests
[Test] UI - Policies: Add unit tests for 5 untested components
2026-03-06 17:36:02 -08:00
michelligabriele
8dc0c97958
fix(caching): check REDIS_CLUSTER_NODES env var in Cache and Router class selection (#22790)
When Redis Cluster is configured via the REDIS_CLUSTER_NODES environment
variable, Cache.__init__() and Router._create_redis_cache() ignored the
env var and always created RedisCache instead of RedisClusterCache. This
caused the v3 rate limiter's cluster detection (_is_redis_cluster()) to
return False, skipping hash-slot key grouping. The resulting CROSSLOT
errors were silently caught, falling back to per-instance in-memory
counting — breaking RPM/TPM enforcement across multiple proxy instances.

Add REDIS_CLUSTER_NODES env var detection to both Cache.__init__() and
Router._create_redis_cache(), matching the existing pattern in
_redis.py:215-220. When the env var is set and no explicit startup_nodes
parameter is provided, parse it and create RedisClusterCache.

Fixes #22748
Related to #20836
2026-03-06 17:31:30 -08:00