Skip to content

chore(release): backport staging fixes onto patch-1.93.0rc2 for the 1.93.0 stable cut - #33847

Merged
yuneng-berri merged 11 commits into
patch-1.93.0rc2from
litellm_backport_1930_promote
Jul 18, 2026
Merged

chore(release): backport staging fixes onto patch-1.93.0rc2 for the 1.93.0 stable cut#33847
yuneng-berri merged 11 commits into
patch-1.93.0rc2from
litellm_backport_1930_promote

Conversation

@yuneng-berri

@yuneng-berri yuneng-berri commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Relevant issues

Promotes v1.93.0-rc.2 into the 1.93.0 stable cut. Backports 11 staging PRs onto patch-1.93.0rc2, a fresh base branch created at the exact v1.93.0-rc.2 tag commit, so the stable build carries the fixes that landed on staging after the rc2 cut. Seven are the requested fix/build set (Anthropic passthrough temperature handling, model_armor attachment handling, /v1/models token limits, Docker runtime image contents, and the Python 3.14 enablement changes); the other four are the dependency maintenance bumps that keep the line's image-scan and osv-scan checks green (ddtrace, mcp, pillow, httplib2/setuptools), matching the dependency posture staging ships today. This PR merged from its 11-pick state; the two remaining changes for the cut, #33853 (fresh-database Docker deployments) and the #33864 follow-up guard for #33721, land via #33869 on the same base branch. Release tooling cuts v1.93.0 once that lands

Linear ticket

Pre-Submission checklist

  • I have added meaningful tests
  • My PR passes all CI/CD checks (e.g., lint, format, unit tests)
  • My PR's scope is as isolated as possible; it only solves 1 specific problem
  • I have received a Greptile Confidence Score of at least 4/5 before requesting a maintainer review

What is included

Cherry-picks in original staging merge order, all -x traceable to litellm_internal_staging:

No version bump: rc2's pyproject.toml already reads 1.93.0 and final v1.93.0 is unreleased (DockerHub and GHCR both 404, no v1.93.0 tag, no release/v1.93.0 branch; only the rc images are published). The picks ride the pending 1.93.0. No production .tsx is touched, so there is no UI rebuild

Base branch and provenance

Base is patch-1.93.0rc2, a new branch created at the exact v1.93.0-rc.2 commit (b5cd431c1e); git diff v1.93.0-rc.2 patch-1.93.0rc2 is empty. Every commit on this PR carries a (cherry picked from commit ...) footer whose SHA is reachable from litellm_internal_staging, original authorship is preserved, and there are no merge commits and no _experimental/out/ artifacts

Adaptation notes

