Skip to content

litellm oss staging 09/02/2026 - #20783

Merged
Sameerlite merged 9 commits into
mainfrom
litellm_oss_staging_02_09_2026
Feb 10, 2026
Merged

litellm oss staging 09/02/2026#20783
Sameerlite merged 9 commits into
mainfrom
litellm_oss_staging_02_09_2026

Conversation

@ghost

@ghost ghost commented Feb 9, 2026

Copy link
Copy Markdown

…TRIBUTES (#20761)

The UI sends empty arrays for enterprise-only fields (guardrails, policies, logging) even when the user has not configured these features. The backend is not None check treated [] as a truthy intent to use the feature, falsely requiring an enterprise license for basic team operations.

Backend: Add and updated_kv[field] != [] and updated_kv[field] != {} guards in _update_metadata_fields so empty collections are skipped.

UI: Conditionally omit guardrails, logging, and policies from the payload when empty instead of defaulting to [].

Fixes #20304

  • fix: allow clearing fields with empty collections while skipping enterprise check

Address PR review feedback:

  1. Move the empty-collection guard into _update_metadata_field (singular) so that empty lists/dicts skip only the premium license check but still get written into metadata. This lets users intentionally clear a previously-set field (e.g. guardrails: []) without being blocked, while the UI's default empty arrays still don't trigger a false enterprise error.

  2. Remove sys.path hack from test file; use standard imports that work with pytest discovery.

  3. Add tests verifying that empty collections are moved into metadata (field clearing works) even though they bypass the premium check.

Fixes #20304

Adds documentation for the litellm.proxy_auth feature that automatically obtains and refreshes OAuth2/JWT tokens when connecting to a LiteLLM Proxy.

The VirtualKeysTable crashed when rendering keys with null or undefined models field. The className expression tried to access .length on null, throwing a TypeError that broke the entire keys table.

Added Array.isArray() guard before accessing .length on the models value.

Fixes #20611


  • Fix spend logs pickle error with Pydantic models

Replace copy.deepcopy() with Pydantic-safe serialization to avoid "cannot pickle '_thread.RLock' object" errors when request/response redaction is enabled.

Changes:

  • Add _convert_to_json_serializable_dict() helper that uses model_dump() for Pydantic models instead of pickle
  • Replace copy.deepcopy() calls in request and response redaction paths with the new helper function
  • Recursively handles nested dicts, lists, and Pydantic models

Root cause: Pydantic v2 BaseModel instances contain internal _thread.RLock objects for thread-safety. When copy.deepcopy() attempts to pickle these objects, it fails because threading primitives cannot be pickled.

Fixes #20647

  • chore: remove unused copy import

Remove unused copy import that was causing lint failure. The copy.deepcopy() calls were replaced with _convert_to_json_serializable_dict() helper function in the previous commit, making the copy module no longer needed.


Vertex AI requires Anthropic beta flags in the request body (anthropic_beta array), not as HTTP headers. The Bedrock handler already extracts user-specified beta headers from the headers dict, but the Vertex handler was missing this, causing extra_headers like interleaved-thinking-2025-05-14 to be silently dropped.

This extracts anthropic-beta values from optional_params extra_headers and merges them into the anthropic_beta request body field, and also removes extra_headers from the request body since the parent's transform_request spreads optional_params into data.

  • fix(streaming): preserve interleaved thinking/redacted blocks

  • test(streaming): build thinking chunks with typed Delta/StreamingChoices

  • Fix video list pagination cursors not encoded with provider metadata

first_id and last_id in the video list response were returned as raw provider IDs while data[].id was properly wrapped with encode_video_id_with_provider(). This caused pagination to break when clients passed unencoded cursors back as the after parameter.

  • Encode first_id/last_id in transform_video_list_response
  • Decode the after param in transform_video_list_request via extract_original_video_id()
  • Add 6 unit tests covering encoding, decoding, passthrough, and full round-trip pagination

Fixes #20708

  • fix(responses): preserve streamed tool deltas when id is omitted

  • fix(responses): guard ambiguous tool-call index reuse

  • Add compaction for vertex ai

  • Add all new feat for v1/messages

  • Add inference_geo as supported messages param

  • Add inference based costing

  • Add inference_geo as supported messages param

  • Add support for fast param

  • Add fast mode for other providers

  • Add documentation for Fast Mode

  • add missing indexes on VerificationToken table

  • Fix structured response of tool call

  • Add tests for WebSearch interception with chat completions API

  • Add doc for chat completion web search

  • Fix: is_web_search_tool_chat_completion

  • Fix double json import

  • Add new vercel ai anthropic models

  • Fix: base_model name for body and deplyment name in URL

  • Add output_config as supported param

  • Add response schema for vercel ai sonnet 4.5

  • handle when litellm_parrams might be none

  • Fix : litellm/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py

  • fix: Missing return statement for async streaming

  • Fix: get_supported_anthropic_messages_params

  • Fix mypy issues

  • Fix mypy issues

  • Add support for extra fields in Generic SSO via GENERIC_USER_EXTRA_ATTRIBUTES

Enables extraction of additional fields from the Generic SSO userinfo endpoint response beyond the standard 8 fields (id, email, name, etc.). Custom handlers can now access these fields via CustomOpenID.extra_fields dict.

Changes:

  • Add extra_fields: Optional[Dict[str, Any]] to CustomOpenID type

  • Add GENERIC_USER_EXTRA_ATTRIBUTES env var (comma-separated field names)

  • Extract specified fields using get_nested_value() with dot notation support

  • Add 4 test cases covering basic, nested, and missing field scenarios

  • Update custom_sso.py example showing how to access extra_fields

Backward compatible: extra_fields is None when env var not set

  • docs: Add documentation for GENERIC_USER_EXTRA_ATTRIBUTES

Document the new GENERIC_USER_EXTRA_ATTRIBUTES environment variable for Generic SSO

  • Add to admin_ui_sso.md: explanation and usage examples

  • Add to config_settings.md: environment variable reference

  • Add to custom_sso.md: code example showing how to access extra_fields

  • Includes examples for nested field paths with dot notation


Relevant issues

Pre-Submission checklist

Please complete all items before asking a LiteLLM maintainer to review your PR

  • I have Added testing in the tests/litellm/ directory, Adding at least 1 test is a hard requirement - see details
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible, it only solves 1 specific problem

CI (LiteLLM team)

CI status guideline:

  • 50-55 passing tests: main is stable with minor issues.
  • 45-49 passing tests: acceptable but needs attention
  • <= 40 passing tests: unstable; be careful with your merges and assess the risk.
  • Branch creation CI run
    Link:

  • CI run for the last commit
    Link:

  • Merge / cherry-pick CI run
    Links:

Type

🆕 New Feature
🐛 Bug Fix
🧹 Refactoring
📖 Documentation
🚄 Infrastructure
✅ Test

Changes

@vercel

vercel Bot commented Feb 9, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Feb 10, 2026 0:20am

Request Review

@greptile-apps

greptile-apps Bot commented Feb 9, 2026

Copy link
Copy Markdown
Contributor

Greptile Overview

Greptile Summary

This PR extends the Generic SSO flow to optionally capture additional userinfo fields into a new CustomOpenID.extra_fields dict, controlled by the GENERIC_USER_EXTRA_ATTRIBUTES env var (supports dot-notation via existing get_nested_value). It also tweaks management endpoint metadata updates so empty lists/dicts don’t trigger the enterprise license check while still being written to metadata (supporting UI defaults and intentional clearing), and adds tests + docs to cover the new behavior.

Confidence Score: 4/5

  • Mostly safe to merge after addressing a small config-parsing edge case.
  • Core changes are localized (new optional field on CustomOpenID, env-var driven extraction, and a narrowly-scoped enterprise-check guard) and are covered by unit tests. The main remaining issue is that the extra-attributes parser does not skip empty entries, which can create an empty-string key in extra_fields for common misconfigurations like trailing commas.
  • litellm/proxy/management_endpoints/ui_sso.py

Important Files Changed

Filename Overview
litellm/proxy/management_endpoints/ui_sso.py Adds GENERIC_USER_EXTRA_ATTRIBUTES support to capture additional userinfo fields into CustomOpenID.extra_fields; needs guard to skip empty attribute names when parsing env var.
litellm/proxy/management_endpoints/types.py Extends CustomOpenID with extra_fields: Optional[Dict[str, Any]] for passing through custom SSO attributes.
litellm/proxy/management_endpoints/common_utils.py Adjusts premium metadata field update logic to skip enterprise license check for empty collections while still writing them to metadata (supports intentional clearing).
tests/test_litellm/proxy/management_endpoints/test_ui_sso.py Adds unit tests covering extra_fields extraction for Generic SSO (basic, unset, nested paths, missing fields).

Sequence Diagram

sequenceDiagram
    participant Env as Environment
    participant SSO as generic_response_convertor()
    participant Util as get_nested_value()
    participant OID as CustomOpenID

    Env->>SSO: GENERIC_USER_*_ATTRIBUTE vars
    Env->>SSO: GENERIC_USER_EXTRA_ATTRIBUTES (csv)
    SSO->>Util: extract standard fields (id/email/name/...)
    alt GENERIC_USER_EXTRA_ATTRIBUTES set
        loop each attr in csv
            SSO->>Util: get_nested_value(response, attr)
            Util-->>SSO: value or None
        end
    end
    SSO->>OID: return CustomOpenID(..., extra_fields)
Loading

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

Comment on lines +480 to +484
if generic_user_extra_attributes:
extra_fields = {}
for attr_name in generic_user_extra_attributes.split(","):
attr_name = attr_name.strip()
extra_fields[attr_name] = get_nested_value(response, attr_name)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Empty attr name creates "" key
If GENERIC_USER_EXTRA_ATTRIBUTES contains a trailing comma or consecutive commas (e.g. "dept,,manager,"), attr_name.strip() can become an empty string andq’ll end up populating extra_fields[""] = .... That’s observable in downstream custom handlers and also masks configuration mistakes. Consider skipping empty attr_name entries before calling get_nested_value().

Also applies to whitespace-only entries.

@CLAassistant

CLAassistant commented Feb 10, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@ghost ghost changed the title Add support for extra fields in Generic SSO via GENERIC_USER_EXTRA_AT… litellm oss staging 09/02/2026 Feb 10, 2026
@ghost
ghost requested a review from Sameerlite February 10, 2026 04:03
Praveena-617 and others added 8 commits February 10, 2026 16:00
…TRIBUTES (#20761)

* Add chat completion support for websearch

* Add chat completion tool calls support and response transformation

* Add new methods in chat completion

* Add chat completion tool format

* Add callback for websearch in completion method

* Add test for web search

* Potential fix for code scanning alert no. 4046: Clear-text logging of sensitive information

Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>

* Update litellm/integrations/websearch_interception/tools.py

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

* fix: empty guardrails/policies arrays should not trigger enterprise license check (#20567)

* fix: empty guardrails/policies arrays should not trigger enterprise license check (#20304)

The UI sends empty arrays for enterprise-only fields (guardrails, policies,
logging) even when the user has not configured these features. The backend
`is not None` check treated `[]` as a truthy intent to use the feature,
falsely requiring an enterprise license for basic team operations.

Backend: Add `and updated_kv[field] != [] and updated_kv[field] != {}`
guards in `_update_metadata_fields` so empty collections are skipped.

UI: Conditionally omit guardrails, logging, and policies from the
payload when empty instead of defaulting to `[]`.

Fixes #20304

* fix: allow clearing fields with empty collections while skipping enterprise check

Address PR review feedback:

1. Move the empty-collection guard into _update_metadata_field (singular)
   so that empty lists/dicts skip only the premium license check but still
   get written into metadata. This lets users intentionally clear a
   previously-set field (e.g. guardrails: []) without being blocked, while
   the UI's default empty arrays still don't trigger a false enterprise
   error.

2. Remove sys.path hack from test file; use standard imports that work
   with pytest discovery.

3. Add tests verifying that empty collections are moved into metadata
   (field clearing works) even though they bypass the premium check.

Fixes #20304

* fix critical CVE vulnerabliltes (#20683)

* fix: add hook to handle db case (#20635)

* Add team policy mapping for zguard (#20608)

* support policy mapping on team key level

* update document

* update document

* address comments

* update document

* add unit test for new feature

* add more test case

* feat: add support for anthropic_messages call type in prompt caching (#19233)

* feat: add support for anthropic_messages call type in prompt caching

* test: move anthropic_messages prompt caching test to main router test file

* add tutorial on using claude code with prompt cache routing

* docs: add SDK proxy authentication (OAuth2/JWT auto-refresh) documentation (#20680)

Adds documentation for the litellm.proxy_auth feature that automatically
obtains and refreshes OAuth2/JWT tokens when connecting to a LiteLLM Proxy.

* Fixes #20582 (#20663)

* fix: show error details instead of Data Not Available for failed requests (#20656)

* fix(ui): add null guard for models in API keys table (#20655)

The VirtualKeysTable crashed when rendering keys with null or undefined
models field. The className expression tried to access .length on null,
throwing a TypeError that broke the entire keys table.

Added Array.isArray() guard before accessing .length on the models value.

Fixes #20611

* Fix: Spend logs pickle error with Pydantic models and redaction (#20685)

* docs: add callback registration optimization to v1.81.9 release notes (#20681)

* docs: add callback registration optimization to v1.81.9 release notes

* Update v1.81.9.md

---------

Co-authored-by: Alexsander Hamir <alexsanderhamirgomesbaptista@gmail.com>

* Fix spend logs pickle error with Pydantic models

Replace copy.deepcopy() with Pydantic-safe serialization to avoid
"cannot pickle '_thread.RLock' object" errors when request/response
redaction is enabled.

Changes:
- Add _convert_to_json_serializable_dict() helper that uses
  model_dump() for Pydantic models instead of pickle
- Replace copy.deepcopy() calls in request and response redaction
  paths with the new helper function
- Recursively handles nested dicts, lists, and Pydantic models

Root cause: Pydantic v2 BaseModel instances contain internal
_thread.RLock objects for thread-safety. When copy.deepcopy()
attempts to pickle these objects, it fails because threading
primitives cannot be pickled.

Fixes #20647

* chore: remove unused copy import

Remove unused copy import that was causing lint failure. The copy.deepcopy()
calls were replaced with _convert_to_json_serializable_dict() helper function
in the previous commit, making the copy module no longer needed.

---------

Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Alexsander Hamir <alexsanderhamirgomesbaptista@gmail.com>

* fix(vertex_ai): propagate extra_headers anthropic-beta to request body (#20666)

Vertex AI requires Anthropic beta flags in the request body
(anthropic_beta array), not as HTTP headers. The Bedrock handler
already extracts user-specified beta headers from the headers dict,
but the Vertex handler was missing this, causing extra_headers like
interleaved-thinking-2025-05-14 to be silently dropped.

This extracts anthropic-beta values from optional_params extra_headers
and merges them into the anthropic_beta request body field, and also
removes extra_headers from the request body since the parent's
transform_request spreads optional_params into data.

* fix(streaming): preserve interleaved thinking/redacted blocks

* test(streaming): build thinking chunks with typed Delta/StreamingChoices

* Fix video list pagination cursors not encoded with provider metadata

first_id and last_id in the video list response were returned as raw
provider IDs while data[].id was properly wrapped with
encode_video_id_with_provider(). This caused pagination to break when
clients passed unencoded cursors back as the `after` parameter.

- Encode first_id/last_id in transform_video_list_response
- Decode the `after` param in transform_video_list_request via
  extract_original_video_id()
- Add 6 unit tests covering encoding, decoding, passthrough, and
  full round-trip pagination

Fixes #20708

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

* fix(responses): preserve streamed tool deltas when id is omitted

* fix(responses): guard ambiguous tool-call index reuse

* Add compaction for vertex ai

* Add all new feat for v1/messages

* Add inference_geo as supported messages param

* Add inference based costing

* Add inference_geo as supported messages param

* Add support for fast param

* Add fast mode for other providers

* Add documentation for Fast Mode

* add missing indexes on VerificationToken table

* Fix structured response of tool call

* Add tests for WebSearch interception with chat completions API

* Add doc for chat completion web search

* Fix: is_web_search_tool_chat_completion

* Fix double json import

* Add new vercel ai anthropic models

* Fix: base_model name for body and deplyment name in URL

* Add output_config as supported param

* Add response schema for vercel ai sonnet 4.5

* handle when litellm_parrams might be none

* Fix : litellm/tests/test_litellm/llms/bedrock/chat/invoke_transformations/test_bedrock_chat_invoke_transformations_anthropic_claude3_transformation.py

* fix: Missing return statement for async streaming

* Fix: get_supported_anthropic_messages_params

* Fix mypy issues

* Fix mypy issues

* Add support for extra fields in Generic SSO via GENERIC_USER_EXTRA_ATTRIBUTES

Enables extraction of additional fields from the Generic SSO userinfo endpoint response beyond the standard 8 fields (id, email, name, etc.). Custom handlers can now access these fields via CustomOpenID.extra_fields dict.

Changes:

- Add extra_fields: Optional[Dict[str, Any]] to CustomOpenID type

- Add GENERIC_USER_EXTRA_ATTRIBUTES env var (comma-separated field names)

- Extract specified fields using get_nested_value() with dot notation support

- Add 4 test cases covering basic, nested, and missing field scenarios

- Update custom_sso.py example showing how to access extra_fields

Backward compatible: extra_fields is None when env var not set

* docs: Add documentation for GENERIC_USER_EXTRA_ATTRIBUTES

Document the new GENERIC_USER_EXTRA_ATTRIBUTES environment variable for Generic SSO

- Add to admin_ui_sso.md: explanation and usage examples

- Add to config_settings.md: environment variable reference

- Add to custom_sso.md: code example showing how to access extra_fields

- Includes examples for nested field paths with dot notation

---------

Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Co-authored-by: Varun Chawla <34209028+veeceey@users.noreply.github.com>
Co-authored-by: Harshit Jain <48647625+Harshit28j@users.noreply.github.com>
Co-authored-by: jwang-gif <j.wang@zscaler.com>
Co-authored-by: nuernber <benjamin.nuernberger@jpl.nasa.gov>
Co-authored-by: Cesar Garcia <128240629+Chesars@users.noreply.github.com>
Co-authored-by: John Lathouwers <john.lathouwers@oracle.com>
Co-authored-by: ryan-crabbe <128659760+ryan-crabbe@users.noreply.github.com>
Co-authored-by: Alexsander Hamir <alexsanderhamirgomesbaptista@gmail.com>
Co-authored-by: Elias Högbom Aronsson <elias.aronson@gmail.com>
Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: tshushan <tshushan@outbrain.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Carlo Alberto Ferraris <cafxx@mercari.com>
* Fix ollama_chat reasoning_context.

For ollama_chat models, reasoning context is ignored after 2 consecutive thinking chunks.

* add test
…#20726)

OIDC providers like Logto may return opaque (non-JWT) access tokens,
which caused jwt.decode() to raise DecodeError and crash the SSO
callback with a 500 error. Catch DecodeError and skip JWT-based
extraction gracefully, since user info is already available from
the UserInfo endpoint.

Fixes #20724
)

* fix(anthropic): route thinking requests through OpenAI responses

* Apply suggestion from @greptile-apps[bot]

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

---------

Co-authored-by: Krish Dholakia <krrishdholakia@gmail.com>
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* fix(responses): preserve streamed tool deltas when id is omitted

* fix(responses): guard ambiguous tool-call index reuse

* add missing indexes on VerificationToken table

* mcp: support http(s) URLs for spec_path in OpenAPI MCP loader

* test(mcp): add unit test for OpenAPI spec_path URL support

* Fix OpenAPI spec URL loading to use shared MCP httpx client

Ensure URL-based OpenAPI loading honors LiteLLM’s custom httpx configuration, add missing imports, and harden tests to prevent regressions or accidental direct httpx usage.

* removed unused import urlparse

* removed unsupported timeout argument

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Carlo Alberto Ferraris <cafxx@mercari.com>
Co-authored-by: Andrea Odorisio <Andrea@BR-FHH9MWDQ2PMAC.local>
* fix(responses): preserve streamed tool deltas when id is omitted

* fix(responses): guard ambiguous tool-call index reuse

* add missing indexes on VerificationToken table

* fix(bedrock): handle concatenated JSON in tool call arguments

When using Bedrock Claude Sonnet 4.5 with tools enabled, the model
sometimes returns multiple tool call arguments as concatenated JSON
objects in a single arguments string, e.g.
  '{"command":["curl",...]}{"command":["curl",...]}{"command":["curl",...]}'

json.loads() fails on this with "Extra data", crashing the entire
request in _convert_to_bedrock_tool_call_invoke.

This commit:
- Adds split_concatenated_json_objects() helper in common_utils.py
  that uses json.JSONDecoder.raw_decode() to walk a string and extract
  each JSON object individually.
- Updates _convert_to_bedrock_tool_call_invoke() to catch JSONDecodeError
  and attempt splitting concatenated objects into separate Bedrock
  toolUse blocks (first block keeps original ID, subsequent blocks get
  suffixed IDs).
- Fixes duplicate json.loads calls and a shadowed 'id' builtin.
- Adds 12 unit tests covering normal, empty, concatenated, and edge cases.

Fixes #20543

---------

Co-authored-by: Emerson Gomes <emerson.gomes@thalesgroup.com>
Co-authored-by: Sameer Kankute <sameer@berri.ai>
Co-authored-by: Carlo Alberto Ferraris <cafxx@mercari.com>
…very (#20700)

* fix(responses): preserve cached tool call objects in tool result recovery

* fix(responses): support attr-based cached tool call recovery

* Update litellm/responses/litellm_completion_transformation/transformation.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>
@Sameerlite
Sameerlite merged commit 5222fd4 into main Feb 10, 2026
50 of 65 checks passed
@ishaan-berri
ishaan-berri deleted the litellm_oss_staging_02_09_2026 branch March 26, 2026 22:29
fzowl pushed a commit to fzowl/litellm that referenced this pull request Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment