Commit graph

34451 commits

Author SHA1 Message Date
Yuneng Jiang
8546225f88
chore: fixes 2026-04-04 23:27:06 -07:00
Cursor Agent
0b934e126c docs: add cache eviction safety rule to AGENTS.md and CLAUDE.md
Prevent future regressions by documenting that LLMClientCache must never
close HTTP/SDK clients on eviction — evicted clients may still be held
by in-flight requests.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-05 19:27:22 +00:00
Cursor Agent
185e2b9a21 test: add e2e regression tests with OpenAI SDK clients for cache eviction safety
Add two new tests using real AsyncOpenAI SDK clients (the exact production
path) that verify clients remain usable after cache eviction:

- test_evicted_openai_sdk_client_stays_usable: size-based eviction
- test_ttl_expired_openai_sdk_client_stays_usable: TTL-based eviction

All four e2e tests now sleep after eviction to drain any background
close tasks — without this sleep, a regression that schedules close via
create_task() would go undetected (the original tests passed by luck).

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-05 19:20:35 +00:00
Cursor Agent
8a70b72ca4 fix: remove cache eviction close that kills in-use httpx clients
LLMClientCache._remove_key() was eagerly closing httpx/OpenAI clients on
cache eviction. If any in-flight request still held a reference to the
evicted client, the request failed with:

  RuntimeError: Cannot send a request, as the client has been closed.

This manifested in production after 1-2 hours (matching the 1-hour
_DEFAULT_TTL_FOR_HTTPX_CLIENTS). The fix was previously applied in PR
#22247 but regressed when commit fb72979432 re-added the close logic to
address unawaited coroutine warnings.

The correct fix is to NOT close clients on eviction at all:
- Evicted clients may still be referenced by in-flight requests
- Without calling close(), no coroutines are created, so no warnings
- Python GC handles cleanup when all references are dropped
- close_litellm_async_clients() handles explicit shutdown cleanup