Five dependency picks (#33233, #33438, #33484, #33801, #33803) hit uv.lock context conflicts because the line's lock differs from staging's. Each was resolved by taking the pick's pyproject.toml change and regenerating the lock on the line with uv itself (uv lock, and uv lock --upgrade-package mcp for #33803, mirroring that PR's own operation); no lock hunk was hand-merged. The pyproject.toml hunks of all six dependency picks are byte-identical to their staging sources (verified per pick). Final locked versions on the line: ddtrace 4.11.0, mcp 1.28.1, pillow 12.3.0, httplib2 0.32.0, setuptools 83.0.0, and the ddtrace 2.x transitives legacy-cgi and xmltodict drop out, all matching staging's lock. uv lock --check passes and uv sync --frozen --all-groups --all-extras installs cleanly on the branch

Two picks needed source-level context resolution:

  • fix(anthropic/passthrough): drop incompatible temperature when downgrading adaptive thinking for pre-4.6 models #33244: staging commit 831dbbc4df (not picked) later moved _cap_thinking_budget_to_max_tokens from AnthropicMessagesConfig to AnthropicConfig, and the pick's context assumed that move. The resolution keeps the line's local _cap_thinking_budget_to_max_tokens and its AnthropicMessagesConfig. call site untouched and adds only the pick's own _drop_incompatible_temperature_for_thinking method and its call site. A name-equality check confirms the resolved diff adds exactly the defs the staging PR adds, in source and tests
  • build(deps): bump mcp lock to 1.28.1 to clear image-scan findings #33803: the pyproject conflict block bundled the mcp floor with neighboring litellm-proxy-extras/litellm-enterprise pins that staging bumped in commits not picked here. The resolution takes only the mcp floor (mcp>=1.28.1,<2.0) and keeps the line's own subpackage pins (0.4.76/0.1.49)

Known noise on this line

tests/test_litellm/proxy/test_proxy_utils.py::test_get_custom_url fails on the untouched rc2 baseline (it expects http://0.0.0.0:4000/litellm/ui/ and a local environment resolves http://localhost...). It is the same single failure before and after the picks and is unrelated to them

Screenshots / Proof of Fix

Targeted test delta, captured at 44b3de5a83 (all 11 picks) versus b5cd431c1e (rc2 baseline), same six-file targeted set (the test files the picks touch plus their mirrored files):

# baseline (rc2, pre-pick)
1 failed, 278 passed        # the known-noise test above
# post-pick
1 failed, 294 passed        # same single known failure; 16 new tests from the picks, all green

Live proxy replay for #33244 (real Anthropic API through the proxy, the exact adaptive-thinking shape Claude Code sends plus a pinned temperature). Before, at b5cd431c1e:

$ curl -s localhost:4001/v1/messages -H 'Authorization: Bearer sk-1234' -H 'Content-Type: application/json' \
    -d '{"model": "claude-haiku-4-5", "max_tokens": 8192, "thinking": {"type": "adaptive"}, "output_config": {"effort": "medium"}, "temperature": 0, "messages": [{"role": "user", "content": "Say hi"}]}'
-> HTTP 400: "`temperature` may only be set to 1 when thinking is enabled. ..."

After, at 44b3de5a83 (same request):

-> HTTP 200, stop_reason end_turn, content blocks ['thinking', 'text']

The downgraded thinking is preserved and the incompatible pinned temperature is dropped, which is exactly the pick's contract

Live /v1/models?include_metadata=true before/after (#33721): config-mapped models keep identical max_input_tokens/max_output_tokens, while models whose limits previously came from Router.get_model_group_info aggregation now source from the cost map with configured deployment limits winning, per that PR's contract (it removes the per-model deep-copy path that could peg a core on wildcard listings). A plain completion through the proxy returns normally after the picks ("postpick ok")

Rust bridge (#33798): cargo build of litellm-rust completes on this branch with pyo3 0.29 (Finished dev profile), so no call site drifted on the line

Dependency scan posture: an OSV query of every registry package in the final lock returns zero findings beyond the one advisory already suppressed in osv-scanner.toml (diskcache, no fixed release). The repo's own scan workflows do not trigger on PRs targeting patch-* branches, so both were dispatched explicitly on this branch at exactly the merged content and both passed: image-scan https://github.com/BerriAI/litellm/actions/runs/29660204419 (success; its Dockerfile.non_root build also exercises #33592's change for real) and osv-scan https://github.com/BerriAI/litellm/actions/runs/29660205106 (success)

Adversarial behavioral review (deep, eight lenses, three independent verification runs): symbol closure and the picks' own-test delta both survived. The review surfaced one edge in #33721: a deployment configured with a non-numeric token limit (for example model_info: {max_input_tokens: "128,000"}) makes the bare int() raise inside the per-model listing loop, turning the entire GET /v1/models response into a 500 where rc2 degraded to a response without limits. The defect exists byte-identically on the pick's staging source commit, so the transplant is faithful and well-formed configs get the fix exactly as claimed. The guard merged on staging as #33864 and is carried onto this base branch by #33869

Type

🐛 Bug Fix
🚄 Infrastructure

Changes

Cherry-picks only; no hand-written code beyond the two documented conflict resolutions inside their own picks, and every lock change is tool-generated by uv. This PR targets patch-1.93.0rc2 so the release flow can cut v1.93.0 from that branch once merged, following the patch-1.92.0rc2 -> stable/1.92.x precedent

yucheng-berri and others added 11 commits July 18, 2026 13:31
Raise the constraint floors for two transitive dependencies so resolution moves them to their latest maintenance releases: httplib2 0.31.2 -> 0.32.0 and setuptools 82.0.1 -> 83.0.0. Both are pulled in only by optional integrations (Google API client, grpc tooling, lunary observability, the nvidia-riva extra), all lower-bound only, so the floors stay inside every requirer's allowed range and a default install is unaffected

(cherry picked from commit 8b32320)
…ading adaptive thinking for pre-4.6 models (#33244)

* fix(anthropic/passthrough): drop temperature and cap thinking budget when downgrading adaptive thinking for pre-4.6 models

* test(anthropic/passthrough): use sufficient max_tokens for reasoning_effort thinking mapping

* fix(anthropic/passthrough): drop incompatible temperature when downgrading adaptive thinking for pre-4.6 models

Narrow the fix to the temperature reconciliation; the reasoning_effort
budget cap is reverted because the live translation grid relies on
budget_tokens >= max_tokens to reject unsupported effort tiers
(xhigh/max) on budget-mode models, so capping turned those 400s into
200s.

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 71dffc1)
…rent releases (#33438)

* build: drop requires-python upper cap so Python 3.14 resolves to current releases

The <3.14 cap made pip on Python 3.14 fall back to litellm 1.83.7, a
pre-April release whose old auth flow fails with 400s. The cap was added
in d9a4602 because deps lacked 3.14 wheels and uv could not resolve
the 3.14 split; both are fixed now via the existing python_version
markers plus a ddtrace version split (2.x has no cp314 wheels, 3.16+
does). Verified on 3.14.5: uv sync --all-extras installs, litellm and
proxy_server import (rust bridge falls back to pure python), real
provider calls succeed sync/async/streaming, and the core-utils test
suite passes.

* build: cap requires-python at <3.15 and keep ddtrace on one major per python band

Reviewer preference to bound the supported window at the newest tested
minor rather than leaving it open-ended, and Greptile flagged the
ddtrace 3.14+ range spanning two majors; every ddtrace 4.x ships cp314
wheels so the band is now >=4.0,<5.0, matching the single-major
convention of the 2.x band.

(cherry picked from commit c6d49a8)
A single ddtrace constraint now covers every supported Python version, so this collapses the version split introduced in #33438. Also aligns the build_from_pip image pin and updates the type-only Tracer import to its current module path

(cherry picked from commit edc38ea)
#33592)

* fix(docker): restore litellm-proxy-extras source dir in runtime images

#30243 narrowed the runtime stage to an allowlist COPY, which dropped
/app/litellm-proxy-extras from the published images. Downstream
migration jobs point prisma migrate deploy at that path; with the
schema gone (or a schema with no adjacent migrations dir, where prisma
exits 0 without applying anything) those jobs went green while never
migrating the database. Restore the folder in all three runtime stages
and assert in image-scan that the schema and a non-empty migrations dir
ship at the source path

* chore(ci): drop image-scan migration-assets assertion

(cherry picked from commit 111d447)
…attachments and remove the attachment count cap (#33554)

* fix(model_armor): add skip_unscannable_attachments to allow reference-only attachments through

* fix(model_armor): wire skip_unscannable_attachments through guardrail config

* fix(model_armor): make max_file_attachments configurable and scan overflow instead of dropping

* fix(model_armor): remove the per-request attachment count cap and scan all attachments

---------

Co-authored-by: yucheng <yucheng@berri.ai>
(cherry picked from commit 0d7b0f7)
…on 3.14 (#33798)

pyo3 0.23.5 hard-caps the interpreter at Python 3.13, so building the
native bridge against a 3.14 interpreter aborts inside pyo3-ffi's build
script before anything links. This raises pyo3 and pyo3-async-runtimes
to 0.29 (currently the newest line, and the range starting at 0.26 that
supports 3.14) and migrates the three call sites whose APIs were renamed
across that range: Python::with_gil is now Python::attach and
Python::allow_threads is now Python::detach. On a GIL-enabled interpreter
those are pure renames with identical semantics, so behavior on 3.10
through 3.13 is unchanged

Verified by compiling the native module for cp313 and cp314 and driving
it directly on both interpreters: gil_stats reports exactly one GIL
release per sync OCR call and the async path completes, matching the
0.23.5 baseline. cargo fmt, clippy, and the workspace tests pass on both
3.13 and 3.14 with the lockfile locked, and the lock churn is confined to
the pyo3 crates

Part of #26343; addresses the pyo3 build failure reported in #33116

(cherry picked from commit f3d2015)
…33801)

Remove the python_version < '3.14' environment markers from redisvl,
pypdf, and openapi-core now that all three install and import cleanly
on 3.14. The relock is marker-only: no package version changed for any
Python branch, and the locked versions (redisvl 0.4.1, pypdf 6.13.3,
openapi-core 0.22.0) now serve 3.14 as well. semantic-router and
aurelio-sdk stay gated because every published release caps
python_requires below 3.14

(cherry picked from commit 967d934)
…3803)

* build(deps): bump mcp lock to 1.28.1 to clear image-scan findings

* build(deps): require mcp>=1.28.1

(cherry picked from commit 40e914c)
…of Router.get_model_group_info (#33721)

* fix(proxy): source /v1/models token limits from cost map instead of Router.get_model_group_info

Resolves the per-model get_model_group_info fan-out on GET /v1/models
(and /models) that pegged the event loop on wildcard listings (#33636).
create_model_info_response now reads max_input_tokens/max_output_tokens
from litellm.get_model_info (the static cost map) rather than the router,
which aggregated and deepcopied every deployment in a group per listed
model.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(proxy): inject model-info lookup into create_model_info_response for deterministic coverage

Inject the cost-map lookup (defaulting to litellm.get_model_info) so the
except and max_output_tokens branches are exercised deterministically and
the token-limit tests no longer hardcode mutable cost-map values.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* feat(proxy): surface custom deployment token limits on /v1/models via cheap index lookup

Add Router.get_configured_token_limits, an O(1) model-name index lookup that
reads a concrete deployment's configured max_input_tokens/max_output_tokens
without triggering pattern matching or deep copies. create_model_info_response
layers this over the cost map so custom deployments absent from the cost map
still surface their limits, and admin-configured limits override cost-map
defaults, while wildcard-expanded names stay on the fast path.

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: ryan <ryan@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
(cherry picked from commit 8536e3b)
@CLAassistant

CLAassistant commented Jul 18, 2026

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
3 out of 4 committers have signed the CLA.

✅ yuneng-berri
✅ yucheng-berri
✅ ryan-crabbe-berri
❌ devin-ai-integration[bot]
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps

greptile-apps Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This is a release stabilization backport that cherry-picks 11 fixes and dependency bumps from staging onto patch-1.93.0rc2 to cut the v1.93.0 stable release. All source-level changes were adapted from staging commits with documented conflict resolutions; lock files were regenerated with uv rather than hand-merged.

  • Anthropic passthrough (transformation.py): drops incompatible temperature when adaptive thinking is downgraded to legacy enabled on pre-4.6 models, fixing the Anthropic 400 that Claude Code's safety classifier triggered.
  • Model Armor (model_armor.py, file_scanning.py, types/guardrails.py): removes the hardcoded 10-attachment cap and adds the operator-controlled skip_unscannable_attachments flag so reference-only attachments (file_id, gs://, http(s) URLs) can pass through without blocking, while real scan API errors still fail closed.
  • /v1/models token limits (utils.py, router.py): replaces the Router.get_model_group_info aggregation path with a cost-map-first lookup overrideable by O(1) deployment config, eliminating the per-model deep-copy on the listing hot path.
  • Infrastructure: restores the missing litellm-proxy-extras copy in all three runtime Dockerfiles, bumps pyo3 to 0.29 and requires-python to <3.15 for Python 3.14 support, updates ddtrace to the 4.x line, and updates Pillow and mcp to address OSV/image-scan findings.

Confidence Score: 4/5

Safe to merge; all cherry-picks are traceable to staging, tests pass, and no hand-written logic was introduced beyond the two documented conflict resolutions.

The changes are well-scoped, individually tested, and the two adapted conflict resolutions are tightly constrained. The only open question is whether first-deployment-wins for multi-deployment groups in the /v1/models listing matches operator expectations, but this affects metadata surfacing only and cannot cause request failures.

litellm/proxy/utils.py and litellm/router.py — the new token-limit sourcing logic returns limits from only the first deployment when a model group has multiple deployments with different configured limits.

Important Files Changed

Filename Overview
litellm/llms/anthropic/experimental_pass_through/messages/transformation.py Adds _drop_incompatible_temperature_for_thinking to strip non-1 temperature from non-adaptive-thinking requests before they reach Anthropic, preventing 400 errors; logic and call-site placement are correct
litellm/proxy/utils.py create_model_info_response now sources token limits from the cost map first, then overrides with deployment-configured limits from get_configured_token_limits; the first-deployment-wins behavior for multi-deployment groups is an intentional design trade-off
litellm/router.py Adds get_configured_token_limits using O(1) index lookup to avoid wildcard pattern-matching overhead on the /v1/models hot path; returns limits from first-matched deployment only, which is documented and intentional
litellm/proxy/guardrails/guardrail_hooks/model_armor/model_armor.py Removes the hard-coded 10-attachment cap and adds skip_unscannable_attachments option to allow reference-only attachments through while still blocking on real scan API errors; logic is correct and well-tested
litellm/types/guardrails.py Adds skip_unscannable_attachments Optional[bool] field to BaseLitellmParams with secure default=False; properly documented and wired through to the guardrail initializer
litellm/litellm_core_utils/dd_tracing.py Updates TYPE_CHECKING import path from ddtrace.tracer to ddtrace.trace for ddtrace 4.x compatibility; import is guard-only so no runtime impact
Dockerfile Adds missing COPY of litellm-proxy-extras source dir into runtime stage; restores previously lost plugin availability
pyproject.toml Extends Python support to <3.15, bumps Pillow to 12.3.0, mcp to >=1.28.1, ddtrace to >=4.8.2; removes python_version guards on redisvl, pypdf, and openapi-core; adds httplib2/setuptools floor constraints

Comments Outside Diff (1)

  1. litellm/proxy/utils.py, line 6152-6159 (link)

    P2 First-deployment wins for multi-deployment model groups

    get_configured_token_limits calls get_deployment_by_model_group_name, which returns only the first deployment for a given model_name. When a model group has multiple deployments with different model_info.max_input_tokens / max_output_tokens (e.g., one deployment at 128k and another at 200k), the /v1/models response will silently surface only the first deployment's limits regardless of which deployment actually handles the request. This is a change in observable behavior versus the previous get_model_group_info aggregation path. Is this first-wins behaviour intentional and acceptable for the listing endpoint? Is silently returning only the first deployment's token limits for a multi-deployment model group the intended contract here, or should the listing fall back to the cost-map value when deployment limits differ?

Reviews (1): Last reviewed commit: "fix(proxy): source /v1/models token limi..." | Re-trigger Greptile

metadata["_model_armor_status"] = "blocked"
raise self._unscannable_block_error(reason)

if len(attachments) > MAX_FILE_ATTACHMENTS_PER_REQUEST:

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.

Medium: Unbounded guardrail request fan-out

Removing this limit lets an authenticated user include arbitrarily many small attachments and trigger one sequential Model Armor HTTP request per attachment. Request-size enforcement is optional and does not bound the number of calls, so this can consume scanning quota and occupy proxy workers with a single inference request. Keep a configurable upper bound and reject requests that exceed it rather than truncating attachments, since truncation would let unscanned files reach the model.

@veria-ai

veria-ai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

PR overview

This PR backports a set of staging changes onto the patch-1.93.0rc2 branch for the 1.93.0 stable release cut. The remaining touched area in review involves Model Armor guardrail handling for proxy requests with attachments.

One security issue remains open: an authenticated user can attach many small files and cause the proxy to issue one sequential Model Armor scan request per attachment. Because request-size limits do not necessarily cap the number of scan calls, this could waste scanning quota and tie up proxy workers until an explicit attachment-count bound is restored. No issues have been addressed yet in the current review state.

Open issues (1)

Fixed/addressed: 0 · PR risk: 5/10

@yuneng-berri
yuneng-berri merged commit 2530e32 into patch-1.93.0rc2 Jul 18, 2026
8 checks passed
@yuneng-berri
yuneng-berri deleted the litellm_backport_1930_promote branch July 18, 2026 21:19
@yuneng-berri yuneng-berri changed the title chore(release): backport 11 staging PRs onto patch-1.93.0rc2 for the 1.93.0 stable cut chore(release): backport staging fixes onto patch-1.93.0rc2 for the 1.93.0 stable cut Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants