Commit graph

3966 commits

Author SHA1 Message Date
Ishaan Jaff
b87d1f8dad
[Feat] - Ishaan main merge branch (#23596)
* fix(bedrock): respect s3_region_name for batch file uploads (#23569)

* fix(bedrock): respect s3_region_name for batch file uploads (GovCloud fix)

* fix: s3_region_name always wins over aws_region_name for S3 signing (Greptile feedback)

* fix: _filter_headers_for_aws_signature - Bedrock KB (#23571)

* fix: _filter_headers_for_aws_signature

* fix: filter None header values in all post-signing re-merge paths

Addresses Greptile feedback: None-valued headers were being filtered
during SigV4 signing but re-merged back into the final headers dict
afterward, which would cause downstream HTTP client failures.

Made-with: Cursor

* feat(router): tag_regex routing — route by User-Agent regex without per-developer tag config (#23594)

* feat(router): add tag_regex support for header-based routing

Adds a new `tag_regex` field to litellm_params that lets operators route
requests based on regex patterns matched against request headers — primarily
User-Agent — without requiring per-developer tag configuration.

Use case: route all Claude Code traffic (User-Agent: claude-code/x.y.z) to
a dedicated deployment by setting:

  tag_regex:
    - "^User-Agent: claude-code\\/"

in the deployment's litellm_params. Works alongside existing `tags` routing;
exact tag match takes precedence over regex match. Unmatched requests fall
through to deployments tagged `default`.

The matched deployment, pattern, and user_agent are recorded in
`metadata["tag_routing"]` so they flow through to SpendLogs automatically.

* fix(tag_regex): address backwards-compat, metadata overwrite, and warning noise

Three issues from code review:

1. Backwards-compat: `has_tag_filter` was widened to activate on any non-empty
   User-Agent, which would raise ValueError for existing deployments using plain
   tags without a `default` fallback. Fix: only activate header-based regex
   filtering when at least one candidate deployment has `tag_regex` configured.

2. Metadata overwrite: `metadata["tag_routing"]` was overwritten for every
   matching deployment in the loop, leaving inaccurate provenance when multiple
   deployments match. Fix: write only for the first match.

3. Warning noise: an invalid regex pattern logged one warning per header string
   rather than once per pattern. Fix: compile first (catching re.error once),
   then iterate over header strings.

Also adds two new tests covering these cases, and adds docs page for
tag_regex routing with a Claude Code walk-through.

* refactor(tag_regex): remove unnecessary _healthy_list copy

* docs: merge tag_regex section into tag_routing.md, remove standalone page

- Add ## Regex-based tag routing (tag_regex) section to existing
  tag_routing.md instead of a separate page
- Remove tag_regex_routing.md standalone doc (odd UX to have a separate
  page for a sub-feature)
- Remove proxy/tag_regex_routing from sidebars.js
- Add match_any=False debug warning in tag_based_routing.py when regex
  routing fires under strict mode (regex always uses OR semantics)

* fix(tag_regex): address greptile review - security docs, strict-mode enforcement, validation order

- Strengthen security note in tag_routing.md: explicitly state User-Agent
  is client-supplied and can be set to any value; frame tag_regex as a
  traffic classification hint, not an access-control mechanism
- Move tag_regex startup validation before _add_deployment() so an invalid
  pattern never leaves partial router state
- Enforce match_any=False strict-tag policy: when a deployment has both
  tags and tag_regex and the strict tag check fails, skip the regex fallback
  rather than silently bypassing the operator's intent
- Extract per-deployment match logic into _match_deployment() helper to
  keep get_deployments_for_tag() readable
- Add two new tests: strict-mode blocks regex fallback, regex-only
  deployment still matches under match_any=False

* fix(ci): apply Black formatting to 14 files and stabilize flaky caplog tests

- Run Black formatter on 14 files that were failing the lint check
- Replace caplog-based assertions in TestAliasConflicts with
  unittest.mock.patch on verbose_logger.warning for xdist compatibility
- The caplog fixture can produce empty text in pytest-xdist workers
  in certain CI environments, causing flaky test failures

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

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Ishaan Jaff <ishaan-jaff@users.noreply.github.com>
2026-03-14 09:40:00 -07:00
Pradyumna Yadav
a94b961c18
fix: auto-fill reasoning_content for moonshot kimi reasoning models in multi-turn tool calling (#23580) 2026-03-13 22:48:45 -07:00
Awais Qureshi
c7ba7948bc
PR #22867 added _remove_scope_from_cache_control for Bedrock and Azur… (#23183)
* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control for Bedrock and Azure AI but omitted Vertex AI. This applies the same pattern to VertexAIPartnerModelsAnthropicMessagesConfig."

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

* PR #22867 added _remove_scope_from_cache_control to AzureAnthropicMessagesConfig
 but missed VertexAIPartnerModelsAnthropicMessagesConfi Rather than duplicating the method again, moved it up to the base AnthropicMessagesConfig so all providers
  inherit it, and removed the now-redundant copy from the Azure AI subclass.

---------

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
2026-03-13 22:41:25 -07:00
yuneng-jiang
3aeca22031 fix(test): update test_responses_background_cost assertions for pagination and stale cleanup
Tests were outdated after #23472 added pagination (take/order) to find_many
and stale-row cleanup via update_many. Updated assertions to match new call
signatures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 16:18:15 -07:00
yuneng-jiang
dca231e3f6
Merge pull request #23557 from BerriAI/litellm_ui_key_org-2
[Feature] Allow Setting organization_id on Key Update
2026-03-13 16:10:35 -07:00
yuneng-jiang
818c097ca9 Fix self-exclusion hash mismatch and missing throughput field checks
The self-exclusion filter compared raw key strings against SHA-256
hashed tokens from the DB, so keys were never excluded and
double-counting persisted. Now hash data.key before comparison.

Also add tpm_limit_type/rpm_limit_type to _throughput_fields_changed
guard, fall back to existing_key_row.team_id for team limit checks
(matching the org pattern), and add team self-exclusion test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:59:23 -07:00
yuneng-jiang
1038a119ce Skip org limit check when non-throughput fields are updated
Only run org validation (get_org_object + _check_org_key_limits) when
the update actually touches throughput-related fields (tpm_limit,
rpm_limit, or organization_id). Previously, any update to a key
belonging to an org would trigger the check, which would fail with a
400 if the org had been deleted — blocking unrelated field changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:38:42 -07:00
yuneng-jiang
133471f882 Fix double-counting bug in org/team key limit checks on update
When updating a key, _check_org_key_limits and _check_team_key_limits
would include the key being updated in the find_many results, causing
its current limits to be counted twice (once from the DB query, once
from the new requested limits). This caused false 400 errors on valid
limit adjustments.

Fix: exclude the key being updated (by matching token) from the
allocated totals before checking limits.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 15:27:56 -07:00
yuneng-jiang
0b3dc00440 Merge remote-tracking branch 'origin' into litellm_internal_dev_03_12_2026 2026-03-13 15:11:49 -07:00
yuneng-jiang
57865ec96e Revert "[Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path"
This reverts commit ca2033036f.
2026-03-13 12:21:39 -07:00
yuneng-jiang
ca2033036f [Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path
The terminal-state DB shortcut in retrieve_batch returned a LiteLLMBatch
with empty _hidden_params, causing the managed_files hook to skip encoding
output_file_id into a unified ID. This adds the same model_id extraction
from unified_batch_id that the non-terminal path already has.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 12:14:58 -07:00
yuneng-jiang
e40ebf262a Revert "[Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path"
This reverts commit 1642a2f7ac.
2026-03-13 11:57:22 -07:00
yuneng-jiang
efe6ddfc68
Merge pull request #23577 from Sameerlite/litellm_gpt54-tools-reasoning-routing
feat(openai): route gpt-5.4+ tools+reasoning to Responses API
2026-03-13 11:49:46 -07:00
Sameer Kankute
7dce61ce48 fix(tests): update TestGPT5ReasoningEffortPreservation for dict normalization
Made-with: Cursor
2026-03-14 00:13:16 +05:30
yuneng-jiang
57397e0d26
Merge pull request #23576 from Sameerlite/litellm_gpt54-tools-reasoning-routing
Litellm gpt54 tools reasoning routing
2026-03-13 11:38:50 -07:00
yuneng-jiang
1642a2f7ac [Fix] Populate _hidden_params.model_id in batch terminal-state shortcut path
The terminal-state DB shortcut in retrieve_batch returned a LiteLLMBatch
with empty _hidden_params, causing the managed_files hook to skip encoding
output_file_id into a unified ID. This adds the same model_id extraction
from unified_batch_id that the non-terminal path already has.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:38:09 -07:00
Sameer Kankute
408b717cb9 Fix gpt 5 transformation tests 2026-03-14 00:00:02 +05:30
Sameer Kankute
30645d683f Reserve reasoning for responses via chat completion 2026-03-13 23:59:57 +05:30
Sameer Kankute
7abbe2dc06 Fix routing of tool call + reasoning effor for gpt-5.4 2026-03-13 23:59:53 +05:30
Sameer Kankute
3596464d11 Revert "feat(openai): drop reasoning_effort for gpt-5.4 when tools present"
This reverts commit 14b52b1318.
2026-03-13 23:59:48 +05:30
yuneng-jiang
2b71b0fb25
Revert "QA: improve gpt-5.4 code/bugs" 2026-03-13 10:15:47 -07:00
yuneng-jiang
8dc198eccf
Merge pull request #23535 from Sameerlite/litellm_improve_qa-5.4
QA:  improve gpt-5.4 code/bugs
2026-03-13 09:37:30 -07:00
yuneng-jiang
6ebd457146 fix(tests): update remaining PKCE SSO tests to mock get_async_httpx_client
The previous fix (124b44ec) only updated 3 tests but missed 10 more
that still patched the old `ui_sso.httpx.AsyncClient` path. Also
updated credential assertions to check Authorization header instead
of httpx.BasicAuth kwargs, matching the production code change.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:13:05 -07:00
yuneng-jiang
61cee53200 fix(tests): fix flaky qwen global endpoint test by mocking AsyncHTTPHandler at class level
The test was creating a real AsyncHTTPHandler instance and patching its
post method, but the internal code creates its own handler, bypassing
the mock. This caused real API calls to Vertex AI, resulting in 401
auth errors in CI. Switched to patching AsyncHTTPHandler at the class
level, matching the pattern used by the passing GPT-OSS test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 09:07:48 -07:00
Sameer Kankute
9b3ffd04ef Reserve reasoning for responses via chat completion 2026-03-13 14:19:40 +05:30
Sameer Kankute
288b08fd25 Fix routing of tool call + reasoning effor for gpt-5.4 2026-03-13 14:19:04 +05:30
Sameer Kankute
90b03f6c67 Revert "feat(openai): drop reasoning_effort for gpt-5.4 when tools present"
This reverts commit 14b52b1318.
2026-03-13 13:40:29 +05:30
yuneng-jiang
377c12b917 Allow setting organization_id on key update endpoint
The /key/update endpoint was missing support for organization_id, which
was already available on /key/generate. This adds the field to
UpdateKeyRequest and validates org key limits during updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:04:59 -07:00
yuneng-jiang
002d64b321 fix(tests): increase MAX_CALLS and reduce sleep in flaky e2e budget test
The test_chat_completion_low_budget test was flaky because async spend
tracking couldn't reliably catch up within 50 calls with 0.5s sleeps.
Increased to 200 calls with 0.1s sleeps (same total time budget) to
give more opportunities for budget enforcement to trigger.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:04:31 -07:00
yuneng-jiang
124b44ec22 fix(tests): update PKCE SSO tests to mock get_async_httpx_client
The recent commit 2a997993d4 replaced httpx.AsyncClient() with
get_async_httpx_client() in ui_sso.py, but the PKCE tests still
patched the old httpx.AsyncClient path. Updated all 10 affected
tests to mock get_async_httpx_client and removed unnecessary
context manager setup since AsyncHTTPHandler is returned directly.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 00:02:12 -07:00
yuneng-jiang
98ed295a24 fix(tests): fix flaky realtime WebRTC endpoint tests
Use dependency_overrides for user_api_key_auth instead of relying on
uninitialized proxy globals. The auth dependency was crashing with 500
(instead of 401) and returning MagicMock user_id/team_id values that
broke json.dumps in _encode_realtime_token_payload.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:14:51 -07:00
yuneng-jiang
8ca744036a [Fix] Malformed messages returning 500 instead of 400
The existing AttributeError detection in proxy error handling only
checked one level deep in the exception chain (__cause__, __context__,
original_exception). In practice, the AttributeError from malformed
messages gets wrapped in multiple layers (AttributeError ->
OpenAIException -> APIConnectionError), so the check never found it.

Extracted the check into _has_attribute_error_in_chain() which walks
the full exception chain recursively (depth-capped at 10 to prevent
infinite loops from circular references).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:01:25 -07:00
yuneng-jiang
0235aafb20
Merge pull request #23500 from BerriAI/litellm_litellm-mypy-errors-28de
[Fix] MyPy Errors
2026-03-12 22:46:10 -07:00
Cursor Agent
ff145398d5
fix(ci): skip tests requiring openai>=2.x and MCP M2M oauth2_flow
- Skip test_apply_patch_tool_call_converted_to_chat_completion_tool_call
  when openai.types.responses.response_apply_patch_tool_call is unavailable
  (CI uses openai==1.100.1 which doesn't have this module)
- Skip MCP M2M tests (test_m2m_credentials_forwarded_to_server_model,
  test_m2m_drops_incoming_oauth2_headers) that fail because PR #23187
  changed has_client_credentials to require explicit oauth2_flow opt-in
  but _execute_with_mcp_client was not updated to pass it through
- Revert source code change to rest_endpoints.py that auto-inferred
  oauth2_flow (regression risk: this changes MCP OAuth behavior)

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-13 01:09:56 +00:00
Cursor Agent
177edb06ae
fix: stabilize 5 CI test failures
- Vertex AI batch cost tests: replace removed gemini-1.5-flash-001 model
  with gemini-2.0-flash-001 in pricing lookups
- MCP test_executes_tool_when_allowed: add server_id and auth_type attrs
  to StubServer to match new _resolve_allowed_mcp_servers_with_ip_filter
- MCP M2M tests: infer oauth2_flow='client_credentials' in
  _execute_with_mcp_client when client_id/client_secret/token_url present
  (NewMCPServerRequest lacks oauth2_flow field)
- Team list test: update mock find_many to filter by team_id per the
  current per-team query pattern in list_team
- Azure DALL-E 3 health check: skip test due to 410 ModelDeprecated

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-13 01:03:35 +00:00
yuneng-jiang
fa3f30c024
Merge pull request #23501 from BerriAI/litellm_public_model_hub_fix
[Fix] Public Model Hub Not Showing Config-Defined Models
2026-03-12 17:51:13 -07:00
Emerson Gomes
92d39c308c
fix(gemini): preserve toolConfig on native generate_content (#23493) 2026-03-12 17:48:09 -07:00
yuneng-jiang
db0819ad26 Fix same stale-overwrite bug in update_useful_links
Apply the same fix: move litellm.public_model_groups_links assignment
to after get_config()/save_config() so it is not overwritten by the
stale DB value read.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:45:03 -07:00
yuneng-jiang
b7c43d948e Fix public model hub not showing config-defined models after save
get_config() internally calls _update_config_from_db which overwrites
litellm.public_model_groups with the stale DB value. Moving the
in-memory assignment to after get_config()/save_config() ensures the
new value persists.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 17:41:55 -07:00
Cursor Agent
9a356644bf
fix(tests): stabilize 3 failing CI tests
1. Add missing __init__.py files in tests/test_litellm/llms/gemini/ and
   subdirectories (realtime/, image_edit/) to fix ModuleNotFoundError
   with pytest-xdist parallel workers.

2. Update test_transform_request_uses_dynamic_max_tokens to use
   claude-3-7-sonnet-20250219 (max_output_tokens=64000) since
   claude-3-5-sonnet-20241022 was removed from model_prices JSON
   during deprecated model cleanup. The test assertion was outdated.

3. Update context caching TTL tests to use gemini-2.5-pro instead of
   gemini-1.5-pro. The old model was removed from model_prices JSON,
   causing supports_system_messages to return False, which prevented
   system_instruction from appearing in the transformation output.

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-13 00:26:31 +00:00
Cursor Agent
003e841737
fix(tests): update BFL image generation tests for new signature
Update transform_image_generation_response test calls to pass required
explicit params (request_data, optional_params, litellm_params, encoding)
that replaced **kwargs in the method signature.

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-13 00:20:52 +00:00
yuneng-jiang
d16c8c5590 [Fix] BaseModelResponseIterator crashes on non-string stream chunks
The empty-line filter in __next__/__anext__ called .strip() without
checking the type first. When the Responses API yields Pydantic
BaseModel events (e.g. ResponseCreatedEvent), this raises
AttributeError. Add an isinstance(str_line, str) guard so non-string
objects pass through to _handle_string_chunk as intended.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 16:16:32 -07:00
Joe Reyna
03a0c37608
Merge pull request #23467 from joereyna/fix/mcp-oauth2-token-cache-tests
fix: add oauth2_flow="client_credentials" to MCPServer test helper
2026-03-12 14:55:42 -07:00
yuneng-jiang
25e7d3372b
Merge pull request #23474 from BerriAI/litellm_litellm-ci-stability-c0eb
Litellm ci stability
2026-03-12 13:15:16 -07:00
Cursor Agent
e242356570
fix(ci): fix ruff lint errors and 9 failing unit tests on main
Lint fixes (check_code_and_doc_quality job):
- Remove unused variable reasoning_effort in gpt_5_transformation.py (F841)
- Remove unused timezone imports in mcp_server rest_endpoints.py and server.py (F401)
- Remove unused ProxyBaseLLMRequestProcessing import in realtime endpoints.py (F401)
- Add BaseRealtimeHTTPConfig to TYPE_CHECKING block in utils.py (F821)
- Add PLR0915 per-file-ignore for mcp_server/rest_endpoints.py in ruff.toml

Test fixes (litellm_mapped_tests_llms job):
- Gemini video cost tests: pass explicit model_info to video_generation_cost()
  instead of relying on gemini/veo-3.0-generate-preview being in model_prices JSON
- Anthropic max_tokens tests: mock get_max_tokens() to return expected values
  instead of depending on claude-3-5-sonnet-20241022 being in model_prices JSON
- Vertex AI pydantic obj test: update from removed gemini-1.5-pro to gemini-2.5-flash,
  update expected request body to use response_json_schema format
- Vertex AI/Bedrock file_content integration tests: update mocks to target
  base_llm_http_handler.retrieve_file_content (the new code path via
  ProviderConfigManager) instead of the old vertex_ai_files_instance/
  bedrock_files_instance paths

Co-authored-by: yuneng-jiang <yuneng-jiang@users.noreply.github.com>
2026-03-12 19:58:43 +00:00
Ishaan Jaff
7697b1c397
fix(sso): direct PKCE token exchange + Redis wiring for multi-instance SSO (#22923)
* fix(sso): add direct PKCE token exchange and Redis cache wiring for multi-instance SSO

When PKCE is enabled, bypass fastapi-sso and perform direct token exchange so
code_verifier is correctly included. Store PKCE verifiers as dict in cache
for proper JSON serialization in Redis. Wire user_api_key_cache to Redis when
available so PKCE verifiers are shared across ECS tasks/pods.

Also adds clearer error messages when PKCE is required but not configured.

* refactor(sso): extract PKCE token exchange into SSOAuthenticationHandler methods

- Move import httpx/jwt to module level (top of file, not inside function)
- Extract inline PKCE token exchange + userinfo logic into two static methods:
  _pkce_token_exchange() and _get_pkce_userinfo()
- get_generic_sso_response PKCE path is now a single method call
- Fix double-logging in except block for non-PKCE errors
- Use %-style log formatting (no f-strings in log calls)

* fix: address greptile review feedback

- Fix access_token missing in PKCE path: read from combined_response directly
  instead of generic_sso.access_token (which is only set by verify_and_process)
- Fix PKCE error hint firing when PKCE is already enabled: only show
  'set GENERIC_CLIENT_USE_PKCE=true' advice when code_verifier was absent
- Fix unguarded KeyError on access_token: check for error field in HTTP 200
  responses before accessing token_response['access_token']
- Fix silent empty userinfo: raise ProxyException when both userinfo endpoint
  and id_token fallback produce no user data
- Fix backward-incompatible Redis wiring: only attach Redis to user_api_key_cache
  when GENERIC_CLIENT_USE_PKCE=true, preserving existing in-memory behaviour

* fix: address second round of greptile review feedback

- Fix PKCE error hint: check env var directly (not code_verifier presence) to
  distinguish 'PKCE not configured' from 'PKCE enabled but cache miss'
- Fix misleading Redis TTL comment in proxy_server.py

* fix: address third round of greptile review feedback

- Fix CRITICAL log firing on every non-PKCE callback: only log when PKCE is enabled
- Remove unused pkce_env_value intermediate variable
- Prefer reusing redis_usage_cache over creating separate RedisCache instance
  (avoids losing advanced connection options like SSL, timeouts, db)

* fix: address fourth round of greptile review feedback

- Strip OAuth token credentials from response_convertor input to prevent
  access_token/id_token appearing in restricted-group error messages
- Reuse single httpx.AsyncClient for both token exchange and userinfo requests
  to avoid a second TCP/TLS handshake per SSO callback
- Revert Redis wiring to user_api_key_cache: PKCE code already uses
  redis_usage_cache directly; wiring would route all API-key lookups through
  Redis unnecessarily. Add startup warning instead when PKCE+Redis mismatch.
- Move _OAUTH_TOKEN_FIELDS to module level

* fix remaining PKCE test assertion for dict-format verifier storage

* sanitize PKCE cache log to not expose verifier content

* address greptile review feedback (greploop iteration 3)

* address greptile review feedback (greploop iteration 4)

* address greptile review feedback (greploop iteration 5)

* simplify _get_pkce_userinfo: remove shared-client complexity, use async with directly

* address greptile review feedback (greploop iteration 6)

* address greptile review feedback (greploop iteration 7)

* address greptile review feedback (greploop iteration 8)

* address greptile review feedback (greploop iteration 9)

* address greptile review feedback (greploop iteration 10)

* address greptile review feedback (greploop iteration 11)

* address greptile review feedback (greploop iteration 12)

* fix misleading comment on user_api_key_cache TTL line

* address greptile review feedback (greploop iteration 13)

* address greptile review feedback (greploop iteration 14)

* address greptile review feedback (greploop iteration 15)

* address greptile review feedback (greploop iteration 16)

* address greptile review feedback (greploop iteration 17)

* address greptile review feedback (greploop iteration 18)

* address greptile review feedback (greploop iteration 19)

* address greptile review feedback (greploop iteration 20)

* address greptile review feedback (greploop iteration 21)

* address greptile review feedback (greploop iteration 22)

* address greptile review feedback (greploop iteration 23)

* address greptile review feedback (greploop iteration 24)

* address greptile review feedback (greploop iteration 25)

* address greptile review feedback (greploop iteration 26)

* address greptile review feedback (greploop iteration 27)

* address greptile review feedback (greploop iteration 28)

* address greptile review feedback (greploop iteration 29)

* address greptile review feedback (greploop iteration 30)

* address greptile review feedback (greploop iteration 31)

* address greptile review feedback (greploop iteration 32)

* address greptile review feedback (greploop iteration 33)

* address greptile review feedback (greploop iteration 34)

* address greptile review feedback (greploop iteration 35)

* address greptile review feedback (greploop iteration 37)

- read GENERIC_CLIENT_USE_PKCE env var once in prepare_token_exchange_parameters
- include actual decode error in jwt.decode failure exception message
- add GENERIC_CLIENT_USE_PKCE=true to no-state regression test

* defer PKCE verifier deletion until after all downstream processing

Move _delete_pkce_verifier to after response_convertor and
process_sso_jwt_access_token complete. If JWT processing raises,
the verifier stays in cache so the user can retry without restarting
the full OAuth flow.

* address greptile review feedback (greploop iteration 38)

- fix strict-mode cache miss error message to differentiate
  cross-instance routing failures (Redis configured) from single-instance
  issues (TTL expiry, pod restart) when only in-memory cache is available
- add comment above _get_pkce_userinfo call explaining that bearer
  credentials are always sourced from token_response in the merge step

* fix null JSON response body in _pkce_token_exchange

- Guard against HTTP 200 with body null: response.json() returns None
  for JSON null, and calling .get() on None raises AttributeError.
  Now raises a clean ProxyException with a clear error message.
- Fix misleading userinfo warning: was always saying "empty dict" but
  also fires for JSON null responses; updated to say "empty or null".
- Add HTTP status code assertion to cache miss test.

* address greptile review feedback (greploop iteration 39)

- fix credential leakage: directly assign received_response from
  combined_response instead of relying on nonlocal mutation; Pyright
  was flagging the old guard as unreachable, meaning credential stripping
  might not execute — now it always runs unconditionally
- add test for legacy plain-string cache format backward compat branch
- add test for HTTP 200 with no error field and no access_token (else branch)
- add test for HTTP 200 with JSON null body (new AttributeError guard)

* fix _OAUTH_TOKEN_FIELDS merge loop to preserve userinfo values on absent fields

When the token endpoint omits a bearer-credential field entirely (field
absent from token_response), the previous code deleted it from merged even
if userinfo provided a valid value. Now:
- non-null in token_response → restore authoritative token endpoint value
- explicit null in token_response → remove key from merged (clean absence)
- field absent from token_response → leave userinfo value unchanged

* use HTTP 401 for PKCE missing config errors

GENERIC_CLIENT_ID and GENERIC_TOKEN_ENDPOINT missing when PKCE is
enabled are auth-flow failures, not server errors. Use 401 instead
of 500 to avoid triggering false-positive server error alerts in
monitoring systems.

* address greptile review feedback (greploop iteration 40)

- fix duplicate error logging: demote first format-error log to DEBUG
  so the detailed ERROR in strict-mode branch is not duplicated
- add HTTP status code assertions to all PKCE ProxyException tests
  for better regression protection against accidental code changes

* add credential absence assertions to test_pkce_token_exchange_basic_auth

Verify that client_id and client_secret are NOT double-sent in the POST
body when Basic Auth is used (include_client_id=False with client_secret).
Catches regressions where credentials leak into both Auth header and body.

* address greptile review feedback (greploop iteration 41)

- add Bearer token header assertion to test_pkce_token_exchange_credentials_in_body
- add cache query assertions to both non-strict mode tests to confirm
  the cache was accessed before the warning path triggers

* address greptile review feedback (greploop iteration 42)

- assert null id_token is absent from merged result in basic auth test
- add test for HTTP 200 empty/null userinfo body with no id_token fallback

* use caplog to verify warning logs in non-strict cache miss tests

The two non-strict mode tests now use pytest's caplog fixture to assert
that a warning is actually emitted, not just that the code continues
without raising. This catches regressions where the warning silently
disappears.

* remove dead-code response=None guard in _pkce_token_exchange

* clean up stale pkce verifier cache entries in non-strict mode

* fix test: configure async_delete_cache as AsyncMock and assert cleanup called

* add sentinel guard so pkce-no-redis warning only fires once across hot-reloads

* fix misleading comments: code_verifier init and bearer-credential merge docs

* add best-effort cleanup in strict-mode for corrupt/empty cache entries

* add redirect_uri assertion, userinfo body in non-200 log, sentinel comment
2026-03-12 12:41:39 -07:00
Chesars
690ad4c45b fix(openai): drop all reasoning_effort for gpt-5.4 + tools, including 'none'
OpenAI rejects any reasoning_effort (even 'none') with tools in
/v1/chat/completions for gpt-5.4. Update the guard to drop reasoning_effort
regardless of value. Add docs explaining the auto-drop behavior.
2026-03-12 16:22:40 -03:00
joereyna
180e72d15d fix: add oauth2_flow=client_credentials to MCPServer test helper 2026-03-12 12:22:18 -07:00
Cesar Garcia
ec763784e0
Merge branch 'main' into litellm_oss_staging_03_11_2026 2026-03-12 16:21:28 -03:00
Joe Reyna
f2f843448e
Merge pull request #23414 from joereyna/fix/pass-through-server-root-path
fix: strip SERVER_ROOT_PATH prefix before checking mapped pass-through routes
2026-03-12 11:57:13 -07:00