Fixes the 'Cannot send a request, as the client has been closed' error
for OpenAI, Azure, and Bedrock streaming after 1+ hours of operation.

Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-05 18:49:59 +00:00
Sameer Kankute
46fa9a33da
Merge pull request #22918 from BerriAI/litellm_gpt-4.5_fix
Fix doc
2026-03-05 23:53:34 +05:30
Sameer Kankute
cae1f5fbae Fix doc 2026-03-05 23:52:56 +05:30
Sameer Kankute
9df686e044
Merge pull request #22917 from BerriAI/litellm_gpt-4.5_fix
Fix doc
2026-03-05 23:51:00 +05:30
Sameer Kankute
cf376d2c0e Fix doc 2026-03-05 23:50:20 +05:30
Ishaan Jaff
a42132f329
fix(passthrough): propagate Azure 429/5xx errors in async streaming instead of silent HTTP 200 (#22913)
* fix(passthrough): raise_for_status in _async_streaming to propagate Azure 429s

* address greptile review feedback (greploop iteration 1)

Guard data/json args when content is provided to avoid httpx ValueError

* address greptile review feedback (greploop iteration 2)

Use bare raise to preserve original traceback in _async_streaming exception handler

* address greptile review feedback (greploop iteration 3)

Close httpx streaming response on error to prevent connection pool exhaustion

* address greptile review feedback (greploop iteration 4)

Guard aclose() call to prevent masking original exception; add explicit test for content param forwarding

* address greptile review feedback (greploop iteration 5)

Pass content to sign_request so AWS body-hash signing is correct when content is the sole body source

* revert sign_request content change - request_data expects dict, not bytes

Bedrock's sign_request calls json.dumps(request_data) — passing content bytes
would TypeError. sign_request should only receive data/json (dict), not raw bytes.
2026-03-05 10:12:43 -08:00
Sameer Kankute
8dca085640
Merge pull request #22916 from BerriAI/litellm_gpt-5.4_day_0
Add day 0 support for gpt-5.4
2026-03-05 23:41:35 +05:30
Sameer Kankute
3b457b5d8e Add day 0 support for gpt-5.4 2026-03-05 23:40:24 +05:30
Sameer Kankute
b9a8d42882 Add day 0 support for gpt-5.4 2026-03-05 23:26:24 +05:30
Julio Quinteros Pro
6db3f2f668
Merge pull request #22892 from BerriAI/fix/greptile-type-safety-improvements
fix(types): address type-safety issues from mypy PR review
2026-03-05 14:06:17 -03:00
Julio Quinteros
023794ba62 fix(merge): resolve conflict with main in cost_tracking_settings
PR #22890 used cast(str, ...) / cast(Optional[str], ...) for the return
statements; this PR's approach uses str() for explicit runtime coercion
(addressing Greptile's concern). Keep the str() version and drop the
now-unused cast import.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 14:01:07 -03:00
Giulio Leone
6b7d767637
feat(anthropic): support top-level cache_control for automatic prompt caching (#22442) 2026-03-05 08:34:56 -08:00
Sameer Kankute
5183a6e850
Merge pull request #22866 from mubashir1osmani/feat/bedrock-mantle-provider-clean
feat: bedrock mantle provider
2026-03-05 18:24:00 +05:30
Sameer Kankute
a282bf9726
Merge pull request #22893 from BerriAI/litellm_messages-to-responses-mapping-docs
docs(anthropic): add v1/messages → /responses parameter mapping reference
2026-03-05 18:21:37 +05:30
Sameer Kankute
0620f99fa4
Merge pull request #22867 from BerriAI/litellm_bedrock-azure-cache-control-scope
fix(bedrock,azure_ai): strip scope from cache_control for Anthropic messages
2026-03-05 18:20:59 +05:30
Sameer Kankute
c04c120df2
Merge pull request #22884 from BerriAI/litellm_vertex-output-config-drop
fix(vertex_ai): drop unsupported output_config parameter from all requests
2026-03-05 18:20:47 +05:30
Sameer Kankute
4fda3e8351
Merge pull request #22896 from BerriAI/litellm_mistral-document-ai-2512-cost-map
feat(cost): add azure_ai/mistral-document-ai-2512 to model cost map
2026-03-05 16:14:27 +05:30
Sameer Kankute
bb1297fe1b feat(cost): add azure_ai/mistral-document-ai-2512 to model cost map
Made-with: Cursor
2026-03-05 16:07:46 +05:30
Sameer Kankute
6a8adf8bdf docs(anthropic): add v1/messages → /responses parameter mapping reference
Documents exactly how every request and response field gets translated
when LiteLLM routes an Anthropic /v1/messages call through the OpenAI
Responses API path (for OpenAI/Azure targets). Covers messages content
block mapping, tools, tool_choice, thinking→reasoning, context_management,
and the reverse response translation. Wired into the /v1/messages sidebar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 15:51:19 +05:30
Julio Quinteros Pro
b52bd43740
Merge pull request #22822 from BerriAI/fix/plr0915-too-many-statements
fix(lint): resolve PLR0915 too-many-statements in 4 files
2026-03-05 07:13:10 -03:00
Julio Quinteros
c1076de5bd fix(types): address type-safety issues from mypy PR review
- CreateBatchRequest.output_expires_after: drop Optional since total=False
  already makes the key absent-or-present; Optional[T] incorrectly allowed
  the key to exist with value None, which is incompatible with the OpenAI
  SDK's OutputExpiresAfter | NotGiven expectation on batches.create()
- cost_tracking_settings._resolve_model_for_cost_lookup: replace implicit
  object-to-str returns with explicit str() calls so the function is safe
  even if the surrounding truthiness guards are later weakened

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 07:11:31 -03:00
Julio Quinteros Pro
ad2969badb
Merge pull request #22890 from BerriAI/fix/mypy-type-errors
fix(mypy): resolve type errors across 9 files
2026-03-05 07:05:23 -03:00
Julio Quinteros Pro
44498da62a
Merge pull request #22887 from BerriAI/fix/schema-add-realtime-mode
fix(test): add 'realtime' to model mode enum in schema validation
2026-03-05 07:03:27 -03:00
Julio Quinteros Pro
de18b47f83
Merge pull request #22891 from BerriAI/fix/prisma-schema-duplicate-spec-path
fix(schema): remove duplicate spec_path field in LiteLLM_MCPServerTable
2026-03-05 07:02:33 -03:00
Julio Quinteros
16f415ad74 fix(schema): remove duplicate spec_path field in LiteLLM_MCPServerTable
PR #22850 (BYOK MCP servers) accidentally re-declared spec_path which was
already added by PR #22820, causing Prisma schema validation to fail with
error P1012 "Field is already defined".

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 07:00:11 -03:00
Julio Quinteros
f45a9df52d fix(mypy): resolve type errors across 9 files
- batches/main.py: import FileExpiresAfter, cast output_expires_after on assignment
- openai/openai.py, azure/batches/handler.py: add # type: ignore[arg-type] on
  batches.create / batches.retrieve TypedDict unpacking calls
- searchapi/transformation.py: cast optional_params["country"] to str before .lower()
- openrouter/image_edit/transformation.py: cast iterated value to str for size/quality params
- spend_log_cleanup.py: narrow bool | None to bool with `or False`
- cost_tracking_settings.py: cast base_model/resolved_model to str and
  custom_llm_provider to Optional[str] in return statements
- text_moderation.py: suppress misc TypedDict ** expansion error; use cast for response
- prompt_shield.py: use cast instead of TypedDict(**response_json) construction

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 06:58:20 -03:00
Julio Quinteros Pro
1c7f93f90c
Update litellm/fine_tuning/main.py
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-05 06:45:31 -03:00
Julio Quinteros
db8e909ef2 fix(test): add 'realtime' to model mode enum in schema validation
gemini/gemini-live-2.5-flash-preview-native-audio-09-2025 uses mode='realtime'
but the schema in test_aaamodel_prices_and_context_window_json_is_valid did
not include 'realtime' as a valid enum value, causing a ValidationError.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 06:41:51 -03:00
Julio Quinteros
0133d11eb2 fix: replace assert with RuntimeError and fix return type annotation
- a2a_protocol/main.py: replace bare assert with descriptive RuntimeError
  in _execute_a2a_send_with_retry so retry exhaustion gives a clear message
- fine_tuning/main.py: fix _resolve_fine_tuning_timeout return type from
  float to Union[float, httpx.Timeout] to accurately reflect the passthrough path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 06:38:38 -03:00
Sameer Kankute
9a13c76e2f
Merge pull request #22553 from dsteeley/fix/streaming-multi-tool-call-premature-finish
fix(streaming): output_item.done for function_call must not emit finish_reason
2026-03-05 15:05:43 +05:30
Julio Quinteros
b3bbcd3955 fix(lint): remove unreachable None check in _resolve_fine_tuning_timeout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 06:29:57 -03:00
Sameer Kankute
a2c11d431a fix(vertex_ai): drop unsupported output_config parameter from all requests
Vertex AI does not support the output_config parameter in its API.
This parameter is being added by Anthropic/Gemini transformations but needs
to be removed before sending requests to Vertex AI endpoints.

This fix addresses the "Extra inputs are not permitted" error (issue #22312)
when using Claude models with structured outputs on Vertex AI.

Changes:
- Drop output_config in Gemini model transformation
- Drop output_config in Anthropic partner model transformation
- Drop output_config in Anthropic experimental pass-through transformation
- Add comprehensive tests to verify output_config is dropped

Fixes: #22312
Made-with: Cursor
2026-03-05 13:02:17 +05:30
Sameer Kankute
cdf2d67fc8
Merge pull request #22503 from giulio-leone/fix/graceful-tool-args-repair
fix(tools): gracefully repair truncated JSON in tool call arguments
2026-03-05 13:00:07 +05:30
Sameer Kankute
f7d5ff9e2a
Merge pull request #22692 from giulio-leone/fix/vertex-ai-streaming-truncation
fix(streaming): prevent Vertex AI Claude content truncation when finish_reason races content
2026-03-05 12:50:49 +05:30
mubashir1osmani
b3f3918e98 fix(provider): register bedrock_mantle in model_list and models_by_provider
Adds bedrock_mantle_models to the model_list union and models_by_provider
dict so models are discoverable via litellm.model_list and
litellm.models_by_provider["bedrock_mantle"].

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 00:34:05 -05:00
mubashir1osmani
1bf0a3adc4
Update ui/litellm-dashboard/src/components/provider_info_helpers.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-05 00:20:20 -05:00
mubashir1osmani
ff7024b801
Update ui/litellm-dashboard/src/components/provider_info_helpers.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-05 00:20:14 -05:00
Sameer Kankute
482bc93910 fix(azure_ai): strip scope from cache_control for Anthropic messages
Azure AI Foundry's Anthropic endpoint does not support the scope field in
cache_control. Strip it from both system and messages before sending.

Made-with: Cursor
2026-03-05 10:49:37 +05:30
Sameer Kankute
cc989b1171 fix(bedrock): strip scope from cache_control for Anthropic messages
Bedrock does not support the scope field in cache_control (e.g. 'global' for
cross-request caching). Only type and ttl are supported per AWS docs.

- Remove scope from cache_control in both system and messages
- Extend _remove_ttl_from_cache_control to process system blocks
- Add test for scope removal

Made-with: Cursor
2026-03-05 10:49:35 +05:30
Ishaan Jaff
1bb713bc7b
feat(mcp): BYOK MCP servers with OAuth 2.1 PKCE authorization flow (#22850)
* feat(mcp): BYOK (Bring Your Own Key) for OpenAPI MCP servers with OAuth 2.1 flow

Adds per-user credential storage for BYOK MCP servers so external clients
can authenticate via standard OAuth 2.1 PKCE without needing a full identity
provider.

Backend:
- New DB table LiteLLM_MCPUserCredentials (user_id, server_id, credential_b64)
- is_byok, byok_description, byok_api_key_help_url fields on MCPServerTable
- OAuth 2.1 authorization server endpoints (/.well-known/oauth-authorization-server,
  /.well-known/oauth-protected-resource, /v1/mcp/oauth/authorize, /v1/mcp/oauth/token)
- 401 challenge with WWW-Authenticate header when BYOK server has no credential
- CRUD endpoints: POST/DELETE /v1/mcp/server/{id}/user-credential
- has_user_credential annotated on GET /v1/mcp/server response

UI:
- ByokCredentialModal: 2-step Connect flow (access description + API key entry)
- BYOK toggle + description fields on admin MCP server create form
- Connect/Connected state in MCP server table
- BYOK Demo page (/tools/byok-demo) showing full OAuth 2.1 PKCE flow

* feat(mcp/byok): redesign OAuth authorize page to match 2-step Connect mockup

- Step 1: L→S logos, requested access checklist, How it works box, Continue button
- Step 2: API key input, Save toggle, Duration pills (1h/24h/7d/30d/until_revoked), security note
- Matches screenshots: white modal on dark bg, progress dots, dark CTA buttons
- Authorize handler now fetches byok_description and byok_api_key_help_url from server registry
- CLAUDE.md: replace SQL snippet with proper DB migration troubleshooting guidance

* fix: address greptile review feedback (greploop iteration 1)

- XSS: escape all user-supplied values in _build_authorize_html() with html.escape()
- Open redirect: validate redirect_uri scheme and URL-encode code/state in redirect
- N+1 query: batch BYOK credential lookup into single find_many() call
- Critical path DB: add 60s TTL in-memory cache to _check_byok_credential()
- Encrypt BYOK credentials at rest using encrypt_value_helper/decrypt_value_helper

* fix(byok): update OAuth popup with LiteLLM logo, MCP title suffix, remove emojis

* fix(byok-demo): fix token endpoint URL (/v1/mcp/oauth/token not /v1/mcp/token)

* feat(byok): inject stored BYOK credential as mcp_auth_header on tool execution

* feat(byok): use contextvars to inject per-user credential into OpenAPI tool closures; remove byok-demo from LiteLLM UI

OpenAPI tools have auth headers baked into their closures at registration time. BYOK servers have
no static auth token, so per-user credentials were never reaching the HTTP calls.

Fix: add _request_auth_header ContextVar in openapi_to_mcp_generator.py. create_tool_function now
reads this var at call time and overrides the Authorization header if set. execute_mcp_tool resolves
the MCP server and performs BYOK checks before the local-tool dispatch branch, then sets the
ContextVar around _handle_local_mcp_tool so the credential flows into the HTTP request.

Also remove the /tools/byok-demo page from the LiteLLM UI dashboard — the demo lives at
~/Downloads/litellm-byok-demo/index.html (served separately on port 8080).

* fix: address greptile review feedback (greploop iteration 2)

- Cache invalidation: add _invalidate_byok_cred_cache() and call it after
  store_user_credential() in both token endpoint and management endpoint
- Unbounded cache: add _BYOK_CRED_CACHE_MAX_SIZE=4096 with clear-on-overflow
- Unbounded auth codes: add _AUTH_CODES_MAX_SIZE=1000 with 503 on overflow
- Double DB query: merge _check_byok_credential + _get_byok_credential into
  single _get_byok_credential call; raise 401 inline if None returned
- Sidebar: remove byok-demo entry (page was deleted in prior commit)
- JWT comment: document why byok_session HS256 token can't be used as proxy auth

* fix: address greptile review feedback (greploop iteration 3)

- auth_type: pre-format Authorization header (Bearer/ApiKey/Basic) in server.py
  before setting ContextVar so openapi_to_mcp_generator respects server auth_type
- cache invalidation on delete: call _invalidate_byok_cred_cache after
  delete_user_credential so stale True entries don't persist for 60s
- ContextVar guard: only set _request_auth_header when mcp_auth_header is set,
  avoiding unnecessary ContextVar overhead on non-BYOK tool calls

* fix: address greptile review feedback (greploop iteration 4)

- Unified credential cache: store actual credential value (Optional[str])
  instead of just bool so _get_byok_credential also benefits from caching —
  eliminates the DB hit on every BYOK tool call within the 60s TTL window
- Extracted _write_byok_cred_cache() helper for consistent cache writes
- Replaced has_user_credential with get_user_credential in _check_byok_credential
  so one DB call satisfies both existence check and value retrieval
- Remove false 'encrypted at rest' claim from OAuth HTML and ByokCredentialModal

* Update tests/test_litellm/proxy/_experimental/mcp_server/test_byok_oauth_endpoints.py

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

* Update tests/test_litellm/proxy/_experimental/mcp_server/test_byok_oauth_endpoints.py

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

---------

Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-04 21:19:25 -08:00
mubashir1osmani
4a4bcced3c docs: add Amazon Bedrock Mantle provider page
Adds provider documentation for bedrock_mantle including:
- API key and region configuration
- Supported models with pricing table
- SDK, streaming, and async usage examples
- LiteLLM Proxy config and usage
- Added to Bedrock category in sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 00:10:00 -05:00
mubashir1osmani
1089945f0e feat(ui): add Amazon Bedrock Mantle to provider UI
Adds `bedrock_mantle` to the provider dropdown in the LiteLLM dashboard:
- Providers enum: "Amazon Bedrock Mantle"
- provider_map: bedrock_mantle backend key
- providerLogoMap: reuses bedrock.svg

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 00:07:08 -05:00
mubashir1osmani
df7e3aa1e5 feat(provider): add Amazon Bedrock Mantle as a first-class provider
Adds `bedrock_mantle` provider for Amazon Bedrock's OpenAI-compatible
inference engine (Project Mantle). Previously users had to use this as
a generic openai_compatible provider, which resulted in incorrect pricing
(OpenAI rates instead of Bedrock rates).

Changes:
- New `BedrockMantleChatConfig` extending `OpenAILikeChatConfig`
  - Regional API base: `https://bedrock-mantle.{region}.api.aws/v1`
  - Auth via `BEDROCK_MANTLE_API_KEY` env var
  - Region resolution: BEDROCK_MANTLE_REGION > AWS_REGION > us-east-1
  - Supports reasoning for gpt-oss models
- Added `BEDROCK_MANTLE` to `LlmProviders` enum
- Added 4 models with correct AWS Bedrock pricing to both pricing files:
  - bedrock_mantle/openai.gpt-oss-120b ($0.15/M in, $0.60/M out)
  - bedrock_mantle/openai.gpt-oss-20b ($0.075/M in, $0.30/M out)
  - bedrock_mantle/openai.gpt-oss-safeguard-120b
  - bedrock_mantle/openai.gpt-oss-safeguard-20b
- Wired provider into get_llm_provider_logic, get_supported_openai_params,
  main.py routing, utils.py map_openai_params + ProviderConfigManager,
  and _lazy_imports_registry
- 19 unit tests covering registration, config, provider resolution, pricing

Usage:
  os.environ["BEDROCK_MANTLE_API_KEY"] = "your-key"
  litellm.completion(model="bedrock_mantle/openai.gpt-oss-120b", ...)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 00:03:40 -05:00
yuneng-jiang
3c389ad6f7
Merge pull request #22857 from BerriAI/litellm_fix_key_org_id_serialization
[Fix] UI - Keys: Organization always shows Not Set
2026-03-04 20:33:29 -08:00
yuneng-jiang
7eafac8e7f Fix remaining org_id fallbacks in filter_helpers and TeamVirtualKeysTable
filter_helpers.ts was not populating the Organization ID filter dropdown
(always empty). TeamVirtualKeysTable was showing the team's org for all
keys instead of each key's own org.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 20:18:54 -08:00
yuneng-jiang
51d876ce79 [Fix] UI - Keys: Organization shows Not Set due to org_id/organization_id mismatch
The /key/list API returns `org_id` (the Pydantic field name), but the UI
was reading `organization_id`, causing the Organization field to always
show "Not Set" and the Organization ID filter to never match.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 20:11:42 -08:00
Sameer Kankute
335c4d4946
Merge pull request #22851 from BerriAI/litellm_v182-messages-routing-note
docs(v1.82.0): add v1/messages routing note and caution to release notes
2026-03-05 09:31:51 +05:30